menu improvements, add generic menu func
This commit is contained in:
+88
-96
@@ -15,11 +15,11 @@
|
||||
|
||||
#define MAX_TEMP 400
|
||||
|
||||
typedef enum GuiScreen {
|
||||
SCREEN_HOME,
|
||||
SCREEN_MANUAL,
|
||||
SCREEN_MANUAL_MENU,
|
||||
} GuiScreen;
|
||||
typedef void (*menu_callback_t)(int choice);
|
||||
|
||||
void screen_menu(GuiEvent event, const char **options, menu_callback_t cb);
|
||||
|
||||
typedef void (*screen_t)(GuiEvent event);
|
||||
|
||||
static struct State {
|
||||
float oven_temp;
|
||||
@@ -32,7 +32,7 @@ static struct State {
|
||||
// true if the button is still held since init (i.e. the push action should not work as "enter")
|
||||
bool initial_pushed;
|
||||
|
||||
GuiScreen screen;
|
||||
screen_t screen;
|
||||
int menu_pos;
|
||||
int menu_len;
|
||||
} s_app = {};
|
||||
@@ -42,25 +42,17 @@ 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 switch_screen(screen_t pScreen, bool init);
|
||||
|
||||
static void calc_set_temp()
|
||||
{
|
||||
@@ -76,14 +68,17 @@ static void calc_set_temp()
|
||||
app_heater_set_target((float) s_app.set_temp);
|
||||
}
|
||||
|
||||
char tmp[100];
|
||||
static char tmp[100];
|
||||
|
||||
/** Main loop */
|
||||
void app_task_gui(void *argument)
|
||||
{
|
||||
// Wait until inited
|
||||
ulTaskNotifyTake(pdTRUE, portMAX_DELAY);
|
||||
PUTS("GUI task starts\r\n");
|
||||
|
||||
switch_screen(screen_home, true);
|
||||
|
||||
while (1) {
|
||||
s_app.oven_temp = app_temp_read_oven();
|
||||
s_app.soc_temp = app_temp_read_soc();
|
||||
@@ -109,26 +104,27 @@ void app_task_gui(void *argument)
|
||||
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();
|
||||
|
||||
screens[s_app.screen](message);
|
||||
s_app.screen(message);
|
||||
|
||||
fb_blit();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void switch_screen(GuiScreen screen, bool init) {
|
||||
/** Switch to a different screen handler.
|
||||
* If "init" is true, immediately call it with the init event. */
|
||||
static void switch_screen(screen_t pScreen, bool init) {
|
||||
s_app.initial_pushed = s_app.pushed;
|
||||
s_app.screen = screen;
|
||||
s_app.screen = pScreen;
|
||||
|
||||
if (init) {
|
||||
screens[screen](GUI_EVENT_SCREEN_INIT);
|
||||
pScreen(GUI_EVENT_SCREEN_INIT);
|
||||
}
|
||||
}
|
||||
|
||||
/** Draw GUI common to all screens */
|
||||
static void draw_common_overlay()
|
||||
{
|
||||
SPRINTF(tmp, "%3.1f°C →%3d°C", s_app.oven_temp, s_app.set_temp);
|
||||
@@ -142,7 +138,7 @@ static void draw_common_overlay()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/** Play input sound effect if this is an input event */
|
||||
static void input_sound_effect(GuiEvent event)
|
||||
{
|
||||
switch (event) {
|
||||
@@ -151,8 +147,24 @@ static void input_sound_effect(GuiEvent event)
|
||||
case GUI_EVENT_KNOB_RELEASE:
|
||||
app_buzzer_beep();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
default:
|
||||
// ------------- home screen ----------------
|
||||
|
||||
static const char* main_menu_opts[] = {
|
||||
"Manual mode",
|
||||
"Calibration",
|
||||
NULL
|
||||
};
|
||||
|
||||
static void main_menu_cb(int opt) {
|
||||
switch (opt) {
|
||||
case 0:
|
||||
switch_screen(screen_manual, true);
|
||||
break;
|
||||
case 1:
|
||||
// TODO
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -160,49 +172,14 @@ static void input_sound_effect(GuiEvent event)
|
||||
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;
|
||||
}
|
||||
screen_menu(event, main_menu_opts, main_menu_cb);
|
||||
}
|
||||
|
||||
// --------- manual mode screen ---------------
|
||||
|
||||
static void screen_manual(GuiEvent event)
|
||||
{
|
||||
if (event == GUI_EVENT_SCREEN_INIT) {
|
||||
@@ -210,9 +187,9 @@ static void screen_manual(GuiEvent event)
|
||||
return;
|
||||
}
|
||||
|
||||
// menu activated by long push
|
||||
// menu is activated by long push
|
||||
if (push_time() >= pdMS_TO_TICKS(500)) {
|
||||
switch_screen(SCREEN_MANUAL_MENU, true);
|
||||
switch_screen(screen_manual_menu, true);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -237,54 +214,72 @@ static void screen_manual(GuiEvent event)
|
||||
s_app.set_temp_wheel--;
|
||||
calc_set_temp();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
default:
|
||||
// ---------------------------
|
||||
|
||||
static const char* manual_menu_opts[] = {
|
||||
"Close menu",
|
||||
"Exit manual",
|
||||
NULL
|
||||
};
|
||||
|
||||
static void manual_menu_cb(int opt) {
|
||||
switch (opt) {
|
||||
case 0:
|
||||
// Close menu
|
||||
switch_screen(screen_manual, false);
|
||||
break;
|
||||
|
||||
case 1:
|
||||
// Close menu
|
||||
switch_screen(screen_home, true);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void screen_manual_menu(GuiEvent event)
|
||||
{
|
||||
screen_menu(event, manual_menu_opts, manual_menu_cb);
|
||||
}
|
||||
|
||||
// ------------------------
|
||||
|
||||
/**
|
||||
* 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 = 2;
|
||||
s_app.menu_len = 0;
|
||||
const char **opt = options;
|
||||
while (*opt) {
|
||||
s_app.menu_len++;
|
||||
opt++;
|
||||
}
|
||||
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);
|
||||
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);
|
||||
}
|
||||
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;
|
||||
}
|
||||
cb(s_app.menu_pos);
|
||||
break;
|
||||
|
||||
case GUI_EVENT_KNOB_PLUS:
|
||||
@@ -298,8 +293,5 @@ static void screen_manual_menu(GuiEvent event)
|
||||
s_app.menu_pos--;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user