menu sliding, add knob prescaller

calib-gui
Ondřej Hruška 1 year ago
parent 64c7d3a94a
commit fcc37515c5
  1. 155
      Core/Src/app_gui.c
  2. 2
      Core/Src/app_gui.h

@ -3,6 +3,7 @@
*/ */
#include <stdbool.h> #include <stdbool.h>
#include <string.h>
#include "app_gui.h" #include "app_gui.h"
#include "app_heater.h" #include "app_heater.h"
#include "app_buzzer.h" #include "app_buzzer.h"
@ -35,15 +36,19 @@ typedef void (*menu_callback_t)(int choice);
*/ */
static void screen_menu(GuiEvent event, const char **options, menu_callback_t cb); static void screen_menu(GuiEvent event, const char **options, menu_callback_t cb);
static struct State { static struct State {
float oven_temp; float oven_temp;
//float soc_temp; //float soc_temp;
// manual mode controls // manual mode controls
int set_temp; int set_temp;
int set_temp_wheel;
bool heater_enabled; bool heater_enabled;
bool down_prescaller;
bool up_prescaller;
bool pushed; bool pushed;
bool paint_needed; bool paint_needed;
uint32_t last_tick_event; uint32_t last_tick_event;
@ -53,8 +58,17 @@ static struct State {
bool initial_pushed; bool initial_pushed;
screen_t screen; screen_t screen;
int menu_pos;
int menu_len; union {
struct menu_state {
int pos;
int len;
uint32_t change_time;
uint32_t slide_end_time;
uint16_t text_slide;
uint8_t tick_counter;
} menu;
} page;
} s_app = {}; } s_app = {};
/** Get push time (while held) */ /** Get push time (while held) */
@ -111,11 +125,33 @@ void app_task_gui(void *argument)
} }
osMessageQueueGet(guiEventQueHandle, &message, NULL, ticks_remain); 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(); uint32_t tickNow = xTaskGetTickCount();
// 10ms tick event // 10ms tick event
if (tickNow - s_app.last_tick_event > pdMS_TO_TICKS(10)) { if (tickNow - s_app.last_tick_event > pdMS_TO_TICKS(10)) {
s_app.screen(GUI_EVENT_TICK); s_app.screen(GUI_EVENT_SCREEN_TICK);
s_app.last_tick_event = tickNow; s_app.last_tick_event = tickNow;
} }
@ -161,6 +197,8 @@ void app_task_gui(void *argument)
static void switch_screen(screen_t pScreen, bool init) { static void switch_screen(screen_t pScreen, bool init) {
s_app.initial_pushed = s_app.pushed; s_app.initial_pushed = s_app.pushed;
s_app.screen = pScreen; s_app.screen = pScreen;
// clear the union field
memset(&s_app.page, 0, sizeof(s_app.page));
request_paint(); request_paint();
if (init) { if (init) {
@ -190,6 +228,8 @@ static void input_sound_effect()
static const char* main_menu_opts[] = { static const char* main_menu_opts[] = {
"Manual mode", "Manual mode",
"Calibration", "Calibration",
"Moderately long text",
"Very very long text that slides",
NULL NULL
}; };
@ -215,23 +255,9 @@ static void screen_home(GuiEvent event)
// --------- manual mode screen --------------- // --------- 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) static void screen_manual(GuiEvent event)
{ {
bool temp_changed = false;
if (event == GUI_EVENT_SCREEN_INIT) { if (event == GUI_EVENT_SCREEN_INIT) {
return; return;
} }
@ -258,23 +284,25 @@ static void screen_manual(GuiEvent event)
break; break;
case GUI_EVENT_KNOB_PLUS: case GUI_EVENT_KNOB_PLUS:
if (s_app.set_temp < MAX_TEMP) { if (s_app.set_temp <= MAX_TEMP - 5) {
input_sound_effect(); s_app.set_temp += 5;
s_app.set_temp_wheel++; temp_changed = true;
manual_calc_set_temp();
request_paint();
} }
break; break;
case GUI_EVENT_KNOB_MINUS: case GUI_EVENT_KNOB_MINUS:
if (s_app.set_temp > 0) { if (s_app.set_temp >= 5) {
input_sound_effect(); s_app.set_temp -= 5;
s_app.set_temp_wheel--; temp_changed = true;
manual_calc_set_temp();
request_paint();
} }
break; break;
} }
if (temp_changed) {
input_sound_effect();
app_heater_set_target((float) s_app.set_temp);
request_paint();
}
} }
// --------------------------- // ---------------------------
@ -308,48 +336,83 @@ static void screen_manual_menu(GuiEvent event)
// ------------------------ // ------------------------
static void screen_menu(GuiEvent event, const char **options, menu_callback_t cb) { static void screen_menu(GuiEvent event, const char **options, menu_callback_t cb) {
bool menu_changed = false;
uint32_t tickNow = xTaskGetTickCount();
struct menu_state *menu = &s_app.page.menu;
switch (event) { switch (event) {
case GUI_EVENT_SCREEN_INIT: case GUI_EVENT_SCREEN_INIT:
s_app.menu_pos = 0; menu->pos = 0;
s_app.menu_len = 0; menu->len = 0;
menu->change_time = tickNow;
menu->text_slide = 0;
const char **opt = options; const char **opt = options;
while (*opt) { while (*opt) {
s_app.menu_len++; menu->len++;
opt++; opt++;
} }
menu->pos = menu->len - 1; // FIXME temporary, for debug
break;
case GUI_EVENT_SCREEN_TICK:
if (tickNow - menu->change_time >= pdMS_TO_TICKS(500)) {
uint32_t textlen = strlen(options[menu->pos]) * 6;
if (textlen >= FBW - 2) {
if (textlen - menu->text_slide > FBW - 2) {
menu->text_slide += 1;
if (textlen - menu->text_slide > FBW - 2) {
menu->slide_end_time = tickNow;
}
} else if (tickNow - menu->slide_end_time >= pdMS_TO_TICKS(500)) {
menu->change_time = tickNow;
menu->slide_end_time = 0;
menu->text_slide = 0;
}
request_paint();
}
}
break; break;
case GUI_EVENT_PAINT: case GUI_EVENT_PAINT:
for (int i = 0; i < s_app.menu_len; i++) { for (int i = 0; i < menu->len; i++) {
fbcolor_t color = s_app.menu_pos != i; bool current = menu->pos == i;
fbcolor_t color = !current;
fbpos_t y = 27 + i * 10; fbpos_t y = 27 + i * 10;
fb_rect(0, y, 64, 10, !color); fb_rect(0, y, FBW, 10, !color);
fb_text(1, y + 1, options[i], FONT_5X7, color); fb_text(1 - (current ? menu->text_slide : 0), y + 1, options[i], FONT_5X7, color);
// ensure the text doesnt escape the screen // ensure the text doesnt escape the screen
fb_vline(63, y, 10, !color); fb_vline(FBW - 1, y, 10, !color);
fb_vline(0, y, 10, !color);
} }
break; break;
// the button is held! release is what activates the button // the button is held! release is what activates the button
case GUI_EVENT_KNOB_RELEASE: case GUI_EVENT_KNOB_RELEASE:
input_sound_effect(); input_sound_effect();
cb(s_app.menu_pos); cb(menu->pos);
break; break;
case GUI_EVENT_KNOB_PLUS: case GUI_EVENT_KNOB_PLUS:
if (s_app.menu_pos < s_app.menu_len - 1) { if (menu->pos < menu->len - 1) {
s_app.menu_pos++; menu->pos++;
input_sound_effect(); menu_changed = true;
request_paint();
} }
break; break;
case GUI_EVENT_KNOB_MINUS: case GUI_EVENT_KNOB_MINUS:
if (s_app.menu_pos > 0) { if (menu->pos > 0) {
s_app.menu_pos--; menu->pos--;
input_sound_effect(); menu_changed = true;
request_paint();
} }
break; break;
} }
if (menu_changed) {
menu->change_time = tickNow;
menu->text_slide = 0;
menu->slide_end_time = 0;
input_sound_effect();
request_paint();
}
} }

@ -22,7 +22,7 @@ typedef enum GuiEvent {
GUI_EVENT_SCREEN_INIT = 1, GUI_EVENT_SCREEN_INIT = 1,
/// Time tick, used to carry timing to the screen functions. /// Time tick, used to carry timing to the screen functions.
/// This tick has 10ms interval /// This tick has 10ms interval
GUI_EVENT_TICK = 2, GUI_EVENT_SCREEN_TICK = 2,
/// Knob rotate CW /// Knob rotate CW
GUI_EVENT_KNOB_PLUS, GUI_EVENT_KNOB_PLUS,
/// Knob rotate CCW /// Knob rotate CCW

Loading…
Cancel
Save