/** * TODO file description */ #include #include #include "app_gui.h" #include "app_buzzer.h" #include "app_temp.h" #include "FreeRTOS.h" #include "task.h" #include "queue.h" #include "ufb/framebuffer.h" #include "ufb/fb_text.h" #include "app_safety.h" #include "app_heater.h" struct State s_app = {}; /** Get push time (while held) */ uint32_t push_time() { return s_app.pushed ? (xTaskGetTickCount() - s_app.push_time) : 0; } /** Schedule paint (the screen func will be called with the PAINT event argument */ void request_paint() { s_app.paint_needed = true; } /** Draw the common overlay / HUD (with temperatures and heater status) */ static void draw_common_overlay(); char stmp[100]; /** Main loop */ void app_task_gui(void *argument) { // Wait until inited ulTaskNotifyTake(pdTRUE, portMAX_DELAY); PUTS("GUI task starts\r\n"); s_app.last_tick_time = xTaskGetTickCount(); switch_screen(screen_home, true); while (1) { uint32_t message = GUI_EVENT_NONE; int32_t ticks_remain = (int32_t) pdMS_TO_TICKS(10) - (int32_t) (xTaskGetTickCount() - s_app.last_tick_time); if (ticks_remain < 0) { ticks_remain = 0; } osMessageQueueGet(guiEventQueHandle, &message, NULL, ticks_remain); if (message == GUI_EVENT_KNOB_PLUS) { if (s_app.up_prescaller) { s_app.up_prescaller = 0; // let this through } else { // consume this s_app.down_prescaller = 0; s_app.up_prescaller = 1; message = GUI_EVENT_NONE; } } else if (message == GUI_EVENT_KNOB_MINUS) { if (s_app.down_prescaller) { s_app.down_prescaller = 0; // let this through } else { // consume this s_app.up_prescaller = 0; s_app.down_prescaller = 1; message = GUI_EVENT_NONE; } } uint32_t tickNow = xTaskGetTickCount(); // 10ms tick event if (tickNow - s_app.last_tick_time > pdMS_TO_TICKS(10)) { s_app.screen(GUI_EVENT_SCREEN_TICK); s_app.last_tick_time = tickNow; } if (tickNow - s_app.last_read_temp_time > pdMS_TO_TICKS(250)) { s_app.oven_temp = app_temp_read_oven(); //s_app.soc_temp = app_temp_read_soc(); request_paint(); s_app.last_read_temp_time = tickNow; } switch (message) { case GUI_EVENT_KNOB_PRESS: s_app.pushed = true; s_app.push_time = tickNow; break; case GUI_EVENT_KNOB_RELEASE: s_app.pushed = false; if (s_app.initial_pushed) { s_app.initial_pushed = false; message = GUI_EVENT_NONE; } break; } if (message != GUI_EVENT_NONE) { s_app.screen(message); } app_safety_pass_display_updating(); if (s_app.paint_needed) { s_app.paint_needed = false; fb_clear(); draw_common_overlay(); s_app.screen(GUI_EVENT_PAINT); fb_blit(); } } } /** Switch to a different screen handler. * If "init" is true, immediately call it with the init event. */ void switch_screen(screen_t pScreen, bool init) { PRINTF("Screen = %p, init=%d\r\n", pScreen, init); s_app.initial_pushed = s_app.pushed; s_app.screen = pScreen; // clear the union field request_paint(); if (init) { pScreen(GUI_EVENT_SCREEN_INIT); } } /** Draw GUI common to all screens */ static void draw_common_overlay() { SPRINTF(stmp, "%5.1f°C →%3d°C", app_temp_read_oven(), (int) app_heater_get_target()); fb_text(3, 3, stmp, FONT_3X5, 1); float soc = app_temp_read_soc(); if (soc > 70) { SPRINTF(stmp, "! CHIP %d°C !", (int) soc); fb_text(3, 14, stmp, FONT_3X5, 1); } if (app_heater_get_state()) { fb_frame(0, 0, FBW, 11, 1, 1); float perc = app_heater_get_percent(); fb_hline(0, 12, (fbpos_t) ((float)FBW * (perc / 100.0f)), 1); } } /** Play input sound effect if this is an input event */ void input_sound_effect() { app_buzzer_beep(); }