/* * TMP144.c * * Created on: 23 Mar 2022 * Author: Jasper */ #include "TMP144.h" #include "stm32f4xx_hal.h" #include "stm32f4xx_hal_def.h" #include "stm32f4xx_hal_uart.h" #include #include 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_TEMP_SENSORS]; volatile uint16_t min_temperature; volatile uint16_t max_temperature; volatile TMP144Bus tmp144_bus_busbar; volatile TMP144Bus tmp144_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) { tmp144_bus_busbar.handle = busbar_side; tmp144_bus_other.handle = other_side; tmp144_bus_busbar.state = TMP144_IDLE; tmp144_bus_other.state = TMP144_IDLE; // TODO: Configure this in EEPROM tmp144_bus_busbar.n_sensors = N_TEMP_SENSORS / 2; tmp144_bus_other.n_sensors = N_TEMP_SENSORS / 2; CHECK_STATUS(tmp144_init_reset(&tmp144_bus_busbar)); // CHECK_STATUS(tmp144_init_reset(&tmp144_bus_other)); return HAL_OK; } HAL_StatusTypeDef tmp144_check_timeouts() { uint32_t now = HAL_GetTick(); uint32_t t1 = tmp144_bus_busbar.expected_response_time; uint32_t t2 = tmp144_bus_other.expected_response_time; if (t1 != 0 && t1 < now) { tmp144_bus_busbar.state = TMP144_ERROR; } // FIXME // if (t2 != 0 && t2 < now) { // tmp144_bus_other.state = TMP144_ERROR; // } 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_DMA(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 > bus->n_sensors) { bus->state = TMP144_ERROR; return HAL_TIMEOUT; } if (bus->handle->RxState == HAL_UART_STATE_READY && bus->state == TMP144_RESETTING) { HAL_UART_DMAStop(bus->handle); CHECK_STATUS(HAL_UART_Receive_DMA(bus->handle, bus->rxbuf, 2)); } CHECK_STATUS(HAL_UART_Transmit_IT(bus->handle, TMP144_SEQ_RESET, sizeof(TMP144_SEQ_RESET))); HAL_Delay(100); tries++; } while (bus->state == TMP144_RESETTING); bus->state = TMP144_INITIALIZING; CHECK_STATUS(HAL_UART_Receive_DMA(bus->handle, bus->rxbuf, 3)); bus->expected_response_time = HAL_GetTick() + 100; 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) { bus->state = TMP144_ERROR; return HAL_ERROR; } bus->state = TMP144_IDLE; return HAL_OK; } HAL_StatusTypeDef tmp144_read_temps() { CHECK_STATUS(tmp144_send_read_temps(&tmp144_bus_busbar)); CHECK_STATUS(tmp144_send_read_temps(&tmp144_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; CHECK_STATUS( HAL_UART_Receive_DMA(bus->handle, bus->rxbuf, sizeof(TMP144_SEQ_READ_TEMPS) + 2 * bus->n_sensors)); bus->expected_response_time = HAL_GetTick() + TMP144_RESPONSE_TIMEOUT; 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; } size_t temperatures_offset = (bus == &tmp144_bus_busbar) ? 0 : N_TEMP_SENSORS / 2; for (size_t i = 0; i < bus->n_sensors; i++) { size_t buf_offset = headerlen + 2 * i; uint16_t temp = (bus->rxbuf[buf_offset] >> 4) | (bus->rxbuf[buf_offset + 1] << 4); if (temp == 0x7FF) { // Extremely unlikely, probably the sensor is just broken temp = 0; } temperatures[temperatures_offset + i] = temp; } uint16_t max = temperatures[0]; uint16_t min = temperatures[0]; // FIXME for (size_t i = 1; i < 16; i++) { if (temperatures[i] > max) { max = temperatures[i]; } if (temperatures[i] < min) { min = temperatures[i]; } } max_temperature = max; min_temperature = min; return HAL_OK; } void tmp144_handle_rx_cplt(UART_HandleTypeDef* handle) { TMP144Bus* bus; if (handle == tmp144_bus_busbar.handle) { bus = &tmp144_bus_busbar; } else if (handle == tmp144_bus_other.handle) { bus = &tmp144_bus_other; } else { // TODO Error_Handler(); } bus->expected_response_time = 0; 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(); } }