|
|
|
@ -16,11 +16,24 @@ |
|
|
|
|
|
|
|
|
|
#define MAX_TEMP 400 |
|
|
|
|
|
|
|
|
|
typedef void (*menu_callback_t)(int choice); |
|
|
|
|
/**
|
|
|
|
|
* Screen callback type. The event is either INIT, PAINT, or one of the input events. |
|
|
|
|
*/ |
|
|
|
|
typedef void (*screen_t)(GuiEvent event); |
|
|
|
|
|
|
|
|
|
void screen_menu(GuiEvent event, const char **options, menu_callback_t cb); |
|
|
|
|
/**
|
|
|
|
|
* Choice callback for the generic menu screen |
|
|
|
|
*/ |
|
|
|
|
typedef void (*menu_callback_t)(int choice); |
|
|
|
|
|
|
|
|
|
typedef void (*screen_t)(GuiEvent event); |
|
|
|
|
/**
|
|
|
|
|
* Generic menu screen (must be called from a screen function with the standard signature) |
|
|
|
|
* |
|
|
|
|
* @param event - currently handled event |
|
|
|
|
* @param options - options for the menu (items to show) |
|
|
|
|
* @param cb - choice callback |
|
|
|
|
*/ |
|
|
|
|
static void screen_menu(GuiEvent event, const char **options, menu_callback_t cb); |
|
|
|
|
|
|
|
|
|
static struct State { |
|
|
|
|
float oven_temp; |
|
|
|
@ -49,36 +62,34 @@ static uint32_t push_time() { |
|
|
|
|
return s_app.pushed ? (xTaskGetTickCount() - s_app.push_tick) : 0; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/** Schedule paint (the screen func will be called with the PAINT event argument */ |
|
|
|
|
static void request_paint() { |
|
|
|
|
s_app.paint_needed = true; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/** Home screen */ |
|
|
|
|
static void screen_home(GuiEvent event); |
|
|
|
|
|
|
|
|
|
/** Manual temperature setting screen */ |
|
|
|
|
static void screen_manual(GuiEvent event); |
|
|
|
|
|
|
|
|
|
/** Menu in the manual temperature setting screen */ |
|
|
|
|
static void screen_manual_menu(GuiEvent event); |
|
|
|
|
|
|
|
|
|
/** Draw the common overlay / HUD (with temperatures and heater status) */ |
|
|
|
|
static void draw_common_overlay(); |
|
|
|
|
|
|
|
|
|
/** Input beep (push or knob turn) */ |
|
|
|
|
static void input_sound_effect(); |
|
|
|
|
|
|
|
|
|
/** Switch to a different screen. Handles initial push state handling (so release
|
|
|
|
|
* does not cause a "click" event). |
|
|
|
|
* |
|
|
|
|
* @param pScreen - screen to switch to |
|
|
|
|
* @param init - call the INIT event immediately after |
|
|
|
|
*/ |
|
|
|
|
static void switch_screen(screen_t pScreen, bool init); |
|
|
|
|
|
|
|
|
|
static void calc_set_temp() |
|
|
|
|
{ |
|
|
|
|
int clamped = s_app.set_temp_wheel; |
|
|
|
|
if (clamped < 0) { |
|
|
|
|
clamped = 0; |
|
|
|
|
} |
|
|
|
|
s_app.set_temp = (clamped / 2) * 5; |
|
|
|
|
if (s_app.set_temp > MAX_TEMP) { |
|
|
|
|
s_app.set_temp = MAX_TEMP; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
app_heater_set_target((float) s_app.set_temp); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static char tmp[100]; |
|
|
|
|
|
|
|
|
|
/** Main loop */ |
|
|
|
@ -93,8 +104,6 @@ void app_task_gui(void *argument) |
|
|
|
|
switch_screen(screen_home, true); |
|
|
|
|
|
|
|
|
|
while (1) { |
|
|
|
|
s_app.paint_needed = false; |
|
|
|
|
|
|
|
|
|
uint32_t message = GUI_EVENT_NONE; |
|
|
|
|
int32_t ticks_remain = (int32_t) pdMS_TO_TICKS(10) - (int32_t)(xTaskGetTickCount() - s_app.last_tick_event); |
|
|
|
|
if (ticks_remain < 0) { |
|
|
|
@ -138,6 +147,7 @@ void app_task_gui(void *argument) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (s_app.paint_needed) { |
|
|
|
|
s_app.paint_needed = false; |
|
|
|
|
fb_clear(); |
|
|
|
|
draw_common_overlay(); |
|
|
|
|
s_app.screen(GUI_EVENT_PAINT); |
|
|
|
@ -205,6 +215,21 @@ static void screen_home(GuiEvent event) |
|
|
|
|
|
|
|
|
|
// --------- manual mode screen ---------------
|
|
|
|
|
|
|
|
|
|
/** Calc set temperature from the current knob position */ |
|
|
|
|
static void manual_calc_set_temp() |
|
|
|
|
{ |
|
|
|
|
int clamped = s_app.set_temp_wheel; |
|
|
|
|
if (clamped < 0) { |
|
|
|
|
clamped = 0; |
|
|
|
|
} |
|
|
|
|
s_app.set_temp = (clamped / 2) * 5; |
|
|
|
|
if (s_app.set_temp > MAX_TEMP) { |
|
|
|
|
s_app.set_temp = MAX_TEMP; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
app_heater_set_target((float) s_app.set_temp); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static void screen_manual(GuiEvent event) |
|
|
|
|
{ |
|
|
|
|
if (event == GUI_EVENT_SCREEN_INIT) { |
|
|
|
@ -218,6 +243,13 @@ static void screen_manual(GuiEvent event) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
switch (event) { |
|
|
|
|
case GUI_EVENT_PAINT: |
|
|
|
|
fb_7seg_number(4, 40, 12, 20, 2, 2, |
|
|
|
|
1, |
|
|
|
|
s_app.set_temp, 3, 0 |
|
|
|
|
); |
|
|
|
|
break; |
|
|
|
|
|
|
|
|
|
case GUI_EVENT_KNOB_RELEASE: |
|
|
|
|
input_sound_effect(); |
|
|
|
|
s_app.heater_enabled ^= 1; |
|
|
|
@ -226,24 +258,21 @@ static void screen_manual(GuiEvent event) |
|
|
|
|
break; |
|
|
|
|
|
|
|
|
|
case GUI_EVENT_KNOB_PLUS: |
|
|
|
|
input_sound_effect(); |
|
|
|
|
s_app.set_temp_wheel++; |
|
|
|
|
calc_set_temp(); |
|
|
|
|
request_paint(); |
|
|
|
|
if (s_app.set_temp < MAX_TEMP) { |
|
|
|
|
input_sound_effect(); |
|
|
|
|
s_app.set_temp_wheel++; |
|
|
|
|
manual_calc_set_temp(); |
|
|
|
|
request_paint(); |
|
|
|
|
} |
|
|
|
|
break; |
|
|
|
|
|
|
|
|
|
case GUI_EVENT_KNOB_MINUS: |
|
|
|
|
input_sound_effect(); |
|
|
|
|
s_app.set_temp_wheel--; |
|
|
|
|
calc_set_temp(); |
|
|
|
|
request_paint(); |
|
|
|
|
break; |
|
|
|
|
|
|
|
|
|
case GUI_EVENT_PAINT: |
|
|
|
|
fb_7seg_number(4, 40, 12, 20, 2, 2, |
|
|
|
|
1, |
|
|
|
|
s_app.set_temp, 3, 0 |
|
|
|
|
); |
|
|
|
|
if (s_app.set_temp > 0) { |
|
|
|
|
input_sound_effect(); |
|
|
|
|
s_app.set_temp_wheel--; |
|
|
|
|
manual_calc_set_temp(); |
|
|
|
|
request_paint(); |
|
|
|
|
} |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
@ -278,26 +307,29 @@ static void screen_manual_menu(GuiEvent event) |
|
|
|
|
|
|
|
|
|
// ------------------------
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Generic screen menu handler |
|
|
|
|
* |
|
|
|
|
* @param event - the currently handled event |
|
|
|
|
* @param options - text labels for the menu buttons. Array of C strings, terminated by NULL |
|
|
|
|
* @param cb - callback func, called when an option is selected |
|
|
|
|
*/ |
|
|
|
|
void screen_menu(GuiEvent event, const char **options, menu_callback_t cb) { |
|
|
|
|
if (event == GUI_EVENT_SCREEN_INIT) { |
|
|
|
|
s_app.menu_pos = 0; |
|
|
|
|
s_app.menu_len = 0; |
|
|
|
|
const char **opt = options; |
|
|
|
|
while (*opt) { |
|
|
|
|
s_app.menu_len++; |
|
|
|
|
opt++; |
|
|
|
|
} |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static void screen_menu(GuiEvent event, const char **options, menu_callback_t cb) { |
|
|
|
|
switch (event) { |
|
|
|
|
case GUI_EVENT_SCREEN_INIT: |
|
|
|
|
s_app.menu_pos = 0; |
|
|
|
|
s_app.menu_len = 0; |
|
|
|
|
const char **opt = options; |
|
|
|
|
while (*opt) { |
|
|
|
|
s_app.menu_len++; |
|
|
|
|
opt++; |
|
|
|
|
} |
|
|
|
|
break; |
|
|
|
|
|
|
|
|
|
case GUI_EVENT_PAINT: |
|
|
|
|
for (int i = 0; i < s_app.menu_len; i++) { |
|
|
|
|
fbcolor_t color = s_app.menu_pos != i; |
|
|
|
|
fbpos_t y = 27 + i * 10; |
|
|
|
|
fb_rect(0, y, 64, 10, !color); |
|
|
|
|
fb_text(1, y + 1, options[i], FONT_5X7, color); |
|
|
|
|
// ensure the text doesnt escape the screen
|
|
|
|
|
fb_vline(63, y, 10, !color); |
|
|
|
|
} |
|
|
|
|
break; |
|
|
|
|
|
|
|
|
|
// the button is held! release is what activates the button
|
|
|
|
|
case GUI_EVENT_KNOB_RELEASE: |
|
|
|
|
input_sound_effect(); |
|
|
|
@ -319,16 +351,5 @@ void screen_menu(GuiEvent event, const char **options, menu_callback_t cb) { |
|
|
|
|
request_paint(); |
|
|
|
|
} |
|
|
|
|
break; |
|
|
|
|
|
|
|
|
|
case GUI_EVENT_PAINT: |
|
|
|
|
for (int i = 0; i < s_app.menu_len; i++) { |
|
|
|
|
fbcolor_t color = s_app.menu_pos != i; |
|
|
|
|
fbpos_t y = 27 + i * 10; |
|
|
|
|
fb_rect(0, y, 64, 10, !color); |
|
|
|
|
fb_text(1, y + 1, options[i], FONT_5X7, color); |
|
|
|
|
// ensure the text doesnt escape the screen
|
|
|
|
|
fb_vline(63, y, 10, !color); |
|
|
|
|
} |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|