Refactor into multiple files

This commit is contained in:
CommanderRedYT
2022-10-13 22:00:16 +02:00
parent f2350c8746
commit a93f34e0ba
27 changed files with 932 additions and 338 deletions

View File

@ -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

View File

@ -0,0 +1,26 @@
#include "setupactions.h"
// 3rdparty lib includes
#include <screenmanager.h>
// 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<SetupBasicButtonsDisplay>(m_early_return);
}
PushPotiCalibrateDisplayAction::PushPotiCalibrateDisplayAction(const bool early_return) :
m_early_return{early_return}
{}
void PushPotiCalibrateDisplayAction::triggered()
{
// espgui::pushScreen<SetupCalibratePotisDisplay>(m_early_return); // commented out until implemented
}

View File

@ -0,0 +1,24 @@
#pragma once
// 3rdparty lib includes
#include <actioninterface.h>
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;
};

View File

@ -1,223 +0,0 @@
#include "buttoncalibratedisplay.h"
// esp-idf includes
#include <esp_log.h>
// 3rdparty lib includes
#include <tftinstance.h>
#include <fmt/core.h>
#include <screenmanager.h>
// 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<StatusDisplay>();
}
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);
}
*/

View File

@ -1,55 +0,0 @@
#pragma once
// 3rdparty lib includes
#include <displaywithtitle.h>
#include <widgets/label.h>
// 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<uint8_t> 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;
};
*/

View File

@ -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<makeComponent<MenuItem, StaticText<TEXT_LOCKSCREENSETTINGS>, PushScreenAction<LockscreenSettingsMenu>, StaticMenuItemIcon<&bobbyicons::lock>>>();
constructMenuItem<makeComponentArgs<MenuItem, PushSetupDisplayAction, StaticText<TEXT_BUTTONCALIBRATE>>>(SetupStep::BASIC_BUTTONS, true);
constructMenuItem<makeComponentArgs<MenuItem, PushButtonCalibrateDisplayAction, StaticText<TEXT_BUTTONCALIBRATE>>>(true);
constructMenuItem<makeComponent<MenuItem, StaticText<TEXT_EXTRABUTTONCALIBRATE>, PushScreenAction<ExtraButtonCalibrateMenu>>>();
constructMenuItem<makeComponent<MenuItem, StaticText<TEXT_QUICKACTIONS>, PushScreenAction<SetupQuickActionsMenu>>>();
constructMenuItem<makeComponent<MenuItem, GasText, DisabledColor, StaticFont<2>, DummyAction>>();
constructMenuItem<makeComponent<MenuItem, BremsText, DisabledColor, StaticFont<2>, DummyAction>>();
constructMenuItem<makeComponentArgs<MenuItem, PushSetupDisplayAction, StaticText<TEXT_POTISCALIBRATE>>>(SetupStep::CALIBRATE_POTIS, true);
constructMenuItem<makeComponentArgs<MenuItem, PushPotiCalibrateDisplayAction, StaticText<TEXT_POTISCALIBRATE>>>(true);
#ifdef FEATURE_JOYSTICK
constructMenuItem<makeComponent<MenuItem, StaticText<TEXT_JOYSTICK>, PushScreenAction<JoystickDebugDisplay>>>();
#endif

View File

@ -0,0 +1,56 @@
#include "ask_calibrate_other_buttons.h"
// 3rdparty lib includes
#include <screenmanager.h>
// 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<SetupFinalInformationDisplay>();
return;
}
Base::start();
setup::lock();
}
void SetupAskCalibrateOtherButtonsDisplay::buttonPressed(espgui::Button button)
{
switch (button)
{
case espgui::Left:
espgui::switchScreen<SetupFinalInformationDisplay>();
return;
case espgui::Right:
m_next_screen = true;
espgui::pushScreen<ExtraButtonCalibrateMenu>();
return;
default:;
}
Base::buttonPressed(button);
}
std::string SetupAskCalibrateOtherButtonsDisplay::text() const
{
return "Other Buttons";
}

View File

@ -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};
};

View File

@ -0,0 +1,53 @@
#include "ask_setup_clouds.h"
// 3rdparty lib includes
#include <screenmanager.h>
// 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<SetupAskCalibrateOtherButtonsDisplay>();
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<SetupCloudDisplay>();
default:;
}
Base::buttonPressed(button);
}
std::string SetupAskSetupCloudsDisplay::text() const
{
return "Cloud Setup";
}

View File

@ -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;
};

View File

@ -0,0 +1,231 @@
#include "basic_buttons.h"
// system includes
#include <esp_log.h>
// 3rdparty lib includes
#include <screenmanager.h>
#include <tftinstance.h>
// 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<SetupAskSetupCloudsDisplay>();
}
}
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);
}
}

View File

@ -0,0 +1,51 @@
#pragma once
// system includes
#include <optional>
// 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<uint8_t> 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);
};

View File

@ -0,0 +1 @@
#include "calibrate_potis.h"

View File

@ -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;
};

View File

@ -0,0 +1,58 @@
#include "final_information.h"
// 3rdparty lib includes
#include <screenmanager.h>
// 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<StatusDisplay>();
}
else
{
espgui::popScreen();
}
Base::buttonPressed(button);
}
std::string SetupFinalInformationDisplay::text() const
{
return "All done!";
}

View File

@ -0,0 +1,20 @@
#pragma once
// 3rdparty lib includes
#include <espchrono.h>
// 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;
};

View File

