/* * TMP144.c * * Created on: 23 Mar 2022 * Author: Jasper */ #include "TMP144.h" #include "string.h" static const uint8_t TMP144_SEQ_RESET[] = {0x55, 0xB4}; static const uint8_t TMP144_SEQ_ADDR[] = {0x55, 0x8C, 0x90}; static const uint8_t TMP144_SEQ_READ_TEMPS[] = {0x55, 0xF1}; volatile uint16_t temperatures[N_CELLS]; static volatile TMP144Bus bus_busbar; static volatile TMP144Bus bus_other; #define CHECK_STATUS(s) \ { \ HAL_StatusTypeDef _s = s; \ if (_s != HAL_OK) \ return _s; \ } HAL_StatusTypeDef tmp144_init(UART_HandleTypeDef* busbar_side, UART_HandleTypeDef* other_side) { bus_busbar.handle = busbar_side; bus_other.handle = other_side; bus_busbar.state = TMP144_IDLE; bus_other.state = TMP144_IDLE; // TODO: Configure this in EEPROM bus_busbar.n_sensors = 11; bus_busbar.sensor_mappings[0] = 8; bus_busbar.sensor_mappings[1] = 8; bus_busbar.sensor_mappings[2] = 8; bus_busbar.sensor_mappings[3] = 6; bus_busbar.sensor_mappings[4] = 6; bus_busbar.sensor_mappings[5] = 4; bus_busbar.sensor_mappings[6] = 4; bus_busbar.sensor_mappings[7] = 4; bus_busbar.sensor_mappings[8] = 2; bus_busbar.sensor_mappings[9] = 2; bus_busbar.sensor_mappings[10] = 2; bus_other.n_sensors = 13; bus_other.sensor_mappings[0] = 1; bus_other.sensor_mappings[1] = 1; bus_other.sensor_mappings[2] = 1; bus_other.sensor_mappings[3] = 3; bus_other.sensor_mappings[4] = 3; bus_other.sensor_mappings[5] = 5; bus_other.sensor_mappings[6] = 5; bus_other.sensor_mappings[7] = 5; bus_other.sensor_mappings[8] = 5; bus_other.sensor_mappings[9] = 7; bus_other.sensor_mappings[10] = 7; bus_other.sensor_mappings[11] = 9; bus_other.sensor_mappings[12] = 9; CHECK_STATUS(tmp144_init_reset(&bus_busbar)); CHECK_STATUS(tmp144_init_reset(&bus_other)); return HAL_OK; } HAL_StatusTypeDef tmp144_init_reset(TMP144Bus* bus) { if (bus->state != TMP144_IDLE) { return HAL_ERROR; } bus->state = TMP144_RESETTING; CHECK_STATUS(HAL_UART_Receive_IT(bus->handle, bus->rxbuf, 2)); // Keep sending Global Software Reset until it echoes back (as per 7.5.2) int tries = 0; do { if (tries > 10) { return HAL_TIMEOUT; } CHECK_STATUS(HAL_UART_Transmit(bus->handle, TMP144_SEQ_RESET, sizeof(TMP144_SEQ_RESET), 100)); HAL_Delay(100); tries++; } while (bus->state == TMP144_RESETTING); bus->state = TMP144_INITIALIZING; CHECK_STATUS(HAL_UART_Receive_IT(bus->handle, bus->rxbuf, 3)); CHECK_STATUS(HAL_UART_Transmit(bus->handle, TMP144_SEQ_ADDR, sizeof(TMP144_SEQ_ADDR), 100)); return HAL_OK; } HAL_StatusTypeDef tmp144_init_post_reset(TMP144Bus* bus) { if (bus->state != TMP144_RESETTING || memcmp(bus->rxbuf, TMP144_SEQ_RESET, sizeof(TMP144_SEQ_RESET)) != 0) { return HAL_ERROR; } bus->state = TMP144_IDLE; return HAL_OK; } HAL_StatusTypeDef tmp144_init_post_addr(TMP144Bus* bus) { size_t idx_response = sizeof(TMP144_SEQ_ADDR) - 1; if (bus->state != TMP144_INITIALIZING || memcmp(bus->rxbuf, TMP144_SEQ_ADDR, idx_response) != 0) { return HAL_ERROR; } uint8_t n_sensors = bus->rxbuf[idx_response] - TMP144_SEQ_ADDR[idx_response]; if (n_sensors != bus->n_sensors) { return HAL_ERROR; } bus->state = TMP144_IDLE; return HAL_OK; } HAL_StatusTypeDef tmp144_read_temps() { CHECK_STATUS(tmp144_send_read_temps(&bus_busbar)); CHECK_STATUS(tmp144_send_read_temps(&bus_other)); return HAL_OK; } HAL_StatusTypeDef tmp144_send_read_temps(TMP144Bus* bus) { if (bus->state != TMP144_IDLE) { return HAL_ERROR; } bus->state = TMP144_READING_TEMP; // HAL_UART_Receive_IT(bus->handle, bus->rxbuf, // sizeof(TMP144_SEQ_READ_TEMPS) + 2 * bus->n_sensors); CHECK_STATUS( HAL_UART_Receive_IT(bus->handle, bus->rxbuf, sizeof(TMP144_SEQ_READ_TEMPS) + 2 * bus->n_sensors)); CHECK_STATUS(HAL_UART_Transmit(bus->handle, TMP144_SEQ_READ_TEMPS, sizeof(TMP144_SEQ_READ_TEMPS), 100)); return HAL_OK; } HAL_StatusTypeDef tmp144_recv_temps(TMP144Bus* bus) { if (bus->state != TMP144_READING_TEMP) { return HAL_ERROR; } bus->state = TMP144_IDLE; size_t headerlen = sizeof(TMP144_SEQ_READ_TEMPS); if (memcmp(bus->rxbuf, TMP144_SEQ_READ_TEMPS, headerlen) != 0) { return HAL_ERROR; } // Find max temperature for each cell uint8_t current_cell = bus->sensor_mappings[0]; uint16_t max_temp = 0; for (size_t i = 0; i < bus->n_sensors; i++) { uint8_t cell = bus->sensor_mappings[i]; if (cell != current_cell) { temperatures[current_cell] = max_temp; current_cell = cell; max_temp = 0; } size_t buf_offset = headerlen + 2 * i; uint16_t temp = (bus->rxbuf[buf_offset] >> 4) | (bus->rxbuf[buf_offset + 1] << 4); if (temp > max_temp) { max_temp = temp; } } temperatures[current_cell] = max_temp; return HAL_OK; } void HAL_UART_RxCpltCallback(UART_HandleTypeDef* handle) { TMP144Bus* bus; if (handle == bus_busbar.handle) { bus = &bus_busbar; } else if (handle == bus_other.handle) { bus = &bus_other; } else { // TODO Error_Handler(); } switch (bus->state) { case TMP144_IDLE: // TODO Error_Handler(); case TMP144_RESETTING: tmp144_init_post_reset(bus); break; case TMP144_INITIALIZING: tmp144_init_post_addr(bus); break; case TMP144_READING_TEMP: tmp144_recv_temps(bus); break; default: // TODO Error_Handler(); } }