/* Reflow Oven Controller * * Copyright (C) 2020 Mario Hüttel * * This file is part of the Reflow Oven Controller Project. * * The reflow oven controller is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * * The Reflow Oven Control Firmware is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with the reflow oven controller project. * If not, see . */ #include #include #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) { int i; if (row > 4) return; if (!data) return; for (i = 0; data[i] && i < LCD_CHAR_WIDTH; i++) { display_buffer[row][i] = data[i]; } 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)) { my_timestamp = systick_get_global_tick(); 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_about(struct lcd_menu *menu, enum menu_entry_func_entry entry_type, void *parent) { static void *my_parent; static bool button_ready; static int page = 0; static uint64_t uptime_secs; uint64_t new_uptime_secs; int16_t rot_delta; enum button_state push_button; char buff[20]; if (entry_type == MENU_ENTRY_FIRST_ENTER) { uptime_secs = 0ULL; page = 0; my_parent = parent; button_ready = false; menu_display_clear(menu); menu_ack_rotary_delta(menu); /* menu->update_display(0, LCD_SHIMATTA_STRING " Reflow"); snprintf(buff, sizeof(buff), "%.*s", LCD_CHAR_WIDTH, xstr(GIT_VER)); menu->update_display(1, buff); if (strlen(xstr(GIT_VER)) > LCD_CHAR_WIDTH) { snprintf(buff, sizeof(buff), "%s", &xstr(GIT_VER)[LCD_CHAR_WIDTH]); menu->update_display(2, buff); } menu->update_display(3, __DATE__); */ } switch (page) { case 0: menu_lcd_output(menu, 0, LCD_SHIMATTA_STRING " Shimatta"); menu_lcd_output(menu, 1, "Oven Controller"); menu_lcd_output(menu, 2, "(c) Mario H\xF5ttel"); menu_lcd_output(menu, 3, " Version->"); break; case 1: menu_lcd_output(menu, 0, "Version Number:"); snprintf(buff, sizeof(buff), "%.*s", LCD_CHAR_WIDTH, xstr(GIT_VER)); menu_lcd_output(menu, 1, buff); if (strlen(xstr(GIT_VER)) > LCD_CHAR_WIDTH) { snprintf(buff, sizeof(buff), "%s", &xstr(GIT_VER)[LCD_CHAR_WIDTH]); menu_lcd_output(menu, 2, buff); } menu_lcd_output(menu, 3, "<-About Uptime->"); break; case 2: new_uptime_secs = (uint64_t)(systick_get_global_tick() / 1000); if (new_uptime_secs != uptime_secs) { uptime_secs = new_uptime_secs; menu_lcd_output(menu, 0, "Uptime:"); snprintf(buff, sizeof(buff), "%u s", (unsigned int)uptime_secs); menu_lcd_output(menu, 1, buff); menu_lcd_output(menu, 3, "<-Version"); } break; default: page = 0; break; } rot_delta = menu_get_rotary_delta(menu); if (rot_delta >= 4) { menu_ack_rotary_delta(menu); if (page < 2) { page++; menu_display_clear(menu); } } else if (rot_delta <= -4) { menu_ack_rotary_delta(menu); if (page > 0) { page--; menu_display_clear(menu); } } push_button = menu_get_button_state(menu); if (push_button == BUTTON_IDLE) button_ready = true; if (button_ready && (push_button == BUTTON_SHORT_RELEASED || 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_entry_names[] = { "About", "Monitoring", NULL }; static const menu_func_t root_entry_funcs[] = { reflow_menu_about, reflow_menu_monitor }; enum button_state push_button; int16_t rot_delta; if (entry_type != MENU_ENTRY_CONTINUE) { menu_display_clear(menu); update_display_buffer(0, "Main Menu"); menu_ack_rotary_delta(menu); if (entry_type == MENU_ENTRY_FIRST_ENTER) { button_valid = false; list.entry_names = root_entry_names; list.submenu_list = root_entry_funcs; list.update_display = menu->update_display; list.currently_selected = 0; menu_list_compute_count(&list); } } push_button = menu_get_button_state(menu); rot_delta = menu_get_rotary_delta(menu); if (push_button == BUTTON_IDLE) { button_valid = true; } else if (button_valid && push_button == BUTTON_SHORT_RELEASED) { /* Enter currently selected menu_entry */ menu_list_enter_selected_entry(&list, menu); } if (rot_delta >= 4) { menu_list_scroll_down(&list); menu_ack_rotary_delta(menu); } else if (rot_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; 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 || lcd_tick_100us >= 5) { lcd_ret = lcd_fsm_write_buffer(display_buffer); lcd_tick_100us = 0UL; } if (lcd_ret == LCD_FSM_CALL_AGAIN) return 0; else return 1; } void reflow_menu_init() { rotary_encoder_setup(); button_init(); lcd_init(); menu_init(reflow_menu_ptr, reflow_menu_root_entry, update_display_buffer); }