commit 05af93cdfbf239496a3d5adc4c95d183abb3a92c
parent e62f6defe36046fac0f527cf1f1b6a425a6e6f33
Author: Martin Kloeckner <mjkloeckner@gmail.com>
Date: Wed, 1 Apr 2026 14:39:00 -0300
Agregar lógica y menus para programar encendido/apagado automático
Diffstat:
5 files changed, 251 insertions(+), 10 deletions(-)
diff --git a/firmware/app/inc/app.h b/firmware/app/inc/app.h
@@ -19,10 +19,17 @@ extern uint32_t g_app_WCET_us;
extern volatile uint32_t g_app_tick_cnt;
typedef struct {
+ uint8_t start_hour, start_min;
+ uint8_t end_hour, end_min;
+ bool enabled;
+} task_system_timer_t;
+
+typedef struct {
int16_t temp_set_point; // Desired temp
- int16_t temp_sensor; // Actual temp
- uint8_t temp_ctrl_pwm_dc; // Duty cycle of output [0, 100]
+ int16_t temp_sensor; // Actual temp
+ uint8_t temp_ctrl_pwm_dc; // Duty cycle of output [0, 100]
bool temp_ctrl_enabled;
+ task_system_timer_t *timer;
} shared_data_type;
extern void app_init(void);
diff --git a/firmware/app/inc/task_system_attribute.h b/firmware/app/inc/task_system_attribute.h
@@ -42,6 +42,9 @@ typedef enum task_system_st {
ST_SYS_IDLE,
ST_SYS_CLOCK_SET,
ST_SYS_TEMP_SET,
+ ST_SYS_TIMER_SET_STATUS,
+ ST_SYS_TIMER_SET_START,
+ ST_SYS_TIMER_SET_END,
} task_system_st_t;
typedef struct {
diff --git a/firmware/app/src/app.c b/firmware/app/src/app.c
@@ -71,6 +71,7 @@ void app_init(void)
p_shared_data->temp_sensor = -20;
p_shared_data->temp_ctrl_pwm_dc = 0;
p_shared_data->temp_ctrl_enabled = false;
+ p_shared_data->timer = NULL;
for (uint32_t index = 0; TASK_QTY > index; index++)
{
diff --git a/firmware/app/src/task_menu.c b/firmware/app/src/task_menu.c
@@ -60,7 +60,7 @@ void task_menu_init(void *parameters)
display_i2c_init();
display_i2c_set_cursor_pos(0, 0);
- display_i2c_write_string("Inicializando...");
+ display_i2c_write_string("Initializing...");
g_display_update = true;
LOGGER_INFO("Done initializing `task_menu`");
@@ -167,6 +167,18 @@ void task_menu_statechart(void *parameters)
menu_set_state(ST_MEN_TEMP_SET);
break;
+ case EV_MEN_ST_TIMER_SET_STATUS:
+ menu_set_state(ST_MEN_TIMER_SET_STATUS);
+ break;
+
+ case EV_MEN_ST_TIMER_SET_START:
+ menu_set_state(ST_MEN_TIMER_SET_START);
+ break;
+
+ case EV_MEN_ST_TIMER_SET_END:
+ menu_set_state(ST_MEN_TIMER_SET_END);
+ break;
+
default: break;
}
}
@@ -265,6 +277,66 @@ void task_menu_statechart(void *parameters)
break;
+ case ST_MEN_TIMER_SET_STATUS:
+
+ if (g_display_update)
+ {
+ g_display_update = false;
+ display_i2c_async_clear();
+ display_i2c_async_write_string("Timer>");
+ display_i2c_async_set_cursor_pos(8, 0);
+ memset(menu_row_str, '\0', sizeof(menu_row_str));
+ sprintf(menu_row_str, "%8s",
+ p_shared_data->timer->enabled ? "enabled" : "disabled");
+ display_i2c_async_write_string(menu_row_str);
+
+ display_i2c_async_set_cursor_pos(3, 1);
+ memset(menu_row_str, '\0', sizeof(menu_row_str));
+ sprintf(menu_row_str, "%s%2d:%02d - %d:%02d",
+ (p_shared_data->timer->end_hour >= 10) ? "" : " ",
+ p_shared_data->timer->start_hour,
+ p_shared_data->timer->start_min,
+ p_shared_data->timer->end_hour,
+ p_shared_data->timer->end_min);
+ display_i2c_async_write_string(menu_row_str);
+ }
+
+ break;
+
+ case ST_MEN_TIMER_SET_START:
+
+ if (g_display_update)
+ {
+ g_display_update = false;
+ display_i2c_async_clear();
+ display_i2c_async_write_string("Timer>start>");
+ display_i2c_async_set_cursor_pos(11, 1);
+ memset(menu_row_str, '\0', sizeof(menu_row_str));
+ sprintf(menu_row_str, "%2d:%02d",
+ p_shared_data->timer->start_hour,
+ p_shared_data->timer->start_min);
+ display_i2c_async_write_string(menu_row_str);
+ }
+
+ break;
+
+ case ST_MEN_TIMER_SET_END:
+
+ if (g_display_update)
+ {
+ g_display_update = false;
+ display_i2c_async_clear();
+ display_i2c_async_write_string("Timer>end>");
+ display_i2c_async_set_cursor_pos(11, 1);
+ memset(menu_row_str, '\0', sizeof(menu_row_str));
+ sprintf(menu_row_str, "%2d:%02d",
+ p_shared_data->timer->end_hour,
+ p_shared_data->timer->end_min);
+ display_i2c_async_write_string(menu_row_str);
+ }
+
+ break;
+
default:
p_task_menu_dta->tick = G_TASK_MEN_TICK_INI;
diff --git a/firmware/app/src/task_system.c b/firmware/app/src/task_system.c
@@ -28,6 +28,14 @@
#define DEL_SYS_MIN 0ul
#define DEL_SYS_MED 50ul
#define DEL_SYS_MAX 500ul
+#define G_TASK_SYSTEM_TICK_UPDATE_RATE_MS 1000ul
+
+// If persistent values are lost these are the timer default values
+#define TIMER_DEFAULT_START_HOUR 0000
+#define TIMER_DEFAULT_START_MIN 0000
+#define TIMER_DEFAULT_END_HOUR 0000
+#define TIMER_DEFAULT_END_MIN 0000
+#define TIMER_DEFAULT_STATUS false
task_system_dta_t task_system_dta = {
DEL_SYS_MIN, ST_SYS_IDLE, EV_SYS_IDLE, false
@@ -35,12 +43,21 @@ task_system_dta_t task_system_dta = {
#define SYSTEM_DTA_QTY (sizeof(task_system_dta)/sizeof(task_system_dta_t))
+// Private variables
+static task_system_timer_t task_system_timer = {
+ TIMER_DEFAULT_START_HOUR, TIMER_DEFAULT_START_MIN,
+ TIMER_DEFAULT_END_HOUR, TIMER_DEFAULT_END_MIN,
+ TIMER_DEFAULT_STATUS
+};
+
+uint32_t g_task_system_timer_tick;
+
// Exported variables
-volatile uint32_t g_task_system_tick;
volatile uint32_t g_task_system_tick_cnt; // Updated every ms by SysTick callback
// Private function declaration
void task_system_statechart(void *parameters);
+void task_system_timer_update(void *parameters);
void task_system_rtc_init(void);
void task_system_rtc_increment_hour(void);
void task_system_rtc_increment_min(void);
@@ -56,7 +73,8 @@ void task_system_init(void *parameters)
LOGGER_INFO("Initializing `task_system`...");
- g_task_system_tick = G_TASK_SYS_CNT_INI;
+ g_task_system_tick_cnt = G_TASK_SYS_TICK_CNT_INI;
+ g_task_system_timer_tick = G_TASK_SYS_CNT_INI;
task_system_interface_init_event_queue();
task_system_rtc_init();
@@ -67,6 +85,9 @@ void task_system_init(void *parameters)
state = ST_SYS_IDLE;
p_task_system_dta->state = state;
+ shared_data_type *p_shared_data = (shared_data_type *)parameters;
+ p_shared_data->timer = &task_system_timer;
+
LOGGER_INFO("Done initializing `task_system`");
}
@@ -84,8 +105,15 @@ void task_system_update(void *parameters)
while (b_time_update_required)
{
- g_task_system_tick++;
-
+ if (0 == g_task_system_timer_tick)
+ {
+ g_task_system_timer_tick = G_TASK_SYSTEM_TICK_UPDATE_RATE_MS;
+ task_system_timer_update(parameters);
+ }
+ else
+ {
+ g_task_system_timer_tick--;
+ }
task_system_statechart(parameters);
__asm("CPSID i");
@@ -307,8 +335,8 @@ void task_system_statechart(void *parameters)
{
case EV_SYS_BTN_A_ACTIVE:
case EV_SYS_BTN_D_ACTIVE:
- p_task_system_dta->state = ST_SYS_IDLE;
- task_menu_interface_put_event(EV_MEN_ST_IDLE);
+ p_task_system_dta->state = ST_SYS_TIMER_SET_STATUS;
+ task_menu_interface_put_event(EV_MEN_ST_TIMER_SET_STATUS);
task_system_eeprom_write_param(parameters);
break;
@@ -330,11 +358,141 @@ void task_system_statechart(void *parameters)
}
break;
- default:
+ case ST_SYS_TIMER_SET_STATUS:
if (true == p_task_system_dta->event_flag)
{
p_task_system_dta->event_flag = false;
+ switch (p_task_system_dta->event)
+ {
+
+ case EV_SYS_BTN_C_ACTIVE:
+ p_shared_data->timer->enabled = !p_shared_data->timer->enabled;
+ task_menu_interface_put_event(EV_MEN_DISPLAY_UPDATE);
+ break;
+
+ case EV_SYS_BTN_A_ACTIVE:
+ case EV_SYS_BTN_B_ACTIVE:
+ p_task_system_dta->state = ST_SYS_IDLE;
+ task_menu_interface_put_event(EV_MEN_ST_IDLE);
+ break;
+
+ case EV_SYS_BTN_D_ACTIVE:
+ p_task_system_dta->state = ST_SYS_TIMER_SET_START;
+ task_menu_interface_put_event(EV_MEN_ST_TIMER_SET_START);
+ break;
+
+ default: break;
+ }
}
break;
+
+ case ST_SYS_TIMER_SET_START:
+ if (true == p_task_system_dta->event_flag)
+ {
+ p_task_system_dta->event_flag = false;
+ switch (p_task_system_dta->event)
+ {
+ case EV_SYS_BTN_B_ACTIVE:
+ p_shared_data->timer->start_hour =
+ ((p_shared_data->timer->start_hour + 1) % 24);
+ task_menu_interface_put_event(EV_MEN_DISPLAY_UPDATE);
+ break;
+
+ case EV_SYS_BTN_C_ACTIVE:
+ p_shared_data->timer->start_min =
+ ((p_shared_data->timer->start_min + 1) % 60);
+ task_menu_interface_put_event(EV_MEN_DISPLAY_UPDATE);
+ break;
+
+ case EV_SYS_BTN_A_ACTIVE:
+ case EV_SYS_BTN_D_ACTIVE:
+ p_task_system_dta->state = ST_SYS_TIMER_SET_END;
+ task_menu_interface_put_event(EV_MEN_ST_TIMER_SET_END);
+ break;
+
+ default: break;
+ }
+ }
+ break;
+
+ case ST_SYS_TIMER_SET_END:
+ if (true == p_task_system_dta->event_flag)
+ {
+ p_task_system_dta->event_flag = false;
+ switch (p_task_system_dta->event)
+ {
+ case EV_SYS_BTN_B_ACTIVE:
+ p_shared_data->timer->end_hour =
+ ((p_shared_data->timer->end_hour + 1) % 24);
+ task_menu_interface_put_event(EV_MEN_DISPLAY_UPDATE);
+ break;
+
+ case EV_SYS_BTN_C_ACTIVE:
+ p_shared_data->timer->end_min =
+ ((p_shared_data->timer->end_min + 1) % 60);
+ task_menu_interface_put_event(EV_MEN_DISPLAY_UPDATE);
+ break;
+
+ case EV_SYS_BTN_A_ACTIVE:
+ case EV_SYS_BTN_D_ACTIVE:
+ p_task_system_dta->state = ST_SYS_IDLE;
+ task_menu_interface_put_event(EV_MEN_ST_IDLE);
+ break;
+
+ default: break;
+ }
+ }
+ break;
+
+ default:
+ p_task_system_dta->state = ST_SYS_IDLE;
+ p_task_system_dta->event_flag = false;
+ p_shared_data->temp_ctrl_enabled = false;
+ task_menu_interface_put_event(EV_MEN_ST_IDLE);
+ task_leds_interface_put_event(EV_LED_XX_OFF, ID_LED_A);
+ task_leds_interface_put_event(EV_LED_XX_OFF, ID_LED_B);
+ break;
+ }
+}
+
+// TOOD: Only check timer conditions every second (not on every tick)
+void task_system_timer_update(void *parameters)
+{
+ shared_data_type *p_shared_data = (shared_data_type *)parameters;
+ uint16_t start_24, end_24, clock_24;
+ bool new_temp_ctrl_state;
+
+ if (false == p_shared_data->timer->enabled)
+ {
+ return;
+ }
+
+ HAL_RTC_GetTime(&hrtc, &s_time, RTC_FORMAT_BIN);
+
+ clock_24 = (s_time.Hours*100) + s_time.Minutes;
+ start_24 = (p_shared_data->timer->start_hour*100) + p_shared_data->timer->start_min;
+ end_24 = (p_shared_data->timer->end_hour*100) + p_shared_data->timer->end_min;
+
+ new_temp_ctrl_state = ((end_24 > start_24)
+ ? ((clock_24 >= start_24) && (clock_24 < end_24))
+ : ((clock_24 >= start_24) || (clock_24 < end_24)));
+
+ if (new_temp_ctrl_state != p_shared_data->temp_ctrl_enabled)
+ {
+ p_shared_data->temp_ctrl_enabled = new_temp_ctrl_state;
+
+ task_menu_interface_put_event(EV_MEN_DISPLAY_UPDATE);
+ task_buzzer_interface_put_event(EV_BUZ_XX_LONG_BEEP, ID_BUZ_A);
+
+ if (true == p_shared_data->temp_ctrl_enabled)
+ {
+ task_leds_interface_put_event(EV_LED_XX_BLINK, ID_LED_A);
+ task_leds_interface_put_event(EV_LED_XX_BLINK, ID_LED_B);
+ }
+ else
+ {
+ task_leds_interface_put_event(EV_LED_XX_OFF, ID_LED_A);
+ task_leds_interface_put_event(EV_LED_XX_OFF, ID_LED_B);
+ }
}
}