|
|
@ -12,6 +12,7 @@ |
|
|
|
#include "queue.h" |
|
|
|
#include "queue.h" |
|
|
|
#include "ufb/framebuffer.h" |
|
|
|
#include "ufb/framebuffer.h" |
|
|
|
#include "ufb/fb_text.h" |
|
|
|
#include "ufb/fb_text.h" |
|
|
|
|
|
|
|
#include "ufb/fb_7seg.h" |
|
|
|
|
|
|
|
|
|
|
|
#define MAX_TEMP 400 |
|
|
|
#define MAX_TEMP 400 |
|
|
|
|
|
|
|
|
|
|
@ -23,12 +24,18 @@ typedef void (*screen_t)(GuiEvent event); |
|
|
|
|
|
|
|
|
|
|
|
static struct State { |
|
|
|
static struct State { |
|
|
|
float oven_temp; |
|
|
|
float oven_temp; |
|
|
|
float soc_temp; |
|
|
|
//float soc_temp;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// manual mode controls
|
|
|
|
int set_temp; |
|
|
|
int set_temp; |
|
|
|
int set_temp_wheel; |
|
|
|
int set_temp_wheel; |
|
|
|
bool heater_enabled; |
|
|
|
bool heater_enabled; |
|
|
|
|
|
|
|
|
|
|
|
bool pushed; |
|
|
|
bool pushed; |
|
|
|
|
|
|
|
bool paint_needed; |
|
|
|
|
|
|
|
uint32_t last_tick_event; |
|
|
|
uint32_t push_tick; |
|
|
|
uint32_t push_tick; |
|
|
|
|
|
|
|
uint32_t last_read_temp_tick; |
|
|
|
// true if the button is still held since init (i.e. the push action should not work as "enter")
|
|
|
|
// true if the button is still held since init (i.e. the push action should not work as "enter")
|
|
|
|
bool initial_pushed; |
|
|
|
bool initial_pushed; |
|
|
|
|
|
|
|
|
|
|
@ -42,6 +49,10 @@ static uint32_t push_time() { |
|
|
|
return s_app.pushed ? (xTaskGetTickCount() - s_app.push_tick) : 0; |
|
|
|
return s_app.pushed ? (xTaskGetTickCount() - s_app.push_tick) : 0; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static void request_paint() { |
|
|
|
|
|
|
|
s_app.paint_needed = true; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
static void screen_home(GuiEvent event); |
|
|
|
static void screen_home(GuiEvent event); |
|
|
|
|
|
|
|
|
|
|
|
static void screen_manual(GuiEvent event); |
|
|
|
static void screen_manual(GuiEvent event); |
|
|
@ -50,7 +61,7 @@ static void screen_manual_menu(GuiEvent event); |
|
|
|
|
|
|
|
|
|
|
|
static void draw_common_overlay(); |
|
|
|
static void draw_common_overlay(); |
|
|
|
|
|
|
|
|
|
|
|
static void input_sound_effect(GuiEvent event); |
|
|
|
static void input_sound_effect(); |
|
|
|
|
|
|
|
|
|
|
|
static void switch_screen(screen_t pScreen, bool init); |
|
|
|
static void switch_screen(screen_t pScreen, bool init); |
|
|
|
|
|
|
|
|
|
|
@ -77,37 +88,59 @@ void app_task_gui(void *argument) |
|
|
|
ulTaskNotifyTake(pdTRUE, portMAX_DELAY); |
|
|
|
ulTaskNotifyTake(pdTRUE, portMAX_DELAY); |
|
|
|
PUTS("GUI task starts\r\n"); |
|
|
|
PUTS("GUI task starts\r\n"); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
s_app.last_tick_event = xTaskGetTickCount(); |
|
|
|
|
|
|
|
|
|
|
|
switch_screen(screen_home, true); |
|
|
|
switch_screen(screen_home, true); |
|
|
|
|
|
|
|
|
|
|
|
while (1) { |
|
|
|
while (1) { |
|
|
|
s_app.oven_temp = app_temp_read_oven(); |
|
|
|
s_app.paint_needed = false; |
|
|
|
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(50)); |
|
|
|
int32_t ticks_remain = (int32_t) pdMS_TO_TICKS(10) - (int32_t)(xTaskGetTickCount() - s_app.last_tick_event); |
|
|
|
|
|
|
|
if (ticks_remain < 0) { |
|
|
|
|
|
|
|
ticks_remain = 0; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
osMessageQueueGet(guiEventQueHandle, &message, NULL, ticks_remain); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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.last_tick_event = tickNow; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (tickNow - s_app.last_read_temp_tick > pdMS_TO_TICKS(250)) { |
|
|
|
|
|
|
|
s_app.oven_temp = app_temp_read_oven(); |
|
|
|
|
|
|
|
//s_app.soc_temp = app_temp_read_soc();
|
|
|
|
|
|
|
|
request_paint(); |
|
|
|
|
|
|
|
s_app.last_read_temp_tick = tickNow; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
switch (message) { |
|
|
|
switch (message) { |
|
|
|
case GUI_EVENT_KNOB_PRESS: |
|
|
|
case GUI_EVENT_KNOB_PRESS: |
|
|
|
s_app.pushed = true; |
|
|
|
s_app.pushed = true; |
|
|
|
s_app.push_tick = xTaskGetTickCount(); |
|
|
|
s_app.push_tick = tickNow; |
|
|
|
break; |
|
|
|
break; |
|
|
|
|
|
|
|
|
|
|
|
case GUI_EVENT_KNOB_RELEASE: |
|
|
|
case GUI_EVENT_KNOB_RELEASE: |
|
|
|
s_app.pushed = false; |
|
|
|
s_app.pushed = false; |
|
|
|
break; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
default: |
|
|
|
if (s_app.initial_pushed) { |
|
|
|
|
|
|
|
s_app.initial_pushed = false; |
|
|
|
|
|
|
|
message = GUI_EVENT_NONE; |
|
|
|
|
|
|
|
} |
|
|
|
break; |
|
|
|
break; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if (s_app.initial_pushed && message == GUI_EVENT_KNOB_RELEASE) { |
|
|
|
if (message != GUI_EVENT_NONE) { |
|
|
|
s_app.initial_pushed = false; |
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
fb_clear(); |
|
|
|
|
|
|
|
draw_common_overlay(); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
s_app.screen(message); |
|
|
|
s_app.screen(message); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (s_app.paint_needed) { |
|
|
|
|
|
|
|
fb_clear(); |
|
|
|
|
|
|
|
draw_common_overlay(); |
|
|
|
|
|
|
|
s_app.screen(GUI_EVENT_PAINT); |
|
|
|
fb_blit(); |
|
|
|
fb_blit(); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
@ -118,6 +151,7 @@ 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; |
|
|
|
|
|
|
|
request_paint(); |
|
|
|
|
|
|
|
|
|
|
|
if (init) { |
|
|
|
if (init) { |
|
|
|
pScreen(GUI_EVENT_SCREEN_INIT); |
|
|
|
pScreen(GUI_EVENT_SCREEN_INIT); |
|
|
@ -129,25 +163,16 @@ static void draw_common_overlay() |
|
|
|
{ |
|
|
|
{ |
|
|
|
SPRINTF(tmp, "%3.1f°C →%3d°C", s_app.oven_temp, s_app.set_temp); |
|
|
|
SPRINTF(tmp, "%3.1f°C →%3d°C", s_app.oven_temp, s_app.set_temp); |
|
|
|
fb_text(3, 3, tmp, FONT_3X5, 1); |
|
|
|
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) { |
|
|
|
if (s_app.heater_enabled) { |
|
|
|
fb_frame(0, 0, FBW, FBH, 2, 1); |
|
|
|
fb_frame(0, 0, FBW, 11, 2, 1); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/** Play input sound effect if this is an input event */ |
|
|
|
/** Play input sound effect if this is an input event */ |
|
|
|
static void input_sound_effect(GuiEvent event) |
|
|
|
static void input_sound_effect() |
|
|
|
{ |
|
|
|
{ |
|
|
|
switch (event) { |
|
|
|
app_buzzer_beep(); |
|
|
|
case GUI_EVENT_KNOB_PLUS: |
|
|
|
|
|
|
|
case GUI_EVENT_KNOB_MINUS: |
|
|
|
|
|
|
|
case GUI_EVENT_KNOB_RELEASE: |
|
|
|
|
|
|
|
app_buzzer_beep(); |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// ------------- home screen ----------------
|
|
|
|
// ------------- home screen ----------------
|
|
|
@ -183,7 +208,6 @@ static void screen_home(GuiEvent event) |
|
|
|
static void screen_manual(GuiEvent event) |
|
|
|
static void screen_manual(GuiEvent event) |
|
|
|
{ |
|
|
|
{ |
|
|
|
if (event == GUI_EVENT_SCREEN_INIT) { |
|
|
|
if (event == GUI_EVENT_SCREEN_INIT) { |
|
|
|
s_app.set_temp_wheel = 0; |
|
|
|
|
|
|
|
return; |
|
|
|
return; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
@ -193,26 +217,33 @@ static void screen_manual(GuiEvent event) |
|
|
|
return; |
|
|
|
return; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
input_sound_effect(event); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
switch (event) { |
|
|
|
switch (event) { |
|
|
|
case GUI_EVENT_KNOB_RELEASE: |
|
|
|
case GUI_EVENT_KNOB_RELEASE: |
|
|
|
if (s_app.initial_pushed) { |
|
|
|
input_sound_effect(); |
|
|
|
s_app.initial_pushed = false; |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
s_app.heater_enabled ^= 1; |
|
|
|
s_app.heater_enabled ^= 1; |
|
|
|
app_heater_enable(s_app.heater_enabled); |
|
|
|
app_heater_enable(s_app.heater_enabled); |
|
|
|
|
|
|
|
request_paint(); |
|
|
|
break; |
|
|
|
break; |
|
|
|
|
|
|
|
|
|
|
|
case GUI_EVENT_KNOB_PLUS: |
|
|
|
case GUI_EVENT_KNOB_PLUS: |
|
|
|
|
|
|
|
input_sound_effect(); |
|
|
|
s_app.set_temp_wheel++; |
|
|
|
s_app.set_temp_wheel++; |
|
|
|
calc_set_temp(); |
|
|
|
calc_set_temp(); |
|
|
|
|
|
|
|
request_paint(); |
|
|
|
break; |
|
|
|
break; |
|
|
|
|
|
|
|
|
|
|
|
case GUI_EVENT_KNOB_MINUS: |
|
|
|
case GUI_EVENT_KNOB_MINUS: |
|
|
|
|
|
|
|
input_sound_effect(); |
|
|
|
s_app.set_temp_wheel--; |
|
|
|
s_app.set_temp_wheel--; |
|
|
|
calc_set_temp(); |
|
|
|
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 |
|
|
|
|
|
|
|
); |
|
|
|
break; |
|
|
|
break; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
@ -233,7 +264,8 @@ static void manual_menu_cb(int opt) { |
|
|
|
break; |
|
|
|
break; |
|
|
|
|
|
|
|
|
|
|
|
case 1: |
|
|
|
case 1: |
|
|
|
// Close menu
|
|
|
|
s_app.heater_enabled = false; |
|
|
|
|
|
|
|
app_heater_enable(false); |
|
|
|
switch_screen(screen_home, true); |
|
|
|
switch_screen(screen_home, true); |
|
|
|
break; |
|
|
|
break; |
|
|
|
} |
|
|
|
} |
|
|
@ -265,32 +297,37 @@ void screen_menu(GuiEvent event, const char **options, menu_callback_t cb) { |
|
|
|
return; |
|
|
|
return; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
input_sound_effect(event); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
switch (event) { |
|
|
|
switch (event) { |
|
|
|
// 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(); |
|
|
|
cb(s_app.menu_pos); |
|
|
|
cb(s_app.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 (s_app.menu_pos < s_app.menu_len - 1) { |
|
|
|
s_app.menu_pos++; |
|
|
|
s_app.menu_pos++; |
|
|
|
|
|
|
|
input_sound_effect(); |
|
|
|
|
|
|
|
request_paint(); |
|
|
|
} |
|
|
|
} |
|
|
|
break; |
|
|
|
break; |
|
|
|
|
|
|
|
|
|
|
|
case GUI_EVENT_KNOB_MINUS: |
|
|
|
case GUI_EVENT_KNOB_MINUS: |
|
|
|
if (s_app.menu_pos > 0) { |
|
|
|
if (s_app.menu_pos > 0) { |
|
|
|
s_app.menu_pos--; |
|
|
|
s_app.menu_pos--; |
|
|
|
|
|
|
|
input_sound_effect(); |
|
|
|
|
|
|
|
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; |
|
|
|
break; |
|
|
|
} |
|
|
|
} |
|
|
|