@ -0,0 +1,59 @@
#include "information.h"
// 3rdparty lib includes
#include <screenmanager.h>
// 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<SetupBasicButtonsDisplay>();
}
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<SetupBasicButtonsDisplay>();
}
}
[[nodiscard]] std::string SetupInformationDisplay::text() const
{
return "First Steps";
}

View File

@ -0,0 +1,25 @@
#pragma once
// 3rdparty lib includes
#include <espchrono.h>
#include <tftinstance.h>
#include <widgets/progressbar.h>
// 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};
};

View File

@ -0,0 +1,103 @@
#include "setup_cloud.h"
// 3rdparty lib includes
#include <actions/popscreenaction.h>
#include <actions/pushscreenaction.h>
#include <changevaluedisplay_string.h>
// 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<std::string>,
espgui::StaticText<TEXT_CLOUD_USERNAME>,
UsernameAccessor,
espgui::ConfirmActionInterface<espgui::PopScreenAction>,
espgui::BackActionInterface<espgui::PopScreenAction>
>;
using CloudURLChangeScreen = espgui::makeComponent<
BobbyChangeValueDisplay<std::string>,
espgui::StaticText<TEXT_CLOUD_URL>,
CloudURLAccessor,
espgui::ConfirmActionInterface<espgui::PopScreenAction>,
espgui::BackActionInterface<espgui::PopScreenAction>
>;
using CloudKeyChangeScreen = espgui::makeComponent<
BobbyChangeValueDisplay<std::string>,
espgui::StaticText<TEXT_CLOUD_KEY>,
CloudKeyAccessor,
espgui::ConfirmActionInterface<espgui::PopScreenAction>,
espgui::BackActionInterface<espgui::PopScreenAction>
>; // cloud setup
template<bool early_return>
class CloudSetupFinishedAction : public virtual ActionInterface
{
public:
void triggered() override
{
if (early_return)
{
espgui::popScreen();
}
else
{
espgui::switchScreen<SetupAskCalibrateOtherButtonsDisplay>();
}
}
};
} // namespace
SetupCloudDisplay::SetupCloudDisplay(const bool early_return) : m_early_return{early_return}
{
constructMenuItem<makeComponent<MenuItem, StaticText<TEXT_ENABLE_CLOUD>, BobbyCheckbox, CloudEnabledAccessor>>();
constructMenuItem<makeComponent<MenuItem, StaticText<TEXT_CLOUD_USERNAME>, PushScreenAction<CloudUsernameChangeScreen>>>();
constructMenuItem<makeComponent<MenuItem, StaticText<TEXT_CLOUD_URL>, PushScreenAction<CloudURLChangeScreen>>>();
constructMenuItem<makeComponent<MenuItem, StaticText<TEXT_CLOUD_KEY>, PushScreenAction<CloudKeyChangeScreen>>>();
if (early_return)
constructMenuItem<makeComponent<MenuItem, StaticText<TEXT_DONE>, CloudSetupFinishedAction<true>>>();
else
constructMenuItem<makeComponent<MenuItem, StaticText<TEXT_DONE>, CloudSetupFinishedAction<false>>>();
}
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";
}

View File

@ -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;
};

View File

@ -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::PopScreenAction>,
espgui::BackActionInterface<espgui::PopScreenAction>
>;
>; // cloud setup
using CloudKeyChangeScreen = espgui::makeComponent<
BobbyChangeValueDisplay<std::string>,
@ -43,7 +38,7 @@ using CloudKeyChangeScreen = espgui::makeComponent<
CloudKeyAccessor,
espgui::ConfirmActionInterface<espgui::PopScreenAction>,
espgui::BackActionInterface<espgui::PopScreenAction>
>;
>; // cloud setup
void SetupDisplay::start()
{

View File

@ -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<Name> after switchScreen<StatusDisplay>*/ \
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<uint8_t> 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<SetupDisplay>(m_setupStep, m_early_return);
}
private:
const SetupStep m_setupStep;
const bool m_early_return;
};

View File

@ -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<SetupDisplay>(*result);
switch(*result)
{
case SetupStep::INFORMATION:
espgui::switchScreen<SetupInformationDisplay>();
break;
case SetupStep::BASIC_BUTTONS:
espgui::switchScreen<SetupBasicButtonsDisplay>(true);
break;
/*case SetupStep::CALIBRATE_POTIS:
espgui::switchScreen<SetupCalibratePotisDisplay>(true);
break;*/
default:;
}
}
else if (configs.lockscreen.keepLockedAfterReboot.value() && configs.lockscreen.locked.value())
{

39
main/setup.cpp Normal file
View File

@ -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

23
main/setup.h Normal file
View File

@ -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

View File

@ -3,6 +3,9 @@
// system includes
#include <utility>
// 3rdparty lib includes
#include <tftinstance.h>
// local includes
#include "globals.h"
#include "newsettings.h"
@ -394,13 +397,44 @@ std::optional<SetupStep> checkIfInCalibration()
configs.dpadMappingDown.value() == INPUT_MAPPING_NONE
)
{
// espgui::switchScreen<ButtonCalibrateDisplay>(true);
return SetupStep::BASIC_BUTTONS;
}
else if (!gas || !brems || *gas > 200.f || *brems > 200.f)
{
// espgui::switchScreen<PotisCalibrateDisplay>(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;
}
}

View File

@ -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<SetupStep> checkIfInCalibration();
void drawLargeText(const std::string&& text);
namespace bobbydpad {
#ifdef FEATURE_DPAD