menu sliding, add knob prescaller
This commit is contained in:
+109
-46
@@ -3,6 +3,7 @@
|
||||
*/
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
#include "app_gui.h"
|
||||
#include "app_heater.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 struct State {
|
||||
float oven_temp;
|
||||
//float soc_temp;
|
||||
|
||||
// manual mode controls
|
||||
int set_temp;
|
||||
int set_temp_wheel;
|
||||
bool heater_enabled;
|
||||
|
||||
bool down_prescaller;
|
||||
bool up_prescaller;
|
||||
|
||||
bool pushed;
|
||||
bool paint_needed;
|
||||
uint32_t last_tick_event;
|
||||
@@ -53,8 +58,17 @@ static struct State {
|
||||
bool initial_pushed;
|
||||
|
||||
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 = {};
|
||||
|
||||
/** Get push time (while held) */
|
||||
@@ -111,11 +125,33 @@ void app_task_gui(void *argument)
|
||||
}
|
||||
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();
|
||||
|
||||
// 10ms tick event
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -161,6 +197,8 @@ void app_task_gui(void *argument)
|
||||
static void switch_screen(screen_t pScreen, bool init) {
|
||||
s_app.initial_pushed = s_app.pushed;
|
||||
s_app.screen = pScreen;
|
||||
// clear the union field
|
||||
memset(&s_app.page, 0, sizeof(s_app.page));
|
||||
request_paint();
|
||||
|
||||
if (init) {
|
||||
@@ -190,6 +228,8 @@ static void input_sound_effect()
|
||||
static const char* main_menu_opts[] = {
|
||||
"Manual mode",
|
||||
"Calibration",
|
||||
"Moderately long text",
|
||||
"Very very long text that slides",
|
||||
NULL
|
||||
};
|
||||
|
||||
@@ -215,23 +255,9 @@ 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)
|
||||
{
|
||||
bool temp_changed = false;
|
||||
if (event == GUI_EVENT_SCREEN_INIT) {
|
||||
return;
|
||||
}
|
||||
@@ -258,23 +284,25 @@ static void screen_manual(GuiEvent event)
|
||||
break;
|
||||
|
||||
case GUI_EVENT_KNOB_PLUS:
|
||||
if (s_app.set_temp < MAX_TEMP) {
|
||||
input_sound_effect();
|
||||
s_app.set_temp_wheel++;
|
||||
manual_calc_set_temp();
|
||||
request_paint();
|
||||
if (s_app.set_temp <= MAX_TEMP - 5) {
|
||||
s_app.set_temp += 5;
|
||||
temp_changed = true;
|
||||
}
|
||||
break;
|
||||
|
||||
case GUI_EVENT_KNOB_MINUS:
|
||||
if (s_app.set_temp > 0) {
|
||||
input_sound_effect();
|
||||
s_app.set_temp_wheel--;
|
||||
manual_calc_set_temp();
|
||||
request_paint();
|
||||
if (s_app.set_temp >= 5) {
|
||||
s_app.set_temp -= 5;
|
||||
temp_changed = true;
|
||||
}
|
||||
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) {
|
||||
bool menu_changed = false;
|
||||
uint32_t tickNow = xTaskGetTickCount();
|
||||
|
||||
struct menu_state *menu = &s_app.page.menu;
|
||||
|
||||
switch (event) {
|
||||
case GUI_EVENT_SCREEN_INIT:
|
||||
s_app.menu_pos = 0;
|
||||
s_app.menu_len = 0;
|
||||
menu->pos = 0;
|
||||
menu->len = 0;
|
||||
menu->change_time = tickNow;
|
||||
menu->text_slide = 0;
|
||||
const char **opt = options;
|
||||
while (*opt) {
|
||||
s_app.menu_len++;
|
||||
menu->len++;
|
||||
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;
|
||||
|
||||
case GUI_EVENT_PAINT:
|
||||
for (int i = 0; i < s_app.menu_len; i++) {
|
||||
fbcolor_t color = s_app.menu_pos != i;
|
||||
for (int i = 0; i < menu->len; i++) {
|
||||
bool current = menu->pos == i;
|
||||
fbcolor_t color = !current;
|
||||
fbpos_t y = 27 + i * 10;
|
||||
fb_rect(0, y, 64, 10, !color);
|
||||
fb_text(1, y + 1, options[i], FONT_5X7, color);
|
||||
fb_rect(0, y, FBW, 10, !color);
|
||||
fb_text(1 - (current ? menu->text_slide : 0), y + 1, options[i], FONT_5X7, color);
|
||||
// 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;
|
||||
|
||||
// the button is held! release is what activates the button
|
||||
case GUI_EVENT_KNOB_RELEASE:
|
||||
input_sound_effect();
|
||||
cb(s_app.menu_pos);
|
||||
cb(menu->pos);
|
||||
break;
|
||||
|
||||
case GUI_EVENT_KNOB_PLUS:
|
||||
if (s_app.menu_pos < s_app.menu_len - 1) {
|
||||
s_app.menu_pos++;
|
||||
input_sound_effect();
|
||||
request_paint();
|
||||
if (menu->pos < menu->len - 1) {
|
||||
menu->pos++;
|
||||
menu_changed = true;
|
||||
}
|
||||
break;
|
||||
|
||||
case GUI_EVENT_KNOB_MINUS:
|
||||
if (s_app.menu_pos > 0) {
|
||||
s_app.menu_pos--;
|
||||
input_sound_effect();
|
||||
request_paint();
|
||||
if (menu->pos > 0) {
|
||||
menu->pos--;
|
||||
menu_changed = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (menu_changed) {
|
||||
menu->change_time = tickNow;
|
||||
menu->text_slide = 0;
|
||||
menu->slide_end_time = 0;
|
||||
input_sound_effect();
|
||||
request_paint();
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -22,7 +22,7 @@ typedef enum GuiEvent {
|
||||
GUI_EVENT_SCREEN_INIT = 1,
|
||||
/// Time tick, used to carry timing to the screen functions.
|
||||
/// This tick has 10ms interval
|
||||
GUI_EVENT_TICK = 2,
|
||||
GUI_EVENT_SCREEN_TICK = 2,
|
||||
/// Knob rotate CW
|
||||
GUI_EVENT_KNOB_PLUS,
|
||||
/// Knob rotate CCW
|
||||
|
||||
Reference in New Issue
Block a user