diff --git a/stm-firmware/include/reflow-controller/lcd-menu.h b/stm-firmware/include/reflow-controller/lcd-menu.h index 9c62911..1f271e2 100644 --- a/stm-firmware/include/reflow-controller/lcd-menu.h +++ b/stm-firmware/include/reflow-controller/lcd-menu.h @@ -21,4 +21,12 @@ #ifndef __LCD_MENU_H__ #define __LCD_MENU_H__ +/** + * @brief Handle the reflow controller's LCD Menu + * @return 0 if a delay is requested, 1 if no delay is requested + */ +int reflow_menu_handle(void); + +void reflow_menu_init(void); + #endif /* __LCD_MENU_H__ */ diff --git a/stm-firmware/include/reflow-controller/ui/menu.h b/stm-firmware/include/reflow-controller/ui/menu.h index 748091d..74885e7 100644 --- a/stm-firmware/include/reflow-controller/ui/menu.h +++ b/stm-firmware/include/reflow-controller/ui/menu.h @@ -48,7 +48,7 @@ struct lcd_menu { struct menu_list { void (*update_display)(uint8_t row, const char *data); - const char **entry_names; + const char * const * entry_names; uint32_t entry_count; uint32_t currently_selected; const menu_func_t *submenu_list; @@ -58,9 +58,13 @@ void menu_handle(struct lcd_menu *menu, int16_t rotary_encoder_delta, enum butto void menu_init(struct lcd_menu *menu, menu_func_t root_node, void (*display_update)(uint8_t row, const char *data)); +void menu_ack_rotary_delta(struct lcd_menu *menu); + +void menu_display_clear(struct lcd_menu *menu); + void menu_entry_dropback(struct lcd_menu *menu, menu_func_t parent_func); -void menu_entry_enter(struct lcd_menu *menu, menu_func_t parent_func, bool handle_immediately); +void menu_entry_enter(struct lcd_menu *menu, menu_func_t entry, bool handle_immediately); void menu_override_lcd_output(struct lcd_menu *menu, uint8_t row_num, const char *text); diff --git a/stm-firmware/lcd-menu.c b/stm-firmware/lcd-menu.c index b51bf93..9e0185b 100644 --- a/stm-firmware/lcd-menu.c +++ b/stm-firmware/lcd-menu.c @@ -21,8 +21,19 @@ #include #include #include +#include +#include +#include +#include +#include +#include +#include +#include +#include static char __attribute__((section(".ccmram"))) display_buffer[4][21] = {0}; +static struct lcd_menu reflow_menu; +static struct lcd_menu *reflow_menu_ptr = &reflow_menu; static void update_display_buffer(uint8_t row, const char *data) { @@ -40,3 +51,132 @@ static void update_display_buffer(uint8_t row, const char *data) display_buffer[row][i] = 0; } +static void reflow_menu_monitor(struct lcd_menu *menu, enum menu_entry_func_entry entry_type, void *parent) +{ + static void *my_parent; + static uint64_t my_timestamp = 0; + char line[17]; + float tmp; + int res; + const char *prefix; + + if (entry_type == MENU_ENTRY_FIRST_ENTER) { + my_parent = parent; + menu_display_clear(menu); + } + + if (systick_ticks_have_passed(my_timestamp, 250)) { + adc_pt1000_get_current_resistance(&tmp); + snprintf(line, sizeof(line), "Res: %.1f", tmp); + menu->update_display(0, line); + + res = temp_converter_convert_resistance_to_temp(tmp, &tmp); + switch (res) { + case -1: + prefix = "<"; + break; + case 1: + prefix = ">"; + break; + default: + prefix = ""; + break; + } + + snprintf(line, sizeof(line), "Temp: %s%.1f " LCD_DEGREE_SYMBOL_STRING "C", prefix, tmp); + menu->update_display(1, line); + + tmp = safety_adc_get_temp(); + snprintf(line, sizeof(line), "Tj: %.1f " LCD_DEGREE_SYMBOL_STRING "C", tmp); + menu->update_display(2, line); + + tmp = safety_adc_get_vref(); + snprintf(line, sizeof(line), "Vref: %.1f mV", tmp); + menu->update_display(3, line); + } + + if (menu->inputs.push_button == BUTTON_SHORT_RELEASED || menu->inputs.push_button == BUTTON_LONG) { + menu_entry_dropback(menu, my_parent); + } +} + +static void reflow_menu_root_entry(struct lcd_menu *menu, enum menu_entry_func_entry entry_type, void *parent) +{ + (void)parent; + static struct menu_list list; + static bool button_valid; + static const char * const root_entries[] = { + "Device Info", + "Safety Monitor", + "Foo", + "bar", + "foobar", + NULL + }; + + if (entry_type != MENU_ENTRY_CONTINUE) { + menu_display_clear(menu); + button_valid = false; + list.entry_names = root_entries; + list.submenu_list = NULL; + list.update_display = menu->update_display; + list.currently_selected = 0; + menu_list_compute_count(&list); + update_display_buffer(0, "Main Menu"); + } + + if (menu->inputs.push_button == BUTTON_IDLE) { + button_valid = true; + } else if (button_valid && menu->inputs.push_button == BUTTON_SHORT_RELEASED) { + switch (list.currently_selected) { + case 1: + menu_entry_enter(menu, reflow_menu_monitor, false); + break; + default: + break; + } + } + + + + if (menu->inputs.rotary_encoder_delta >= 4) { + menu_list_scroll_down(&list); + menu_ack_rotary_delta(menu); + } else if (menu->inputs.rotary_encoder_delta <= -4) { + menu_list_scroll_up(&list); + menu_ack_rotary_delta(menu); + } + + menu_list_display(&list, 1, 3); +} + + +int reflow_menu_handle() +{ + int32_t rot_delta; + enum button_state button; + static enum lcd_fsm_ret lcd_ret = LCD_FSM_NOP; + static uint64_t lcd_timestamp = 0ULL; + + rot_delta = rotary_encoder_get_change_val(); + button = button_read_event(); + + menu_handle(reflow_menu_ptr, (int16_t)rot_delta, button); + + if (lcd_ret != LCD_FSM_WAIT_CALL || systick_ticks_have_passed(lcd_timestamp, 2)) + lcd_ret = lcd_fsm_write_buffer(display_buffer); + + if (lcd_ret == LCD_FSM_CALL_AGAIN) + return 1; + else + return 0; +} + +void reflow_menu_init() +{ + rotary_encoder_setup(); + button_init(); + lcd_init(); + + menu_init(reflow_menu_ptr, reflow_menu_root_entry, update_display_buffer); +} diff --git a/stm-firmware/main.c b/stm-firmware/main.c index 312551e..e27ab44 100644 --- a/stm-firmware/main.c +++ b/stm-firmware/main.c @@ -34,21 +34,19 @@ #include #include #include -#include #include #include "fatfs/shimatta_sdio_driver/shimatta_sdio.h" #include -#include #include #include #include #include #include #include -#include #include #include #include +#include static void setup_nvic_priorities() { @@ -67,7 +65,6 @@ static volatile int pt1000_value_status; static uint32_t rot; static float target_temperature; static struct pid_controller pid; -static volatile enum button_state button; FATFS fs; FATFS *fs_ptr = &fs; @@ -175,9 +172,7 @@ static inline void setup_system() digio_setup_default_all(); led_setup(); loudspeaker_setup(); - rotary_encoder_setup(); - button_init(); - lcd_init(); + reflow_menu_init(); safety_adc_init(); uart_gpio_config(); @@ -204,15 +199,13 @@ int main() { bool sd_card_mounted = false; shellmatta_handle_t shell_handle; - uint64_t pid_timestamp = 0ULL; bool pid_controller_active = false; int32_t pid_controller_output; uint64_t display_timestamp = 0ULL; - char disp[4][21] = {0}; - enum lcd_fsm_ret lcd_ret = LCD_FSM_NOP; int temp_status; float current_temp; + int menu_wait_request; target_temperature = 25.0f; @@ -224,13 +217,10 @@ int main() pid_init(&pid, 0.1, 0.1, 4.0, 0.0, 100.0, 40.0, 0.25); pid_zero(&pid); - snprintf(&disp[2][0], 17, " \xBC\xCF\xAF\xC0 Reflow"); while (1) { sd_card_mounted = mount_sd_card_if_avail(sd_card_mounted); - snprintf(&disp[0][0], 17, "SD %smounted", sd_card_mounted ? "" : "un"); - pt1000_value_status = adc_pt1000_get_current_resistance(&pt1000_value); if (systick_ticks_have_passed(pid_timestamp, 250)) { @@ -250,9 +240,6 @@ int main() led_set(0, !led_get(0)); else led_set(0, 0); - - snprintf(&disp[3][0], 17, "Temp: %s%.1f ""\xDF""C", (temp_status == 0 ? "" : temp_status < 0 ? "<" : ">") - , current_temp); } /* Handle error in case PID controller should be active, but temperature measurement failed */ @@ -267,35 +254,15 @@ int main() oven_driver_set_power(pid_controller_output < 0 ? 0U : (uint8_t)pid_controller_output); } - button = button_read_event(); - - if (button == BUTTON_SHORT_RELEASED) { - rotary_encoder_zero(); - } else if (button == BUTTON_LONG_RELEASED) { - adc_pt1000_clear_error(); - } - - - rot = rotary_encoder_get_abs_val(); oven_driver_set_power(rot > 100U ? 100U : rot); - - /* TODO: handle gui */ - snprintf(&disp[1][0], 17, "Rot: %u %s", (unsigned int)rot, (button == BUTTON_SHORT ? "SHORT" : (button == BUTTON_LONG ? "LONG" : ""))); - handle_shell_uart_input(shell_handle); - if (systick_ticks_have_passed(display_timestamp, 2) || lcd_ret == LCD_FSM_CALL_AGAIN) { - lcd_ret = lcd_fsm_write_buffer(disp); - display_timestamp = systick_get_global_tick(); - } - - if (lcd_ret == LCD_FSM_CALL_AGAIN) { - /* Nothing */ - } else { + menu_wait_request = reflow_menu_handle(); + if (!menu_wait_request) __WFI(); - } + } } diff --git a/stm-firmware/shell.c b/stm-firmware/shell.c index 23cc473..2c939ac 100644 --- a/stm-firmware/shell.c +++ b/stm-firmware/shell.c @@ -239,11 +239,10 @@ static shellmatta_retCode_t shell_cmd_rot(const shellmatta_handle_t handle, (void)length; uint32_t rot_val; - int32_t delta; rot_val = rotary_encoder_get_abs_val(); - delta = rotary_encoder_get_change_val(); - shellmatta_printf(handle, "Rotary encoder value: %u, delta: %d\r\n", rot_val, delta); + //delta = rotary_encoder_get_change_val(); + shellmatta_printf(handle, "Rotary encoder value: %u\r\n", rot_val); return SHELLMATTA_OK; } diff --git a/stm-firmware/ui/menu.c b/stm-firmware/ui/menu.c index 85427b0..becf402 100644 --- a/stm-firmware/ui/menu.c +++ b/stm-firmware/ui/menu.c @@ -30,7 +30,7 @@ void menu_handle(struct lcd_menu *menu, int16_t rotary_encoder_delta, enum butto return; menu->inputs.push_button = push_button; - menu->inputs.rotary_encoder_delta = rotary_encoder_delta; + menu->inputs.rotary_encoder_delta += rotary_encoder_delta; if (menu->active_entry == NULL) menu->active_entry = menu->root_entry; @@ -121,7 +121,7 @@ void menu_list_display(struct menu_list *list, uint32_t top_row, uint32_t bottom } /* Calculate list parameters */ - row_count = top_row - bottom_row + 1; + row_count = bottom_row - top_row + 1; mid_row = (top_row + bottom_row) / 2; count_above_mid = mid_row - top_row; count_below_mid = bottom_row - mid_row; @@ -133,11 +133,11 @@ void menu_list_display(struct menu_list *list, uint32_t top_row, uint32_t bottom start_index = list->currently_selected - count_above_mid; } else if (list->currently_selected < count_above_mid) { start_index = 0; - } else if ((list->entry_count - list->currently_selected - 1) < count_below_mid) { - if (list->entry_count < row_count) { + } else if ((list->entry_count - list->currently_selected - 1) <= count_below_mid) { + if (list->entry_count < row_count) start_index = 0; - } - start_index = list->entry_count - row_count; + else + start_index = list->entry_count - row_count; } else { start_index = 0; } @@ -182,3 +182,22 @@ void menu_list_scroll_up(struct menu_list *list) if (list->currently_selected > 0) list->currently_selected--; } + +void menu_ack_rotary_delta(struct lcd_menu *menu) +{ + if (!menu) + return; + + menu->inputs.rotary_encoder_delta = 0; +} + +void menu_display_clear(struct lcd_menu *menu) +{ + uint8_t i; + + if (!menu || !menu->update_display) + return; + + for (i = 0; i < 4; i++) + menu->update_display(i, ""); +}