|
|
|
@ -15,15 +15,55 @@ |
|
|
|
|
|
|
|
|
|
#define MAX_TEMP 400 |
|
|
|
|
|
|
|
|
|
typedef enum GuiScreen { |
|
|
|
|
SCREEN_HOME, |
|
|
|
|
SCREEN_MANUAL, |
|
|
|
|
SCREEN_MANUAL_MENU, |
|
|
|
|
} GuiScreen; |
|
|
|
|
|
|
|
|
|
static struct State { |
|
|
|
|
float oven_temp; |
|
|
|
|
float soc_temp; |
|
|
|
|
int set_temp; |
|
|
|
|
int set_temp_wheel; |
|
|
|
|
bool heater_enabled; |
|
|
|
|
bool pushed; |
|
|
|
|
uint32_t push_tick; |
|
|
|
|
// true if the button is still held since init (i.e. the push action should not work as "enter")
|
|
|
|
|
bool initial_pushed; |
|
|
|
|
|
|
|
|
|
GuiScreen screen; |
|
|
|
|
int menu_pos; |
|
|
|
|
int menu_len; |
|
|
|
|
} s_app = {}; |
|
|
|
|
|
|
|
|
|
static void calc_set_temp() { |
|
|
|
|
/** Get push time (while held) */ |
|
|
|
|
static uint32_t push_time() { |
|
|
|
|
return s_app.pushed ? (xTaskGetTickCount() - s_app.push_tick) : 0; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
typedef void (*screen_t)(GuiEvent event); |
|
|
|
|
|
|
|
|
|
static void screen_home(GuiEvent event); |
|
|
|
|
|
|
|
|
|
static void screen_manual(GuiEvent event); |
|
|
|
|
|
|
|
|
|
static void screen_manual_menu(GuiEvent event); |
|
|
|
|
|
|
|
|
|
static screen_t screens[] = { |
|
|
|
|
[SCREEN_HOME] = screen_home, |
|
|
|
|
[SCREEN_MANUAL] = screen_manual, |
|
|
|
|
[SCREEN_MANUAL_MENU] = screen_manual_menu, |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
static void draw_common_overlay(); |
|
|
|
|
|
|
|
|
|
static void input_sound_effect(GuiEvent event); |
|
|
|
|
|
|
|
|
|
static void switch_screen(GuiScreen screen, bool init); |
|
|
|
|
|
|
|
|
|
static void calc_set_temp() |
|
|
|
|
{ |
|
|
|
|
int clamped = s_app.set_temp_wheel; |
|
|
|
|
if (clamped < 0) { |
|
|
|
|
clamped = 0; |
|
|
|
@ -36,58 +76,230 @@ static void calc_set_temp() { |
|
|
|
|
app_heater_set_target((float) s_app.set_temp); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void app_task_gui(void *argument) { |
|
|
|
|
char tmp[100]; |
|
|
|
|
|
|
|
|
|
void app_task_gui(void *argument) |
|
|
|
|
{ |
|
|
|
|
// Wait until inited
|
|
|
|
|
ulTaskNotifyTake(pdTRUE, portMAX_DELAY); |
|
|
|
|
PUTS("GUI task starts\r\n"); |
|
|
|
|
|
|
|
|
|
char tmp[100]; |
|
|
|
|
|
|
|
|
|
while (1) { |
|
|
|
|
s_app.oven_temp = app_temp_read_oven(); |
|
|
|
|
s_app.soc_temp = app_temp_read_soc(); |
|
|
|
|
|
|
|
|
|
uint32_t message = GUI_EVENT_NONE; |
|
|
|
|
osMessageQueueGet(guiEventQueHandle, &message, NULL, pdMS_TO_TICKS(1000)); |
|
|
|
|
osMessageQueueGet(guiEventQueHandle, &message, NULL, pdMS_TO_TICKS(50)); |
|
|
|
|
|
|
|
|
|
switch (message) { |
|
|
|
|
case GUI_NOTIFY_KNOB_PLUS: |
|
|
|
|
s_app.set_temp_wheel++; |
|
|
|
|
calc_set_temp(); |
|
|
|
|
break; |
|
|
|
|
case GUI_NOTIFY_KNOB_MINUS: |
|
|
|
|
s_app.set_temp_wheel--; |
|
|
|
|
calc_set_temp(); |
|
|
|
|
case GUI_EVENT_KNOB_PRESS: |
|
|
|
|
s_app.pushed = true; |
|
|
|
|
s_app.push_tick = xTaskGetTickCount(); |
|
|
|
|
break; |
|
|
|
|
case GUI_NOTIFY_KNOB_PRESS: |
|
|
|
|
break; |
|
|
|
|
case GUI_NOTIFY_KNOB_RELEASE: |
|
|
|
|
s_app.heater_enabled ^= 1; |
|
|
|
|
app_heater_enable(s_app.heater_enabled); |
|
|
|
|
app_buzzer_beep(); |
|
|
|
|
|
|
|
|
|
case GUI_EVENT_KNOB_RELEASE: |
|
|
|
|
s_app.pushed = false; |
|
|
|
|
break; |
|
|
|
|
|
|
|
|
|
default: |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
fb_clear(); |
|
|
|
|
if (s_app.initial_pushed && message == GUI_EVENT_KNOB_RELEASE) { |
|
|
|
|
s_app.initial_pushed = false; |
|
|
|
|
} else { |
|
|
|
|
fb_clear(); |
|
|
|
|
SPRINTF(tmp, "%d", s_app.screen); |
|
|
|
|
fb_text(3, 80, tmp, FONT_5X7, 1); |
|
|
|
|
draw_common_overlay(); |
|
|
|
|
|
|
|
|
|
SPRINTF(tmp, "T=%.1f°C", s_app.oven_temp); |
|
|
|
|
fb_text(3, 3, tmp, FONT_5X7, 1); |
|
|
|
|
screens[s_app.screen](message); |
|
|
|
|
|
|
|
|
|
SPRINTF(tmp, "Cil=%d°C", s_app.set_temp); |
|
|
|
|
fb_text(3, 11, tmp, FONT_5X7, 1); |
|
|
|
|
fb_blit(); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
SPRINTF(tmp, "Stav=%s", s_app.heater_enabled ? "ZAP" : "VYP"); |
|
|
|
|
fb_text(3, 19, tmp, FONT_5X7, 1); |
|
|
|
|
static void switch_screen(GuiScreen screen, bool init) { |
|
|
|
|
s_app.initial_pushed = s_app.pushed; |
|
|
|
|
s_app.screen = screen; |
|
|
|
|
|
|
|
|
|
SPRINTF(tmp, "Tsoc=%.1f°C", s_app.soc_temp); |
|
|
|
|
fb_text(3, 27, tmp, FONT_5X7, 1); |
|
|
|
|
if (init) { |
|
|
|
|
screens[screen](GUI_EVENT_SCREEN_INIT); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (s_app.heater_enabled) { |
|
|
|
|
fb_frame(0, 0, FBW, FBH, 2, 1); |
|
|
|
|
} |
|
|
|
|
static void draw_common_overlay() |
|
|
|
|
{ |
|
|
|
|
SPRINTF(tmp, "%3.1f°C →%3d°C", s_app.oven_temp, s_app.set_temp); |
|
|
|
|
fb_text(3, 3, tmp, FONT_3X5, 1); |
|
|
|
|
//
|
|
|
|
|
// SPRINTF(tmp, "Tsoc=%.1f°C", s_app.soc_temp);
|
|
|
|
|
// fb_text(3, 19, tmp, FONT_5X7, 1);
|
|
|
|
|
|
|
|
|
|
if (s_app.heater_enabled) { |
|
|
|
|
fb_frame(0, 0, FBW, FBH, 2, 1); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static void input_sound_effect(GuiEvent event) |
|
|
|
|
{ |
|
|
|
|
switch (event) { |
|
|
|
|
case GUI_EVENT_KNOB_PLUS: |
|
|
|
|
case GUI_EVENT_KNOB_MINUS: |
|
|
|
|
case GUI_EVENT_KNOB_RELEASE: |
|
|
|
|
app_buzzer_beep(); |
|
|
|
|
break; |
|
|
|
|
|
|
|
|
|
default: |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static void screen_home(GuiEvent event) |
|
|
|
|
{ |
|
|
|
|
if (event == GUI_EVENT_SCREEN_INIT) { |
|
|
|
|
s_app.menu_pos = 0; |
|
|
|
|
s_app.menu_len = 1; |
|
|
|
|
// Disable heater
|
|
|
|
|
app_heater_enable(false); |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
input_sound_effect(event); |
|
|
|
|
|
|
|
|
|
// Menu with one item, lol
|
|
|
|
|
|
|
|
|
|
SPRINTF(tmp, "Manual mode", s_app.soc_temp); |
|
|
|
|
if (s_app.menu_pos == 0) { |
|
|
|
|
fb_rect(3, 27, 64, 8, 1); |
|
|
|
|
} |
|
|
|
|
fb_text(3, 27, tmp, FONT_5X7, s_app.menu_pos != 0); |
|
|
|
|
|
|
|
|
|
switch (event) { |
|
|
|
|
case GUI_EVENT_KNOB_RELEASE: |
|
|
|
|
switch (s_app.menu_pos) { |
|
|
|
|
case 0: |
|
|
|
|
switch_screen(SCREEN_MANUAL, true); |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
break; |
|
|
|
|
|
|
|
|
|
case GUI_EVENT_KNOB_PLUS: |
|
|
|
|
if (s_app.menu_pos < s_app.menu_len - 1) { |
|
|
|
|
s_app.menu_pos++; |
|
|
|
|
} |
|
|
|
|
break; |
|
|
|
|
|
|
|
|
|
case GUI_EVENT_KNOB_MINUS: |
|
|
|
|
if (s_app.menu_pos > 0) { |
|
|
|
|
s_app.menu_pos--; |
|
|
|
|
} |
|
|
|
|
break; |
|
|
|
|
|
|
|
|
|
default: |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static void screen_manual(GuiEvent event) |
|
|
|
|
{ |
|
|
|
|
if (event == GUI_EVENT_SCREEN_INIT) { |
|
|
|
|
s_app.set_temp_wheel = 0; |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// menu activated by long push
|
|
|
|
|
if (push_time() >= pdMS_TO_TICKS(500)) { |
|
|
|
|
switch_screen(SCREEN_MANUAL_MENU, true); |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
input_sound_effect(event); |
|
|
|
|
|
|
|
|
|
switch (event) { |
|
|
|
|
case GUI_EVENT_KNOB_RELEASE: |
|
|
|
|
if (s_app.initial_pushed) { |
|
|
|
|
s_app.initial_pushed = false; |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
s_app.heater_enabled ^= 1; |
|
|
|
|
app_heater_enable(s_app.heater_enabled); |
|
|
|
|
break; |
|
|
|
|
|
|
|
|
|
case GUI_EVENT_KNOB_PLUS: |
|
|
|
|
s_app.set_temp_wheel++; |
|
|
|
|
calc_set_temp(); |
|
|
|
|
break; |
|
|
|
|
|
|
|
|
|
case GUI_EVENT_KNOB_MINUS: |
|
|
|
|
s_app.set_temp_wheel--; |
|
|
|
|
calc_set_temp(); |
|
|
|
|
break; |
|
|
|
|
|
|
|
|
|
default: |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static void screen_manual_menu(GuiEvent event) |
|
|
|
|
{ |
|
|
|
|
if (event == GUI_EVENT_SCREEN_INIT) { |
|
|
|
|
s_app.menu_pos = 0; |
|
|
|
|
s_app.menu_len = 2; |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
input_sound_effect(event); |
|
|
|
|
|
|
|
|
|
SPRINTF(tmp, "Close menu", s_app.soc_temp); |
|
|
|
|
if (s_app.menu_pos == 0) { |
|
|
|
|
fb_rect(3, 27, 64, 8, 1); |
|
|
|
|
} |
|
|
|
|
fb_text(3, 27, tmp, FONT_5X7, s_app.menu_pos != 0); |
|
|
|
|
|
|
|
|
|
SPRINTF(tmp, "Exit manual", s_app.soc_temp); |
|
|
|
|
if (s_app.menu_pos == 1) { |
|
|
|
|
fb_rect(3, 27 + 8, 64, 8, 1); |
|
|
|
|
} |
|
|
|
|
fb_text(3, 27 + 8, tmp, FONT_5X7, s_app.menu_pos != 1); |
|
|
|
|
|
|
|
|
|
switch (event) { |
|
|
|
|
// the button is held! release is what activates the button
|
|
|
|
|
case GUI_EVENT_KNOB_RELEASE: |
|
|
|
|
if (s_app.initial_pushed) { |
|
|
|
|
s_app.initial_pushed = false; |
|
|
|
|
} |
|
|
|
|
break; |
|
|
|
|
|
|
|
|
|
case GUI_EVENT_KNOB_PRESS: |
|
|
|
|
switch (s_app.menu_pos) { |
|
|
|
|
case 0: |
|
|
|
|
// Close menu
|
|
|
|
|
switch_screen(SCREEN_MANUAL, false); |
|
|
|
|
break; |
|
|
|
|
|
|
|
|
|
case 1: |
|
|
|
|
// Close menu
|
|
|
|
|
switch_screen(SCREEN_HOME, true); |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
break; |
|
|
|
|
|
|
|
|
|
case GUI_EVENT_KNOB_PLUS: |
|
|
|
|
if (s_app.menu_pos < s_app.menu_len - 1) { |
|
|
|
|
s_app.menu_pos++; |
|
|
|
|
} |
|
|
|
|
break; |
|
|
|
|
|
|
|
|
|
case GUI_EVENT_KNOB_MINUS: |
|
|
|
|
if (s_app.menu_pos > 0) { |
|
|
|
|
s_app.menu_pos--; |
|
|
|
|
} |
|
|
|
|
break; |
|
|
|
|
|
|
|
|
|
fb_blit(); |
|
|
|
|
default: |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|