firmware-nucleo/App/Src/task_remote.c (9549B)
1 /* 2 * Copyright (c) 2026 Martin Javier Klöckner <mklockner@fi.uba.ar> 3 * 4 * See file `LICENSE` for full details 5 */ 6 7 #include <stdio.h> 8 #include <stdint.h> 9 #include <stdbool.h> 10 #include <string.h> 11 #include <time.h> 12 13 #include "main.h" 14 #include "app.h" 15 16 #include "task_remote.h" 17 #include "task_system_attribute.h" 18 #include "task_system_interface.h" 19 #include "logger.h" 20 21 #define G_TASK_REMOTE_TICK_INI 0ul 22 #define G_TASK_REMOTE_TEMP_UPDATE_RATE_MS 1000ul 23 24 // Public variables 25 //// this variable is incremented by 1 on every ms by HAL_SysTick 26 volatile uint32_t g_task_remote_tick_cnt; 27 queue_t task_remote_rx_queue; 28 uint8_t task_remote_uart_rx_byte; 29 uint8_t task_remote_uart_tx_dma_buffer[G_TASK_REMOTE_QUEUE_LEN]; 30 31 // Private types declaration 32 typedef enum { 33 TX_DATA_STATUS_OK = 'A', 34 TX_DATA_MAIN_OUTPUT_TOGGLE_OK = 'B', 35 TX_DATA_TIMER_TOGGLE_OK = 'C', 36 TX_DATA_TIMER_SET_VALUES_OK = 'D', 37 TX_DATA_TEMP_STATUS_OK = 'E', 38 TX_DATA_TEMP_SET_OK = 'F' 39 } uart_tx_data_e; 40 41 typedef enum { 42 RX_DATA_STATUS = 'A', 43 RX_DATA_MAIN_OUTPUT_TOGGLE = 'B', 44 RX_DATA_TIMER_TOGGLE = 'C', 45 RX_DATA_TIMER_SET_VALUES = 'D', 46 RX_DATA_TEMP_STATUS = 'E', 47 RX_DATA_TEMP_SET = 'F' 48 } uart_rx_data_e; 49 50 // Private variables definition 51 uint32_t g_task_remote_tick; 52 time_t system_time; 53 static queue_t task_remote_tx_queue; 54 55 // Public functions declaration 56 void task_remote_queue_enqueue(queue_t *queue, uint8_t value); 57 58 // Private functions declaration 59 static void task_remote_rx_data_handler(void *parameters); 60 static void task_remote_queue_init(queue_t *queue); 61 static uint8_t task_remote_queue_peek(queue_t *queue); 62 static uint8_t task_remote_queue_count(queue_t *queue); 63 static uint8_t task_remote_queue_dequeue(queue_t *queue); 64 static uint8_t task_remote_queue_is_empty(queue_t *queue); 65 66 // Public funtions implementation 67 void task_remote_init(void *parameters) 68 { 69 LOGGER_INFO("Initializing `task_remote`..."); 70 71 task_remote_queue_init(&task_remote_tx_queue); 72 task_remote_queue_init(&task_remote_rx_queue); 73 74 g_task_remote_tick = G_TASK_REMOTE_TICK_INI; 75 HAL_UART_Receive_IT(&huart3, &task_remote_uart_rx_byte, 1); 76 77 LOGGER_INFO("Done initializing `task_remote`"); 78 } 79 80 void task_remote_update(void *parameters) 81 { 82 bool b_time_update_required = false; 83 shared_data_type *p_shared_data = (shared_data_type *)parameters; 84 85 __asm("CPSID i"); 86 if (G_TASK_REMOTE_TICK_INI < g_task_remote_tick_cnt) 87 { 88 g_task_remote_tick_cnt--; 89 b_time_update_required = true; 90 } 91 __asm("CPSIE i"); 92 93 while (b_time_update_required) 94 { 95 __asm("CPSID i"); 96 if (G_TASK_REMOTE_TICK_INI < g_task_remote_tick_cnt) 97 { 98 g_task_remote_tick_cnt--; 99 b_time_update_required = true; 100 } 101 else 102 { 103 b_time_update_required = false; 104 } 105 __asm("CPSIE i"); 106 107 if (!task_remote_queue_is_empty(&task_remote_rx_queue)) 108 { 109 task_remote_rx_data_handler(parameters); 110 } 111 112 // Send temp updated values to remote module 113 if (0 == g_task_remote_tick) 114 { 115 g_task_remote_tick = G_TASK_REMOTE_TEMP_UPDATE_RATE_MS; 116 task_remote_queue_enqueue(&task_remote_tx_queue, TX_DATA_TEMP_STATUS_OK); 117 task_remote_queue_enqueue(&task_remote_tx_queue, p_shared_data->temp_sensor); 118 task_remote_queue_enqueue(&task_remote_tx_queue, p_shared_data->temp_set_point); 119 } 120 else 121 { 122 g_task_remote_tick--; 123 } 124 125 if(!task_remote_queue_is_empty(&task_remote_tx_queue)) 126 { 127 uint8_t i; 128 for (i = 0; !task_remote_queue_is_empty(&task_remote_tx_queue); ++i) 129 { 130 task_remote_uart_tx_dma_buffer[i] = task_remote_queue_dequeue(&task_remote_tx_queue); 131 } 132 HAL_UART_Transmit_DMA(&huart3, task_remote_uart_tx_dma_buffer, i); 133 } 134 } 135 } 136 137 void task_remote_queue_enqueue(queue_t *queue, uint8_t value) 138 { 139 queue->count++; 140 queue->data[queue->head++] = value; 141 } 142 143 // Private function implementation 144 static void task_remote_rx_data_handler(void *parameters) 145 { 146 shared_data_type *p_shared_data = (shared_data_type *)parameters; 147 148 uint8_t query_type = task_remote_queue_peek(&task_remote_rx_queue); 149 150 switch(query_type) 151 { 152 case RX_DATA_STATUS: 153 task_remote_queue_dequeue(&task_remote_rx_queue); // skip query type 154 155 task_remote_queue_enqueue(&task_remote_tx_queue, TX_DATA_STATUS_OK); 156 task_remote_queue_enqueue(&task_remote_tx_queue, 157 p_shared_data->temp_ctrl_enabled); 158 159 HAL_RTC_GetTime(&hrtc, &s_time, RTC_FORMAT_BIN); 160 HAL_RTC_GetDate(&hrtc, &s_date, RTC_FORMAT_BIN); 161 162 struct tm time_tm = { 163 .tm_year = s_date.Year + 100, 164 .tm_mon = s_date.Month - 1, 165 .tm_mday = s_date.Date, 166 .tm_hour = s_time.Hours, 167 .tm_min = s_time.Minutes, 168 .tm_sec = s_time.Seconds, 169 }; 170 171 system_time = mktime(&time_tm); 172 173 // LSB first 174 task_remote_queue_enqueue(&task_remote_tx_queue, 175 (uint8_t)(system_time & 0xFF)); 176 task_remote_queue_enqueue(&task_remote_tx_queue, 177 (uint8_t)((system_time >> 8) & 0xFF)); 178 task_remote_queue_enqueue(&task_remote_tx_queue, 179 (uint8_t)((system_time >> 16) & 0xFF)); 180 task_remote_queue_enqueue(&task_remote_tx_queue, 181 (uint8_t)((system_time >> 24) & 0xFF)); 182 183 task_remote_queue_enqueue(&task_remote_tx_queue, p_shared_data->timer->enabled); 184 task_remote_queue_enqueue(&task_remote_tx_queue, p_shared_data->timer->start_hour); 185 task_remote_queue_enqueue(&task_remote_tx_queue, p_shared_data->timer->start_min); 186 task_remote_queue_enqueue(&task_remote_tx_queue, p_shared_data->timer->end_hour); 187 task_remote_queue_enqueue(&task_remote_tx_queue, p_shared_data->timer->end_min); 188 189 task_remote_queue_enqueue(&task_remote_tx_queue, p_shared_data->temp_sensor); 190 task_remote_queue_enqueue(&task_remote_tx_queue, p_shared_data->temp_set_point); 191 192 break; 193 194 case RX_DATA_MAIN_OUTPUT_TOGGLE: 195 196 task_remote_queue_dequeue(&task_remote_rx_queue); // skip query type 197 task_system_interface_put_event(EV_SYS_REM_TEMP_CTRL_ENABLED); 198 task_remote_queue_enqueue(&task_remote_tx_queue, 199 TX_DATA_MAIN_OUTPUT_TOGGLE_OK); 200 201 break; 202 203 case RX_DATA_TIMER_TOGGLE: 204 205 task_remote_queue_dequeue(&task_remote_rx_queue); // skip query type 206 task_system_interface_put_event(EV_SYS_REM_TIMER_TOGGLE); 207 task_remote_queue_enqueue(&task_remote_tx_queue, 208 TX_DATA_TIMER_TOGGLE_OK); 209 210 break; 211 212 case RX_DATA_TIMER_SET_VALUES: 213 214 if (task_remote_queue_count(&task_remote_rx_queue) < 5) 215 { 216 // wait for additional data 217 break; 218 } 219 220 task_remote_queue_dequeue(&task_remote_rx_queue); // skip query type 221 222 p_shared_data->timer->start_hour = task_remote_queue_dequeue(&task_remote_rx_queue); 223 p_shared_data->timer->start_min = task_remote_queue_dequeue(&task_remote_rx_queue); 224 p_shared_data->timer->end_hour = task_remote_queue_dequeue(&task_remote_rx_queue); 225 p_shared_data->timer->end_min = task_remote_queue_dequeue(&task_remote_rx_queue); 226 227 task_remote_queue_enqueue(&task_remote_tx_queue, TX_DATA_TIMER_SET_VALUES_OK); 228 229 break; 230 231 case RX_DATA_TEMP_STATUS: 232 233 task_remote_queue_dequeue(&task_remote_rx_queue); // skip query type 234 235 task_remote_queue_enqueue(&task_remote_tx_queue, TX_DATA_TEMP_STATUS_OK); 236 task_remote_queue_enqueue(&task_remote_tx_queue, p_shared_data->temp_sensor); 237 task_remote_queue_enqueue(&task_remote_tx_queue, p_shared_data->temp_set_point); 238 239 break; 240 241 case RX_DATA_TEMP_SET: 242 243 if (task_remote_queue_count(&task_remote_rx_queue) < 2) 244 { 245 // wait for additional data 246 break; 247 } 248 249 task_remote_queue_dequeue(&task_remote_rx_queue); // skip query type 250 p_shared_data->temp_set_point = task_remote_queue_dequeue(&task_remote_rx_queue); 251 task_remote_queue_enqueue(&task_remote_tx_queue, TX_DATA_TEMP_SET_OK); 252 task_system_interface_put_event(EV_SYS_REM_TEMP_SET); 253 254 break; 255 256 default: 257 task_remote_queue_dequeue(&task_remote_rx_queue); 258 break; 259 } 260 } 261 262 static void task_remote_queue_init(queue_t *queue) 263 { 264 queue->head = 0; 265 queue->tail = 0; 266 queue->count = 0; 267 268 for (uint8_t i = 0; i < G_TASK_REMOTE_QUEUE_LEN; ++i) 269 { 270 queue->data[i] = 0; 271 } 272 } 273 274 static uint8_t task_remote_queue_peek(queue_t *queue) 275 { 276 return queue->data[queue->tail]; 277 } 278 279 static uint8_t task_remote_queue_count(queue_t *queue) 280 { 281 return queue->count; 282 } 283 284 static uint8_t task_remote_queue_dequeue(queue_t *queue) 285 { 286 if(task_remote_queue_is_empty(queue)) 287 { 288 return task_remote_queue_peek(queue); 289 } 290 291 queue->count--; 292 return queue->data[queue->tail++]; 293 } 294 295 static uint8_t task_remote_queue_is_empty(queue_t *queue) 296 { 297 return (queue->count == 0); 298 } 299
