diff --git a/platformio.ini b/platformio.ini index c960fea..a4ac334 100644 --- a/platformio.ini +++ b/platformio.ini @@ -16,6 +16,7 @@ framework = arduino lib_deps = TFT_eSPI https://github.com/Ferdi265/cxx-ring-buffer + https://github.com/TartanLlama/optional lib_compat_mode = strict build_unflags = @@ -42,6 +43,13 @@ build_flags = -DDEFAULT_FIELDWEAKMAX=5 -DDEFAULT_FIELDADVMAX=40 +[default_wheels_inverted] +build_flags = +-DDEFAULT_INVERTFRONTLEFT=false +-DDEFAULT_INVERTFRONTRIGHT=true +-DDEFAULT_INVERTBACKLEFT=false +-DDEFAULT_INVERTBACKRIGHT=true + [peters_platine_common] build_flags = -DILI9341_DRIVER=1 @@ -107,6 +115,10 @@ build_flags = -DPINS_TX1=5 -DPINS_RX2=22 -DPINS_TX2=23 + -DDEFAULT_INVERTFRONTLEFT=false + -DDEFAULT_INVERTFRONTRIGHT=true + -DDEFAULT_INVERTBACKLEFT=true + -DDEFAULT_INVERTBACKRIGHT=false ; -DFEATURE_MOSFETS ; -DPINS_MOSFET0=18 ; -DPINS_MOSFET1=19 @@ -116,10 +128,21 @@ build_flags = -DDEVICE_PREFIX=bobbyquad -DAP_PASSWORD=Passwort_123 -DFEATURE_WEBSERVER -; -DFEATURE_DPAD_3WIRESW -; -DPINS_DPAD_3WIRESW_OUT=0 -; -DPINS_DPAD_3WIRESW_IN1=16 -; -DPINS_DPAD_3WIRESW_IN2=27 + -DFEATURE_DPAD_5WIRESW + -DPINS_DPAD_5WIRESW_OUT=32 + -DPINS_DPAD_5WIRESW_IN1=25 + -DPINS_DPAD_5WIRESW_IN2=26 + -DPINS_DPAD_5WIRESW_IN3=27 + -DPINS_DPAD_5WIRESW_IN4=21 + -DDPAD_5WIRESW_UP=4 + -DDPAD_5WIRESW_DOWN=3 + -DDPAD_5WIRESW_CONFIRM=7 + -DDPAD_5WIRESW_BACK=0 + -DDPAD_5WIRESW_PROFILE0=1 + -DDPAD_5WIRESW_PROFILE1=5 + -DDPAD_5WIRESW_PROFILE2=2 + -DDPAD_5WIRESW_PROFILE3=6 +; -DDPAD_5WIRESW_DEBUG -DDEFAULT_GASMIN=850 -DDEFAULT_GASMAX=3700 -DDEFAULT_BREMSMIN=1300 @@ -177,6 +200,7 @@ build_flags = ${peters_platine.build_flags} ${ota_common.build_flags} ${default_limits.build_flags} + ${default_wheels_inverted.build_flags} -DDEVICE_PREFIX=bobbycar -DAP_PASSWORD=Passwort_123 -DFEATURE_WEBSERVER @@ -235,6 +259,7 @@ build_flags = ${peters_platine.build_flags} ${ota_common.build_flags} ${default_limits.build_flags} + ${default_wheels_inverted.build_flags} -DDEVICE_PREFIX=bobbyquad -DAP_PASSWORD=Passwort_123 -DFEATURE_WEBSERVER @@ -283,6 +308,7 @@ build_flags = -DSPI_FREQUENCY=20000000 -DSPI_TOUCH_FREQUENCY=2500000 -DDEFAULT_SWAPSCREENBYTES=false + ${default_wheels_inverted.build_flags} ; TODO: actually assign pins -DPINS_RX1=22 -DPINS_TX1=25 @@ -310,6 +336,7 @@ build_flags = ${peters_platine_reversed.build_flags} ${ota_common.build_flags} ${default_limits.build_flags} + ${default_wheels_inverted.build_flags} -DDEVICE_PREFIX=bobbycar -DAP_PASSWORD=Passwort_123 -DFEATURE_WEBSERVER diff --git a/src/actions/erasenvsaction.h b/src/actions/erasenvsaction.h new file mode 100644 index 0000000..aef8a88 --- /dev/null +++ b/src/actions/erasenvsaction.h @@ -0,0 +1,41 @@ +#pragma once + +#include + +#include "actioninterface.h" +#include "globals.h" +#include "presets.h" + +namespace { +class EraseNvsAction : public virtual ActionInterface +{ +public: + void triggered() override + { + const auto profile = settingsPersister.currentlyOpenProfileIndex(); + + if (!settingsPersister.erase()) + { + Serial.println("EraseNvsAction::triggered() erase failed"); + return; + } + + settings = presets::defaultSettings; + + if (!profile) + return; + + if (!settingsPersister.openProfile(*profile)) + { + Serial.println("EraseNvsAction::triggered() openProfile failed"); + return; + } + + if (!settingsPersister.load(settings)) + { + Serial.println("EraseNvsAction::triggered() load failed"); + return; + } + } +}; +} diff --git a/src/actions/switchprofileaction.h b/src/actions/switchprofileaction.h new file mode 100644 index 0000000..797e4c2 --- /dev/null +++ b/src/actions/switchprofileaction.h @@ -0,0 +1,27 @@ +#pragma once + +#include + +#include "actioninterface.h" +#include "globals.h" +#include "presets.h" + +namespace { +template +class SwitchProfileAction : public virtual ActionInterface +{ +public: + void triggered() override + { + settings = presets::defaultSettings; + + if (settingsPersister.openProfile(profile)) + { + if (!settingsPersister.load(settings)) + Serial.println("SwitchProfileAction::triggered() load failed"); + } + else + Serial.println("SwitchProfileAction::triggered() openProfile failed"); + } +}; +} diff --git a/src/displays/dpad5wiredebugdisplay.h b/src/displays/dpad5wiredebugdisplay.h new file mode 100644 index 0000000..bb5905e --- /dev/null +++ b/src/displays/dpad5wiredebugdisplay.h @@ -0,0 +1,54 @@ +#pragma once + +#include "display.h" +#include "globals.h" +#include "widgets/label.h" +#include "dpad5wire.h" + +namespace { +#ifdef FEATURE_DPAD_5WIRESW +class DPad5WireDebugDisplay : public Display, public virtual DummyConfirm, public virtual DummyBack +{ +public: + void initScreen() override; + void redraw() override; + +private: + Label m_label0{30, 100}; + Label m_label1{30, 125}; + Label m_label2{30, 150}; +}; + +void DPad5WireDebugDisplay::initScreen() +{ + tft.fillScreen(TFT_BLACK); + tft.setTextFont(4); + tft.setTextColor(TFT_YELLOW); + + tft.drawString("DPad 5wire debug", 5, 5); + + tft.fillRect(0, 34, tft.width(), 3, TFT_WHITE); + + tft.setTextColor(TFT_WHITE, TFT_BLACK); + + m_label0.start(); + m_label1.start(); + m_label2.start(); +} + +void DPad5WireDebugDisplay::redraw() +{ + m_label0.redraw(String{} + + (std::get<0>(dpad5wire::lastState) ? '1' : '0') + ' ' + + (std::get<1>(dpad5wire::lastState) ? '1' : '0') + ' ' + + (std::get<2>(dpad5wire::lastState) ? '1' : '0') + ' ' + + (std::get<3>(dpad5wire::lastState) ? '1' : '0') + ' ' + + (std::get<4>(dpad5wire::lastState) ? '1' : '0') + ' ' + + (std::get<5>(dpad5wire::lastState) ? '1' : '0') + ' ' + + (std::get<6>(dpad5wire::lastState) ? '1' : '0') + ' ' + + (std::get<7>(dpad5wire::lastState) ? '1' : '0')); + m_label1.redraw(String{raw_gas}); + m_label2.redraw(String{raw_brems}); +} +#endif +} diff --git a/src/displays/menus/boardcomputerhardwaresettingsmenu.h b/src/displays/menus/boardcomputerhardwaresettingsmenu.h index f52394e..26b7d41 100644 --- a/src/displays/menus/boardcomputerhardwaresettingsmenu.h +++ b/src/displays/menus/boardcomputerhardwaresettingsmenu.h @@ -66,7 +66,7 @@ using BremsMaxChangeScreen = makeComponent< SwitchScreenAction >; -#if defined(FEATURE_DPAD) || defined(FEATURE_DPAD_3WIRESW) +#if defined(FEATURE_DPAD) || defined(FEATURE_DPAD_3WIRESW) || defined(FEATURE_DPAD_5WIRESW) using DPadDebounceChangeScreen = makeComponent< ChangeValueDisplay, StaticText, @@ -147,7 +147,7 @@ class BoardcomputerHardwareSettingsMenu : makeComponent, SwitchScreenAction>, makeComponent, SwitchScreenAction>, makeComponent, SwitchScreenAction>, -#if defined(FEATURE_DPAD) || defined(FEATURE_DPAD_3WIRESW) +#if defined(FEATURE_DPAD) || defined(FEATURE_DPAD_3WIRESW) || defined(FEATURE_DPAD_5WIRESW) makeComponent, SwitchScreenAction>, #endif #ifdef FEATURE_GAMETRAK diff --git a/src/displays/menus/debugmenu.h b/src/displays/menus/debugmenu.h index 8f9232c..b869294 100644 --- a/src/displays/menus/debugmenu.h +++ b/src/displays/menus/debugmenu.h @@ -6,6 +6,7 @@ #include "menuitem.h" #include "actions/loadsettingsaction.h" #include "actions/savesettingsaction.h" +#include "actions/erasenvsaction.h" #include "actions/switchscreenaction.h" #include "actions/dummyaction.h" #include "actions/toggleboolaction.h" @@ -40,6 +41,7 @@ class DebugMenu : public StaticMenuDefinition< makeComponent, LoadSettingsAction>, makeComponent, SaveSettingsAction>, + makeComponent, EraseNvsAction>, makeComponent, DummyAction>, makeComponent, SwitchScreenAction>, makeComponent, SwitchScreenAction>, diff --git a/src/displays/menus/mainmenu.h b/src/displays/menus/mainmenu.h index e1374ef..aee6a1f 100644 --- a/src/displays/menus/mainmenu.h +++ b/src/displays/menus/mainmenu.h @@ -21,6 +21,7 @@ namespace { class StatusDisplay; class SelectModeMenu; +class ProfilesMenu; class PresetsMenu; class GraphsMenu; class BmsMenu; @@ -42,6 +43,7 @@ class MainMenu : makeComponent, SwitchScreenAction, StaticMenuItemIcon<&icons::modes>>, makeComponent, ModeSettingsAction>, makeComponent, SwitchScreenAction, StaticMenuItemIcon<&icons::presets>>, + makeComponent, SwitchScreenAction>, makeComponent, SwitchScreenAction, StaticMenuItemIcon<&icons::graph>>, #ifdef FEATURE_BMS makeComponent, SwitchScreenAction, StaticMenuItemIcon<&icons::bms>>, diff --git a/src/displays/menus/presetsmenu.h b/src/displays/menus/presetsmenu.h index 8c28979..aff3b55 100644 --- a/src/displays/menus/presetsmenu.h +++ b/src/displays/menus/presetsmenu.h @@ -4,7 +4,7 @@ #include "menudisplay.h" #include "staticmenudefinition.h" #include "utils.h" -#include "actions/dummyaction.h" +#include "actions/multiaction.h" #include "actions/switchscreenaction.h" #include "icons/back.h" #include "texts.h" @@ -77,17 +77,17 @@ class PresetsMenu : public StaticText, public BackActionInterface>, public StaticMenuDefinition< - makeComponent, ApplySettingsPresetAction<&presets::defaultSettings>>, - makeComponent, ApplyLimitsPresetAction<&presets::defaultLimits>>, - makeComponent, ApplyLimitsPresetAction<&presets::kidsLimits>>, - makeComponent, ApplyControllerHardwarePresetAction<&presets::defaultControllerHardware>>, - makeComponent, ApplyControllerHardwarePresetAction<&presets::mosfetsOffControllerHardware>>, - makeComponent, ApplyControllerHardwarePresetAction<&presets::spinnerControllerHardware>>, - makeComponent, ApplyBoardcomputerHardwarePresetAction<&presets::defaultBoardcomputerHardware>>, - makeComponent, ApplyDefaultModePresetAction<&presets::defaultDefaultMode>>, - makeComponent, ApplyDefaultModePresetAction<&presets::sinusoidalDefaultMode>>, - makeComponent, ApplyTempomatModePresetAction<&presets::defaultTempomatMode>>, - makeComponent, ApplyLarsmModePresetAction<&presets::defaultLarsmMode>>, + makeComponent, MultiAction, SwitchScreenAction>>, + makeComponent, MultiAction, SwitchScreenAction>>, + makeComponent, MultiAction, SwitchScreenAction>>, + makeComponent, MultiAction, SwitchScreenAction>>, + makeComponent, MultiAction, SwitchScreenAction>>, + makeComponent, MultiAction, SwitchScreenAction>>, + makeComponent, MultiAction, SwitchScreenAction>>, + makeComponent, MultiAction, SwitchScreenAction>>, + makeComponent, MultiAction, SwitchScreenAction>>, + makeComponent, MultiAction, SwitchScreenAction>>, + makeComponent, MultiAction, SwitchScreenAction>>, makeComponent, SwitchScreenAction, StaticMenuItemIcon<&icons::back>> > {}; diff --git a/src/displays/menus/profilesmenu.h b/src/displays/menus/profilesmenu.h new file mode 100644 index 0000000..4727234 --- /dev/null +++ b/src/displays/menus/profilesmenu.h @@ -0,0 +1,27 @@ +#pragma once + +#include "menudisplay.h" +#include "staticmenudefinition.h" +#include "actions/switchprofileaction.h" +#include "actions/switchscreenaction.h" +#include "icons/back.h" +#include "texts.h" + +namespace { +class MainMenu; +} + +namespace { +class ProfilesMenu : + public MenuDisplay, + public StaticText, + public BackActionInterface>, + public StaticMenuDefinition< + makeComponent, SwitchProfileAction<0>>, + makeComponent, SwitchProfileAction<1>>, + makeComponent, SwitchProfileAction<2>>, + makeComponent, SwitchProfileAction<3>>, + makeComponent, SwitchScreenAction, StaticMenuItemIcon<&icons::back>> + > +{}; +} diff --git a/src/displays/statusdisplay.h b/src/displays/statusdisplay.h index 115dd94..ce48a09 100644 --- a/src/displays/statusdisplay.h +++ b/src/displays/statusdisplay.h @@ -99,6 +99,7 @@ private: Label m_labelPerformance{85, bottomLines[2]}; // 40, 15 Label m_labelMode{165, bottomLines[2]}; // 75, 15 Label m_labelName{40, bottomLines[3]}; // 40, 15 + Label m_labelProfile{205, bottomLines[3]}; // 35, 15 static const constexpr int bottomLines[4] { 251, 266, 281, 296 }; }; @@ -136,6 +137,7 @@ void StatusDisplay::initScreen() m_labelMode.start(); tft.drawString("Name:", 0, bottomLines[3]); m_labelName.start(); + m_labelProfile.start(); tft.setTextColor(TFT_WHITE, TFT_BLACK); } @@ -161,6 +163,8 @@ void StatusDisplay::redraw() m_labelPerformance.redraw(String{performance.last}); m_labelMode.redraw(currentMode->displayName()); m_labelName.redraw(&deviceName[0]); + const auto profile = settingsPersister.currentlyOpenProfileIndex(); + m_labelProfile.redraw(profile?String{*profile}:"-"); } void StatusDisplay::rotate(int offset) diff --git a/src/dpad5wire.h b/src/dpad5wire.h new file mode 100644 index 0000000..90e70b5 --- /dev/null +++ b/src/dpad5wire.h @@ -0,0 +1,158 @@ +#pragma once + +#include + +#include + +#include "globals.h" +#include "types.h" +#include "actions/switchprofileaction.h" + +namespace { +namespace dpad5wire +{ +using State = std::tuple; + +template +class Helper +{ +public: + static constexpr auto OutPin = OUT; + static constexpr auto In1Pin = IN1; + static constexpr auto In2Pin = IN2; + static constexpr auto In3Pin = IN3; + static constexpr auto In4Pin = IN4; + + void begin(); + + State read(); +}; + +template +void Helper::begin() +{ + pinMode(OUT, OUTPUT); +} + +template +State Helper::read() +{ + digitalWrite(OUT, LOW); + + pinMode(IN1, INPUT_PULLUP); + pinMode(IN2, INPUT_PULLUP); + pinMode(IN3, INPUT_PULLUP); + pinMode(IN4, INPUT_PULLUP); + + delay(1); + + const bool result0 = digitalRead(IN1)==LOW; + const bool result1 = digitalRead(IN2)==LOW; + const bool result2 = digitalRead(IN3)==LOW; + const bool result3 = digitalRead(IN4)==LOW; + + digitalWrite(OUT, HIGH); + + pinMode(IN1, INPUT_PULLDOWN); + pinMode(IN2, INPUT_PULLDOWN); + pinMode(IN3, INPUT_PULLDOWN); + pinMode(IN4, INPUT_PULLDOWN); + + delay(1); + + const bool result4 = digitalRead(IN1); + const bool result5 = digitalRead(IN2); + const bool result6 = digitalRead(IN3); + const bool result7 = digitalRead(IN4); + + return std::make_tuple(result0, result1, result2, result3, result4, result5, result6, result7); +} + +#ifdef FEATURE_DPAD_5WIRESW +Helper helper; +State lastState; +millis_t debounceUp, debounceDown, debounceConfirm, debounceBack, debounceProfile0, debounceProfile1, debounceProfile2, debounceProfile3; + +void init() +{ + helper.begin(); + debounceUp = debounceDown = debounceConfirm = debounceBack = debounceProfile0 = debounceProfile1 = debounceProfile2 = debounceProfile3 = millis(); +} + +void update() +{ + const auto state = helper.read(); + +#ifdef DPAD_5WIRESW_DEBUG + lastState = state; + return; +#endif + + const auto now = millis(); + + if (std::get(lastState) != std::get(state) && now-debounceUp > settings.boardcomputerHardware.dpadDebounce) + { + if (std::get(state)) + InputDispatcher::rotate(-1); + std::get(lastState) = std::get(state); + debounceUp = now; + } + if (std::get(lastState) != std::get(state) && now-debounceDown > settings.boardcomputerHardware.dpadDebounce) + { + if (std::get(state)) + InputDispatcher::rotate(1); + std::get(lastState) = std::get(state); + debounceDown = now; + } + if (std::get(lastState) != std::get(state) && now-debounceConfirm > settings.boardcomputerHardware.dpadDebounce) + { + InputDispatcher::confirmButton(std::get(state)); + std::get(lastState) = std::get(state); + debounceConfirm = now; + } + if (std::get(lastState) != std::get(state) && now-debounceBack > settings.boardcomputerHardware.dpadDebounce) + { + InputDispatcher::backButton(std::get(state)); + std::get(lastState) = std::get(state); + debounceBack = now; + } + if (std::get(lastState) != std::get(state) && now-debounceProfile0 > settings.boardcomputerHardware.dpadDebounce) + { + if (std::get(state)) + { + SwitchProfileAction<0>{}.triggered(); + } + std::get(lastState) = std::get(state); + debounceProfile0 = now; + } + if (std::get(lastState) != std::get(state) && now-debounceProfile1 > settings.boardcomputerHardware.dpadDebounce) + { + if (std::get(state)) + { + SwitchProfileAction<1>{}.triggered(); + } + std::get(lastState) = std::get(state); + debounceProfile1 = now; + } + if (std::get(lastState) != std::get(state) && now-debounceProfile2 > settings.boardcomputerHardware.dpadDebounce) + { + if (std::get(state)) + { + SwitchProfileAction<2>{}.triggered(); + } + std::get(lastState) = std::get(state); + debounceProfile2 = now; + } + if (std::get(lastState) != std::get(state) && now-debounceProfile3 > settings.boardcomputerHardware.dpadDebounce) + { + if (std::get(state)) + { + SwitchProfileAction<3>{}.triggered(); + } + std::get(lastState) = std::get(state); + debounceProfile3 = now; + } +} +#endif +} +} diff --git a/src/globals.h b/src/globals.h index 3cba3d0..d2ec02b 100644 --- a/src/globals.h +++ b/src/globals.h @@ -11,7 +11,7 @@ #include "display.h" #include "modeinterface.h" #include "settings.h" -#include "settingssaver.h" +#include "settingspersister.h" #include "types.h" namespace { @@ -26,7 +26,7 @@ float avgSpeed, avgSpeedKmh, sumCurrent; char deviceName[32]; Settings settings; -SettingsSaver settingsSaver; +SettingsPersister settingsPersister; constexpr auto TFT_GREY = 0x5AEB; diff --git a/src/main.cpp b/src/main.cpp index a8c5f32..ff9ea69 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -12,9 +12,11 @@ #include "globals.h" #include "modes/defaultmode.h" #include "modes/tempomatmode.h" +#include "displays/dpad5wiredebugdisplay.h" #include "screens.h" #include "dpad.h" #include "dpad3wire.h" +#include "dpad5wire.h" #include "rotary.h" #include "serialhandler.h" #include "ota.h" @@ -48,18 +50,27 @@ void setup() initScreen(); #ifdef FEATURE_DPAD + bootLabel.redraw("dpad"); dpad::init(); #endif #ifdef FEATURE_DPAD_3WIRESW + bootLabel.redraw("dpad3wire"); dpad3wire::init(); #endif +#ifdef FEATURE_DPAD_5WIRESW + bootLabel.redraw("dpad5wire"); + dpad5wire::init(); +#endif + #ifdef FEATURE_ROTARY + bootLabel.redraw("rotary"); initRotary(); #endif #ifdef FEATURE_MOSFETS + bootLabel.redraw("mosfets"); pinMode(PINS_MOSFET0, OUTPUT); pinMode(PINS_MOSFET1, OUTPUT); pinMode(PINS_MOSFET2, OUTPUT); @@ -69,45 +80,71 @@ void setup() digitalWrite(PINS_MOSFET2, LOW); #endif + bootLabel.redraw("settings"); settings = presets::defaultSettings; - if (settingsSaver.init()) - loadSettings(); + if (settingsPersister.init()) + { + if (settingsPersister.openProfile(0)) + { + loadSettings(); + } + } + bootLabel.redraw("swap front back"); updateSwapFrontBack(); + bootLabel.redraw("deviceName"); { uint8_t macAddress[6]; WiFi.macAddress(&macAddress[0]); std::sprintf(deviceName, STRING(DEVICE_PREFIX) "_%02hhx%02hhx%02hhx", macAddress[3], macAddress[4], macAddress[5]); } + bootLabel.redraw("setHostname"); if (!WiFi.setHostname(deviceName)) Serial.println("Could not setHostname"); + bootLabel.redraw("softAPsetHostname"); if (!WiFi.softAPsetHostname(deviceName)) Serial.println("Could not softAPsetHostname"); + bootLabel.redraw("WiFi mode"); if (!WiFi.mode(settings.wifiSettings.autoWifiMode)) Serial.println("Could not set mode to WIFI_AP_STA"); if (settings.wifiSettings.autoEnableAp) + { + bootLabel.redraw("WiFi softAp"); WifiSoftApAction{}.triggered(); + } + bootLabel.redraw("WiFi begin"); if (!WiFi.begin("realraum", "r3alraum")) Serial.println("Could not begin WiFi"); if (settings.bluetoothSettings.autoBluetoothMode == BluetoothMode::Master) { + bootLabel.redraw("bluetooth begin master"); BluetoothBeginMasterAction{}.triggered(); #ifdef FEATURE_BMS if (settings.autoConnectBms) + { + bootLabel.redraw("connect BMS"); BluetoothConnectBmsAction{}.triggered(); + } #endif - } else if (settings.bluetoothSettings.autoBluetoothMode == BluetoothMode::Slave) + } + else if (settings.bluetoothSettings.autoBluetoothMode == BluetoothMode::Slave) + { + bootLabel.redraw("bluetooth begin"); BluetoothBeginAction{}.triggered(); + } + bootLabel.redraw("front Serial begin"); controllers.front.serial.get().begin(38400, SERIAL_8N1, PINS_RX1, PINS_TX1); + + bootLabel.redraw("back Serial begin"); controllers.back.serial.get().begin(38400, SERIAL_8N1, PINS_RX2, PINS_TX2); raw_gas = 0; @@ -121,13 +158,21 @@ void setup() currentMode = &modes::defaultMode; #ifdef FEATURE_OTA + bootLabel.redraw("ota"); initOta(); #endif + bootLabel.redraw("webserver"); initWebserver(); + bootLabel.redraw("potis"); readPotis(); +#if defined(FEATURE_DPAD_5WIRESW) && defined(DPAD_5WIRESW_DEBUG) + switchScreen(); + return; +#endif + if (gas > 200.f || brems > 200.f) switchScreen(true); else @@ -146,6 +191,10 @@ void loop() dpad3wire::update(); #endif +#ifdef FEATURE_DPAD_5WIRESW + dpad5wire::update(); +#endif + if (!lastPotiRead || now - lastPotiRead >= 1000/settings.boardcomputerHardware.timersSettings.potiReadRate) { readPotis(); diff --git a/src/presets.h b/src/presets.h index 0e5d61c..e4b4e98 100644 --- a/src/presets.h +++ b/src/presets.h @@ -25,10 +25,10 @@ constexpr Settings::ControllerHardware defaultControllerHardware { .enableBackLeft = true, .enableBackRight = true, - .invertFrontLeft = false, - .invertFrontRight = true, - .invertBackLeft = false, - .invertBackRight = true, + .invertFrontLeft = DEFAULT_INVERTFRONTLEFT, + .invertFrontRight = DEFAULT_INVERTFRONTRIGHT, + .invertBackLeft = DEFAULT_INVERTBACKLEFT, + .invertBackRight = DEFAULT_INVERTBACKRIGHT, .wheelDiameter = 165, .numMagnetPoles = 15, @@ -41,10 +41,10 @@ constexpr Settings::ControllerHardware mosfetsOffControllerHardware { .enableBackLeft = false, .enableBackRight = false, - .invertFrontLeft = false, - .invertFrontRight = true, - .invertBackLeft = false, - .invertBackRight = true, + .invertFrontLeft = DEFAULT_INVERTFRONTLEFT, + .invertFrontRight = DEFAULT_INVERTFRONTRIGHT, + .invertBackLeft = DEFAULT_INVERTBACKLEFT, + .invertBackRight = DEFAULT_INVERTBACKRIGHT, .wheelDiameter = 165, .numMagnetPoles = 15, @@ -57,7 +57,7 @@ constexpr Settings::WifiSettings defaultWifiSettings { }; constexpr Settings::BluetoothSettings defaultBluetoothSettings { - .autoBluetoothMode = BluetoothMode::Off + .autoBluetoothMode = BluetoothMode::Master }; constexpr Settings::ControllerHardware spinnerControllerHardware { @@ -66,10 +66,10 @@ constexpr Settings::ControllerHardware spinnerControllerHardware { .enableBackLeft = true, .enableBackRight = true, - .invertFrontLeft = false, - .invertFrontRight = false, - .invertBackLeft = false, - .invertBackRight = false, + .invertFrontLeft = DEFAULT_INVERTFRONTLEFT, + .invertFrontRight = !DEFAULT_INVERTFRONTRIGHT, + .invertBackLeft = DEFAULT_INVERTBACKLEFT, + .invertBackRight = !DEFAULT_INVERTBACKRIGHT, .wheelDiameter = 165, .numMagnetPoles = 15, @@ -90,7 +90,7 @@ constexpr Settings::BoardcomputerHardware defaultBoardcomputerHardware { .gasMax = DEFAULT_GASMAX, .bremsMin = DEFAULT_BREMSMIN, .bremsMax = DEFAULT_BREMSMAX, -#if defined(FEATURE_DPAD) || defined(FEATURE_DPAD_3WIRESW) +#if defined(FEATURE_DPAD) || defined(FEATURE_DPAD_3WIRESW) || defined(FEATURE_DPAD_5WIRESW) .dpadDebounce = 25, #endif #ifdef FEATURE_GAMETRAK diff --git a/src/screens.h b/src/screens.h index 00e61e9..9a7c752 100644 --- a/src/screens.h +++ b/src/screens.h @@ -1,5 +1,7 @@ #pragma once +#include + #include "displays/menus/aboutmenu.h" #include "displays/menus/accesspointwifisettingsmenu.h" #include "displays/menus/bluetoothsettingsmenu.h" @@ -25,6 +27,7 @@ #include "displays/menus/mosfetsmenu.h" #include "displays/menus/motorfeedbackdebugmenu.h" #include "displays/menus/motorstatedebugmenu.h" +#include "displays/menus/profilesmenu.h" #include "displays/menus/presetsmenu.h" #include "displays/menus/boardcomputerhardwaresettingsmenu.h" #include "displays/menus/selectmodemenu.h" @@ -35,6 +38,7 @@ #include "displays/menus/wifisettingsmenu.h" #include "displays/bmsdisplay.h" #include "displays/calibratedisplay.h" +#include "displays/dpad5wiredebugdisplay.h" #include "displays/gameoflifedisplay.h" #include "displays/gametrakcalibratedisplay.h" #include "displays/lockscreen.h" @@ -48,9 +52,12 @@ #include "globals.h" #include "utils.h" +#include "widgets/label.h" #include "icons/logo.h" namespace { +Label bootLabel{32, 250}; + union X { X() {} ~X() { ((Display&)statusDisplay).~Display(); } @@ -95,6 +102,7 @@ union X { BackLeftMotorFeedbackDebugMenu backLeftMotorFeedbackDebugMenu; BackRightMotorFeedbackDebugMenu backRightMotorFeedbackDebugMenu; BoardcomputerHardwareSettingsMenu boardcomputerHardwareSettingsMenu; + ProfilesMenu profilesMenu; PresetsMenu presetsMenu; SelectModeMenu selectModeMenu; SettingsMenu settingsMenu; @@ -107,6 +115,9 @@ union X { BmsDisplay bmsDisplay; #endif CalibrateDisplay calibrateDisplay; +#if defined(FEATURE_DPAD_5WIRESW) && defined(DPAD_5WIRESW_DEBUG) + DPad5WireDebugDisplay dPad5WireDebugDisplay; +#endif GameOfLifeDisplay gameOfLifeDisplay; #ifdef FEATURE_GAMETRAK GametrakCalibrateDisplay gametrakCalibrateDisplay; @@ -167,7 +178,7 @@ union X { GasMaxChangeScreen changeGasMax; BremsMinChangeScreen changeBremsMin; BremsMaxChangeScreen changeBremsMax; -#if defined(FEATURE_DPAD) || defined(FEATURE_DPAD_3WIRESW) +#if defined(FEATURE_DPAD) || defined(FEATURE_DPAD_3WIRESW) || defined(FEATURE_DPAD_5WIRESW) DPadDebounceChangeScreen dPadDebounceChangeScreen; #endif #ifdef FEATURE_GAMETRAK @@ -249,6 +260,7 @@ template<> decltype(displays.frontLeftMotorFeedbackDebugMenu) & template<> decltype(displays.frontRightMotorFeedbackDebugMenu) &getRefByType() { return displays.frontRightMotorFeedbackDebugMenu; } template<> decltype(displays.backLeftMotorFeedbackDebugMenu) &getRefByType() { return displays.backLeftMotorFeedbackDebugMenu; } template<> decltype(displays.backRightMotorFeedbackDebugMenu) &getRefByType() { return displays.backRightMotorFeedbackDebugMenu; } +template<> decltype(displays.profilesMenu) &getRefByType() { return displays.profilesMenu; } template<> decltype(displays.presetsMenu) &getRefByType() { return displays.presetsMenu; } template<> decltype(displays.selectModeMenu) &getRefByType() { return displays.selectModeMenu; } template<> decltype(displays.settingsMenu) &getRefByType() { return displays.settingsMenu; } @@ -262,6 +274,9 @@ template<> decltype(displays.wifiSettingsMenu) & template<> decltype(displays.bmsDisplay) &getRefByType() { return displays.bmsDisplay; } #endif template<> decltype(displays.calibrateDisplay) &getRefByType() { return displays.calibrateDisplay; } +#if defined(FEATURE_DPAD_5WIRESW) && defined(DPAD_5WIRESW_DEBUG) +template<> decltype(displays.dPad5WireDebugDisplay) &getRefByType() { return displays.dPad5WireDebugDisplay; } +#endif template<> decltype(displays.gameOfLifeDisplay) &getRefByType() { return displays.gameOfLifeDisplay; } #ifdef FEATURE_GAMETRAK template<> decltype(displays.gametrakCalibrateDisplay) &getRefByType() { return displays.gametrakCalibrateDisplay; } @@ -322,7 +337,7 @@ template<> decltype(displays.changeGasMin) & template<> decltype(displays.changeGasMax) &getRefByType() { return displays.changeGasMax; } template<> decltype(displays.changeBremsMin) &getRefByType() { return displays.changeBremsMin; } template<> decltype(displays.changeBremsMax) &getRefByType() { return displays.changeBremsMax; } -#if defined(FEATURE_DPAD) || defined(FEATURE_DPAD_3WIRESW) +#if defined(FEATURE_DPAD) || defined(FEATURE_DPAD_3WIRESW) || defined(FEATURE_DPAD_5WIRESW) template<> decltype(displays.dPadDebounceChangeScreen) &getRefByType() { return displays.dPadDebounceChangeScreen; } #endif #ifdef FEATURE_GAMETRAK @@ -402,10 +417,12 @@ void initScreen() { tft.init(); tft.fillScreen(TFT_WHITE); - tft.setTextColor(TFT_BLACK); + tft.setTextColor(TFT_BLACK, TFT_WHITE); + tft.setTextFont(4); tft.pushImage(0, 40, icons::logo.WIDTH, icons::logo.HEIGHT, icons::logo.buffer); - tft.drawString("Bobbycar-OS", 32, 200, 4); - tft.drawString("booting...", 32, 225, 4); + tft.drawString("Bobbycar-OS", 32, 200); + tft.drawString("booting...", 32, 225); + bootLabel.start(); } void updateDisplay() diff --git a/src/settings.h b/src/settings.h index 447b1f7..27a9385 100644 --- a/src/settings.h +++ b/src/settings.h @@ -53,7 +53,7 @@ struct Settings struct BoardcomputerHardware { int16_t sampleCount; int16_t gasMin, gasMax, bremsMin, bremsMax; -#if defined(FEATURE_DPAD) || defined(FEATURE_DPAD_3WIRESW) +#if defined(FEATURE_DPAD) || defined(FEATURE_DPAD_3WIRESW) || defined(FEATURE_DPAD_5WIRESW) uint8_t dpadDebounce; #endif #ifdef FEATURE_GAMETRAK @@ -141,7 +141,7 @@ void Settings::executeForEverySetting(T &&callable) callable("gasMax", boardcomputerHardware.gasMax); callable("bremsMin", boardcomputerHardware.bremsMin); callable("bremsMax", boardcomputerHardware.bremsMax); -#if defined(FEATURE_DPAD) || defined(FEATURE_DPAD_3WIRESW) +#if defined(FEATURE_DPAD) || defined(FEATURE_DPAD_3WIRESW) || defined(FEATURE_DPAD_5WIRESW) callable("dpadDebounce", boardcomputerHardware.dpadDebounce); #endif #ifdef FEATURE_GAMETRAK diff --git a/src/settingsaccessors.h b/src/settingsaccessors.h index e130259..08d5794 100644 --- a/src/settingsaccessors.h +++ b/src/settingsaccessors.h @@ -64,7 +64,7 @@ struct GasMinAccessor : public RefAccessorSaveSettings { int16_t &getRe struct GasMaxAccessor : public RefAccessorSaveSettings { int16_t &getRef() const override { return settings.boardcomputerHardware.gasMax; } }; struct BremsMinAccessor : public RefAccessorSaveSettings { int16_t &getRef() const override { return settings.boardcomputerHardware.bremsMin; } }; struct BremsMaxAccessor : public RefAccessorSaveSettings { int16_t &getRef() const override { return settings.boardcomputerHardware.bremsMax; } }; -#if defined(FEATURE_DPAD) || defined(FEATURE_DPAD_3WIRESW) +#if defined(FEATURE_DPAD) || defined(FEATURE_DPAD_3WIRESW) || defined(FEATURE_DPAD_5WIRESW) struct DPadDebounceAccessor : public RefAccessorSaveSettings { uint8_t &getRef() const override { return settings.boardcomputerHardware.dpadDebounce; } }; #endif #ifdef FEATURE_GAMETRAK diff --git a/src/settingssaver.h b/src/settingspersister.h similarity index 77% rename from src/settingssaver.h rename to src/settingspersister.h index b169d80..d8bff67 100644 --- a/src/settingssaver.h +++ b/src/settingspersister.h @@ -6,36 +6,41 @@ #include #include +#include + #include "settings.h" #include "bluetoothmode.h" #include "unifiedmodelmode.h" namespace { -class SettingsSaver +class SettingsPersister { public: bool init(); + bool erase(); + bool openProfile(uint8_t index); + void closeProfile(); bool load(Settings &settings); bool save(Settings &settings); + tl::optional currentlyOpenProfileIndex() const; + private: - nvs_handle my_handle; + struct CurrentlyOpenProfile { + nvs_handle handle; + uint8_t profileIndex; + }; + tl::optional m_profile; }; -bool SettingsSaver::init() +bool SettingsPersister::init() { esp_err_t err = nvs_flash_init(); if (err == ESP_ERR_NVS_NO_FREE_PAGES || err == ESP_ERR_NVS_NEW_VERSION_FOUND) { Serial.printf("nvs_flash_init() returned: %s, trying to erase\r\n", esp_err_to_name(err)); - err = nvs_flash_erase(); - if (err != ESP_OK) - { - Serial.printf("nvs_flash_erase() returned: %s, aborting\r\n", esp_err_to_name(err)); - return false; - } - err = nvs_flash_init(); + return erase(); } if (err != ESP_OK) @@ -44,16 +49,55 @@ bool SettingsSaver::init() return false; } - err = nvs_open("bobbycar", NVS_READWRITE, &my_handle); + return true; +} + +bool SettingsPersister::erase() +{ + esp_err_t err = nvs_flash_erase(); + if (err != ESP_OK) + { + Serial.printf("nvs_flash_erase() returned: %s, aborting\r\n", esp_err_to_name(err)); + return false; + } + + err = nvs_flash_init(); + if (err != ESP_OK) + { + Serial.printf("nvs_flash_init() returned: %s\r\n", esp_err_to_name(err)); + return false; + } + + return true; +} + +bool SettingsPersister::openProfile(uint8_t index) +{ + closeProfile(); + + nvs_handle handle; + esp_err_t err = nvs_open((String{"bobbycar"}+index).c_str(), NVS_READWRITE, &handle); if (err != ESP_OK) { Serial.printf("nvs_open() returned: %s\r\n", esp_err_to_name(err)); return false; } + m_profile = {handle, index}; + return true; } +void SettingsPersister::closeProfile() +{ + if (!m_profile) + return; + + nvs_close(m_profile->handle); + + m_profile = tl::nullopt; +} + template struct nvsGetterHelper; template<> struct nvsGetterHelper { static constexpr auto nvs_get = &nvs_get_i8; }; template<> struct nvsGetterHelper { static constexpr auto nvs_get = &nvs_get_u8; }; @@ -118,13 +162,19 @@ template<> struct nvsGetterHelper { static esp_err_t nvs_get(nvs_ha return err; }}; -bool SettingsSaver::load(Settings &settings) +bool SettingsPersister::load(Settings &settings) { + if (!m_profile) + { + Serial.println("SettingsPersister::load() no profile open currently!"); + return false; + } + bool result{true}; settings.executeForEverySetting([&](const char *key, auto &value) { - esp_err_t err = nvsGetterHelper>::nvs_get(my_handle, key, &value); + esp_err_t err = nvsGetterHelper>::nvs_get(m_profile->handle, key, &value); if (err != ESP_OK) { Serial.printf("nvs_get_i32() for %s returned: %s\r\n", key, esp_err_to_name(err)); @@ -168,13 +218,19 @@ template<> struct nvsSetterHelper { static esp_err_t nvs_set(nvs_ha return nvs_set_u8(handle, key, uint8_t(value)); }}; -bool SettingsSaver::save(Settings &settings) +bool SettingsPersister::save(Settings &settings) { + if (!m_profile) + { + Serial.println("SettingsPersister::save() no profile open currently!"); + return false; + } + bool result{true}; settings.executeForEverySetting([&](const char *key, auto value) { - esp_err_t err = nvsSetterHelper::nvs_set(my_handle, key, value); + esp_err_t err = nvsSetterHelper::nvs_set(m_profile->handle, key, value); if (err != ESP_OK) { Serial.printf("nvs_get_i32() for %s returned: %s\r\n", key, esp_err_to_name(err)); @@ -185,4 +241,12 @@ bool SettingsSaver::save(Settings &settings) return result; } + +tl::optional SettingsPersister::currentlyOpenProfileIndex() const +{ + if (m_profile) + return m_profile->profileIndex; + + return tl::nullopt; +} } diff --git a/src/texts.h b/src/texts.h index 196e66c..3d8fd8e 100644 --- a/src/texts.h +++ b/src/texts.h @@ -36,6 +36,7 @@ constexpr char TEXT_TURNOFFDISCHARGE[] = "Turn off discharge"; //DebugMenu constexpr char TEXT_LOADSETTINGS[] = "Load settings"; constexpr char TEXT_SAVESETTINGS[] = "Save settings"; +constexpr char TEXT_ERASENVS[] = "Erase NVS"; constexpr char TEXT_FRONTCOMMAND[] = "Front command"; constexpr char TEXT_BACKCOMMAND[] = "Back command"; constexpr char TEXT_FRONTLEFTCOMMAND[] = "Front left command"; @@ -56,6 +57,7 @@ constexpr char TEXT_STATUS[] = "Status"; constexpr char TEXT_SELECTMODE[] = "Select mode"; constexpr char TEXT_MODESETTINGS[] = "Mode settings"; constexpr char TEXT_PRESETS[] = "Presets"; +constexpr char TEXT_PROFILES[] = "Profiles"; constexpr char TEXT_GRAPHS[] = "Graphs"; //constexpr char TEXT_BMS[] = "BMS"; constexpr char TEXT_SETTINGS[] = "Settings"; @@ -254,6 +256,14 @@ constexpr char TEXT_SWAPSCREENBYTES[] = "Swap screen bytes"; constexpr char TEXT_TIMERS[] = "Timers"; //constexpr char TEXT_BACK[] = "Back"; +//ProfilesMenu +//constexpr char TEXT_PROFILES[] = "Profiles"; +constexpr char TEXT_PROFILE0[] = "Profile 0"; +constexpr char TEXT_PROFILE1[] = "Profile 1"; +constexpr char TEXT_PROFILE2[] = "Profile 2"; +constexpr char TEXT_PROFILE3[] = "Profile 3"; +//constexpr char TEXT_BACK[] = "Back"; + //PresetsMenu //constexpr char TEXT_PRESETS[] = "Presets"; constexpr char TEXT_DEFAULTEVERYTHING[] = "Default everything"; diff --git a/src/utils.h b/src/utils.h index 3451039..dbfaffc 100644 --- a/src/utils.h +++ b/src/utils.h @@ -266,12 +266,12 @@ void updateSwapFrontBack() void loadSettings() { - settingsSaver.load(settings); + settingsPersister.load(settings); } void saveSettings() { - settingsSaver.save(settings); + settingsPersister.save(settings); } void updateAccumulators() diff --git a/src/widgets/label.h b/src/widgets/label.h index fea7edb..5171033 100644 --- a/src/widgets/label.h +++ b/src/widgets/label.h @@ -8,7 +8,7 @@ namespace { class Label { public: - Label(int x, int y) : m_x{x}, m_y{y} {} + Label(int x, int y); int x() const { return m_x; }; int y() const { return m_y; }; @@ -29,6 +29,12 @@ private: int m_lastHeight; }; +Label::Label(int x, int y) : + m_x{x}, + m_y{y} +{ +} + void Label::start() { m_lastStr.clear(); @@ -71,7 +77,7 @@ void Label::redraw(const String &str, bool forceRedraw) void Label::clear() { if (m_lastWidth || m_lastHeight) - tft.fillRect(m_x, m_y, m_lastWidth, m_lastHeight, TFT_BLACK); + tft.fillRect(m_x, m_y, m_lastWidth, m_lastHeight, tft.textbgcolor); start(); }