diff --git a/Core/Inc/git_rev.h b/Core/Inc/git_rev.h index c052e63..41284d1 100644 --- a/Core/Inc/git_rev.h +++ b/Core/Inc/git_rev.h @@ -7,6 +7,6 @@ // Auto generated header file containing the last git revision -#define GIT_HASH "408c69b" +#define GIT_HASH "527ebdc" #endif //FLOATPUMP_GIT_REVISION_TEMPLATE_H \ No newline at end of file diff --git a/Core/Src/main.cpp b/Core/Src/main.cpp index eab7328..112104b 100644 --- a/Core/Src/main.cpp +++ b/Core/Src/main.cpp @@ -17,6 +17,7 @@ #include "RelayChannel.h" #include "GPIChannel.h" #include "Menu_Entry_Type_Execute.h" +#include "NewMenu.h" #define SLAVE_ADDRESS_LCD 0x4e @@ -77,7 +78,7 @@ void CheckRefillConditions(Config_Store &cfg, io::PressureChannel &tankLevel, io if (cfg.RefillEnable.getValue()) { //Check whether refilling is necessary - if(HAL_GetTick() > (c_RefillCooldown + (cfg.RefillCooldown.getValue() * 60*1000))) { + if (HAL_GetTick() > (c_RefillCooldown + (cfg.RefillCooldown.getValue() * 60 * 1000))) { S_refillcooldown = 0; if (tankLevel.getPercent() < cfg.RefillBelow.getValue()) { if (cfg.RefillBlockEnable.getValue() && !rblock) { @@ -90,7 +91,7 @@ void CheckRefillConditions(Config_Store &cfg, io::PressureChannel &tankLevel, io S_refilling = false; S_refillempty = true; //Reset cooldown only if it was previously on - if(c_LastState) + if (c_LastState) c_RefillCooldown = HAL_GetTick(); c_LastState = false; } else { @@ -103,14 +104,15 @@ void CheckRefillConditions(Config_Store &cfg, io::PressureChannel &tankLevel, io refillPump.switchRelay(io::RelayChannel::state::OFF); S_refilling = false; S_refillempty = false; - if(c_LastState) + if (c_LastState) c_RefillCooldown = HAL_GetTick(); c_LastState = false; } } else { HAL_GPIO_TogglePin(LED3_GPIO_Port, LED3_Pin); refillPump.switchRelay(io::RelayChannel::state::OFF); - S_refillcooldown = (((c_RefillCooldown + (cfg.RefillCooldown.getValue() * 60*1000)) - HAL_GetTick()) / 1000); + S_refillcooldown = (((c_RefillCooldown + (cfg.RefillCooldown.getValue() * 60 * 1000)) - HAL_GetTick()) / + 1000); } } else { refillPump.switchRelay(io::RelayChannel::state::OFF); @@ -149,6 +151,15 @@ int main(void) { initializer.runInitSequence(); + //EXP + + using namespace floatpump::newmenu; + + + + //EXP + + /// /// /// LOGICAL CODE BEGIN @@ -159,79 +170,38 @@ int main(void) { using namespace floatpump; - menu::Menu tankmenu("Tank"); + newmenu::Menu tankmenu("Tank"); bool a_caliblow, a_calibhigh = false; - menu::Menu_Entry_Type_Execute t_exCalibLow; - menu::Menu_Entry_Type_Execute t_exCalibHigh; - t_exCalibLow.linkConfig(&a_caliblow); - t_exCalibHigh.linkConfig(&a_calibhigh); - menu::Menu_Entry exCalibLow(t_exCalibLow, "Kal. Unt. Punkt"); - menu::Menu_Entry exCalibHigh(t_exCalibHigh, "Kal. Ob. Punkt"); + tankmenu.addEntry(&a_caliblow, "Kal. Unt. Punkt"); + tankmenu.addEntry(&a_calibhigh, "Kal. Ob. Punkt"); - menu::Menu_Entry_Type_Numeric t_CalibLow(0); - menu::Menu_Entry_Type_Numeric t_CalibHigh(65535); - t_CalibLow.linkConfig(globalConfig.TankCalibLow.getLink()); - t_CalibHigh.linkConfig(globalConfig.TankCalibHigh.getLink()); - menu::Menu_Entry CalibLow(t_CalibLow, "K Unten"); - menu::Menu_Entry CalibHigh(t_CalibHigh, "K Oben"); + tankmenu.addEntry(globalConfig.TankCalibLow.getLink(), "K Unten"); + tankmenu.addEntry(globalConfig.TankCalibHigh.getLink(), "K Oben"); - menu::Menu_Entry_Type_Percent t_tankLevel(25); - t_tankLevel.linkConfig(globalConfig.TankMinLevel.getLink()); - menu::Menu_Entry TankLevel(t_tankLevel, "Min. Fuellst."); + tankmenu.addEntry(globalConfig.TankMinLevel.getLink(), "Min. Fuellst."); + tankmenu.addEntry(globalConfig.TankHysteresis.getLink(), "Hysterese"); - menu::Menu_Entry_Type_Percent t_tankHysteresis(5); - t_tankHysteresis.linkConfig(globalConfig.TankHysteresis.getLink()); - menu::Menu_Entry TankHysteresis(t_tankHysteresis, "Hysterese"); - - menu::Menu_Entry_Type_Checkable t_tankInvert(false); - t_tankInvert.linkConfig(globalConfig.TankPumpInvert.getLink()); - menu::Menu_Entry TankInvert(t_tankInvert, "Inv. Relais"); - - tankmenu.addEntry(exCalibLow); - tankmenu.addEntry(exCalibHigh); - tankmenu.addEntry(CalibLow); - tankmenu.addEntry(CalibHigh); - tankmenu.addEntry(TankLevel); - tankmenu.addEntry(TankHysteresis); - tankmenu.addEntry(TankInvert); + tankmenu.addEntry(globalConfig.TankPumpInvert.getLink(), "Inv Relais"); - menu::Menu refillmenu("Nachspeisung"); + newmenu::Menu refillmenu("Nachspeisung"); - menu::Menu_Entry_Type_Checkable t_refillEnable(false); - menu::Menu_Entry_Type_Checkable t_refillBlock(true); - menu::Menu_Entry_Type_Checkable t_refillBlockInvert(false); - t_refillEnable.linkConfig(globalConfig.RefillEnable.getLink()); - t_refillBlock.linkConfig(globalConfig.RefillBlockEnable.getLink()); - t_refillBlockInvert.linkConfig(globalConfig.RefillBlockInvert.getLink()); - menu::Menu_Entry refillEnable(t_refillEnable, "Nachsp. akt."); - menu::Menu_Entry refillBlock(t_refillBlock, "Notabschalt."); - menu::Menu_Entry refillBlockInvert(t_refillBlockInvert, "NotAbs. Inv."); + refillmenu.addEntry(globalConfig.RefillEnable.getLink(), "Nachsp. akt."); + refillmenu.addEntry(globalConfig.RefillBlockEnable.getLink(), "Notabschalt."); + refillmenu.addEntry(globalConfig.RefillBlockInvert.getLink(), "NotAbs. Inv."); - menu::Menu_Entry_Type_Percent t_RefillBelow(20); - menu::Menu_Entry_Type_Percent t_RefillHysteresis(5); - t_RefillBelow.linkConfig(globalConfig.RefillBelow.getLink()); - t_RefillHysteresis.linkConfig(globalConfig.RefillHysteresis.getLink()); - menu::Menu_Entry refillBelow(t_RefillBelow, "Auff. bis"); - menu::Menu_Entry refillHysteresis(t_RefillHysteresis, "Hysterese"); + refillmenu.addEntry(globalConfig.RefillBelow.getLink(), "Auff. bis"); + refillmenu.addEntry(globalConfig.RefillHysteresis.getLink(), "Hysterese"); - menu::Menu_Entry_Type_Numeric t_RefillCooldown(10); - t_RefillCooldown.linkConfig(reinterpret_cast(globalConfig.RefillCooldown.getLink())); - menu::Menu_Entry refillCooldown(t_RefillCooldown, "Wartezeit"); + refillmenu.addEntry(globalConfig.RefillCooldown.getLink(), "Wartezeit"); - refillmenu.addEntry(refillEnable); - refillmenu.addEntry(refillBlock); - refillmenu.addEntry(refillBlockInvert); - refillmenu.addEntry(refillBelow); - refillmenu.addEntry(refillHysteresis); - refillmenu.addEntry(refillCooldown); - menu::Menu mainmenu("Hauptmenu"); + newmenu::Menu mainmenu("Hauptmenu"); mainmenu.addSubmenu(&tankmenu); mainmenu.addSubmenu(&refillmenu); - menu::Menu_Controller controller(&mainmenu, display); + newmenu::Menu_Controller controller(&mainmenu, display); static int old_pos = 0; //Instantiate Input and Output modules @@ -246,16 +216,16 @@ int main(void) { uint32_t last_backlight_retrigger = 0; bool f_store = false, f_restore = false; - menu::Menu_Entry_Type_Execute t_MStore; - menu::Menu_Entry_Type_Execute t_MRestore; - t_MStore.linkConfig(&f_store); - t_MRestore.linkConfig(&f_restore); - menu::Menu_Entry MStore(t_MStore, "Speichern"); - menu::Menu_Entry MRestore(t_MRestore, "Laden"); - - - mainmenu.addEntry(MStore); - mainmenu.addEntry(MRestore); +// menu::Menu_Entry_Type_Execute t_MStore; +// menu::Menu_Entry_Type_Execute t_MRestore; +// t_MStore.linkConfig(&f_store); +// t_MRestore.linkConfig(&f_restore); +// menu::Menu_Entry MStore(t_MStore, "Speichern"); +// menu::Menu_Entry MRestore(t_MRestore, "Laden"); +// +// +// mainmenu.addEntry(MStore); +// mainmenu.addEntry(MRestore); while (1) { @@ -264,7 +234,8 @@ int main(void) { display.LCDSetCursor(0, 0); display.LCDSendCString( - const_cast(std::string("Fuellstand " + std::to_string(tankLevel0.getPercent()) + " %").c_str())); + const_cast(std::string( + "Fuellstand " + std::to_string(tankLevel0.getPercent()) + " %").c_str())); display.LCDSetCursor(0, 1); if (S_tankempty) { display.LCDSendCString(const_cast(std::string("Tank Wassermangel ").c_str())); @@ -288,10 +259,12 @@ int main(void) { display.LCDSetCursor(0, 3); if (S_refillcooldown > 0) { int remaining_mins = S_refillcooldown / 60; - if(remaining_mins > 0) - display.LCDSendCString(const_cast(std::string("Nsp. wartet: min " + std::to_string( S_refillcooldown / 60)).c_str())); + if (remaining_mins > 0) + display.LCDSendCString(const_cast(std::string( + "Nsp. wartet: min " + std::to_string(S_refillcooldown / 60)).c_str())); else - display.LCDSendCString(const_cast(std::string("Nsp. wartet: s " + std::to_string(S_refillcooldown)).c_str())); + display.LCDSendCString( + const_cast(std::string("Nsp. wartet: s " + std::to_string(S_refillcooldown)).c_str())); } else if (S_refillempty) { display.LCDSendCString(const_cast(std::string("Nachspeisung mangel ").c_str())); HAL_GPIO_WritePin(LED3_GPIO_Port, LED3_Pin, GPIO_PIN_RESET); @@ -303,17 +276,17 @@ int main(void) { //Check for rotation to enable display backlight if (old_pos < rot_counter) { - controller.pushEvent(menu::Menu_Controller::Event::Increase); + controller.pushEvent(newmenu::Menu_Controller::Event::Increase); old_pos = rot_counter; last_backlight_retrigger = HAL_GetTick(); } else if (old_pos > rot_counter) { - controller.pushEvent(menu::Menu_Controller::Event::Decrease); + controller.pushEvent(newmenu::Menu_Controller::Event::Decrease); old_pos = rot_counter; last_backlight_retrigger = HAL_GetTick(); } //Check and toggle backlight state - if(HAL_GetTick() > last_backlight_retrigger + 60000) { + if (HAL_GetTick() > last_backlight_retrigger + 60000) { S_backlight = false; } else { S_backlight = true; @@ -328,16 +301,16 @@ int main(void) { controller.execute(); if (rot_button) { rot_button = false; - controller.pushEvent(menu::Menu_Controller::Event::Push); + controller.pushEvent(newmenu::Menu_Controller::Event::Push); last_menu_retrigger = HAL_GetTick(); } if (old_pos < rot_counter) { - controller.pushEvent(menu::Menu_Controller::Event::Increase); + controller.pushEvent(newmenu::Menu_Controller::Event::Increase); old_pos = rot_counter; last_menu_retrigger = HAL_GetTick(); } else if (old_pos > rot_counter) { - controller.pushEvent(menu::Menu_Controller::Event::Decrease); + controller.pushEvent(newmenu::Menu_Controller::Event::Decrease); old_pos = rot_counter; last_menu_retrigger = HAL_GetTick(); } diff --git a/Middlewares/floatpump/Inc/Menu_Controller.h b/Middlewares/floatpump/Inc/Menu_Controller.h index 62ab825..a11a91f 100644 --- a/Middlewares/floatpump/Inc/Menu_Controller.h +++ b/Middlewares/floatpump/Inc/Menu_Controller.h @@ -5,9 +5,10 @@ #ifndef FLOATPUMP_MENU_CONTROLLER_H #define FLOATPUMP_MENU_CONTROLLER_H -#include "Menu.h" +#include "NewMenu.h" +#include "LCD_I2C_Driver.h" -namespace floatpump::menu { +namespace floatpump::newmenu { class Menu_Controller { public: diff --git a/Middlewares/floatpump/Inc/NewMenu.h b/Middlewares/floatpump/Inc/NewMenu.h new file mode 100644 index 0000000..097794f --- /dev/null +++ b/Middlewares/floatpump/Inc/NewMenu.h @@ -0,0 +1,255 @@ +// +// Created by robtor on 26.01.23. +// + +#ifndef FLOATPUMP_NEWMENU_H +#define FLOATPUMP_NEWMENU_H + +#include +#include +#include +#include +#include + +namespace floatpump { + namespace newmenu { + + struct IMenuEntry { + virtual ~IMenuEntry() = default; + + virtual auto u_press() -> void = 0; + + virtual auto u_increase(uint16_t steps = 1) -> void = 0; + + virtual auto u_decrease(uint16_t steps = 1) -> void = 0; + + virtual auto is_entered() -> bool = 0; + + virtual auto toString() -> std::string = 0; + }; + + template + class MenuEntry : public IMenuEntry { + public: + MenuEntry(T *linked_config, std::string name) : m_name(name) { + m_storage = linked_config; + }; + + auto getValue() -> T & { + return (*m_storage); + } + + auto setValue(T &value) -> void { + *m_storage = value; + } + + auto relinkConfig(T *linked_config) -> void { + m_storage = linked_config; + } + + protected: + T *m_storage; + std::string m_name; + bool m_entered = false; + + auto buildString(std::string appendix) -> std::string { + int spaces = 19 - (m_name.length() + appendix.length()); + std::string spacer; + if (spaces > 0) + spacer.append(spaces, ' '); + else if (spaces < 0) + return "ERROR"; + + return {m_name + spacer + appendix}; + } + + }; + + class MenuEntryCheckable : public MenuEntry { + public: + MenuEntryCheckable(bool *linked_config, const std::string &name) : MenuEntry(linked_config, name) {} + + auto toString() -> std::string override { + return buildString({(*m_storage) ? "ON " : "OFF"}); + } + + auto u_press() -> void override { + *m_storage = !(*m_storage); + } + + auto u_increase(uint16_t steps) -> void override { + + } + + auto u_decrease(uint16_t steps) -> void override { + + } + + auto is_entered() -> bool override { + return false; + } + }; + + class MenuEntryExecute : public MenuEntry { + public: + MenuEntryExecute(bool *linked_config, const std::string &name) : MenuEntry(linked_config, name) {} + + auto u_press() -> void override { + *m_storage = true; + } + + auto u_increase(uint16_t steps) -> void override { + + } + + auto u_decrease(uint16_t steps) -> void override { + + } + + auto is_entered() -> bool override { + return false; + } + + auto toString() -> std::string override { + return buildString({(*m_storage) ? "[--]" : "[XX]"}); + } + }; + + class MenuEntryNumeric : public MenuEntry { + public: + MenuEntryNumeric(uint16_t *linked_config, const std::string &name) : MenuEntry(linked_config, name) {} + + auto u_press() -> void override { + m_entered = !m_entered; + } + + auto u_increase(uint16_t steps) -> void override { + (*m_storage)++; + } + + auto u_decrease(uint16_t steps) -> void override { + (*m_storage)--; + } + + auto is_entered() -> bool override { + return m_entered; + } + + auto toString() -> std::string override { + if (m_entered) { + return buildString({"> " + std::to_string(*m_storage)}); + } else { + return buildString({" " + std::to_string(*m_storage)}); + } + } + }; + + class MenuEntryPercent : public MenuEntry { + public: + MenuEntryPercent(uint8_t *linked_config, const std::string &name) : MenuEntry(linked_config, name) {} + + auto u_press() -> void override { + m_entered = !m_entered; + } + + auto u_increase(uint16_t steps) -> void override { + if (*m_storage < 100) + (*m_storage)++; + } + + auto u_decrease(uint16_t steps) -> void override { + if (*m_storage > 0) { + (*m_storage)--; + } + } + + auto is_entered() -> bool override { + return m_entered; + } + + auto toString() -> std::string override { + if (m_entered) { + return buildString({"> %" + std::to_string(*m_storage)}); + } else { + return buildString({" %" + std::to_string(*m_storage)}); + } + } + }; + + class Menu { + public: + explicit Menu(const std::string &m_name) : m_name(m_name) {} + + template + auto addEntry(As&& ...args) -> void{ + m_entries.push_back(std::make_unique(std::forward(args)...)); + } + + auto addSubmenu(Menu *submenu) -> void { + submenu->m_parent = this; + m_submenus.push_back(submenu); + } + + auto printLine() -> const std::string { + return m_name; + } + + auto getDisplayList() -> std::vector { + std::vector list; + + list.reserve(m_submenus.size() + m_entries.size()); + + //Append all Submenus + for (auto &m_submenu: m_submenus) { + list.push_back(m_submenu->printLine()); + } + + //Append all Entries + for (auto &m_entry: m_entries) { + list.push_back(m_entry->toString()); + } + + //Append Go-Back-Entry if we are within a submenu + if (m_parent != nullptr) { + list.emplace_back("<- Zurueck"); + } + + return list; + } + + auto getAllEntriesNum() -> unsigned const int { + return (m_entries.size() + m_submenus.size()) + ((m_parent != nullptr) ? 1 : 0); + } + + auto getSubmenu(int index) -> Menu* { + if (index >= 0 && index < m_submenus.size()) { + return m_submenus[index]; + } else { + return nullptr; + } + } + + auto getEntry(int index) -> std::optional> { + if (index >= m_submenus.size() && index < m_entries.size() + m_submenus.size()) { + return *m_entries[index - m_submenus.size()]; + } else { + return std::nullopt; + } + } + + auto getParent() -> Menu* { + return m_parent; + } + + private: + std::vector> m_entries; + std::vector m_submenus; + Menu *m_parent = nullptr; + std::string m_name; + }; + + } +} + + +#endif //FLOATPUMP_NEWMENU_H diff --git a/Middlewares/floatpump/Src/Menu_Controller.cpp b/Middlewares/floatpump/Src/Menu_Controller.cpp index f49387c..4d8110b 100644 --- a/Middlewares/floatpump/Src/Menu_Controller.cpp +++ b/Middlewares/floatpump/Src/Menu_Controller.cpp @@ -4,7 +4,7 @@ #include "Menu_Controller.h" -namespace floatpump::menu { +namespace floatpump::newmenu { void Menu_Controller::execute() { displayMenu(m_menu); @@ -70,8 +70,8 @@ namespace floatpump::menu { m_menu = m->getSubmenu(m_current_index); m_current_index = 0; //Forward press action if entry is entry - } else if (m->getEntry(m_current_index) != nullptr) { - m->getEntry(m_current_index)->action_press(); + } else if (m->getEntry(m_current_index) != std::nullopt) { + m->getEntry(m_current_index)->get().u_press(); //If we are on the Go-Back-Entry and have a parent: replace menu with parent menu } else if (m_menu->getParent() != nullptr) { m_menu = m_menu->getParent(); @@ -81,10 +81,10 @@ namespace floatpump::menu { void Menu_Controller::increase(Menu *m) { if (m_current_index < m->getAllEntriesNum()) { - if (m->getEntry(m_current_index) != nullptr) { + if (m->getEntry(m_current_index) != std::nullopt) { //Forward increase action to entry if we have an entered entry - if (m->getEntry(m_current_index)->isEntered()) { - m->getEntry(m_current_index)->action_increase(); + if (m->getEntry(m_current_index)->get().is_entered()) { + m->getEntry(m_current_index)->get().u_increase(); } else if (m_current_index < m->getAllEntriesNum() - 1) { m_current_index++; } @@ -98,10 +98,10 @@ namespace floatpump::menu { void Menu_Controller::decrease(Menu *m) { if (m_current_index > 0) { - if (m->getEntry(m_current_index) != nullptr) { + if (m->getEntry(m_current_index) != std::nullopt) { //Forward decrease action to entry if we have an entered entry - if (m->getEntry(m_current_index)->isEntered()) { - m->getEntry(m_current_index)->action_decrease(); + if (m->getEntry(m_current_index)->get().is_entered()) { + m->getEntry(m_current_index)->get().u_decrease(); } else { m_current_index--; }