/* * Menu.cpp * * Created on: Jun 8, 2024 * Author: Carst */ #include #include #include #include "Menu.hpp" #include "Display.hpp" #include "Button.hpp" #include "Timer.hpp" #include "ElektronischeLast.hpp" #include "STM32G071KBT6.hpp" namespace ElektronischeLast { static Timer timer_MainScreen = Timer(); static Timer timer_Backlight = Timer(); static Button ok = Button(); static Button up = Button(); static Button down = Button(); static Display lcd = Display(); static const uint8_t degreeSymbol[] = { 0x0E, 0x0A, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00 }; static const uint8_t arrowUp[] = { 0x04, 0x0E, 0x1F, 0x04, 0x04, 0x04, 0x04, 0x04 }; static const uint8_t arrowDown[] = { 0x04, 0x04, 0x04, 0x04, 0x04, 0x1F, 0x0E, 0x04 }; void Menu::init() { timer_MainScreen.start(500U); timer_Backlight.start(3UL * 60UL * 1000UL); ok.init(GPIOA, LL_GPIO_PIN_7); up.init(GPIOA, LL_GPIO_PIN_9); down.init(GPIOA, LL_GPIO_PIN_8); lcd.init(); while(lcd.ready_for_data() == false) { lcd.run(); } lcd.lcd_set_user_chars(Display::FirstSign, arrowUp); while(lcd.ready_for_data() == false) { lcd.run(); } lcd.lcd_set_user_chars(Display::ThirdSign, arrowDown); while(lcd.ready_for_data() == false) { lcd.run(); } lcd.lcd_set_user_chars(Display::SecondSign, degreeSymbol); while(lcd.ready_for_data() == false) { lcd.run(); } lcd.lcd_set_display(Display::eDispalyOn, Display::eCursorOff, Display::eCursorBlinkOff); lcd.print(Display::Line1, "Elektronische Last"); up.cyclic(); down.cyclic(); if(up.isPressed() && down.isPressed()) { menu_level = MenuLevel_Call; } } void Menu::set_measurements(uint32_t spannung, uint32_t strom, uint32_t temperatur, uint32_t geschwindigkeit) { this->spannung = spannung; this->strom = strom; this->temperatur = temperatur; this->geschwindigkeit = geschwindigkeit; } void Menu::run() { if(ok.cyclic()) { timer_Backlight.restart(); lcd.set_backlight(true); } if(up.cyclic()) { timer_Backlight.restart(); lcd.set_backlight(true); } if(down.cyclic()) { timer_Backlight.restart(); lcd.set_backlight(true); } if(timer_Backlight.elapsed()) { lcd.set_backlight(false); this->menu_locked = true; } switch(menu_level) { case MenuLevel_Call: menu_call(); break; case MenuLevel_ICallInit: menu_icall_init(); break; case MenuLevel_ICall: menu_icall(); break; case MenuLevel_UCallInit: menu_ucall_init(); break; case MenuLevel_UCall: menu_ucall(); break; case MenuLevel_ISoll: menu_isoll(); break; case MenuLevel_Main: default: menu_main(); break; } lcd.run(); } void Menu::menu_main(void) { if(timer_MainScreen.elapsed()) { if(lcd.ready_for_data()) { timer_MainScreen.start(500U); char data[17U]; int32_t len = snprintf(data, sizeof(data) - 1, "%2" PRIu32 ".%02" PRIu32 "V", spannung / 1000U, spannung % 1000U / 10U); std::memset(&data[len], (int)' ', 16U - len); snprintf(&data[12], sizeof(data) - 12, "%2" PRIu32 "%cC", temperatur, 0x1); data[16] = '\0'; lcd.print(Display::Line1, data); if(strom < 1000UL) { len = snprintf(data, sizeof(data) - 1, "%3" PRIu32 "mA", strom); } else { len = snprintf(data, sizeof(data) - 1, "%" PRIu32 ".%02" PRIu32 "A", strom / 1000U, strom % 1000U / 10U); } std::memset(&data[len], (int)' ', 16U - len); snprintf(&data[9], sizeof(data) - 9, "%4" PRIu32 "RPM", geschwindigkeit); data[16] = '\0'; lcd.print(Display::Line2, data); } } if(ok.isReleased()) { if(this->menu_locked) { this->menu_locked = false; } else { this->menu_level = MenuLevel_ISoll; this->configurations = 0UL; } } if(up.isReleased() || down.isReleased()) { this->menu_locked = false; } } void Menu::menu_call(void) { if(lcd.ready_for_data()) { switch(this->configurations) { case 0UL: lcd.print(Display::Line1, "Kalibrierung: I"); lcd.print(Display::Line2, "Kalibrierung: U"); this->configurations++; break; case 1UL: lcd.lcd_set_display(Display::eDispalyOn, Display::eCursorOn, Display::eCursorBlinkOn); this->configurations++; break; case 2UL: lcd.set_cursor(Display::Line1, 15U); this->configurations++; this->cursor = 1UL; break; default: break; } } if(ok.isReleased()) { if(this->cursor == 1UL) { this->menu_level = MenuLevel_ICallInit; } else if(this->cursor == 2UL) { this->menu_level = MenuLevel_UCallInit; } this->configurations = 0UL; } else if(up.isReleased()) { if(this->cursor == 1UL) { this->cursor = 2UL; lcd.set_cursor(Display::Line2, 15U); } else if(this->cursor == 2UL) { this->cursor = 1UL; lcd.set_cursor(Display::Line1, 15U); } } else if(down.isReleased()) { if(this->cursor == 1UL) { this->cursor = 2UL; lcd.set_cursor(Display::Line2, 15U); } else if(this->cursor == 2UL) { this->cursor = 1UL; lcd.set_cursor(Display::Line1, 15U); } } } void Menu::menu_icall_init(void) { char data[17U]; if(lcd.ready_for_data()) { switch(this->configurations) { case 0UL: set_new_sollstrom(1000UL); soll = get_current_sollstrom(); snprintf(data, sizeof(data), "iSoll: %5" PRIu32 "mA", soll); lcd.print(Display::Line1, "Stelle 1A ein "); lcd.print(Display::Line2, data); this->configurations++; break; case 1UL: lcd.set_cursor(Display::Line2, 13UL); this->configurations++; break; default: break; } } if(ok.isReleased()) { this->menu_level = MenuLevel_ICall; this->configurations = 0UL; } else if(down.isReleased()) { soll--; set_new_sollstrom(soll); snprintf(data, sizeof(data), "iSoll: %5" PRIu32 "mA", soll); lcd.print(Display::Line2, data); this->configurations = 1UL; } else if(up.isReleased()) { soll++; set_new_sollstrom(soll); snprintf(data, sizeof(data), "iSoll: %5" PRIu32 "mA", soll); lcd.print(Display::Line2, data); this->configurations = 1UL; } } void Menu::menu_icall(void) { if(this->configurations == 0UL) { start_icall(); lcd.print(Display::Line1, "Kalibrierung... "); lcd.print(Display::Line2, " "); this->configurations++; } } void Menu::menu_ucall_init(void) { if(this->configurations == 0UL) { set_new_sollstrom(0UL); lcd.print(Display::Line1, "Lege 15V an "); lcd.print(Display::Line2, " "); this->configurations++; } if(ok.isReleased()) { this->menu_level = MenuLevel_UCall; this->configurations = 0UL; } } void Menu::menu_ucall(void) { if(this->configurations == 0UL) { start_ucall(); lcd.print(Display::Line1, "Kalibrierung... "); lcd.print(Display::Line2, " "); this->configurations++; } } void Menu::menu_isoll(void) { const char *header = "Sollstrom: "; char data[17U]; int32_t len; bool changed = false; if(lcd.ready_for_data()) { switch(this->configurations) { case 0UL: cursor = 0U; soll = get_current_sollstrom(); len = snprintf(data, sizeof(data) - 1, "%05" PRIu32 "mA", soll); std::memset(&data[len], (int)' ', 16U - len); data[16] = '\0'; lcd.print(Display::Line1, header); lcd.print(Display::Line2, data); this->configurations++; break; case 1UL: lcd.lcd_set_display(Display::eDispalyOn, Display::eCursorOn, Display::eCursorBlinkOn); this->configurations++; break; case 2UL: lcd.set_cursor(Display::Line2, cursor); this->configurations++; break; default: if(ok.isReleased()) { cursor++; if(cursor > 3U) { menu_level = MenuLevel_Main; set_new_sollstrom(soll); lcd.lcd_set_display(Display::eDispalyOn, Display::eCursorOff, Display::eCursorBlinkOff); } else { lcd.set_cursor(Display::Line2, cursor); } } else if(up.isReleased()) { uint32_t step = 10000UL; uint32_t i = 0U; while(i < cursor) { step /= 10UL; i++; } this->soll = (this->soll + step) % 11000UL; changed = true; } else if(down.isReleased()) { uint32_t step = 10000UL; uint32_t i = 0U; while(i < cursor) { step /= 10UL; i++; } this->soll = (this->soll - step) % 11000UL; changed = true; } if(changed) { len = snprintf(data, sizeof(data) - 1, "%05" PRIu32 "mA", this->soll); std::memset(&data[len], (int)' ', 16U - len); data[16] = '\0'; lcd.print(Display::Line2, data); this->configurations = 2U; } break; } } } }