diff --git a/main/accessors/settingsaccessors.h b/main/accessors/settingsaccessors.h index cd9466f..3679eb9 100644 --- a/main/accessors/settingsaccessors.h +++ b/main/accessors/settingsaccessors.h @@ -32,8 +32,7 @@ struct NMotMaxRpmAccessor : public RefAccessorSaveSettings { int16_t &g struct FieldWeakMaxAccessor : public RefAccessorSaveSettings { int16_t &getRef() const override { return settings.limits.fieldWeakMax; } }; struct PhaseAdvMaxAccessor : public RefAccessorSaveSettings { int16_t &getRef() const override { return settings.limits.phaseAdvMax; } }; -struct AutoWifiModeAccessor : public RefAccessorSaveSettings { wifi_mode_t &getRef() const override { return settings.wifiSettings.autoWifiMode; } }; -struct AutoEnableApAccessor : public RefAccessorSaveSettings { bool &getRef() const override { return settings.wifiSettings.autoEnableAp; } }; +struct WifiEnabledAccessor : public RefAccessorSaveSettings { bool &getRef() const override { return settings.wifiSettings.wifiEnabled; } }; #ifdef FEATURE_BLUETOOTH struct AutoBluetoothModeAccessor : public RefAccessorSaveSettings { BluetoothMode &getRef() const override { return settings.bluetoothSettings.autoBluetoothMode; } }; @@ -65,6 +64,8 @@ struct SwapFrontBackAccessor : public RefAccessorSaveSettings { #ifdef FEATURE_CAN struct SendFrontCanCmdAccessor : public RefAccessorSaveSettings { bool &getRef() const override { return settings.controllerHardware.sendFrontCanCmd; } }; struct SendBackCanCmdAccessor : public RefAccessorSaveSettings { bool &getRef() const override { return settings.controllerHardware.sendBackCanCmd; } }; +struct CanTransmitTimeoutAccessor : public RefAccessorSaveSettings { int16_t &getRef() const override { return settings.controllerHardware.canTransmitTimeout; } }; +struct CanReceiveTimeoutAccessor : public RefAccessorSaveSettings { int16_t &getRef() const override { return settings.controllerHardware.canReceiveTimeout; } }; #endif struct SampleCountAccessor : public RefAccessorSaveSettings { int16_t &getRef() const override { return settings.boardcomputerHardware.sampleCount; } }; @@ -89,6 +90,9 @@ struct ModeUpdateRateAccessor : public RefAccessorSaveSettings { int16_ struct StatsUpdateRateAccessor : public RefAccessorSaveSettings { int16_t &getRef() const override { return settings.boardcomputerHardware.timersSettings.statsUpdateRate; } }; struct DisplayUpdateRateAccessor : public RefAccessorSaveSettings { int16_t &getRef() const override { return settings.boardcomputerHardware.timersSettings.displayUpdateRate; } }; struct DisplayRedrawRateAccessor : public RefAccessorSaveSettings { int16_t &getRef() const override { return settings.boardcomputerHardware.timersSettings.displayRedrawRate; } }; +#ifdef FEATURE_CAN +struct CanReceiveRateAccessor : public RefAccessorSaveSettings { int16_t &getRef() const override { return settings.boardcomputerHardware.timersSettings.canReceiveRate; } }; +#endif struct DefaultModeModelModeAccessor : public RefAccessorSaveSettings { UnifiedModelMode &getRef() const override { return settings.defaultMode.modelMode; } }; struct DefaultModeSquareGasAccessor : public RefAccessorSaveSettings { bool &getRef() const override { return settings.defaultMode.squareGas; } }; diff --git a/main/actions/erasenvsaction.h b/main/actions/erasenvsaction.h index bcb1ddd..76ddb95 100644 --- a/main/actions/erasenvsaction.h +++ b/main/actions/erasenvsaction.h @@ -1,5 +1,9 @@ #pragma once +// esp-idf includes +#include + +// local includes #include "actioninterface.h" #include "globals.h" #include "presets.h" @@ -14,25 +18,31 @@ public: if (!settingsPersister.erase()) { - //Serial.println("EraseNvsAction::triggered() erase failed"); - return; + ESP_LOGE("BOBBY", "erase() failed"); + //return; } settings = presets::defaultSettings; - if (!profile) - return; - - if (!settingsPersister.openProfile(*profile)) + if (!settingsPersister.openCommon()) { - //Serial.println("EraseNvsAction::triggered() openProfile failed"); - return; + ESP_LOGE("BOBBY", "openCommon() failed"); + //return; + } + + if (profile) + { + if (!settingsPersister.openProfile(*profile)) + { + ESP_LOGE("BOBBY", "openProfile(%hhu) failed", *profile); + //return; + } } if (!settingsPersister.load(settings)) { - //Serial.println("EraseNvsAction::triggered() load failed"); - return; + ESP_LOGE("BOBBY", "load() failed"); + //return; } } }; diff --git a/main/can.h b/main/can.h index 4671552..b36ee9d 100644 --- a/main/can.h +++ b/main/can.h @@ -10,6 +10,7 @@ #include #include +#include #include "bobbycar-can.h" @@ -36,7 +37,7 @@ CanButtonsState lastButtonsState; void initCan() { - //Serial.println("initCan()"); + ESP_LOGI(TAG, "called"); twai_general_config_t g_config = TWAI_GENERAL_CONFIG_DEFAULT(GPIO_NUM_21, GPIO_NUM_22, TWAI_MODE_NORMAL); twai_timing_config_t t_config TWAI_TIMING_CONFIG_250KBITS(); @@ -50,29 +51,29 @@ void initCan() if (const auto result = twai_driver_install(&g_config, &t_config, &f_config); result == ESP_OK) { - //Serial.printf("CAN info twai_driver_install() succeeded\r\n"); + ESP_LOGI(TAG, "twai_driver_install() succeeded"); } else { - //Serial.printf("CAN err twai_driver_install() failed with %s\r\n", esp_err_to_name(result)); + ESP_LOGE(TAG, "twai_driver_install() failed with %s", esp_err_to_name(result)); return; } if (const auto result = twai_start(); result == ESP_OK) { - //Serial.printf("CAN info twai_start() succeeded\r\n"); + ESP_LOGI(TAG, "twai_start() succeeded"); } else { - //Serial.printf("CAN err twai_start() failed with %s\r\n", esp_err_to_name(result)); + ESP_LOGE(TAG, "twai_start() failed with %s", esp_err_to_name(result)); if (const auto result = twai_driver_uninstall(); result == ESP_OK) { - //Serial.printf("CAN info twai_driver_uninstall() succeeded\r\n"); + ESP_LOGI(TAG, "twai_driver_uninstall() succeeded"); } else { - //Serial.printf("CAN err twai_driver_uninstall() failed with %s\r\n", esp_err_to_name(result)); + ESP_LOGE(TAG, "twai_driver_uninstall() failed with %s", esp_err_to_name(result)); } return; @@ -220,11 +221,12 @@ bool parseBoardcomputerCanMessage(const twai_message_t &message) bool tryParseCanInput() { twai_message_t message; - if (const auto result = twai_receive(&message, pdMS_TO_TICKS(10)); result != ESP_OK) + const auto timeout = std::chrono::ceil(espchrono::milliseconds32{settings.controllerHardware.canReceiveTimeout}).count(); + if (const auto result = twai_receive(&message, timeout); result != ESP_OK) { if (result != ESP_ERR_TIMEOUT) { - ESP_LOGE(TAG, "CAN err twai_receive() failed with %s", esp_err_to_name(result)); + ESP_LOGE(TAG, "twai_receive() failed with %s", esp_err_to_name(result)); } if (espchrono::millis_clock::now() - controllers.front.lastCanFeedback > 100ms) @@ -269,7 +271,7 @@ bool tryParseCanInput() if (parseBoardcomputerCanMessage(message)) return true; - //Serial.printf("WARNING Unknown CAN info received .identifier = %u\r\n", message.identifier); + ESP_LOGW(TAG, "Unknown CAN info received .identifier = %u", message.identifier); return true; } @@ -291,7 +293,8 @@ void sendCanCommands() std::fill(std::begin(message.data), std::end(message.data), 0); std::memcpy(message.data, &value, sizeof(value)); - const auto result = twai_transmit(&message, pdMS_TO_TICKS(200)); + const auto timeout = std::chrono::ceil(espchrono::milliseconds32{settings.controllerHardware.canTransmitTimeout}).count(); + const auto result = twai_transmit(&message, timeout); if (result != ESP_OK && result != ESP_ERR_TIMEOUT) { ESP_LOGE(TAG, "ERROR: twai_transmit() failed with %s", esp_err_to_name(result)); diff --git a/main/changevaluedisplay.h b/main/changevaluedisplay.h index 45f87e7..16a759b 100644 --- a/main/changevaluedisplay.h +++ b/main/changevaluedisplay.h @@ -1,5 +1,7 @@ #pragma once +#include + #include "display.h" #include "textinterface.h" #include "actioninterface.h" @@ -122,6 +124,18 @@ void ChangeValueDisplay::redraw() m_valueLabel.redraw(std::to_string(m_value)); } +template<> +void ChangeValueDisplay::redraw() +{ + tft.setTextFont(4); + tft.setTextColor(TFT_YELLOW); + m_titleLabel.redraw(text()); + + tft.setTextColor(TFT_WHITE, TFT_BLACK); + tft.setTextFont(7); + m_valueLabel.redraw(fmt::format("{:02f}", m_value)); +} + template void ChangeValueDisplay::rotate(int offset) { diff --git a/main/changevaluedisplay_controlmode.h b/main/changevaluedisplay_controlmode.h index a053643..01f1ddf 100644 --- a/main/changevaluedisplay_controlmode.h +++ b/main/changevaluedisplay_controlmode.h @@ -1,5 +1,7 @@ #pragma once +#include + #include "changevaluedisplay.h" #include "menudisplay.h" #include "utils.h" @@ -45,7 +47,7 @@ void ChangeValueDisplay::start() case ControlMode::Speed: setSelectedIndex(2); break; case ControlMode::Torque: setSelectedIndex(3); break; default: - //Serial.printf("Unknown ControlMode: %i\r\n", int(value)); + ESP_LOGW("BOBBY", "Unknown ControlMode: %i", int(value)); setSelectedIndex(4); } } diff --git a/main/changevaluedisplay_controltype.h b/main/changevaluedisplay_controltype.h index 837b429..a9dd249 100644 --- a/main/changevaluedisplay_controltype.h +++ b/main/changevaluedisplay_controltype.h @@ -1,5 +1,7 @@ #pragma once +#include + #include "changevaluedisplay.h" #include "menudisplay.h" #include "utils.h" @@ -43,7 +45,7 @@ void ChangeValueDisplay::start() case ControlType::Sinusoidal: setSelectedIndex(1); break; case ControlType::FieldOrientedControl: setSelectedIndex(2); break; default: - //Serial.printf("Unknown ControlType: %i\r\n", int(value)); + ESP_LOGW("BOBBY", "Unknown ControlType: %i", int(value)); setSelectedIndex(3); } } diff --git a/main/changevaluedisplay_larsmmode_mode.h b/main/changevaluedisplay_larsmmode_mode.h index 1b9ddc0..ce5ddfc 100644 --- a/main/changevaluedisplay_larsmmode_mode.h +++ b/main/changevaluedisplay_larsmmode_mode.h @@ -1,5 +1,7 @@ #pragma once +#include + #include "changevaluedisplay.h" #include "menudisplay.h" #include "utils.h" @@ -44,7 +46,7 @@ void ChangeValueDisplay::start() case LarsmModeMode::Mode3: setSelectedIndex(2); break; case LarsmModeMode::Mode4: setSelectedIndex(3); break; default: - //Serial.printf("Unknown LarsmModeMode: %i\r\n", int(value)); + ESP_LOGW("BOBBY", "Unknown LarsmModeMode: %i", int(value)); setSelectedIndex(4); } } diff --git a/main/changevaluedisplay_unifiedmodelmode.h b/main/changevaluedisplay_unifiedmodelmode.h index cf08511..ac40c1d 100644 --- a/main/changevaluedisplay_unifiedmodelmode.h +++ b/main/changevaluedisplay_unifiedmodelmode.h @@ -1,5 +1,7 @@ #pragma once +#include + #include "changevaluedisplay.h" #include "menudisplay.h" #include "utils.h" @@ -46,7 +48,7 @@ void ChangeValueDisplay::start() case UnifiedModelMode::FocSpeed: setSelectedIndex(3); break; case UnifiedModelMode::FocTorque: setSelectedIndex(4); break; default: - //Serial.printf("Unknown UnifiedModelMode: %i\r\n", int(value)); + ESP_LOGW("BOBBY", "Unknown UnifiedModelMode: %i", int(value)); setSelectedIndex(5); } } diff --git a/main/changevaluedisplay_wifi_mode_t.h b/main/changevaluedisplay_wifi_mode_t.h index 76731d6..f98d2ab 100644 --- a/main/changevaluedisplay_wifi_mode_t.h +++ b/main/changevaluedisplay_wifi_mode_t.h @@ -1,6 +1,7 @@ #pragma once #include +#include #include "changevaluedisplay.h" #include "menudisplay.h" @@ -45,7 +46,7 @@ void ChangeValueDisplay::start() case WIFI_MODE_AP: setSelectedIndex(2); break; case WIFI_MODE_APSTA: setSelectedIndex(3); break; default: - //Serial.printf("Unknown wifi_mode_t: %i\r\n", int(value)); + ESP_LOGW("BOBBY", "Unknown wifi_mode_t: %i", int(value)); setSelectedIndex(4); } } diff --git a/main/displays/menus/controllerhardwaresettingsmenu.h b/main/displays/menus/controllerhardwaresettingsmenu.h index c2f573a..a2e0d0b 100644 --- a/main/displays/menus/controllerhardwaresettingsmenu.h +++ b/main/displays/menus/controllerhardwaresettingsmenu.h @@ -46,6 +46,22 @@ using NumMagnetPolesChangeScreen = makeComponent< BackActionInterface>, SwitchScreenAction >; +#ifdef FEATURE_CAN +using CanTransmitTimeoutChangeScreen = makeComponent< + ChangeValueDisplay, + StaticText, + CanTransmitTimeoutAccessor, + BackActionInterface>, + SwitchScreenAction +>; +using CanReceiveTimeoutChangeScreen = makeComponent< + ChangeValueDisplay, + StaticText, + CanReceiveTimeoutAccessor, + BackActionInterface>, + SwitchScreenAction +>; +#endif class ControllerHardwareSettingsMenu : public MenuDisplay, @@ -62,8 +78,10 @@ public: constructMenuItem, SwitchScreenAction>>(); constructMenuItem, ToggleBoolAction, CheckboxIcon, SwapFrontBackAccessor>>(); #ifdef FEATURE_CAN - constructMenuItem, ToggleBoolAction, CheckboxIcon, SendFrontCanCmdAccessor>>(); - constructMenuItem, ToggleBoolAction, CheckboxIcon, SendBackCanCmdAccessor>>(); + constructMenuItem, ToggleBoolAction, CheckboxIcon, SendFrontCanCmdAccessor>>(); + constructMenuItem, ToggleBoolAction, CheckboxIcon, SendBackCanCmdAccessor>>(); + constructMenuItem, SwitchScreenAction>>(); + constructMenuItem, SwitchScreenAction>>(); #endif constructMenuItem, SwitchScreenAction, StaticMenuItemIcon<&icons::back>>>(); } diff --git a/main/displays/menus/timersmenu.h b/main/displays/menus/timersmenu.h index 204c1f2..bbced8a 100644 --- a/main/displays/menus/timersmenu.h +++ b/main/displays/menus/timersmenu.h @@ -57,6 +57,16 @@ using DisplayRedrawRateChangeDisplay = makeComponent< SwitchScreenAction >; +#ifdef FEATURE_CAN +using CanReceiveRateChangeDisplay = makeComponent< + ChangeValueDisplay, + StaticText, + CanReceiveRateAccessor, + BackActionInterface>, + SwitchScreenAction +>; +#endif + class TimersMenu : public MenuDisplay, public StaticText, @@ -70,6 +80,9 @@ public: constructMenuItem, SwitchScreenAction>>(); constructMenuItem, SwitchScreenAction>>(); constructMenuItem, SwitchScreenAction>>(); +#ifdef FEATURE_CAN + constructMenuItem, SwitchScreenAction>>(); +#endif constructMenuItem, SwitchScreenAction, StaticMenuItemIcon<&icons::back>>>(); } }; diff --git a/main/displays/menus/wifiscanmenu.h b/main/displays/menus/wifiscanmenu.h index 989006c..04981c1 100644 --- a/main/displays/menus/wifiscanmenu.h +++ b/main/displays/menus/wifiscanmenu.h @@ -1,6 +1,15 @@ #pragma once +// system includes +#include + +// esp-idf includes +#include + +// 3rdparty lib includes #include +#include +#include // local includes #include "menudisplay.h" @@ -10,12 +19,15 @@ #include "actions/dummyaction.h" #include "icons/back.h" #include "texts.h" +#include "wifi_bobbycar.h" // forward declares namespace { class WifiSettingsMenu; } // namespace +using namespace std::chrono_literals; + namespace { class WifiScanMenu : public MenuDisplay, public BackActionInterface> { @@ -31,7 +43,7 @@ public: void stop() override; private: - espchrono::millis_clock::time_point m_lastScanComplete; + std::optional m_lastScanComplete; std::vector>> m_reusableItems; }; @@ -43,13 +55,13 @@ WifiScanMenu::WifiScanMenu() std::string WifiScanMenu::text() const { - auto text = std::to_string(menuItemCount()-1) + " found"; - //switch (WiFi.scanComplete()) - //{ - //case WIFI_SCAN_RUNNING: text += " (scanning)"; break; - //case WIFI_SCAN_FAILED: text += " (error)"; break; - //} - text += " (not implemented)"; + const auto scanStatus = wifi_stack::get_scan_status(); + auto text = wifi_stack::toString(scanStatus); + + if (scanStatus != wifi_stack::WiFiScanStatus::Scanning) + if (const auto &result = wifi_stack::get_scan_result()) + text += fmt::format(" ({} found)", result->entries.size()); + return text; } @@ -59,63 +71,73 @@ void WifiScanMenu::start() m_lastScanComplete = {}; - //WiFi.scanNetworks(true); + if (wifi_stack::get_scan_status() != wifi_stack::WiFiScanStatus::Scanning) + if (const auto result = wifi_scan(); result != ESP_OK) + ESP_LOGE("BOBBY", "wifi_scan() failed with %s", esp_err_to_name(result)); } void WifiScanMenu::update() { - //const auto n = WiFi.scanComplete(); - //if (n >= 0) - //{ - // const auto now = espchrono::millis_clock::now(); - // if (!m_lastScanComplete) - // { - // auto backButton = takeLastMenuItem(); - // - // for (std::size_t i = 0; i < n; i++) - // { - // const auto ssid = to_string(WiFi.SSID(i)); - // if (menuItemCount() <= i) - // { - // if (m_reusableItems.empty()) - // { - // auto &item = constructMenuItem>(); - // item.setTitle(ssid); - // } - // else - // { - // std::unique_ptr> ptr = std::move(m_reusableItems.back()); - // m_reusableItems.pop_back(); - // ptr->setTitle(ssid); - // emplaceMenuItem(std::move(ptr)); - // } - // } - // else - // { - // auto &item = *(makeComponent*)(&getMenuItem(i)); - // item.setTitle(ssid); - // } - // } - // - // while (menuItemCount() > n) - // m_reusableItems.emplace_back((makeComponent*)takeLastMenuItem().release()); - // - // emplaceMenuItem(std::move(backButton)); - // - // m_lastScanComplete = now; - // } - // else if (now - m_lastScanComplete >= 2000) - // { - // m_lastScanComplete = 0; - // WiFi.scanNetworks(true); - // } - //} + if (wifi_stack::get_scan_status() == wifi_stack::WiFiScanStatus::Scanning) + { + // TODO + } + else + { + const auto now = espchrono::millis_clock::now(); + + if (!m_lastScanComplete) + { + const auto &result = wifi_stack::get_scan_result(); + + auto backButton = takeLastMenuItem(); + + for (std::size_t i = 0; i < (result ? result->entries.size() : 0); i++) + { + std::string ssid{reinterpret_cast(result->entries[i].ssid)}; + if (menuItemCount() <= i) + { + if (m_reusableItems.empty()) + { + auto &item = constructMenuItem>(); + item.setTitle(std::move(ssid)); + } + else + { + std::unique_ptr> ptr = std::move(m_reusableItems.back()); + m_reusableItems.pop_back(); + ptr->setTitle(std::move(ssid)); + emplaceMenuItem(std::move(ptr)); + } + } + else + { + auto &item = *(makeComponent*)(&getMenuItem(i)); + item.setTitle(std::move(ssid)); + } + } + + while (menuItemCount() > (result ? result->entries.size() : 0)) + m_reusableItems.emplace_back((makeComponent*)takeLastMenuItem().release()); + + emplaceMenuItem(std::move(backButton)); + + m_lastScanComplete = now; + } + else if (espchrono::ago(*m_lastScanComplete) >= 10s) + { + m_lastScanComplete = {}; + + if (const auto result = wifi_scan(); result != ESP_OK) + ESP_LOGE("BOBBY", "wifi_scan() failed with %s", esp_err_to_name(result)); + } + } Base::update(); } void WifiScanMenu::stop() { - //WiFi.scanDelete(); + wifi_stack::delete_scan_result(); } } // namespace diff --git a/main/displays/menus/wifisettingsmenu.h b/main/displays/menus/wifisettingsmenu.h index a9f0a1b..cab656e 100644 --- a/main/displays/menus/wifisettingsmenu.h +++ b/main/displays/menus/wifisettingsmenu.h @@ -24,14 +24,6 @@ class SettingsMenu; namespace { class WifiSettingsMenu; -using AutoWifiModeChangeDisplay = makeComponent< - ChangeValueDisplay, - StaticText, - AutoWifiModeAccessor, - BackActionInterface>, - SwitchScreenAction ->; - class WifiSettingsMenu : public MenuDisplay, public StaticText, @@ -40,8 +32,7 @@ class WifiSettingsMenu : public: WifiSettingsMenu() { - constructMenuItem, SwitchScreenAction>>(); - constructMenuItem, ToggleBoolAction, CheckboxIcon, AutoEnableApAccessor>>(); + constructMenuItem, ToggleBoolAction, CheckboxIcon, WifiEnabledAccessor>>(); constructMenuItem, SwitchScreenAction>>(); constructMenuItem, SwitchScreenAction>>(); constructMenuItem, SwitchScreenAction, StaticMenuItemIcon<&icons::scan>>>(); diff --git a/main/icons/logo.h b/main/icons/logo.h index db7ade9..4406913 100644 --- a/main/icons/logo.h +++ b/main/icons/logo.h @@ -4,8 +4,7 @@ namespace { namespace icons { -/* -const Icon<240, 130> logo{{ +constexpr const Icon<240, 130> logo{{ 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0010 (16) pixels 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0020 (32) pixels 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x0030 (48) pixels @@ -1957,6 +1956,5 @@ const Icon<240, 130> logo{{ 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x79D0 (31184) pixels 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, // 0x79E0 (31200) pixels }}; -*/ } } diff --git a/main/main.cpp b/main/main.cpp index 479c147..fd8e3ed 100644 --- a/main/main.cpp +++ b/main/main.cpp @@ -180,11 +180,17 @@ extern "C" void app_main() if (settingsPersister.init()) { - if (settingsPersister.openProfile(0)) - { - loadSettings(); - } + if (!settingsPersister.openCommon()) + ESP_LOGE("BOBBY", "openCommon() failed"); + + if (!settingsPersister.openProfile(0)) + ESP_LOGE("BOBBY", "openProfile(0) failed"); + + loadSettings(); } + else + ESP_LOGE("BOBBY", "init() failed"); + printMemoryStats("loadSettings()"); bootLabel.redraw("deviceName"); @@ -372,8 +378,9 @@ extern "C" void app_main() } #ifdef FEATURE_CAN - if (!lastCanParse || now - *lastCanParse >= 50ms) + if (!lastCanParse || now - *lastCanParse >= 1000ms/settings.boardcomputerHardware.timersSettings.canReceiveRate) { + //can::tryParseCanInput(); can::parseCanInput(); lastCanParse = now; diff --git a/main/presets.h b/main/presets.h index f158a57..0a0fb84 100644 --- a/main/presets.h +++ b/main/presets.h @@ -36,6 +36,8 @@ constexpr Settings::ControllerHardware defaultControllerHardware { #ifdef FEATURE_CAN .sendFrontCanCmd = true, .sendBackCanCmd = true, + .canTransmitTimeout = 200, + .canReceiveTimeout = 0, #endif }; @@ -56,12 +58,13 @@ constexpr Settings::ControllerHardware mosfetsOffControllerHardware { #ifdef FEATURE_CAN .sendFrontCanCmd = true, .sendBackCanCmd = true, + .canTransmitTimeout = 200, + .canReceiveTimeout = 0, #endif }; constexpr Settings::WifiSettings defaultWifiSettings { - .autoWifiMode = WIFI_MODE_APSTA, - .autoEnableAp = true + .wifiEnabled = true }; #ifdef FEATURE_BLUETOOTH @@ -87,6 +90,8 @@ constexpr Settings::ControllerHardware spinnerControllerHardware { #ifdef FEATURE_CAN .sendFrontCanCmd = true, .sendBackCanCmd = true, + .canTransmitTimeout = 200, + .canReceiveTimeout = 0, #endif }; @@ -95,7 +100,10 @@ constexpr Settings::BoardcomputerHardware::TimersSettings defaultTimersSettings .modeUpdateRate = 50, .statsUpdateRate = 50, .displayUpdateRate = 50, - .displayRedrawRate = 50 + .displayRedrawRate = 50, +#ifdef FEATURE_CAN + .canReceiveRate = 100, +#endif }; constexpr Settings::BoardcomputerHardware defaultBoardcomputerHardware { diff --git a/main/screens.h b/main/screens.h index 374cd46..07d9bfb 100644 --- a/main/screens.h +++ b/main/screens.h @@ -50,7 +50,7 @@ void initScreen() tft.fillScreen(TFT_WHITE); tft.setTextColor(TFT_BLACK, TFT_WHITE); tft.setTextFont(4); - //tft.pushImage(0, 40, icons::logo.WIDTH, icons::logo.HEIGHT, icons::logo.buffer); + tft.pushImage(0, 40, icons::logo.WIDTH, icons::logo.HEIGHT, icons::logo.buffer); tft.drawString("Bobbycar-OS", 32, 200); tft.drawString("booting...", 32, 225); bootLabel.start(); diff --git a/main/settings.h b/main/settings.h index f2665b0..428fd26 100644 --- a/main/settings.h +++ b/main/settings.h @@ -35,8 +35,7 @@ struct Settings } limits; struct WifiSettings { - wifi_mode_t autoWifiMode; - bool autoEnableAp; + bool wifiEnabled; } wifiSettings; #ifdef FEATURE_BLUETOOTH @@ -57,6 +56,8 @@ struct Settings #ifdef FEATURE_CAN bool sendFrontCanCmd; bool sendBackCanCmd; + int16_t canTransmitTimeout; // in ms + int16_t canReceiveTimeout; // in ms #endif } controllerHardware; @@ -77,6 +78,9 @@ struct Settings int16_t statsUpdateRate; int16_t displayUpdateRate; int16_t displayRedrawRate; +#ifdef FEATURE_CAN + int16_t canReceiveRate; +#endif } timersSettings; } boardcomputerHardware; @@ -107,44 +111,24 @@ struct Settings template - void executeForEverySetting(T &&callable); + void executeForEveryCommonSetting(T &&callable); + + template + void executeForEveryProfileSetting(T &&callable); }; template -void Settings::executeForEverySetting(T &&callable) +void Settings::executeForEveryCommonSetting(T &&callable) { #ifdef FEATURE_BMS callable("autoConnectBms", autoConnectBms); #endif - callable("reverseBeep", reverseBeep); - callable("revBeepFreq0", reverseBeepFreq0); - callable("revBeepFreq1", reverseBeepFreq1); - callable("revBeepDur0", reverseBeepDuration0); - callable("revBeepDur1", reverseBeepDuration1); - - callable("iMotMax", limits.iMotMax); - callable("iDcMax", limits.iDcMax); - callable("nMotMax", limits.nMotMax); - callable("fieldWeakMax", limits.fieldWeakMax); - callable("phaseAdvMax", limits.phaseAdvMax); - #ifdef FEATURE_BLUETOOTH callable("autoBluetoothMo", bluetoothSettings.autoBluetoothMode); #endif - callable("autoWifiMode", wifiSettings.autoWifiMode); - callable("autoEnableAp", wifiSettings.autoEnableAp); - - callable("enableFrontLeft", controllerHardware.enableFrontLeft); - callable("enableFrontRigh", controllerHardware.enableFrontRight); - callable("enableBackLeft", controllerHardware.enableBackLeft); - callable("enableBackRight", controllerHardware.enableBackRight); - - callable("invertFrontLeft", controllerHardware.invertFrontLeft); - callable("invertFrontRigh", controllerHardware.invertFrontRight); - callable("invertBackLeft", controllerHardware.invertBackLeft); - callable("invertBackRight", controllerHardware.invertBackRight); + callable("wifiEnabled", wifiSettings.wifiEnabled); callable("wheelDiameter", controllerHardware.wheelDiameter); callable("numMagnetPoles", controllerHardware.numMagnetPoles); @@ -152,6 +136,8 @@ void Settings::executeForEverySetting(T &&callable) #ifdef FEATURE_CAN callable("sendFrontCanCmd", controllerHardware.sendFrontCanCmd); callable("sendBackCanCmd", controllerHardware.sendBackCanCmd); + callable("canTransmitTime", controllerHardware.canTransmitTimeout); + callable("canReceiveTimeo", controllerHardware.canReceiveTimeout); #endif callable("sampleCount", boardcomputerHardware.sampleCount); @@ -177,6 +163,35 @@ void Settings::executeForEverySetting(T &&callable) callable("statsUpdateRate", boardcomputerHardware.timersSettings.statsUpdateRate); callable("displayUpdateRa", boardcomputerHardware.timersSettings.displayUpdateRate); callable("displayRedrawRa", boardcomputerHardware.timersSettings.displayRedrawRate); +#ifdef FEATURE_CAN + callable("canReceiveRate", boardcomputerHardware.timersSettings.canReceiveRate); +#endif +} + +template +void Settings::executeForEveryProfileSetting(T &&callable) +{ + callable("reverseBeep", reverseBeep); + callable("revBeepFreq0", reverseBeepFreq0); + callable("revBeepFreq1", reverseBeepFreq1); + callable("revBeepDur0", reverseBeepDuration0); + callable("revBeepDur1", reverseBeepDuration1); + + callable("iMotMax", limits.iMotMax); + callable("iDcMax", limits.iDcMax); + callable("nMotMax", limits.nMotMax); + callable("fieldWeakMax", limits.fieldWeakMax); + callable("phaseAdvMax", limits.phaseAdvMax); + + callable("enableFrontLeft", controllerHardware.enableFrontLeft); + callable("enableFrontRigh", controllerHardware.enableFrontRight); + callable("enableBackLeft", controllerHardware.enableBackLeft); + callable("enableBackRight", controllerHardware.enableBackRight); + + callable("invertFrontLeft", controllerHardware.invertFrontLeft); + callable("invertFrontRigh", controllerHardware.invertFrontRight); + callable("invertBackLeft", controllerHardware.invertBackLeft); + callable("invertBackRight", controllerHardware.invertBackRight); callable("default.modelMo", defaultMode.modelMode); callable("default.enableS", defaultMode.enableSmoothing); diff --git a/main/settingspersister.h b/main/settingspersister.h index bc2fe0b..27e0805 100644 --- a/main/settingspersister.h +++ b/main/settingspersister.h @@ -5,6 +5,10 @@ #include #include +#include + +#include +#include #include "settings.h" #ifdef FEATURE_BLUETOOTH @@ -18,6 +22,8 @@ class SettingsPersister public: bool init(); bool erase(); + bool openCommon(); + void closeCommon(); bool openProfile(uint8_t index); void closeProfile(); bool load(Settings &settings); @@ -26,6 +32,9 @@ public: std::optional currentlyOpenProfileIndex() const; private: + // for common settings + nvs_handle m_handle{}; + struct CurrentlyOpenProfile { nvs_handle handle; uint8_t profileIndex; @@ -35,17 +44,15 @@ private: 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) + if (esp_err_t result = nvs_flash_init(); + cpputils::is_in(result, ESP_ERR_NVS_NO_FREE_PAGES, ESP_ERR_NVS_NEW_VERSION_FOUND)) { - //Serial.printf("nvs_flash_init() returned: %s, trying to erase\r\n", esp_err_to_name(err)); - + ESP_LOGE("BOBBY", "nvs_flash_init() failed with %s, trying to erase...", esp_err_to_name(result)); return erase(); } - - if (err != ESP_OK) + else if (result != ESP_OK) { - //Serial.printf("nvs_flash_init() returned: %s\r\n", esp_err_to_name(err)); + ESP_LOGE("BOBBY", "nvs_flash_init() failed with %s", esp_err_to_name(result)); return false; } @@ -54,32 +61,61 @@ bool SettingsPersister::init() bool SettingsPersister::erase() { - esp_err_t err = nvs_flash_erase(); - if (err != ESP_OK) + closeProfile(); + closeCommon(); + + bool result{true}; + + if (esp_err_t result = nvs_flash_erase(); result != ESP_OK) { - //Serial.printf("nvs_flash_erase() returned: %s, aborting\r\n", esp_err_to_name(err)); + ESP_LOGE("BOBBY", "nvs_flash_erase() failed with %s", esp_err_to_name(result)); + result = false; + } + + if (esp_err_t result = nvs_flash_init(); result != ESP_OK) + { + ESP_LOGE("BOBBY", "nvs_flash_init() failed with %s", esp_err_to_name(result)); + result = false; + } + + return result; +} + +bool SettingsPersister::openCommon() +{ + closeCommon(); + + nvs_handle handle; + if (esp_err_t result = nvs_open("bobbycar", NVS_READWRITE, &handle); result != ESP_OK) + { + ESP_LOGE("BOBBY", "nvs_open() COMMON %s failed with %s", "bobbycar", esp_err_to_name(result)); 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; - } + m_handle = handle; return true; } +void SettingsPersister::closeCommon() +{ + if (!m_handle) + return; + + nvs_close(m_handle); + + m_handle = {}; +} + bool SettingsPersister::openProfile(uint8_t index) { closeProfile(); nvs_handle handle; - esp_err_t err = nvs_open(("bobbycar"+std::to_string(index)).c_str(), NVS_READWRITE, &handle); - if (err != ESP_OK) + const auto name = fmt::format("bobbycar{}", index); + if (esp_err_t result = nvs_open(name.c_str(), NVS_READWRITE, &handle); result != ESP_OK) { - //Serial.printf("nvs_open() returned: %s\r\n", esp_err_to_name(err)); + ESP_LOGE("BOBBY", "nvs_open() PROFILE %s failed with %s", name.c_str(), esp_err_to_name(result)); return false; } @@ -166,23 +202,41 @@ template<> struct nvsGetterHelper { static esp_err_t nvs_get(nvs_ha 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) + if (m_handle) { - esp_err_t err = nvsGetterHelper>::nvs_get(m_profile->handle, key, &value); - if (err != ESP_OK) + settings.executeForEveryCommonSetting([&](const char *key, auto &value) { - //Serial.printf("nvs_get_i32() for %s returned: %s\r\n", key, esp_err_to_name(err)); - result = false; - } - }); + if (esp_err_t result = nvsGetterHelper>::nvs_get(m_handle, key, &value); result != ESP_OK) + { + ESP_LOGE("BOBBY", "nvs_get() COMMON %s failed with %s", key, esp_err_to_name(result)); + result = false; + } + }); + } + else + { + ESP_LOGW("BOBBY", "common nvs handle not valid!"); + result = false; + } + + if (m_profile) + { + settings.executeForEveryProfileSetting([&](const char *key, auto &value) + { + if (esp_err_t result = nvsGetterHelper>::nvs_get(m_profile->handle, key, &value); result != ESP_OK) + { + ESP_LOGE("BOBBY", "nvs_get() PROFILE %s failed with %s", key, esp_err_to_name(result)); + result = false; + } + }); + } + else + { + ESP_LOGW("BOBBY", "no profile open currently!"); + result = false; + } return result; } @@ -224,23 +278,41 @@ template<> struct nvsSetterHelper { static esp_err_t nvs_set(nvs_ha 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) + if (m_handle) { - esp_err_t err = nvsSetterHelper::nvs_set(m_profile->handle, key, value); - if (err != ESP_OK) + settings.executeForEveryCommonSetting([&](const char *key, auto value) { - //Serial.printf("nvs_get_i32() for %s returned: %s\r\n", key, esp_err_to_name(err)); - result = false; - } - }); + if (esp_err_t result = nvsSetterHelper::nvs_set(m_handle, key, value); result != ESP_OK) + { + ESP_LOGE("BOBBY", "nvs_set() PROFILE %s failed with %s", key, esp_err_to_name(result)); + result = false; + } + }); + } + else + { + ESP_LOGW("BOBBY", "common nvs handle not valid!"); + result = false; + } + + if (m_profile) + { + settings.executeForEveryProfileSetting([&](const char *key, auto value) + { + if (esp_err_t result = nvsSetterHelper::nvs_set(m_profile->handle, key, value); result != ESP_OK) + { + ESP_LOGE("BOBBY", "nvs_set() PROFILE %s failed with %s", key, esp_err_to_name(result)); + result = false; + } + }); + } + else + { + ESP_LOGW("BOBBY", "no profile open currently!"); + result = false; + } return result; } diff --git a/main/settingsutils.h b/main/settingsutils.h index 3cec2e1..61e29e1 100644 --- a/main/settingsutils.h +++ b/main/settingsutils.h @@ -1,5 +1,8 @@ #pragma once +// esp-idf includes +#include + // local includes #include "globals.h" #include "presets.h" @@ -9,16 +12,16 @@ void switchProfile(uint8_t index) { settings = presets::defaultSettings; - if (settingsPersister.openProfile(index)) + if (!settingsPersister.openProfile(index)) { - if (!settingsPersister.load(settings)) - { - //Serial.println("switchProfile() load failed"); - } + ESP_LOGE("BOBBY", "openProfile() failed"); + return; } - else + + if (!settingsPersister.load(settings)) { - //Serial.println("switchProfile() openProfile failed"); + ESP_LOGE("BOBBY", "load() failed"); + return; } } } diff --git a/main/texts.h b/main/texts.h index 8b0ee58..f7d95eb 100644 --- a/main/texts.h +++ b/main/texts.h @@ -99,13 +99,14 @@ constexpr char TEXT_SWAPFRONTBACK[] = "Swap front/back"; #ifdef FEATURE_CAN constexpr char TEXT_FRONTSENDCAN[] = "Front send CAN"; constexpr char TEXT_BACKSENDCAN[] = "Back send CAN"; +constexpr char TEXT_CANTRANSMITTIMEOUT[] = "CanTransmitTimeout"; +constexpr char TEXT_CANRECEIVETIMEOUT[] = "CanReceiveTimeout"; #endif //constexpr char TEXT_BACK[] = "Back"; //StationWifiSettingsMenu constexpr char TEXT_STATIONWIFISETTINGS[] = "Station WiFi settings"; -constexpr char TEXT_AUTOWIFIMODE[] = "Auto wifi mode"; -constexpr char TEXT_AUTOENABLEAP[] = "Auto enable AP"; +constexpr char TEXT_WIFIENABLED[] = "WiFi enabled"; constexpr char TEXT_WIFIRECONNECT[] = "reconnect()"; constexpr char TEXT_WIFIDISCONNECT[] = "disconnect()"; constexpr char TEXT_WIFICHANGEAUTOCONNECT[] = "Change auto connect"; @@ -310,6 +311,9 @@ constexpr char TEXT_MODEUPDATERATE[] = "Mode update rate"; constexpr char TEXT_STATSUPDATERATE[] = "Stats update rate"; constexpr char TEXT_DISPLAYUPDATERATE[] = "Display update rate"; constexpr char TEXT_DISPLAYREDRAWRATE[] = "Display redraw rate"; +#ifdef FEATURE_CAN +constexpr char TEXT_CANRECEIVERATE[] = "CAN receive rate"; +#endif //constexpr char TEXT_BACK[] = "Back"; //ChangeValueDisplay diff --git a/main/webserver.h b/main/webserver.h index f035027..ab22349 100644 --- a/main/webserver.h +++ b/main/webserver.h @@ -297,7 +297,7 @@ esp_err_t webserver_triggerItem_handler(httpd_req_t *req) if (!menuDisplay) CALL_AND_EXIT(httpd_resp_send_err, req, HTTPD_400_BAD_REQUEST, "currentDisplay is not a menu display"); - if (index < 0 || index >= menuDisplay->menuItemCount()) + if (/*index < 0 ||*/ index >= menuDisplay->menuItemCount()) CALL_AND_EXIT(httpd_resp_send_err, req, HTTPD_400_BAD_REQUEST, fmt::format("{} out of range", indexParamName).c_str()); menuDisplay->getMenuItem(index).triggered(); diff --git a/main/wifi_bobbycar.h b/main/wifi_bobbycar.h index 4a70003..46a279e 100644 --- a/main/wifi_bobbycar.h +++ b/main/wifi_bobbycar.h @@ -1,5 +1,8 @@ #pragma once +// esp-idf includes +#include + // 3rdparty lib includes #include @@ -10,7 +13,7 @@ namespace { wifi_stack::config wifi_create_config() { static wifi_stack::config config { - .wifiEnabled = true, + .wifiEnabled = settings.wifiSettings.wifiEnabled, .hostname = deviceName, .sta = { .wifis = std::array { @@ -49,44 +52,21 @@ wifi_stack::config wifi_create_config() void wifi_begin() { wifi_stack::init(wifi_create_config()); - //bootLabel.redraw("setHostname"); - //if (!WiFi.setHostname(deviceName)) - //{ - //Serial.println("Could not setHostname"); - //} - //printMemoryStats("setHostname()"); - - //bootLabel.redraw("softAPsetHostname"); - //if (!WiFi.softAPsetHostname(deviceName)) - //{ - //Serial.println("Could not softAPsetHostname"); - //} - //printMemoryStats("softAPsetHostname()"); - - //bootLabel.redraw("WiFi mode"); - //if (!WiFi.mode(settings.wifiSettings.autoWifiMode)) - //{ - //Serial.println("Could not set mode to WIFI_AP_STA"); - //} - //printMemoryStats("WiFi.mode()"); - - //if (settings.wifiSettings.autoEnableAp) - //{ - //bootLabel.redraw("WiFi softAp"); - //WifiSoftApAction{}.triggered(); - //printMemoryStats("WifiSoftApAction()"); - //} - - //bootLabel.redraw("WiFi begin"); - //if (!WiFi.begin("realraum", "r3alraum")) - //{ - //Serial.println("Could not begin WiFi"); - //} - //printMemoryStats("WiFi.begin()"); } void wifi_update() { wifi_stack::update(wifi_create_config()); } + +esp_err_t wifi_scan() +{ + if (const auto result = wifi_stack::begin_scan(wifi_create_config()); result != ESP_OK) + { + ESP_LOGE("BOBBY", "begin_scan() failed with %s", esp_err_to_name(result)); + return result; + } + + return ESP_OK; +} } // namespace