From a93f34e0badfb57873a3f9d75c94aef6e7dec021 Mon Sep 17 00:00:00 2001 From: CommanderRedYT Date: Thu, 13 Oct 2022 22:00:16 +0200 Subject: [PATCH] Refactor into multiple files --- main/CMakeLists.txt | 22 +- main/actions/setupactions.cpp | 26 ++ main/actions/setupactions.h | 24 ++ main/displays/buttoncalibratedisplay.cpp | 223 ----------------- main/displays/buttoncalibratedisplay.h | 55 ----- .../boardcomputerhardwaresettingsmenu.cpp | 7 +- .../setup/ask_calibrate_other_buttons.cpp | 56 +++++ .../setup/ask_calibrate_other_buttons.h | 18 ++ main/displays/setup/ask_setup_clouds.cpp | 53 ++++ main/displays/setup/ask_setup_clouds.h | 16 ++ main/displays/setup/basic_buttons.cpp | 231 ++++++++++++++++++ main/displays/setup/basic_buttons.h | 51 ++++ main/displays/setup/calibrate_potis.cpp | 1 + main/displays/setup/calibrate_potis.h | 29 +++ main/displays/setup/final_information.cpp | 58 +++++ main/displays/setup/final_information.h | 20 ++ main/displays/setup/information.cpp | 59 +++++ main/displays/setup/information.h | 25 ++ main/displays/setup/setup_cloud.cpp | 103 ++++++++ main/displays/setup/setup_cloud.h | 20 ++ main/displays/setupdisplay.cpp | 9 +- main/displays/setupdisplay.h | 42 +--- main/main.cpp | 19 +- main/setup.cpp | 39 +++ main/setup.h | 23 ++ main/utils.cpp | 38 ++- main/utils.h | 3 +- 27 files changed, 932 insertions(+), 338 deletions(-) create mode 100644 main/actions/setupactions.cpp create mode 100644 main/actions/setupactions.h delete mode 100644 main/displays/buttoncalibratedisplay.cpp delete mode 100644 main/displays/buttoncalibratedisplay.h create mode 100644 main/displays/setup/ask_calibrate_other_buttons.cpp create mode 100644 main/displays/setup/ask_calibrate_other_buttons.h create mode 100644 main/displays/setup/ask_setup_clouds.cpp create mode 100644 main/displays/setup/ask_setup_clouds.h create mode 100644 main/displays/setup/basic_buttons.cpp create mode 100644 main/displays/setup/basic_buttons.h create mode 100644 main/displays/setup/calibrate_potis.cpp create mode 100644 main/displays/setup/calibrate_potis.h create mode 100644 main/displays/setup/final_information.cpp create mode 100644 main/displays/setup/final_information.h create mode 100644 main/displays/setup/information.cpp create mode 100644 main/displays/setup/information.h create mode 100644 main/displays/setup/setup_cloud.cpp create mode 100644 main/displays/setup/setup_cloud.h create mode 100644 main/setup.cpp create mode 100644 main/setup.h diff --git a/main/CMakeLists.txt b/main/CMakeLists.txt index f143b67..ffb26d6 100644 --- a/main/CMakeLists.txt +++ b/main/CMakeLists.txt @@ -26,6 +26,7 @@ set(BOBBY_HEADERS actions/rebootaction.h actions/resetnvsaction.h actions/savesettingsaction.h + actions/setupactions.h actions/switchprofileaction.h actions/tempomatmodeapplycurrentpeedaction.h actions/updateswapfrontbackaction.h @@ -72,7 +73,6 @@ set(BOBBY_HEADERS displays/bobbymenudisplay.h displays/bobbypopupdisplay.h displays/bobbysplitgraphdisplay.h - displays/buttoncalibratedisplay.h displays/calibratevoltagedisplay.h displays/confiscationdisplay.h displays/gameoflifedisplay.h @@ -159,7 +159,13 @@ set(BOBBY_HEADERS displays/qrcodedebug.h displays/qrdisplay.h displays/qrimportdisplay.h - displays/setupdisplay.h + displays/setup/ask_calibrate_other_buttons.h + displays/setup/ask_setup_clouds.h + displays/setup/basic_buttons.h + displays/setup/calibrate_potis.h + displays/setup/final_information.h + displays/setup/information.h + displays/setup/setup_cloud.h displays/speedinfodisplay.h displays/spirodisplay.h displays/starfielddisplay.h @@ -234,6 +240,7 @@ set(BOBBY_HEADERS serial_bobby.h settingspersister.h settingsutils.h + setup.h softpwmlimiter.h statistics.h statustexthelper.h @@ -283,6 +290,7 @@ set(BOBBY_SOURCES actions/rebootaction.cpp actions/resetnvsaction.cpp actions/savesettingsaction.cpp + actions/setupactions.cpp actions/switchprofileaction.cpp actions/tempomatmodeapplycurrentpeedaction.cpp actions/updateswapfrontbackaction.cpp @@ -326,7 +334,6 @@ set(BOBBY_SOURCES displays/bobbymenudisplay.cpp displays/bobbypopupdisplay.cpp displays/bobbysplitgraphdisplay.cpp - displays/buttoncalibratedisplay.cpp displays/calibratevoltagedisplay.cpp displays/confiscationdisplay.cpp displays/gameoflifedisplay.cpp @@ -411,7 +418,13 @@ set(BOBBY_SOURCES displays/qrcodedebug.cpp displays/qrdisplay.cpp displays/qrimportdisplay.cpp - displays/setupdisplay.cpp + displays/setup/ask_calibrate_other_buttons.cpp + displays/setup/ask_setup_clouds.cpp + displays/setup/basic_buttons.cpp + displays/setup/calibrate_potis.cpp + displays/setup/final_information.cpp + displays/setup/information.cpp + displays/setup/setup_cloud.cpp displays/speedinfodisplay.cpp displays/spirodisplay.cpp displays/starfielddisplay.cpp @@ -487,6 +500,7 @@ set(BOBBY_SOURCES serial_bobby.cpp settingspersister.cpp settingsutils.cpp + setup.cpp softpwmlimiter.cpp statistics.cpp statustexthelper.cpp diff --git a/main/actions/setupactions.cpp b/main/actions/setupactions.cpp new file mode 100644 index 0000000..1bd1488 --- /dev/null +++ b/main/actions/setupactions.cpp @@ -0,0 +1,26 @@ +#include "setupactions.h" + +// 3rdparty lib includes +#include + +// local includes +#include "displays/setup/basic_buttons.h" +#include "displays/setup/calibrate_potis.h" + +PushButtonCalibrateDisplayAction::PushButtonCalibrateDisplayAction(const bool early_return) : + m_early_return{early_return} +{} + +void PushButtonCalibrateDisplayAction::triggered() +{ + espgui::pushScreen(m_early_return); +} + +PushPotiCalibrateDisplayAction::PushPotiCalibrateDisplayAction(const bool early_return) : + m_early_return{early_return} +{} + +void PushPotiCalibrateDisplayAction::triggered() +{ + // espgui::pushScreen(m_early_return); // commented out until implemented +} diff --git a/main/actions/setupactions.h b/main/actions/setupactions.h new file mode 100644 index 0000000..bd3fd43 --- /dev/null +++ b/main/actions/setupactions.h @@ -0,0 +1,24 @@ +#pragma once + +// 3rdparty lib includes +#include + +class PushButtonCalibrateDisplayAction : public virtual espgui::ActionInterface +{ +public: + explicit PushButtonCalibrateDisplayAction(bool early_return); + + void triggered() override; +private: + const bool m_early_return; +}; + +class PushPotiCalibrateDisplayAction : public virtual espgui::ActionInterface +{ +public: + explicit PushPotiCalibrateDisplayAction(bool early_return); + + void triggered() override; +private: + const bool m_early_return; +}; diff --git a/main/displays/buttoncalibratedisplay.cpp b/main/displays/buttoncalibratedisplay.cpp deleted file mode 100644 index 46cc49f..0000000 --- a/main/displays/buttoncalibratedisplay.cpp +++ /dev/null @@ -1,223 +0,0 @@ -#include "buttoncalibratedisplay.h" - -// esp-idf includes -#include - -// 3rdparty lib includes -#include -#include -#include - -// local includes -#include "bobbyerrorhandler.h" -#include "displays/statusdisplay.h" -#include "newsettings.h" - -namespace { -constexpr const char TAG[] = "BUTTON"; -} // namespace - -/* -std::string ButtonCalibrateDisplay::text() const -{ - return "Button calibrate"; -} - -void ButtonCalibrateDisplay::start() -{ - Base::start(); - - m_oldMode = currentMode; - currentMode = &m_mode; - m_lastButton = std::nullopt; - m_status = WaitingLeft; - - m_finished = false; -} - -void ButtonCalibrateDisplay::initScreen() -{ - Base::initScreen(); - - m_labelInstruction.start(); - m_labelLeft.start(); - m_labelRight.start(); - m_labelUp.start(); - m_labelDown.start(); - m_labelEnd.start(); -} - -void ButtonCalibrateDisplay::update() -{ - Base::update(); - - if (m_finished) - { - m_finished = false; - - if (auto result = configs.write_config(configs.dpadMappingLeft, m_leftButton); !result) - { - BobbyErrorHandler{}.errorOccurred(std::move(result).error()); - return; - } - else - { - ESP_LOGI(TAG, "Left button set to %d", m_leftButton); - } - - if (auto result = configs.write_config(configs.dpadMappingRight, m_rightButton); !result) - { - BobbyErrorHandler{}.errorOccurred(std::move(result).error()); - return; - } - else - { - ESP_LOGI(TAG, "Right button set to %d", m_rightButton); - } - if (auto result = configs.write_config(configs.dpadMappingUp, m_upButton); !result) - { - BobbyErrorHandler{}.errorOccurred(std::move(result).error()); - return; - } - else - { - ESP_LOGI(TAG, "Up button set to %d", m_upButton); - } - if (auto result = configs.write_config(configs.dpadMappingDown, m_downButton); !result) - { - BobbyErrorHandler{}.errorOccurred(std::move(result).error()); - return; - } - else - { - ESP_LOGI(TAG, "Down button set to %d", m_downButton); - } - - if (espgui::displayStack.empty()) - { - espgui::switchScreen(); - } - else - espgui::popScreen(); - } -} - -void ButtonCalibrateDisplay::redraw() -{ - Base::redraw(); - - espgui::tft.setTextColor(TFT_WHITE, TFT_BLACK); - - switch (m_status) - { - case WaitingLeft: - if (m_lastButton) - m_labelInstruction.redraw("Press LEFT again"); - else - m_labelInstruction.redraw("Press LEFT"); - break; - case WaitingRight: - if (m_lastButton) - m_labelInstruction.redraw("Press RIGHT again"); - else - m_labelInstruction.redraw("Press RIGHT"); - break; - case WaitingUp: - if (m_lastButton) - m_labelInstruction.redraw("Press UP again"); - else - m_labelInstruction.redraw("Press UP"); - break; - case WaitingDown: - if (m_lastButton) - m_labelInstruction.redraw("Press DOWN again"); - else - m_labelInstruction.redraw("Press DOWN"); - break; - case Finished: - m_labelInstruction.redraw("Finished"); - break; - } - - m_labelLeft.redraw(m_status > WaitingLeft ? fmt::format("Left: {}", m_leftButton) : std::string{}); - m_labelRight.redraw(m_status > WaitingRight ? fmt::format("Right: {}", m_rightButton) : std::string{}); - m_labelUp.redraw(m_status > WaitingUp ? fmt::format("Up: {}", m_upButton) : std::string{}); - m_labelDown.redraw(m_status > WaitingDown ? fmt::format("Down: {}", m_downButton) : std::string{}); - - m_labelEnd.redraw(m_status == Finished ? "Press RIGHT to save" : ""); -} - -void ButtonCalibrateDisplay::stop() -{ - Base::stop(); - - if (currentMode == &m_mode) - { - // to avoid crash after deconstruction - m_mode.stop(); - lastMode = nullptr; - - currentMode = m_oldMode; - } -} - -void ButtonCalibrateDisplay::rawButtonPressed(uint8_t button) -{ - //Base::rawButtonPressed(button); - - if (m_status == Finished) - { - if (button == m_rightButton) - { - ESP_LOGI(TAG, "correct button"); - m_finished = true; - } - else - ESP_LOGI(TAG, "wrong button"); - } - else if (!m_lastButton || *m_lastButton != button) - m_lastButton = button; - else - { - switch (m_status) - { - case WaitingLeft: - m_leftButton = button; - m_lastButton = std::nullopt; - m_status = WaitingRight; - break; - case WaitingRight: - m_rightButton = button; - m_lastButton = std::nullopt; - m_status = WaitingUp; - break; - case WaitingUp: - m_upButton = button; - m_lastButton = std::nullopt; - m_status = WaitingDown; - break; - case WaitingDown: - m_downButton = button; - m_lastButton = std::nullopt; - m_status = Finished; - break; - case Finished:; - } - } -} - -void ButtonCalibrateDisplay::rawButtonReleased(uint8_t button) -{ - //Base::rawButtonReleased(button); -} - -void ButtonCalibrateDisplay::buttonPressed(espgui::Button button) -{ - //Base::buttonPressed(button); -} - -void ButtonCalibrateDisplay::buttonReleased(espgui::Button button) -{ - //Base::buttonReleased(button); -} -*/ diff --git a/main/displays/buttoncalibratedisplay.h b/main/displays/buttoncalibratedisplay.h deleted file mode 100644 index 0aa3317..0000000 --- a/main/displays/buttoncalibratedisplay.h +++ /dev/null @@ -1,55 +0,0 @@ -#pragma once - -// 3rdparty lib includes -#include -#include - -// local includes -#include "globals.h" -#include "modeinterface.h" -#include "modes/ignoreinputmode.h" - -/* -class ButtonCalibrateDisplay : public espgui::DisplayWithTitle -{ - using Base = espgui::DisplayWithTitle; - -public: - ButtonCalibrateDisplay() = default; - explicit ButtonCalibrateDisplay(bool bootup) : m_bootup{bootup} {} - - std::string text() const override; - void start() override; - void initScreen() override; - void update() override; - void redraw() override; - void stop() override; - - void rawButtonPressed(uint8_t button) override; - void rawButtonReleased(uint8_t button) override; - void buttonPressed(espgui::Button button) override; - void buttonReleased(espgui::Button button) override; - -private: - const bool m_bootup{false}; - ModeInterface *m_oldMode; - IgnoreInputMode m_mode{0, bobbycar::protocol::ControlType::FieldOrientedControl, bobbycar::protocol::ControlMode::Torque}; - - std::optional m_lastButton; - - enum { WaitingLeft, WaitingRight, WaitingUp, WaitingDown, Finished } m_status; - - espgui::Label m_labelInstruction{25, 72}; - - espgui::Label m_labelLeft{25, 100}; - espgui::Label m_labelRight{25, 125}; - espgui::Label m_labelUp{25, 150}; - espgui::Label m_labelDown{25, 175}; - - espgui::Label m_labelEnd{25, 225}; - - uint8_t m_leftButton, m_rightButton, m_upButton, m_downButton; - - bool m_finished; -}; -*/ diff --git a/main/displays/menus/boardcomputerhardwaresettingsmenu.cpp b/main/displays/menus/boardcomputerhardwaresettingsmenu.cpp index 785f7a5..a2c4893 100644 --- a/main/displays/menus/boardcomputerhardwaresettingsmenu.cpp +++ b/main/displays/menus/boardcomputerhardwaresettingsmenu.cpp @@ -11,15 +11,14 @@ // local includes #include "accessors/settingsaccessors.h" +#include "actions/setupactions.h" #include "bobbycheckbox.h" #include "displays/bobbychangevaluedisplay.h" -#include "displays/buttoncalibratedisplay.h" #include "displays/menus/extrabuttoncalibratemenu.h" #include "displays/menus/lockscreensettingsmenu.h" #include "displays/menus/setupquickactionsmenu.h" #include "displays/menus/timersmenu.h" #include "displays/potiscalibratedisplay.h" -#include "displays/setupdisplay.h" #include "icons/lock.h" #ifdef FEATURE_JOYSTICK @@ -193,12 +192,12 @@ using namespace espgui; BoardcomputerHardwareSettingsMenu::BoardcomputerHardwareSettingsMenu() { constructMenuItem, PushScreenAction, StaticMenuItemIcon<&bobbyicons::lock>>>(); - constructMenuItem>>(SetupStep::BASIC_BUTTONS, true); + constructMenuItem>>(true); constructMenuItem, PushScreenAction>>(); constructMenuItem, PushScreenAction>>(); constructMenuItem, DummyAction>>(); constructMenuItem, DummyAction>>(); - constructMenuItem>>(SetupStep::CALIBRATE_POTIS, true); + constructMenuItem>>(true); #ifdef FEATURE_JOYSTICK constructMenuItem, PushScreenAction>>(); #endif diff --git a/main/displays/setup/ask_calibrate_other_buttons.cpp b/main/displays/setup/ask_calibrate_other_buttons.cpp new file mode 100644 index 0000000..e641d13 --- /dev/null +++ b/main/displays/setup/ask_calibrate_other_buttons.cpp @@ -0,0 +1,56 @@ +#include "ask_calibrate_other_buttons.h" + +// 3rdparty lib includes +#include + +// local includes +#include "displays/menus/extrabuttoncalibratemenu.h" +#include "displays/setup/final_information.h" +#include "setup.h" +#include "utils.h" + +namespace { +constexpr char const askSetupOtherButtonsText[] = "Do you want to setup other\nbuttons?\n(Blinker, Profile Buttons, etc.)\n\nPress LEFT to skip other buttons.\nPress RIGHT to setup buttons."; +} // namespace + +void SetupAskCalibrateOtherButtonsDisplay::initScreen() +{ + Base::initScreen(); + + drawLargeText(askSetupOtherButtonsText); +} + +void SetupAskCalibrateOtherButtonsDisplay::start() +{ + if (m_next_screen) + { + espgui::switchScreen(); + return; + } + + Base::start(); + + setup::lock(); +} + +void SetupAskCalibrateOtherButtonsDisplay::buttonPressed(espgui::Button button) +{ + switch (button) + { + case espgui::Left: + espgui::switchScreen(); + return; + case espgui::Right: + m_next_screen = true; + espgui::pushScreen(); + return; + default:; + } + + Base::buttonPressed(button); +} + +std::string SetupAskCalibrateOtherButtonsDisplay::text() const +{ + return "Other Buttons"; +} diff --git a/main/displays/setup/ask_calibrate_other_buttons.h b/main/displays/setup/ask_calibrate_other_buttons.h new file mode 100644 index 0000000..e1a0a3c --- /dev/null +++ b/main/displays/setup/ask_calibrate_other_buttons.h @@ -0,0 +1,18 @@ +#pragma once + +// local includes +#include "displays/bobbydisplaywithtitle.h" + +class SetupAskCalibrateOtherButtonsDisplay : public virtual BobbyDisplayWithTitle +{ + using Base = BobbyDisplayWithTitle; +public: + void initScreen() override; + void start() override; + + void buttonPressed(espgui::Button button) override; + + [[nodiscard]] std::string text() const override; +private: + bool m_next_screen{false}; +}; diff --git a/main/displays/setup/ask_setup_clouds.cpp b/main/displays/setup/ask_setup_clouds.cpp new file mode 100644 index 0000000..383c53b --- /dev/null +++ b/main/displays/setup/ask_setup_clouds.cpp @@ -0,0 +1,53 @@ +#include "ask_setup_clouds.h" + +// 3rdparty lib includes +#include + +// local includes +#include "displays/setup/ask_calibrate_other_buttons.h" +#include "displays/setup/setup_cloud.h" +#include "setup.h" +#include "taskmanager.h" +#include "utils.h" + +namespace { +constexpr char const askCloudText[] = "Do you want to setup cloud?\nWith this, you will be able\nto send data to graphana,\nremote control things like Buttons\nand NVS and more!\n\nPress LEFT to skip cloud.\nPress RIGHT to setup cloud."; +} // namespace + +void SetupAskSetupCloudsDisplay::initScreen() +{ + Base::initScreen(); + + drawLargeText(askCloudText); +} + +void SetupAskSetupCloudsDisplay::start() +{ + Base::start(); + + setup::lock(); +} + +void SetupAskSetupCloudsDisplay::buttonPressed(espgui::Button button) +{ + switch (button) + { + case espgui::Left: // skip cloud setup + espgui::switchScreen(); + return; + case espgui::Right: // enter cloud setup + configs.write_config(configs.feature.cloud.isEnabled, true); + configs.write_config(configs.feature.udpcloud.isEnabled, true); + + reload_tasks(); + espgui::switchScreen(); + default:; + } + + Base::buttonPressed(button); +} + +std::string SetupAskSetupCloudsDisplay::text() const +{ + return "Cloud Setup"; +} diff --git a/main/displays/setup/ask_setup_clouds.h b/main/displays/setup/ask_setup_clouds.h new file mode 100644 index 0000000..0a80598 --- /dev/null +++ b/main/displays/setup/ask_setup_clouds.h @@ -0,0 +1,16 @@ +#pragma once + +// local includes +#include "displays/bobbydisplaywithtitle.h" + +class SetupAskSetupCloudsDisplay : public virtual BobbyDisplayWithTitle +{ + using Base = BobbyDisplayWithTitle; +public: + void initScreen() override; + void start() override; + + void buttonPressed(espgui::Button button) override; + + [[nodiscard]] std::string text() const override; +}; diff --git a/main/displays/setup/basic_buttons.cpp b/main/displays/setup/basic_buttons.cpp new file mode 100644 index 0000000..1cc25ec --- /dev/null +++ b/main/displays/setup/basic_buttons.cpp @@ -0,0 +1,231 @@ +#include "basic_buttons.h" + +// system includes +#include + +// 3rdparty lib includes +#include +#include + +// local includes +#include "bobbyerrorhandler.h" +#include "displays/setup/ask_setup_clouds.h" +// #include "displays/setup/calibrate_potis.h" // commented out until implemented +#include "setup.h" +#include "utils.h" + +namespace { +constexpr char const buttonText[] = "Please press the highlighted\n buttons!"; +constexpr const char * const TAG = "SETUP-BUTTONS"; +} + +void SetupBasicButtonsDisplay::initScreen() +{ + Base::initScreen(); + + drawLargeText(buttonText); + drawButtons(m_button_cal_status); +} + +void SetupBasicButtonsDisplay::start() +{ + Base::start(); + + setup::lock(); + + m_lastButton = std::nullopt; + m_button_cal_status = LEFT; + m_button_cal_finished = false; +} + +void SetupBasicButtonsDisplay::update() +{ + if (m_button_cal_finished) + { + m_button_cal_finished = false; + saveButtons(); + + if (m_early_return) + { + setup::unlock(); + espgui::popScreen(); + } + else + { + espgui::switchScreen(); + } + } + + Base::update(); +} + +void SetupBasicButtonsDisplay::redraw() +{ + Base::redraw(); +} + +void SetupBasicButtonsDisplay::rawButtonPressed(uint8_t button) +{ + if (m_button_cal_status == FINISHED) + { + if (button == m_rightButton) + { + m_button_cal_finished = true; + } + } + else if (!m_lastButton || *m_lastButton != button) + m_lastButton = button; + else + { + switch (m_button_cal_status) + { + case LEFT: + m_leftButton = button; + m_lastButton = std::nullopt; + m_button_cal_status = RIGHT; + break; + case RIGHT: + m_rightButton = button; + m_lastButton = std::nullopt; + m_button_cal_status = UP; + break; + case UP: + m_upButton = button; + m_lastButton = std::nullopt; + m_button_cal_status = DOWN; + break; + case DOWN: + m_downButton = button; + m_lastButton = std::nullopt; + m_button_cal_status = FINISHED; + break; + default:; + } + } + + drawButtons(m_button_cal_status); + + Base::rawButtonPressed(button); +} + +void SetupBasicButtonsDisplay::rawButtonReleased(uint8_t button) +{ + // Base::rawButtonReleased(button); +} + +void SetupBasicButtonsDisplay::buttonPressed(espgui::Button button) +{ + // Base::buttonPressed(button); +} + +void SetupBasicButtonsDisplay::buttonReleased(espgui::Button button) +{ + // Base::buttonReleased(button); +} + +std::string SetupBasicButtonsDisplay::text() const +{ + return "Calibrate Buttons"; +} + +void SetupBasicButtonsDisplay::saveButtons() const +{ + if (auto result = configs.write_config(configs.dpadMappingLeft, m_leftButton); !result) + { + BobbyErrorHandler{}.errorOccurred(std::move(result).error()); + return; + } + else + { + ESP_LOGI(TAG, "Left button set to %d", m_leftButton); + } + + if (auto result = configs.write_config(configs.dpadMappingRight, m_rightButton); !result) + { + BobbyErrorHandler{}.errorOccurred(std::move(result).error()); + return; + } + else + { + ESP_LOGI(TAG, "Right button set to %d", m_rightButton); + } + if (auto result = configs.write_config(configs.dpadMappingUp, m_upButton); !result) + { + BobbyErrorHandler{}.errorOccurred(std::move(result).error()); + return; + } + else + { + ESP_LOGI(TAG, "Up button set to %d", m_upButton); + } + if (auto result = configs.write_config(configs.dpadMappingDown, m_downButton); !result) + { + BobbyErrorHandler{}.errorOccurred(std::move(result).error()); + return; + } + else + { + ESP_LOGI(TAG, "Down button set to %d", m_downButton); + } +} + +void SetupBasicButtonsDisplay::drawButtons(const SetupBasicButtonsDisplay::CurrentButton button) +{ + using namespace espgui; + + const int16_t x_mid = tft.width() / 2; + const int16_t y_mid = tft.height() / 2; + + const auto offset = 40; + const auto radius = 15; + const auto subtract = 2; + + const auto up_x = x_mid; + const auto up_y = y_mid - offset; + + const auto down_x = x_mid; + const auto down_y = y_mid + offset; + + const auto left_x = x_mid - offset; + const auto left_y = y_mid; + + const auto right_x = x_mid + offset; + const auto right_y = y_mid; + + tft.fillCircle(up_x, up_y, radius-subtract, TFT_BLACK); + tft.fillCircle(down_x, down_y, radius-subtract, TFT_BLACK); + tft.fillCircle(left_x, left_y, radius-subtract, TFT_BLACK); + tft.fillCircle(right_x, right_y, radius-subtract, TFT_BLACK); + + tft.drawCircle(up_x, up_y, radius, TFT_WHITE); + tft.drawCircle(down_x, down_y, radius, TFT_WHITE); + tft.drawCircle(left_x, left_y, radius, TFT_WHITE); + tft.drawCircle(right_x, right_y, radius, TFT_WHITE); + + if (m_button_cal_finished) + { + return; + } + + switch(button) + { + case UP: + tft.fillCircle(up_x, up_y, radius-subtract, m_lastButton ? TFT_YELLOW : TFT_WHITE); + break; + case DOWN: + tft.fillCircle(down_x, down_y, radius-subtract, m_lastButton ? TFT_YELLOW : TFT_WHITE); + break; + case LEFT: + tft.fillCircle(left_x, left_y, radius-subtract, m_lastButton ? TFT_YELLOW : TFT_WHITE); + break; + case RIGHT: + tft.fillCircle(right_x, right_y, radius-subtract, m_lastButton ? TFT_YELLOW : TFT_WHITE); + break; + default:; + } + + if (m_button_cal_status == FINISHED) + { + tft.fillCircle(right_x, right_y, radius-subtract, TFT_GREEN); + } +} diff --git a/main/displays/setup/basic_buttons.h b/main/displays/setup/basic_buttons.h new file mode 100644 index 0000000..88853fa --- /dev/null +++ b/main/displays/setup/basic_buttons.h @@ -0,0 +1,51 @@ +#pragma once + +// system includes +#include + +// local includes +#include "displays/bobbydisplaywithtitle.h" + +class SetupBasicButtonsDisplay : public virtual BobbyDisplayWithTitle +{ + using Base = BobbyDisplayWithTitle; + + enum CurrentButton : int8_t + { + UP, + DOWN, + LEFT, + RIGHT, + FINISHED + }; // button calibration +public: + explicit SetupBasicButtonsDisplay(bool early_return = false) : + m_early_return{early_return} + {} + + void initScreen() override; + void start() override; + void update() override; + void redraw() override; + + void rawButtonPressed(uint8_t button) override; + void rawButtonReleased(uint8_t button) override; + void buttonPressed(espgui::Button button) override; + void buttonReleased(espgui::Button button) override; + + [[nodiscard]] std::string text() const override; +private: + const bool m_early_return; + + std::optional m_lastButton; + + CurrentButton m_button_cal_status; + + uint8_t m_leftButton, m_rightButton, m_upButton, m_downButton; + + bool m_button_cal_finished; + + void saveButtons() const; + + void drawButtons(CurrentButton button); +}; diff --git a/main/displays/setup/calibrate_potis.cpp b/main/displays/setup/calibrate_potis.cpp new file mode 100644 index 0000000..8b98fb4 --- /dev/null +++ b/main/displays/setup/calibrate_potis.cpp @@ -0,0 +1 @@ +#include "calibrate_potis.h" diff --git a/main/displays/setup/calibrate_potis.h b/main/displays/setup/calibrate_potis.h new file mode 100644 index 0000000..421f100 --- /dev/null +++ b/main/displays/setup/calibrate_potis.h @@ -0,0 +1,29 @@ +#pragma once + +// local includes +#include "displays/bobbydisplaywithtitle.h" + +class SetupCalibratePotisDisplay : public virtual BobbyDisplayWithTitle +{ + using Base = BobbyDisplayWithTitle; +public: + explicit SetupCalibratePotisDisplay(bool early_return = false) : + m_early_return{early_return} + {} + + void initScreen() override; + void start() override; + void update() override; + void redraw() override; + void stop() override; + + void rawButtonPressed(uint8_t button) override; + void rawButtonReleased(uint8_t button) override; + void buttonPressed(espgui::Button button) override; + void buttonReleased(espgui::Button button) override; + + [[nodiscard]] std::string text() const override; + +private: + const bool m_early_return; +}; diff --git a/main/displays/setup/final_information.cpp b/main/displays/setup/final_information.cpp new file mode 100644 index 0000000..d934f09 --- /dev/null +++ b/main/displays/setup/final_information.cpp @@ -0,0 +1,58 @@ +#include "final_information.h" + +// 3rdparty lib includes +#include + +// local includes +#include "displays/menus/extrabuttoncalibratemenu.h" +#include "displays/statusdisplay.h" +#include "newsettings.h" +#include "setup.h" +#include "utils.h" + +using namespace std::chrono_literals; + +namespace { +constexpr char const finalInformationText[] = "Setup is done!\nIf cloud is setup, go to\nhttps://service.bobbycar.cloud/\nand register this bobbycar!\nThis is also used\nto setup udp cloud.\nPress any button to exit."; +} // namespace + +void SetupFinalInformationDisplay::initScreen() +{ + Base::initScreen(); + + drawLargeText(finalInformationText); +} + +void SetupFinalInformationDisplay::start() +{ + Base::start(); + + setup::lock(); +} + +void SetupFinalInformationDisplay::stop() +{ + Base::stop(); + + setup::unlock(); +} + +void SetupFinalInformationDisplay::buttonPressed(espgui::Button button) +{ + configs.write_config(configs.boardcomputerHardware.setupFinished, true); + if (espgui::displayStack.empty()) + { + espgui::switchScreen(); + } + else + { + espgui::popScreen(); + } + + Base::buttonPressed(button); +} + +std::string SetupFinalInformationDisplay::text() const +{ + return "All done!"; +} diff --git a/main/displays/setup/final_information.h b/main/displays/setup/final_information.h new file mode 100644 index 0000000..a56303a --- /dev/null +++ b/main/displays/setup/final_information.h @@ -0,0 +1,20 @@ +#pragma once + +// 3rdparty lib includes +#include + +// local includes +#include "displays/bobbydisplaywithtitle.h" + +class SetupFinalInformationDisplay : public virtual BobbyDisplayWithTitle +{ + using Base = BobbyDisplayWithTitle; +public: + void initScreen() override; + void start() override; + void stop() override; + + void buttonPressed(espgui::Button button) override; + + [[nodiscard]] std::string text() const override; +}; diff --git a/main/displays/setup/information.cpp b/main/displays/setup/information.cpp new file mode 100644 index 0000000..a8add3e --- /dev/null +++ b/main/displays/setup/information.cpp @@ -0,0 +1,59 @@ +#include "information.h" + +// 3rdparty lib includes +#include + +// local includes +#include "displays/setup/basic_buttons.h" +#include "setup.h" +#include "utils.h" + +using namespace std::chrono_literals; + +namespace { +constexpr char const informationText[] = "Congratulations on your new\nbobbycar! This guide will help\nyou through initial setup,\ncalibrate everything and\nget you ready!"; +} // namespace + +void SetupInformationDisplay::initScreen() +{ + Base::initScreen(); + + m_init_text_progressbar.start(); + + drawLargeText(informationText); +} + +void SetupInformationDisplay::start() +{ + Base::start(); + + setup::lock(); + + m_menu_opened_timestamp = espchrono::millis_clock::now(); +} + +void SetupInformationDisplay::update() +{ + if (espchrono::ago(m_menu_opened_timestamp) > 5s) + { + espgui::switchScreen(); + } + + m_init_text_progressbar.redraw(espchrono::ago(m_menu_opened_timestamp) / 50ms ); + + Base::update(); +} + +void SetupInformationDisplay::buttonPressed(espgui::Button button) +{ + if (espchrono::ago(m_menu_opened_timestamp) > 500ms) + { + espgui::switchScreen(); + } +} + +[[nodiscard]] std::string SetupInformationDisplay::text() const +{ + return "First Steps"; +} + diff --git a/main/displays/setup/information.h b/main/displays/setup/information.h new file mode 100644 index 0000000..84454c3 --- /dev/null +++ b/main/displays/setup/information.h @@ -0,0 +1,25 @@ +#pragma once + +// 3rdparty lib includes +#include +#include +#include + +// local includes +#include "displays/bobbydisplaywithtitle.h" + +class SetupInformationDisplay : public virtual BobbyDisplayWithTitle +{ + using Base = BobbyDisplayWithTitle; +public: + void initScreen() override; + void start() override; + void update() override; + + void buttonPressed(espgui::Button button) override; + + [[nodiscard]] std::string text() const override; +private: + espchrono::millis_clock::time_point m_menu_opened_timestamp; + espgui::ProgressBar m_init_text_progressbar{10, espgui::tft.height()/2, espgui::tft.width()-20, 30, 0, 100}; +}; diff --git a/main/displays/setup/setup_cloud.cpp b/main/displays/setup/setup_cloud.cpp new file mode 100644 index 0000000..e7885d3 --- /dev/null +++ b/main/displays/setup/setup_cloud.cpp @@ -0,0 +1,103 @@ +#include "setup_cloud.h" + +// 3rdparty lib includes +#include +#include +#include + +// local includes +#include "accessors/settingsaccessors.h" +#include "bobbycheckbox.h" +#include "displays/bobbychangevaluedisplay.h" +#include "displays/setup/ask_calibrate_other_buttons.h" +#include "setup.h" + +using namespace espgui; + +namespace { +constexpr const char TEXT_ENABLE_CLOUD[] = "Enable Cloud"; +constexpr const char TEXT_CLOUD_USERNAME[] = "Cloud Username"; +constexpr const char TEXT_CLOUD_URL[] = "Cloud URL"; +constexpr const char TEXT_CLOUD_KEY[] = "Cloud Key"; +constexpr const char TEXT_DONE[] = "Done"; + +using CloudUsernameChangeScreen = espgui::makeComponent< + BobbyChangeValueDisplay, + espgui::StaticText, + UsernameAccessor, + espgui::ConfirmActionInterface, + espgui::BackActionInterface +>; + +using CloudURLChangeScreen = espgui::makeComponent< + BobbyChangeValueDisplay, + espgui::StaticText, + CloudURLAccessor, + espgui::ConfirmActionInterface, + espgui::BackActionInterface +>; + +using CloudKeyChangeScreen = espgui::makeComponent< + BobbyChangeValueDisplay, + espgui::StaticText, + CloudKeyAccessor, + espgui::ConfirmActionInterface, + espgui::BackActionInterface +>; // cloud setup + +template +class CloudSetupFinishedAction : public virtual ActionInterface +{ +public: + void triggered() override + { + if (early_return) + { + espgui::popScreen(); + } + else + { + espgui::switchScreen(); + } + } +}; +} // namespace + +SetupCloudDisplay::SetupCloudDisplay(const bool early_return) : m_early_return{early_return} +{ + constructMenuItem, BobbyCheckbox, CloudEnabledAccessor>>(); + constructMenuItem, PushScreenAction>>(); + constructMenuItem, PushScreenAction>>(); + constructMenuItem, PushScreenAction>>(); + + if (early_return) + constructMenuItem, CloudSetupFinishedAction>>(); + else + constructMenuItem, CloudSetupFinishedAction>>(); +} + +void SetupCloudDisplay::start() +{ + Base::start(); + + setup::lock(); +} + +void SetupCloudDisplay::stop() +{ + if (m_early_return) + { + setup::unlock(); + } + + Base::stop(); +} + +void SetupCloudDisplay::back() +{} + +std::string SetupCloudDisplay::text() const +{ + return "WebSocket Cloud"; +} + diff --git a/main/displays/setup/setup_cloud.h b/main/displays/setup/setup_cloud.h new file mode 100644 index 0000000..3db4996 --- /dev/null +++ b/main/displays/setup/setup_cloud.h @@ -0,0 +1,20 @@ +#pragma once + +// local includes +#include "displays/bobbymenudisplay.h" + +class SetupCloudDisplay : public virtual BobbyMenuDisplay +{ + using Base = BobbyMenuDisplay; +public: + explicit SetupCloudDisplay(bool early_return = false); + + void start() override; + void stop() override; + + void back() override; + + [[nodiscard]] std::string text() const override; +private: + const bool m_early_return; +}; diff --git a/main/displays/setupdisplay.cpp b/main/displays/setupdisplay.cpp index 2afb99c..d850251 100644 --- a/main/displays/setupdisplay.cpp +++ b/main/displays/setupdisplay.cpp @@ -21,11 +21,6 @@ using namespace espgui; using namespace std::chrono_literals; namespace setupdisplay { -constexpr char const InformationText[] = "Congratulations on your new\nbobbycar! This guide will help\nyou through initial setup,\ncalibrate everything and\nget you ready!"; -constexpr char const ButtonText[] = "Please press the highlighted\n buttons!"; -constexpr char const AskCloudText[] = "Do you want to setup cloud?\nWith this, you will be able\nto send data to graphana,\nremote control things like Buttons\nand NVS and more!\n\nPress LEFT to skip cloud.\nPress RIGHT to setup cloud."; -constexpr char const AskSetupOtherButtonsText[] = "Do you want to setup other\nbuttons?\n(Blinker, Profile Buttons, etc.)\n\nPress LEFT to skip other buttons.\nPress RIGHT to setup buttons."; -constexpr char const FinalInformationText[] = "Setup is done!\nIf cloud is setup, go to\nhttps://service.bobbycar.cloud/\nand register this bobbycar!\nThis is also used\nto setup udp cloud.\nPress any button to exit."; constexpr const char * const TAG = "SETUPDISPLAY"; } // setupdisplay @@ -35,7 +30,7 @@ using CloudURLChangeScreen = espgui::makeComponent< CloudURLAccessor, espgui::ConfirmActionInterface, espgui::BackActionInterface ->; +>; // cloud setup using CloudKeyChangeScreen = espgui::makeComponent< BobbyChangeValueDisplay, @@ -43,7 +38,7 @@ using CloudKeyChangeScreen = espgui::makeComponent< CloudKeyAccessor, espgui::ConfirmActionInterface, espgui::BackActionInterface ->; +>; // cloud setup void SetupDisplay::start() { diff --git a/main/displays/setupdisplay.h b/main/displays/setupdisplay.h index c8de1f8..d955dd6 100644 --- a/main/displays/setupdisplay.h +++ b/main/displays/setupdisplay.h @@ -17,27 +17,7 @@ #include "modeinterface.h" #include "modes/ignoreinputmode.h" -#define SetupStepValues(x) \ - x(INFORMATION) \ - x(BASIC_BUTTONS) \ - x(CALIBRATE_POTIS) \ - x(ASK_SETUP_CLOUDS) \ - x(SETUP_CLOUD) \ - x(ASK_CALIBRATE_OTHER_BUTTONS) /*add pushScreen after switchScreen*/ \ - x(FINAL_INFORMATION) - -DECLARE_BOBBYTYPESAFE_ENUM(SetupStep, : uint8_t, SetupStepValues); - namespace setupdisplay { -enum CurrentButton : int8_t -{ - UP, - DOWN, - LEFT, - RIGHT, - FINISHED -}; - enum CurrentCloudSelect : uint8_t { CLOUD_ENABLE, @@ -45,10 +25,10 @@ enum CurrentCloudSelect : uint8_t CLOUD_KEY, DONE, _LAST, -}; +}; // cloud setup namespace { -constexpr char const TEXT_CLOUDURL[] = "Cloud URL"; -constexpr char const TEXT_CLOUDKEY[] = "Cloud Key"; +constexpr char const TEXT_CLOUDURL[] = "Cloud URL"; // cloud setup +constexpr char const TEXT_CLOUDKEY[] = "Cloud Key"; // cloud setup } // namespace } @@ -94,7 +74,6 @@ private: IgnoreInputMode m_mode{0, bobbycar::protocol::ControlType::FieldOrientedControl, bobbycar::protocol::ControlMode::Torque}; std::optional m_lastButton; - setupdisplay::CurrentButton m_button_cal_status; uint8_t m_leftButton, m_rightButton, m_upButton, m_downButton; bool m_button_cal_finished; @@ -108,18 +87,3 @@ private: setupdisplay::CurrentCloudSelect m_cloud_selected_item{setupdisplay::CLOUD_ENABLE}; }; -class PushSetupDisplayAction : public virtual espgui::ActionInterface { -public: - explicit PushSetupDisplayAction(SetupStep setupStep, bool early_return = false) : - m_setupStep{setupStep}, - m_early_return{early_return} - {} - - void triggered() override - { - espgui::pushScreen(m_setupStep, m_early_return); - } -private: - const SetupStep m_setupStep; - const bool m_early_return; -}; diff --git a/main/main.cpp b/main/main.cpp index b030581..cbc307f 100644 --- a/main/main.cpp +++ b/main/main.cpp @@ -31,11 +31,12 @@ using namespace std::chrono_literals; #else #include "modes/defaultmode.h" #endif -#include "displays/buttoncalibratedisplay.h" #include "displays/lockscreen.h" #include "displays/menus/recoverymenu.h" #include "displays/potiscalibratedisplay.h" -#include "displays/setupdisplay.h" +#include "displays/setup/information.h" +#include "displays/setup/basic_buttons.h" +#include "displays/setup/calibrate_potis.h" #include "displays/statusdisplay.h" #include "newsettings.h" #include "taskmanager.h" @@ -133,7 +134,19 @@ extern "C" void app_main() if (const auto result = checkIfInCalibration(); result) { - espgui::switchScreen(*result); + switch(*result) + { + case SetupStep::INFORMATION: + espgui::switchScreen(); + break; + case SetupStep::BASIC_BUTTONS: + espgui::switchScreen(true); + break; + /*case SetupStep::CALIBRATE_POTIS: + espgui::switchScreen(true); + break;*/ + default:; + } } else if (configs.lockscreen.keepLockedAfterReboot.value() && configs.lockscreen.locked.value()) { diff --git a/main/setup.cpp b/main/setup.cpp new file mode 100644 index 0000000..d00c52e --- /dev/null +++ b/main/setup.cpp @@ -0,0 +1,39 @@ +#include "setup.h" + +// local includes +#include "globals.h" + +namespace setup { +bool currently_locked; +ModeInterface* oldMode; +IgnoreInputMode setup_mode{0, bobbycar::protocol::ControlType::FieldOrientedControl, bobbycar::protocol::ControlMode::Torque}; + +void lock() +{ + if (currently_locked) + return; + + oldMode = currentMode; + currentMode = &setup_mode; +} + +void unlock() +{ + if (!currently_locked) + return; + + if (currentMode == &setup_mode) + { + // to avoid crash after deconstruction + setup_mode.stop(); + lastMode = nullptr; + + currentMode = oldMode; + } +} + +bool isLocked() +{ + return currently_locked; +} +} // namespace setup diff --git a/main/setup.h b/main/setup.h new file mode 100644 index 0000000..0e074ad --- /dev/null +++ b/main/setup.h @@ -0,0 +1,23 @@ +#pragma once + +// local includes +#include "bobbytypesafeenum.h" +#include "modeinterface.h" +#include "modes/ignoreinputmode.h" + +#define SetupStepValues(x) \ + x(INFORMATION) \ + x(BASIC_BUTTONS) \ + x(CALIBRATE_POTIS) + +DECLARE_BOBBYTYPESAFE_ENUM(SetupStep, : uint8_t, SetupStepValues); + +namespace setup { +extern bool currently_locked; +extern ModeInterface* oldMode; +extern IgnoreInputMode setup_mode; + +void lock(); +void unlock(); +bool isLocked(); +} // namespace setup diff --git a/main/utils.cpp b/main/utils.cpp index efe72c0..5ed372f 100644 --- a/main/utils.cpp +++ b/main/utils.cpp @@ -3,6 +3,9 @@ // system includes #include +// 3rdparty lib includes +#include + // local includes #include "globals.h" #include "newsettings.h" @@ -394,13 +397,44 @@ std::optional checkIfInCalibration() configs.dpadMappingDown.value() == INPUT_MAPPING_NONE ) { - // espgui::switchScreen(true); return SetupStep::BASIC_BUTTONS; } else if (!gas || !brems || *gas > 200.f || *brems > 200.f) { - // espgui::switchScreen(true); return SetupStep::CALIBRATE_POTIS; } return std::nullopt; } + +void drawLargeText(const std::string&& text) +{ + using namespace espgui; + + const auto topMargin = 50; + const uint8_t leftMargin = 8; + const auto rightMargin = leftMargin; + const auto bottomMargin = leftMargin; + + int x = leftMargin + 5; + int y = topMargin + 5; + + tft.setTextColor(TFT_WHITE); + + for (char c : text) + { + if (c == '\n' || x > tft.width() - rightMargin - 10) + { + x = leftMargin + 5; + y += tft.fontHeight(2); + } + + if (c != '\n') + { + const auto addedWidth = tft.drawChar(tft.decodeUTF8(c), x, y, 2); + x += addedWidth; + } + + if (y >= tft.height() - bottomMargin) + break; + } +} diff --git a/main/utils.h b/main/utils.h index 437b217..51e5d43 100644 --- a/main/utils.h +++ b/main/utils.h @@ -46,7 +46,7 @@ #ifdef DPAD_BOARDCOMPUTER_V2 #include "dpad_boardcomputer_v2.h" #endif -#include "displays/setupdisplay.h" +#include "setup.h" extern bool currentlyReverseBeeping; extern bool reverseBeepToggle; @@ -103,6 +103,7 @@ bool is_valid_timestamp(espchrono::utc_clock::time_point timestamp); std::string toString(esp_chip_model_t esp_chip_model); std::optional checkIfInCalibration(); +void drawLargeText(const std::string&& text); namespace bobbydpad { #ifdef FEATURE_DPAD