diff --git a/main/CMakeLists.txt b/main/CMakeLists.txt index 76816d4..c4a5a07 100644 --- a/main/CMakeLists.txt +++ b/main/CMakeLists.txt @@ -159,8 +159,7 @@ set(BOBBY_HEADERS displays/qrcodedebug.h displays/qrdisplay.h displays/qrimportdisplay.h - displays/setup/bobbycloudconfig.h - displays/setup/screenorientation.h + displays/setupdisplay.h displays/speedinfodisplay.h displays/spirodisplay.h displays/starfielddisplay.h @@ -412,8 +411,7 @@ set(BOBBY_SOURCES displays/qrcodedebug.cpp displays/qrdisplay.cpp displays/qrimportdisplay.cpp - displays/setup/bobbycloudconfig.cpp - displays/setup/screenorientation.cpp + displays/setupdisplay.cpp displays/speedinfodisplay.cpp displays/spirodisplay.cpp displays/starfielddisplay.cpp diff --git a/main/displays/buttoncalibratedisplay.cpp b/main/displays/buttoncalibratedisplay.cpp index eb8300d..d1c4d3a 100644 --- a/main/displays/buttoncalibratedisplay.cpp +++ b/main/displays/buttoncalibratedisplay.cpp @@ -17,6 +17,7 @@ namespace { constexpr const char TAG[] = "BUTTON"; } // namespace + std::string ButtonCalibrateDisplay::text() const { return "Button calibrate"; @@ -219,3 +220,4 @@ void ButtonCalibrateDisplay::buttonReleased(espgui::Button button) { //Base::buttonReleased(button); } + diff --git a/main/displays/buttoncalibratedisplay.h b/main/displays/buttoncalibratedisplay.h index 135eac0..9aee10f 100644 --- a/main/displays/buttoncalibratedisplay.h +++ b/main/displays/buttoncalibratedisplay.h @@ -9,6 +9,7 @@ #include "modeinterface.h" #include "modes/ignoreinputmode.h" + class ButtonCalibrateDisplay : public espgui::DisplayWithTitle { using Base = espgui::DisplayWithTitle; @@ -51,3 +52,4 @@ private: bool m_finished; }; + diff --git a/main/displays/menus/boardcomputerhardwaresettingsmenu.cpp b/main/displays/menus/boardcomputerhardwaresettingsmenu.cpp index 5474529..bb5c871 100644 --- a/main/displays/menus/boardcomputerhardwaresettingsmenu.cpp +++ b/main/displays/menus/boardcomputerhardwaresettingsmenu.cpp @@ -192,12 +192,12 @@ using namespace espgui; BoardcomputerHardwareSettingsMenu::BoardcomputerHardwareSettingsMenu() { constructMenuItem, PushScreenAction, StaticMenuItemIcon<&bobbyicons::lock>>>(); - constructMenuItem, PushScreenAction>>(); + // constructMenuItem, PushScreenAction>>(); constructMenuItem, PushScreenAction>>(); constructMenuItem, PushScreenAction>>(); constructMenuItem, DummyAction>>(); constructMenuItem, DummyAction>>(); - constructMenuItem, PushScreenAction>>(); + // constructMenuItem, PushScreenAction>>(); #ifdef FEATURE_JOYSTICK constructMenuItem, PushScreenAction>>(); #endif diff --git a/main/displays/potiscalibratedisplay.cpp b/main/displays/potiscalibratedisplay.cpp index 06ff592..43e32c8 100644 --- a/main/displays/potiscalibratedisplay.cpp +++ b/main/displays/potiscalibratedisplay.cpp @@ -16,6 +16,7 @@ namespace { constexpr char TEXT_CALIBRATE[] = "Potis Calibrate"; } // namespace + std::string PotisCalibrateDisplay::text() const { return TEXT_CALIBRATE; diff --git a/main/displays/potiscalibratedisplay.h b/main/displays/potiscalibratedisplay.h index 5b4044f..fd56f84 100644 --- a/main/displays/potiscalibratedisplay.h +++ b/main/displays/potiscalibratedisplay.h @@ -16,6 +16,7 @@ #include "modeinterface.h" #include "modes/ignoreinputmode.h" + class PotisCalibrateDisplay : public BobbyDisplayWithTitle { using Base = BobbyDisplayWithTitle; diff --git a/main/displays/setup/bobbycloudconfig.cpp b/main/displays/setup/bobbycloudconfig.cpp deleted file mode 100644 index 9847e44..0000000 --- a/main/displays/setup/bobbycloudconfig.cpp +++ /dev/null @@ -1 +0,0 @@ -#include "bobbycloudconfig.h" diff --git a/main/displays/setup/bobbycloudconfig.h b/main/displays/setup/bobbycloudconfig.h deleted file mode 100644 index 6f70f09..0000000 --- a/main/displays/setup/bobbycloudconfig.h +++ /dev/null @@ -1 +0,0 @@ -#pragma once diff --git a/main/displays/setup/screenorientation.cpp b/main/displays/setup/screenorientation.cpp deleted file mode 100644 index 5e79da8..0000000 --- a/main/displays/setup/screenorientation.cpp +++ /dev/null @@ -1 +0,0 @@ -#include "screenorientation.h" diff --git a/main/displays/setup/screenorientation.h b/main/displays/setup/screenorientation.h deleted file mode 100644 index 6f70f09..0000000 --- a/main/displays/setup/screenorientation.h +++ /dev/null @@ -1 +0,0 @@ -#pragma once diff --git a/main/displays/setupdisplay.cpp b/main/displays/setupdisplay.cpp new file mode 100644 index 0000000..7e0712d --- /dev/null +++ b/main/displays/setupdisplay.cpp @@ -0,0 +1,170 @@ +#include "setupdisplay.h" + +// system includes +#include + +// 3rdparty lib includes +#include + +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!"; +} // setupdisplay + +void SetupDisplay::start() +{ + Base::start(); + m_menu_opened_timestamp = espchrono::millis_clock::now(); +} + +void SetupDisplay::initScreen() +{ + Base::initScreen(); +} + +void SetupDisplay::update() +{ + Base::update(); +} + +void SetupDisplay::redraw() +{ + Base::redraw(); + + if (m_current_setupStep != m_last_setupStep || initialRender) + { + initialRender = false; + m_last_setupStep = m_current_setupStep; + + switch(m_current_setupStep) + { + case SetupStep::INFORMATION: + drawLargeText(setupdisplay::InformationText); + break; + case SetupStep::BASIC_BUTTONS: + clearLargeText(); + break; + case SetupStep::CALIBRATE_POTIS: + break; + case SetupStep::ASK_SETUP_CLOUDS: + break; + case SetupStep::SETUP_CLOUD: + break; + case SetupStep::SETUP_UDPCLOUD: + break; + case SetupStep::ASK_CALIBRATE_OTHER_BUTTONS: + break; + case SetupStep::FINAL_INFORMATION: + break; + } + } + + if (m_current_setupStep == SetupStep::INFORMATION && espchrono::ago(m_menu_opened_timestamp) > 5s) + { + nextStep(); + } +} + +void SetupDisplay::stop() +{ + Base::stop(); +} + +void SetupDisplay::buttonPressed(espgui::Button button) +{ + Base::buttonPressed(button); +} + +std::string SetupDisplay::text() const +{ + switch (m_current_setupStep) + { + case SetupStep::INFORMATION: + return "First Steps"; + case SetupStep::BASIC_BUTTONS: + return "Calibrate Buttons"; + case SetupStep::CALIBRATE_POTIS: + return "Calibrate Potis"; + case SetupStep::ASK_SETUP_CLOUDS: + return "Cloud Setup"; + case SetupStep::SETUP_CLOUD: + return "WebSocket Cloud"; + case SetupStep::SETUP_UDPCLOUD: + return "UDP Cloud"; + case SetupStep::ASK_CALIBRATE_OTHER_BUTTONS: + return "Other Buttons"; + case SetupStep::FINAL_INFORMATION: + return "All done!"; + } + return {}; +} + +void SetupDisplay::drawLargeText(const std::string&& text) +{ + 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; + } +} + +void SetupDisplay::nextStep() +{ + ESP_LOGI("SetupDisplay", "nextStep (%s)", toString(m_current_setupStep).c_str()); + switch(m_current_setupStep) + { + case SetupStep::INFORMATION: + m_current_setupStep = SetupStep::BASIC_BUTTONS; + break; + case SetupStep::BASIC_BUTTONS: + m_current_setupStep = SetupStep::CALIBRATE_POTIS; + break; + case SetupStep::CALIBRATE_POTIS: + m_current_setupStep = SetupStep::ASK_SETUP_CLOUDS; + break; + case SetupStep::ASK_SETUP_CLOUDS: + m_current_setupStep = SetupStep::SETUP_CLOUD; + break; + case SetupStep::SETUP_CLOUD: + m_current_setupStep = SetupStep::SETUP_UDPCLOUD; + break; + case SetupStep::SETUP_UDPCLOUD: + m_current_setupStep = SetupStep::ASK_CALIBRATE_OTHER_BUTTONS; + break; + case SetupStep::ASK_CALIBRATE_OTHER_BUTTONS: + m_current_setupStep = SetupStep::FINAL_INFORMATION; + break; + case SetupStep::FINAL_INFORMATION: + break; + } + ESP_LOGI("SetupDisplay", "nextStep after (%s)", toString(m_current_setupStep).c_str()); +} + +void SetupDisplay::clearLargeText() +{ + tft.fillRect(0, 50, tft.width(), tft.height()-50, TFT_BLACK); +} diff --git a/main/displays/setupdisplay.h b/main/displays/setupdisplay.h new file mode 100644 index 0000000..2b60e03 --- /dev/null +++ b/main/displays/setupdisplay.h @@ -0,0 +1,52 @@ +#pragma once + +// system includes +#include + +// 3rdparty lib includes +#include + +// local includes +#include "bobbydisplaywithtitle.h" +#include "bobbytypesafeenum.h" + +#define SetupStepValues(x) \ + x(INFORMATION) \ + x(BASIC_BUTTONS) \ + x(CALIBRATE_POTIS) \ + x(ASK_SETUP_CLOUDS) \ + x(SETUP_CLOUD) \ + x(SETUP_UDPCLOUD) \ + x(ASK_CALIBRATE_OTHER_BUTTONS) /*add pushScreen after switchScreen*/ \ + x(FINAL_INFORMATION) + +DECLARE_BOBBYTYPESAFE_ENUM(SetupStep, : uint8_t, SetupStepValues); + +class SetupDisplay : public BobbyDisplayWithTitle +{ + using Base = BobbyDisplayWithTitle; +public: + explicit SetupDisplay(SetupStep initialStep = SetupStep::INFORMATION) : + m_current_setupStep{initialStep}, + m_last_setupStep{initialStep} + {} + + void start() override; + void initScreen() override; + void redraw() override; + void update() override; + void stop() override; + + void buttonPressed(espgui::Button button) override; + + std::string text() const override; +private: + SetupStep m_current_setupStep; + SetupStep m_last_setupStep; + espchrono::millis_clock::time_point m_menu_opened_timestamp; + bool initialRender{true}; + + static void drawLargeText(const std::string&& text); + static void clearLargeText(); + void nextStep(); +}; diff --git a/main/main.cpp b/main/main.cpp index ed1272a..b030581 100644 --- a/main/main.cpp +++ b/main/main.cpp @@ -35,6 +35,7 @@ using namespace std::chrono_literals; #include "displays/lockscreen.h" #include "displays/menus/recoverymenu.h" #include "displays/potiscalibratedisplay.h" +#include "displays/setupdisplay.h" #include "displays/statusdisplay.h" #include "newsettings.h" #include "taskmanager.h" @@ -130,12 +131,9 @@ extern "C" void app_main() bootLabel.redraw("switchScreen"); - if (configs.dpadMappingLeft.value() == INPUT_MAPPING_NONE || - configs.dpadMappingRight.value() == INPUT_MAPPING_NONE || - configs.dpadMappingUp.value() == INPUT_MAPPING_NONE || - configs.dpadMappingDown.value() == INPUT_MAPPING_NONE) + if (const auto result = checkIfInCalibration(); result) { - espgui::switchScreen(true); + espgui::switchScreen(*result); } else if (configs.lockscreen.keepLockedAfterReboot.value() && configs.lockscreen.locked.value()) { @@ -144,12 +142,7 @@ extern "C" void app_main() } else { - if (!gas || !brems || *gas > 200.f || *brems > 200.f) - espgui::switchScreen(true); - else - { - espgui::switchScreen(); - } + espgui::switchScreen(); } esp_chip_info(&chip_info); diff --git a/main/newsettings.h b/main/newsettings.h index 57cfb6d..cb5f37e 100644 --- a/main/newsettings.h +++ b/main/newsettings.h @@ -364,7 +364,8 @@ public: ConfigWrapperLegacy cloudSendRate {1, DoReset, {}, "cloudSendRate" }; ConfigWrapperLegacy udpSendRateMs {65, DoReset, {}, "udpSendRate" }; } timersSettings; - ConfigWrapperLegacy flipScreen {false, NoReset, {}, "flipScreen" }; + ConfigWrapperLegacy flipScreen {false, NoReset, {}, "flipScreen" }; + ConfigWrapperLegacy setupFinished {false, DoReset, {}, "setupFinished" }; } boardcomputerHardware; struct { @@ -712,9 +713,10 @@ public: x(boardcomputerHardware.timersSettings.statsUpdateRate) \ x(boardcomputerHardware.timersSettings.cloudCollectRate) \ x(boardcomputerHardware.timersSettings.cloudSendRate) \ - x(boardcomputerHardware.timersSettings.udpSendRateMs) \ + x(boardcomputerHardware.timersSettings.udpSendRateMs) \ \ x(boardcomputerHardware.flipScreen) \ + x(boardcomputerHardware.setupFinished) \ \ x(cloudSettings.cloudEnabled) \ x(cloudSettings.cloudTransmitTimeout) \ diff --git a/main/udpcloud.cpp b/main/udpcloud.cpp index 76fce7d..f31f6d6 100644 --- a/main/udpcloud.cpp +++ b/main/udpcloud.cpp @@ -240,7 +240,7 @@ void sendUdpCloudPacket() timestampLastFailed = espchrono::millis_clock::now(); ESP_LOGE(TAG, "send to cloud failed: %.*s (ip=%s)", result.error().size(), result.error().data(), wifi_stack::toString(udpCloudIp.u_addr.ip4).c_str()); } - + visualSendUdpPacket = !visualSendUdpPacket; } } diff --git a/main/utils.cpp b/main/utils.cpp index 6bd27d7..efe72c0 100644 --- a/main/utils.cpp +++ b/main/utils.cpp @@ -380,3 +380,27 @@ std::string toString(esp_chip_model_t esp_chip_model) return "invalid"; } } + +std::optional checkIfInCalibration() +{ + if (!configs.boardcomputerHardware.setupFinished.value()) + { + return SetupStep::INFORMATION; + } + else if ( + configs.dpadMappingLeft.value() == INPUT_MAPPING_NONE || + configs.dpadMappingRight.value() == INPUT_MAPPING_NONE || + configs.dpadMappingUp.value() == INPUT_MAPPING_NONE || + 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; +} diff --git a/main/utils.h b/main/utils.h index 8139a96..437b217 100644 --- a/main/utils.h +++ b/main/utils.h @@ -46,6 +46,7 @@ #ifdef DPAD_BOARDCOMPUTER_V2 #include "dpad_boardcomputer_v2.h" #endif +#include "displays/setupdisplay.h" extern bool currentlyReverseBeeping; extern bool reverseBeepToggle; @@ -101,6 +102,7 @@ float float_map(float x, float in_min, float in_max, float out_min, float out_ma bool is_valid_timestamp(espchrono::utc_clock::time_point timestamp); std::string toString(esp_chip_model_t esp_chip_model); +std::optional checkIfInCalibration(); namespace bobbydpad { #ifdef FEATURE_DPAD