base of menu system
This commit is contained in:
+245
-33
@@ -15,15 +15,55 @@
|
|||||||
|
|
||||||
#define MAX_TEMP 400
|
#define MAX_TEMP 400
|
||||||
|
|
||||||
|
typedef enum GuiScreen {
|
||||||
|
SCREEN_HOME,
|
||||||
|
SCREEN_MANUAL,
|
||||||
|
SCREEN_MANUAL_MENU,
|
||||||
|
} GuiScreen;
|
||||||
|
|
||||||
static struct State {
|
static struct State {
|
||||||
float oven_temp;
|
float oven_temp;
|
||||||
float soc_temp;
|
float soc_temp;
|
||||||
int set_temp;
|
int set_temp;
|
||||||
int set_temp_wheel;
|
int set_temp_wheel;
|
||||||
bool heater_enabled;
|
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 = {};
|
} 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;
|
int clamped = s_app.set_temp_wheel;
|
||||||
if (clamped < 0) {
|
if (clamped < 0) {
|
||||||
clamped = 0;
|
clamped = 0;
|
||||||
@@ -36,58 +76,230 @@ static void calc_set_temp() {
|
|||||||
app_heater_set_target((float) s_app.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
|
// Wait until inited
|
||||||
ulTaskNotifyTake(pdTRUE, portMAX_DELAY);
|
ulTaskNotifyTake(pdTRUE, portMAX_DELAY);
|
||||||
PUTS("GUI task starts\r\n");
|
PUTS("GUI task starts\r\n");
|
||||||
|
|
||||||
char tmp[100];
|
|
||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
s_app.oven_temp = app_temp_read_oven();
|
s_app.oven_temp = app_temp_read_oven();
|
||||||
s_app.soc_temp = app_temp_read_soc();
|
s_app.soc_temp = app_temp_read_soc();
|
||||||
|
|
||||||
uint32_t message = GUI_EVENT_NONE;
|
uint32_t message = GUI_EVENT_NONE;
|
||||||
osMessageQueueGet(guiEventQueHandle, &message, NULL, pdMS_TO_TICKS(1000));
|
osMessageQueueGet(guiEventQueHandle, &message, NULL, pdMS_TO_TICKS(50));
|
||||||
|
|
||||||
switch (message) {
|
switch (message) {
|
||||||
case GUI_NOTIFY_KNOB_PLUS:
|
case GUI_EVENT_KNOB_PRESS:
|
||||||
s_app.set_temp_wheel++;
|
s_app.pushed = true;
|
||||||
calc_set_temp();
|
s_app.push_tick = xTaskGetTickCount();
|
||||||
break;
|
break;
|
||||||
case GUI_NOTIFY_KNOB_MINUS:
|
|
||||||
s_app.set_temp_wheel--;
|
case GUI_EVENT_KNOB_RELEASE:
|
||||||
calc_set_temp();
|
s_app.pushed = false;
|
||||||
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();
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
break;
|
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);
|
screens[s_app.screen](message);
|
||||||
fb_text(3, 3, tmp, FONT_5X7, 1);
|
|
||||||
|
|
||||||
SPRINTF(tmp, "Cil=%d°C", s_app.set_temp);
|
fb_blit();
|
||||||
fb_text(3, 11, tmp, FONT_5X7, 1);
|
|
||||||
|
|
||||||
SPRINTF(tmp, "Stav=%s", s_app.heater_enabled ? "ZAP" : "VYP");
|
|
||||||
fb_text(3, 19, tmp, FONT_5X7, 1);
|
|
||||||
|
|
||||||
SPRINTF(tmp, "Tsoc=%.1f°C", s_app.soc_temp);
|
|
||||||
fb_text(3, 27, tmp, FONT_5X7, 1);
|
|
||||||
|
|
||||||
if (s_app.heater_enabled) {
|
|
||||||
fb_frame(0, 0, FBW, FBH, 2, 1);
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fb_blit();
|
static void switch_screen(GuiScreen screen, bool init) {
|
||||||
|
s_app.initial_pushed = s_app.pushed;
|
||||||
|
s_app.screen = screen;
|
||||||
|
|
||||||
|
if (init) {
|
||||||
|
screens[screen](GUI_EVENT_SCREEN_INIT);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+16
-7
@@ -13,13 +13,22 @@ extern osMessageQueueId_t guiEventQueHandle;
|
|||||||
void app_task_gui(void *argument);
|
void app_task_gui(void *argument);
|
||||||
|
|
||||||
// sent through the notify queue
|
// sent through the notify queue
|
||||||
enum GuiNotify {
|
typedef enum GuiEvent {
|
||||||
|
/// No event, zero; This is a default value.
|
||||||
GUI_EVENT_NONE = 0,
|
GUI_EVENT_NONE = 0,
|
||||||
GUI_NOTIFY_KNOB_PLUS,
|
/// Used as the argument when initing a screen
|
||||||
GUI_NOTIFY_KNOB_MINUS,
|
GUI_EVENT_SCREEN_INIT = 1,
|
||||||
GUI_NOTIFY_KNOB_PRESS,
|
/// Knob rotate CW
|
||||||
GUI_NOTIFY_KNOB_RELEASE,
|
GUI_EVENT_KNOB_PLUS,
|
||||||
GUI_NOTIFY_TEMP_CHANGE,
|
/// Knob rotate CCW
|
||||||
};
|
GUI_EVENT_KNOB_MINUS,
|
||||||
|
/// Knob pressed
|
||||||
|
GUI_EVENT_KNOB_PRESS,
|
||||||
|
/// Knob released
|
||||||
|
GUI_EVENT_KNOB_RELEASE,
|
||||||
|
/// Temperature readings changed.
|
||||||
|
/// Not really an input event, but it should trigger a redraw
|
||||||
|
GUI_EVENT_TEMP_CHANGE,
|
||||||
|
} GuiEvent;
|
||||||
|
|
||||||
#endif //BLUEPILLTROUBA_APP_GUI_H
|
#endif //BLUEPILLTROUBA_APP_GUI_H
|
||||||
|
|||||||
@@ -122,7 +122,7 @@ void app_task_heater(void *argument)
|
|||||||
state.oven_temp = app_temp_read_oven();
|
state.oven_temp = app_temp_read_oven();
|
||||||
state.soc_temp = app_temp_read_soc();
|
state.soc_temp = app_temp_read_soc();
|
||||||
|
|
||||||
enum GuiNotify ev = GUI_NOTIFY_TEMP_CHANGE;
|
enum GuiEvent ev = GUI_EVENT_TEMP_CHANGE;
|
||||||
xQueueSend(guiEventQueHandle, &ev, pdMS_TO_TICKS(100));
|
xQueueSend(guiEventQueHandle, &ev, pdMS_TO_TICKS(100));
|
||||||
|
|
||||||
heaterEnterCritical();
|
heaterEnterCritical();
|
||||||
|
|||||||
+3
-3
@@ -48,13 +48,13 @@ void app_knob_turn_isr()
|
|||||||
|
|
||||||
while (wheel_change > 0) {
|
while (wheel_change > 0) {
|
||||||
wheel_change--;
|
wheel_change--;
|
||||||
enum GuiNotify ev = GUI_NOTIFY_KNOB_PLUS;
|
enum GuiEvent ev = GUI_EVENT_KNOB_PLUS;
|
||||||
xQueueSendFromISR(guiEventQueHandle, &ev, &yield);
|
xQueueSendFromISR(guiEventQueHandle, &ev, &yield);
|
||||||
}
|
}
|
||||||
|
|
||||||
while (wheel_change < 0) {
|
while (wheel_change < 0) {
|
||||||
wheel_change++;
|
wheel_change++;
|
||||||
enum GuiNotify ev = GUI_NOTIFY_KNOB_MINUS;
|
enum GuiEvent ev = GUI_EVENT_KNOB_MINUS;
|
||||||
xQueueSendFromISR(guiEventQueHandle, &ev, &yield);
|
xQueueSendFromISR(guiEventQueHandle, &ev, &yield);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -87,6 +87,6 @@ void app_knob_push_isr(bool push)
|
|||||||
|
|
||||||
void app_push_debounce(void *argument) {
|
void app_push_debounce(void *argument) {
|
||||||
bool push = (bool) argument;
|
bool push = (bool) argument;
|
||||||
enum GuiNotify ev = push ? GUI_NOTIFY_KNOB_PRESS : GUI_NOTIFY_KNOB_RELEASE;
|
enum GuiEvent ev = push ? GUI_EVENT_KNOB_PRESS : GUI_EVENT_KNOB_RELEASE;
|
||||||
xQueueSend(guiEventQueHandle, &ev, pdMS_TO_TICKS(100));
|
xQueueSend(guiEventQueHandle, &ev, pdMS_TO_TICKS(100));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -99,4 +99,5 @@ static const font3x_bitmap_t PROGMEM font35_ascii[] = {
|
|||||||
static const struct utf_glyph3x PROGMEM font35_extra[] = {
|
static const struct utf_glyph3x PROGMEM font35_extra[] = {
|
||||||
{.utf={.symbol="�"}, {{0x1f, 0x1f, 0x1f}}},
|
{.utf={.symbol="�"}, {{0x1f, 0x1f, 0x1f}}},
|
||||||
{.utf={.symbol="°"}, {{0x07, 0x05, 0x07}}},
|
{.utf={.symbol="°"}, {{0x07, 0x05, 0x07}}},
|
||||||
|
{.utf={.symbol="→"}, {{0x15, 0x0e, 0x04}}},
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -588,11 +588,18 @@ const char *font_extras[] = {
|
|||||||
"xxx",
|
"xxx",
|
||||||
" ",
|
" ",
|
||||||
" ",
|
" ",
|
||||||
|
// Extra 2 "→"
|
||||||
|
"x ",
|
||||||
|
" x ",
|
||||||
|
"xxx",
|
||||||
|
" x ",
|
||||||
|
"x ",
|
||||||
};
|
};
|
||||||
|
|
||||||
const char *font_extras_utf[] = {
|
const char *font_extras_utf[] = {
|
||||||
"�",
|
"�",
|
||||||
"°",
|
"°",
|
||||||
|
"→",
|
||||||
};
|
};
|
||||||
|
|
||||||
#include "fontedit_render.inc.c"
|
#include "fontedit_render.inc.c"
|
||||||
|
|||||||
+3
-3
@@ -99,10 +99,10 @@ void main() {
|
|||||||
fb_text(15, 15, "MEOW", FONT_DOUBLEH, 1);
|
fb_text(15, 15, "MEOW", FONT_DOUBLEH, 1);
|
||||||
fb_text(40, 15, "MEOW", FONT_DOUBLEW, 1);
|
fb_text(40, 15, "MEOW", FONT_DOUBLEW, 1);
|
||||||
fb_text(40, 23, "MEOW", FONT_BOLD, 1);
|
fb_text(40, 23, "MEOW", FONT_BOLD, 1);
|
||||||
|
|
||||||
fb_text(5, 5, "Tiny 3x5", FONT_3X5, 1);
|
fb_text(5, 5, "Tiny 3x5→", FONT_3X5, 1);
|
||||||
fb_text(40, 5, "Tiny 4x5 MEOW", FONT_4X5, 1);
|
fb_text(40, 5, "Tiny 4x5 MEOW", FONT_4X5, 1);
|
||||||
|
|
||||||
fb_frame(12,12,80,20,1,1);
|
fb_frame(12,12,80,20,1,1);
|
||||||
|
|
||||||
// fb_text(36, 5, "-123456789.0 CPM°", FONT_TINY, 1);
|
// fb_text(36, 5, "-123456789.0 CPM°", FONT_TINY, 1);
|
||||||
|
|||||||
Reference in New Issue
Block a user