From 3ea02d912f2cdc62a3487b0a018ffc2ff537bba4 Mon Sep 17 00:00:00 2001 From: Ken Van Hoeylandt Date: Fri, 17 Jan 2025 19:37:42 +0100 Subject: [PATCH] Merge develop into main (#167) - WiFi Connect app is now hidden by default, but accessible at the bottom of the WiFi Manage app when WiFi is turned on. - WiFi service now turns on WiFi when calling connect() and WiFi is not on. - Removed `blocking` option for `service::loader::startApp()`. This feature was unused and complex. - Various apps: Moved private headers into Private/ folder. - Various apps: created start() function for easy starting. - Added documentation to all TactilityC APIs - Refactored various `enum` into `class enum` - Refactor M5Stack `initBoot()` (but VBus is still 0V for some reason) --- Boards/LilygoTdeck/Source/LilygoTdeck.cpp | 4 +- Boards/LilygoTdeck/Source/hal/TdeckPower.cpp | 16 +- Boards/LilygoTdeck/Source/hal/TdeckSdCard.cpp | 2 +- Boards/M5stackCore2/Source/InitBoot.cpp | 4 +- Boards/M5stackCore2/Source/M5stackCore2.cpp | 4 +- Boards/M5stackCore2/Source/hal/Core2Power.cpp | 16 +- .../M5stackCore2/Source/hal/Core2SdCard.cpp | 2 +- Boards/M5stackCoreS3/CMakeLists.txt | 2 +- Boards/M5stackCoreS3/Source/Aw9523/Aw9523.cpp | 24 +++ Boards/M5stackCoreS3/Source/Aw9523/Aw9523.h | 20 ++ .../M5stackCoreS3/Source/Axp2101/Axp2101.cpp | 61 +++---- Boards/M5stackCoreS3/Source/Axp2101/Axp2101.h | 23 +-- .../Source/I2cDevice/I2cDevice.cpp | 59 ++++++ .../Source/I2cDevice/I2cDevice.h | 25 +++ Boards/M5stackCoreS3/Source/InitBoot.cpp | 154 ++++++++++++---- Boards/M5stackCoreS3/Source/M5stackCoreS3.cpp | 4 +- .../Source/hal/CoreS3Display.cpp | 2 +- .../M5stackCoreS3/Source/hal/CoreS3Power.cpp | 16 +- .../M5stackCoreS3/Source/hal/CoreS3SdCard.cpp | 2 +- Boards/Simulator/Source/LvglTask.cpp | 4 +- Boards/Simulator/Source/hal/Configuration.cpp | 4 +- .../Simulator/Source/hal/SimulatorPower.cpp | 16 +- Boards/Simulator/Source/hal/SimulatorSdCard.h | 6 +- Boards/YellowBoard/Source/YellowBoard.cpp | 4 +- .../YellowBoard/Source/hal/YellowSdCard.cpp | 2 +- Tactility/Private/app/AppInstance.h | 2 +- .../app/crashdiagnostics/QrHelpers.h | 0 .../app/crashdiagnostics/QrUrl.h | 0 .../{Source => Private}/app/files/FileUtils.h | 0 Tactility/Private/app/files/FilesPrivate.h | 34 ++++ .../{Source => Private}/app/files/State.h | 2 +- .../{Source => Private}/app/files/View.h | 3 +- .../app/i2cscanner/I2cHelpers.h | 0 .../app/i2cscanner/I2cScannerPrivate.h | 37 ++++ .../app/i2cscanner/I2cScannerThread.h | 2 +- .../app/screenshot/ScreenshotUi.h | 0 .../app/wificonnect/Bindings.h | 0 .../app/wificonnect/State.h | 0 .../app/wificonnect/View.h | 0 .../app/wificonnect/WifiConnectPrivate.h | 45 +++++ .../app/wifimanage/Bindings.h | 2 + .../app/wifimanage/State.h | 16 +- .../{Source => Private}/app/wifimanage/View.h | 8 +- .../app/wifimanage/WifiManagePrivate.h | 35 ++++ Tactility/Private/service/gui/Gui_i.h | 2 +- Tactility/Private/service/loader/Loader_i.h | 15 +- Tactility/Source/app/ManifestRegistry.cpp | 2 +- .../Source/app/alertdialog/AlertDialog.cpp | 4 +- .../Source/app/alertdialog/AlertDialog.h | 8 +- Tactility/Source/app/applist/AppList.cpp | 2 +- .../app/crashdiagnostics/CrashDiagnostics.cpp | 6 +- .../Source/app/crashdiagnostics/QrHelpers.cpp | 3 +- .../Source/app/crashdiagnostics/QrUrl.cpp | 2 +- Tactility/Source/app/files/FileUtils.cpp | 3 +- Tactility/Source/app/files/Files.cpp | 8 +- Tactility/Source/app/files/Files.h | 20 +- Tactility/Source/app/files/State.cpp | 5 +- Tactility/Source/app/files/View.cpp | 15 +- Tactility/Source/app/gpio/Gpio.cpp | 2 +- .../Source/app/i2cscanner/I2cHelpers.cpp | 2 +- .../Source/app/i2cscanner/I2cScanner.cpp | 12 +- Tactility/Source/app/i2cscanner/I2cScanner.h | 24 +-- .../app/i2cscanner/I2cScannerThread.cpp | 4 +- .../Source/app/imageviewer/ImageViewer.cpp | 9 +- .../Source/app/imageviewer/ImageViewer.h | 6 +- .../Source/app/inputdialog/InputDialog.cpp | 2 +- Tactility/Source/app/launcher/Launcher.cpp | 3 +- Tactility/Source/app/log/Log.cpp | 15 +- Tactility/Source/app/power/Power.cpp | 10 +- .../Source/app/screenshot/Screenshot.cpp | 2 +- .../Source/app/screenshot/ScreenshotUi.cpp | 8 +- .../app/selectiondialog/SelectionDialog.cpp | 4 +- .../app/selectiondialog/SelectionDialog.h | 2 +- .../Source/app/textviewer/TextViewer.cpp | 9 + Tactility/Source/app/textviewer/TextViewer.h | 6 +- .../app/timedatesettings/TimeDateSettings.cpp | 3 +- Tactility/Source/app/timezone/TimeZone.cpp | 2 +- .../app/wifiapsettings/WifiApSettings.cpp | 4 +- Tactility/Source/app/wificonnect/Parameters.h | 4 - Tactility/Source/app/wificonnect/State.cpp | 2 +- Tactility/Source/app/wificonnect/View.cpp | 13 +- .../Source/app/wificonnect/WifiConnect.cpp | 27 ++- .../Source/app/wificonnect/WifiConnect.h | 46 +---- Tactility/Source/app/wifimanage/State.cpp | 12 +- Tactility/Source/app/wifimanage/View.cpp | 70 +++++-- .../Source/app/wifimanage/WifiManage.cpp | 47 +++-- Tactility/Source/app/wifimanage/WifiManage.h | 29 +-- Tactility/Source/lvgl/Statusbar.cpp | 4 +- Tactility/Source/service/loader/Loader.cpp | 24 ++- Tactility/Source/service/loader/Loader.h | 10 +- .../Source/service/screenshot/Screenshot.cpp | 10 +- .../Source/service/screenshot/Screenshot.h | 14 +- .../service/screenshot/ScreenshotTask.h | 2 +- .../Source/service/statusbar/Statusbar.cpp | 32 ++-- TactilityC/Source/tt_app_alertdialog.cpp | 3 +- TactilityC/Source/tt_app_alertdialog.h | 11 ++ TactilityC/Source/tt_app_context.h | 20 ++ TactilityC/Source/tt_app_manifest.h | 10 + TactilityC/Source/tt_app_selectiondialog.cpp | 3 +- TactilityC/Source/tt_app_selectiondialog.h | 7 + TactilityC/Source/tt_bundle.h | 53 +++++- TactilityC/Source/tt_hal_i2c.cpp | 8 +- TactilityC/Source/tt_hal_i2c.h | 88 ++++++++- TactilityC/Source/tt_init.h | 4 + TactilityC/Source/tt_lvgl_spinner.h | 1 + TactilityC/Source/tt_lvgl_toolbar.h | 3 + TactilityC/Source/tt_message_queue.cpp | 4 + TactilityC/Source/tt_message_queue.h | 38 ++++ TactilityC/Source/tt_mutex.cpp | 4 +- TactilityC/Source/tt_mutex.h | 26 ++- TactilityC/Source/tt_semaphore.h | 30 ++- TactilityC/Source/tt_service_loader.cpp | 4 +- TactilityC/Source/tt_service_loader.h | 16 +- TactilityC/Source/tt_thread.cpp | 4 +- TactilityC/Source/tt_thread.h | 80 +++++++- TactilityC/Source/tt_timer.h | 62 ++++++- TactilityCore/Source/Bundle.cpp | 18 +- TactilityCore/Source/Bundle.h | 10 +- TactilityCore/Source/Dispatcher.cpp | 2 +- TactilityCore/Source/Log.cpp | 20 +- TactilityCore/Source/Log.h | 26 +-- TactilityCore/Source/Mutex.cpp | 12 +- TactilityCore/Source/Mutex.h | 8 +- TactilityCore/Source/Semaphore.h | 2 +- TactilityCore/Source/Thread.cpp | 8 +- TactilityCore/Source/Thread.h | 11 +- TactilityCore/Source/Timer.cpp | 2 +- TactilityCore/Source/Timer.h | 18 +- .../Private/service/ServiceInstance.h | 2 +- TactilityHeadless/Source/hal/Power.h | 10 +- TactilityHeadless/Source/hal/SdCard.h | 18 +- TactilityHeadless/Source/hal/SpiSdCard.cpp | 8 +- TactilityHeadless/Source/hal/i2c/I2c.cpp | 44 ++++- TactilityHeadless/Source/hal/i2c/I2c.h | 18 +- TactilityHeadless/Source/hal/i2c/I2cMock.cpp | 4 +- TactilityHeadless/Source/hal/usb/Usb.cpp | 8 +- TactilityHeadless/Source/hal/usb/Usb.h | 8 +- TactilityHeadless/Source/hal/usb/UsbMock.cpp | 2 +- .../Source/service/ServiceRegistry.cpp | 4 +- .../Source/service/sdcard/Sdcard.cpp | 6 +- .../Source/service/wifi/Wifi.cpp | 23 +++ TactilityHeadless/Source/service/wifi/Wifi.h | 51 +++--- .../Source/service/wifi/WifiEsp.cpp | 171 +++++++++--------- .../Source/service/wifi/WifiMock.cpp | 30 +-- .../Source/service/wifi/WifiSettings.h | 6 +- Tests/TactilityCore/MutexTest.cpp | 2 +- Tests/TactilityCore/TimerTest.cpp | 14 +- 147 files changed, 1538 insertions(+), 739 deletions(-) create mode 100644 Boards/M5stackCoreS3/Source/Aw9523/Aw9523.cpp create mode 100644 Boards/M5stackCoreS3/Source/Aw9523/Aw9523.h create mode 100644 Boards/M5stackCoreS3/Source/I2cDevice/I2cDevice.cpp create mode 100644 Boards/M5stackCoreS3/Source/I2cDevice/I2cDevice.h rename Tactility/{Source => Private}/app/crashdiagnostics/QrHelpers.h (100%) rename Tactility/{Source => Private}/app/crashdiagnostics/QrUrl.h (100%) rename Tactility/{Source => Private}/app/files/FileUtils.h (100%) create mode 100644 Tactility/Private/app/files/FilesPrivate.h rename Tactility/{Source => Private}/app/files/State.h (96%) rename Tactility/{Source => Private}/app/files/View.h (97%) rename Tactility/{Source => Private}/app/i2cscanner/I2cHelpers.h (100%) create mode 100644 Tactility/Private/app/i2cscanner/I2cScannerPrivate.h rename Tactility/{Source => Private}/app/i2cscanner/I2cScannerThread.h (86%) rename Tactility/{Source => Private}/app/screenshot/ScreenshotUi.h (100%) rename Tactility/{Source => Private}/app/wificonnect/Bindings.h (100%) rename Tactility/{Source => Private}/app/wificonnect/State.h (100%) rename Tactility/{Source => Private}/app/wificonnect/View.h (100%) create mode 100644 Tactility/Private/app/wificonnect/WifiConnectPrivate.h rename Tactility/{Source => Private}/app/wifimanage/Bindings.h (83%) rename Tactility/{Source => Private}/app/wifimanage/State.h (55%) rename Tactility/{Source => Private}/app/wifimanage/View.h (77%) create mode 100644 Tactility/Private/app/wifimanage/WifiManagePrivate.h delete mode 100644 Tactility/Source/app/wificonnect/Parameters.h create mode 100644 TactilityHeadless/Source/service/wifi/Wifi.cpp diff --git a/Boards/LilygoTdeck/Source/LilygoTdeck.cpp b/Boards/LilygoTdeck/Source/LilygoTdeck.cpp index f4193696..36d2619e 100644 --- a/Boards/LilygoTdeck/Source/LilygoTdeck.cpp +++ b/Boards/LilygoTdeck/Source/LilygoTdeck.cpp @@ -20,7 +20,7 @@ extern const tt::hal::Configuration lilygo_tdeck = { tt::hal::i2c::Configuration { .name = "Internal", .port = I2C_NUM_0, - .initMode = tt::hal::i2c::InitByTactility, + .initMode = tt::hal::i2c::InitMode::ByTactility, .canReinit = false, .hasMutableConfiguration = false, .config = (i2c_config_t) { @@ -38,7 +38,7 @@ extern const tt::hal::Configuration lilygo_tdeck = { tt::hal::i2c::Configuration { .name = "External", .port = I2C_NUM_1, - .initMode = tt::hal::i2c::InitByTactility, + .initMode = tt::hal::i2c::InitMode::ByTactility, .canReinit = true, .hasMutableConfiguration = true, .config = (i2c_config_t) { diff --git a/Boards/LilygoTdeck/Source/hal/TdeckPower.cpp b/Boards/LilygoTdeck/Source/hal/TdeckPower.cpp index 834d074f..56e97d81 100644 --- a/Boards/LilygoTdeck/Source/hal/TdeckPower.cpp +++ b/Boards/LilygoTdeck/Source/hal/TdeckPower.cpp @@ -56,11 +56,11 @@ TdeckPower::~TdeckPower() { bool TdeckPower::supportsMetric(MetricType type) const { switch (type) { - case BATTERY_VOLTAGE: - case CHARGE_LEVEL: + case MetricType::BatteryVoltage: + case MetricType::ChargeLevel: return true; - case IS_CHARGING: - case CURRENT: + case MetricType::IsCharging: + case MetricType::Current: return false; } @@ -69,17 +69,17 @@ bool TdeckPower::supportsMetric(MetricType type) const { bool TdeckPower::getMetric(Power::MetricType type, Power::MetricData& data) { switch (type) { - case BATTERY_VOLTAGE: + case MetricType::BatteryVoltage: return readBatteryVoltageSampled(data.valueAsUint32); - case CHARGE_LEVEL: + case MetricType::ChargeLevel: if (readBatteryVoltageSampled(data.valueAsUint32)) { data.valueAsUint32 = estimateChargeLevelFromVoltage(data.valueAsUint32); return true; } else { return false; } - case IS_CHARGING: - case CURRENT: + case MetricType::IsCharging: + case MetricType::Current: return false; } diff --git a/Boards/LilygoTdeck/Source/hal/TdeckSdCard.cpp b/Boards/LilygoTdeck/Source/hal/TdeckSdCard.cpp index 26589583..02dc0bb9 100644 --- a/Boards/LilygoTdeck/Source/hal/TdeckSdCard.cpp +++ b/Boards/LilygoTdeck/Source/hal/TdeckSdCard.cpp @@ -18,7 +18,7 @@ std::shared_ptr createTdeckSdCard() { GPIO_NUM_NC, GPIO_NUM_NC, GPIO_NUM_NC, - SdCard::MountBehaviourAtBoot, + SdCard::MountBehaviour::AtBoot, tt::lvgl::getLvglSyncLockable(), { TDECK_RADIO_PIN_CS, diff --git a/Boards/M5stackCore2/Source/InitBoot.cpp b/Boards/M5stackCore2/Source/InitBoot.cpp index 143c3dfd..c33e6953 100644 --- a/Boards/M5stackCore2/Source/InitBoot.cpp +++ b/Boards/M5stackCore2/Source/InitBoot.cpp @@ -16,11 +16,11 @@ axp192_t axpDevice; static int32_t axpI2cRead(TT_UNUSED void* handle, uint8_t address, uint8_t reg, uint8_t* buffer, uint16_t size) { - return tt::hal::i2c::masterRead(I2C_NUM_0, address, reg, buffer, size, 50 / portTICK_PERIOD_MS); + return tt::hal::i2c::masterReadRegister(I2C_NUM_0, address, reg, buffer, size, 50 / portTICK_PERIOD_MS); } static int32_t axpI2cWrite(TT_UNUSED void* handle, uint8_t address, uint8_t reg, const uint8_t* buffer, uint16_t size) { - return tt::hal::i2c::masterWrite(I2C_NUM_0, address, reg, buffer, size, 50 / portTICK_PERIOD_MS); + return tt::hal::i2c::masterWriteRegister(I2C_NUM_0, address, reg, buffer, size, 50 / portTICK_PERIOD_MS); } static bool initSpi2() { diff --git a/Boards/M5stackCore2/Source/M5stackCore2.cpp b/Boards/M5stackCore2/Source/M5stackCore2.cpp index a8b4608d..ddbf0c03 100644 --- a/Boards/M5stackCore2/Source/M5stackCore2.cpp +++ b/Boards/M5stackCore2/Source/M5stackCore2.cpp @@ -15,7 +15,7 @@ extern const tt::hal::Configuration m5stack_core2 = { tt::hal::i2c::Configuration { .name = "Internal", .port = I2C_NUM_0, - .initMode = tt::hal::i2c::InitByTactility, + .initMode = tt::hal::i2c::InitMode::ByTactility, .canReinit = false, // Might be set to try after trying out what it does AXP and screen .hasMutableConfiguration = false, .config = (i2c_config_t) { @@ -33,7 +33,7 @@ extern const tt::hal::Configuration m5stack_core2 = { tt::hal::i2c::Configuration { .name = "External", // (Grove) .port = I2C_NUM_1, - .initMode = tt::hal::i2c::InitByTactility, + .initMode = tt::hal::i2c::InitMode::ByTactility, .canReinit = true, .hasMutableConfiguration = true, .config = (i2c_config_t) { diff --git a/Boards/M5stackCore2/Source/hal/Core2Power.cpp b/Boards/M5stackCore2/Source/hal/Core2Power.cpp index 7c68c0b6..1501169f 100644 --- a/Boards/M5stackCore2/Source/hal/Core2Power.cpp +++ b/Boards/M5stackCore2/Source/hal/Core2Power.cpp @@ -8,11 +8,11 @@ extern axp192_t axpDevice; bool Core2Power::supportsMetric(MetricType type) const { switch (type) { - case BATTERY_VOLTAGE: - case CHARGE_LEVEL: - case IS_CHARGING: + case MetricType::BatteryVoltage: + case MetricType::ChargeLevel: + case MetricType::IsCharging: return true; - case CURRENT: + case MetricType::Current: return false; } @@ -21,7 +21,7 @@ bool Core2Power::supportsMetric(MetricType type) const { bool Core2Power::getMetric(Power::MetricType type, Power::MetricData& data) { switch (type) { - case BATTERY_VOLTAGE: { + case MetricType::BatteryVoltage: { float voltage; if (axp192_read(&axpDevice, AXP192_BATTERY_VOLTAGE, &voltage) == ESP_OK) { data.valueAsUint32 = (uint32_t)TT_MAX((voltage * 1000.f), 0.0f); @@ -30,7 +30,7 @@ bool Core2Power::getMetric(Power::MetricType type, Power::MetricData& data) { return false; } } - case CHARGE_LEVEL: { + case MetricType::ChargeLevel: { float vbat, charge_current; if ( axp192_read(&axpDevice, AXP192_BATTERY_VOLTAGE, &vbat) == ESP_OK && @@ -51,7 +51,7 @@ bool Core2Power::getMetric(Power::MetricType type, Power::MetricData& data) { return false; } } - case IS_CHARGING: { + case MetricType::IsCharging: { float charge_current; if (axp192_read(&axpDevice, AXP192_CHARGE_CURRENT, &charge_current) == ESP_OK) { data.valueAsBool = charge_current > 0.001f; @@ -60,7 +60,7 @@ bool Core2Power::getMetric(Power::MetricType type, Power::MetricData& data) { return false; } } - case CURRENT: { + case MetricType::Current: { float charge_current, discharge_current; if ( axp192_read(&axpDevice, AXP192_CHARGE_CURRENT, &charge_current) == ESP_OK && diff --git a/Boards/M5stackCore2/Source/hal/Core2SdCard.cpp b/Boards/M5stackCore2/Source/hal/Core2SdCard.cpp index 2e6e4310..fac1b7c5 100644 --- a/Boards/M5stackCore2/Source/hal/Core2SdCard.cpp +++ b/Boards/M5stackCore2/Source/hal/Core2SdCard.cpp @@ -16,7 +16,7 @@ std::shared_ptr createSdCard() { GPIO_NUM_NC, GPIO_NUM_NC, GPIO_NUM_NC, - SdCard::MountBehaviourAtBoot, + SdCard::MountBehaviour::AtBoot, tt::lvgl::getLvglSyncLockable(), { CORE2_LCD_PIN_CS diff --git a/Boards/M5stackCoreS3/CMakeLists.txt b/Boards/M5stackCoreS3/CMakeLists.txt index 6c14c994..4f6440a1 100644 --- a/Boards/M5stackCoreS3/CMakeLists.txt +++ b/Boards/M5stackCoreS3/CMakeLists.txt @@ -1,5 +1,5 @@ idf_component_register( - SRC_DIRS "Source" "Source/hal" "Source/Axp2101" + SRC_DIRS "Source" "Source/hal" "Source/Axp2101" "Source/Aw9523" "Source/I2cDevice" INCLUDE_DIRS "Source" REQUIRES Tactility esp_lvgl_port esp_lcd esp_lcd_ili9341 esp_lcd_touch_ft5x06 driver vfs fatfs ) diff --git a/Boards/M5stackCoreS3/Source/Aw9523/Aw9523.cpp b/Boards/M5stackCoreS3/Source/Aw9523/Aw9523.cpp new file mode 100644 index 00000000..e1c0a889 --- /dev/null +++ b/Boards/M5stackCoreS3/Source/Aw9523/Aw9523.cpp @@ -0,0 +1,24 @@ +#include "Aw9523.h" + +#define AW9523_REGISTER_P0 0x02 +#define AW9523_REGISTER_P1 0x03 + +bool Aw9523::readP0(uint8_t& output) const { + return readRegister8(AW9523_REGISTER_P0, output); +} + +bool Aw9523::readP1(uint8_t& output) const { + return readRegister8(AW9523_REGISTER_P1, output); +} + +bool Aw9523::writeP0(uint8_t value) const { + return writeRegister8(AW9523_REGISTER_P0, value); +} + +bool Aw9523::writeP1(uint8_t value) const { + return writeRegister8(AW9523_REGISTER_P1, value); +} + +bool Aw9523::bitOnP1(uint8_t bitmask) const { + return bitOn(AW9523_REGISTER_P1, bitmask); +} diff --git a/Boards/M5stackCoreS3/Source/Aw9523/Aw9523.h b/Boards/M5stackCoreS3/Source/Aw9523/Aw9523.h new file mode 100644 index 00000000..cc3c8c20 --- /dev/null +++ b/Boards/M5stackCoreS3/Source/Aw9523/Aw9523.h @@ -0,0 +1,20 @@ +#pragma once + +#include "I2cDevice/I2cDevice.h" + +#define AW9523_ADDRESS 0x58 + +class Aw9523 : I2cDevice { + +public: + + explicit Aw9523(i2c_port_t port) : I2cDevice(port, AW9523_ADDRESS) {} + + bool readP0(uint8_t& output) const; + bool readP1(uint8_t& output) const; + + bool writeP0(uint8_t value) const; + bool writeP1(uint8_t value) const; + + bool bitOnP1(uint8_t bitmask) const; +}; diff --git a/Boards/M5stackCoreS3/Source/Axp2101/Axp2101.cpp b/Boards/M5stackCoreS3/Source/Axp2101/Axp2101.cpp index 675157a7..80efff44 100644 --- a/Boards/M5stackCoreS3/Source/Axp2101/Axp2101.cpp +++ b/Boards/M5stackCoreS3/Source/Axp2101/Axp2101.cpp @@ -1,44 +1,6 @@ #include "Axp2101.h" #include "Log.h" -bool Axp2101::readRegister12(uint8_t reg, float& out) const { - std::uint8_t data[2] = {0}; - if (tt::hal::i2c::masterRead(port, DEFAULT_ADDRESS, reg, data, 2, DEFAULT_TIMEOUT) == ESP_OK) { - out = (data[0] & 0x0F) << 8 | data[1]; - return true; - } else { - return false; - } -} - -bool Axp2101::readRegister14(uint8_t reg, float& out) const { - std::uint8_t data[2] = {0}; - if (tt::hal::i2c::masterRead(port, DEFAULT_ADDRESS, reg, data, 2, DEFAULT_TIMEOUT) == ESP_OK) { - out = (data[0] & 0x3F) << 8 | data[1]; - return true; - } else { - return false; - } -} - -bool Axp2101::readRegister16(uint8_t reg, uint16_t& out) const { - std::uint8_t data[2] = {0}; - if (tt::hal::i2c::masterRead(port, DEFAULT_ADDRESS, reg, data, 2, DEFAULT_TIMEOUT) == ESP_OK) { - out = data[0] << 8 | data[1]; - return true; - } else { - return false; - } -} - -bool Axp2101::readRegister8(uint8_t reg, uint8_t& result) const { - return tt::hal::i2c::masterWriteRead(port, DEFAULT_ADDRESS, ®, 1, &result, 1, DEFAULT_TIMEOUT); -} - -bool Axp2101::writeRegister8(uint8_t reg, uint8_t value) const { - return tt::hal::i2c::masterWrite(port, DEFAULT_ADDRESS, reg, &value, 1, DEFAULT_TIMEOUT); -} - bool Axp2101::getBatteryVoltage(float& vbatMillis) const { return readRegister14(0x34, vbatMillis); } @@ -72,3 +34,26 @@ bool Axp2101::setChargingEnabled(bool enabled) const { return false; } } + +bool Axp2101::isVBus() const { + uint8_t value; + return readRegister8(0x00, value) && (value & 0x20); +} + +bool Axp2101::getVBusVoltage(float& out) const { + if (!isVBus()) { + return false; + } else { + float vbus; + if (readRegister14(0x38, vbus) && vbus < 16375) { + out = vbus / 1000.0f; + return true; + } else { + return false; + } + } +} + +bool Axp2101::setRegisters(uint8_t* bytePairs, size_t bytePairsSize) const { + return tt::hal::i2c::masterWriteRegisterArray(port, address, bytePairs, bytePairsSize, DEFAULT_TIMEOUT); +} diff --git a/Boards/M5stackCoreS3/Source/Axp2101/Axp2101.h b/Boards/M5stackCoreS3/Source/Axp2101/Axp2101.h index f4b82ea2..7deb0b55 100644 --- a/Boards/M5stackCoreS3/Source/Axp2101/Axp2101.h +++ b/Boards/M5stackCoreS3/Source/Axp2101/Axp2101.h @@ -1,24 +1,16 @@ #pragma once #include "hal/i2c/I2c.h" +#include "I2cDevice/I2cDevice.h" + +#define AXP2101_ADDRESS 0x34 /** * References: * - https://github.com/m5stack/M5Unified/blob/master/src/utility/AXP2101_Class.cpp * - http://file.whycan.com/files/members/6736/AXP2101_Datasheet_V1.0_en_3832.pdf */ -class Axp2101 { - - i2c_port_t port; - - static constexpr uint8_t DEFAULT_ADDRESS = 0x34; - static constexpr TickType_t DEFAULT_TIMEOUT = 1000 / portTICK_PERIOD_MS; - - bool readRegister8(uint8_t reg, uint8_t& result) const; - bool writeRegister8(uint8_t reg, uint8_t value) const; - bool readRegister12(uint8_t reg, float& out) const; - bool readRegister14(uint8_t reg, float& out) const; - bool readRegister16(uint8_t reg, uint16_t& out) const; +class Axp2101 : I2cDevice { public: @@ -28,10 +20,15 @@ public: CHARGE_STATUS_STANDBY = 0b00 }; - Axp2101(i2c_port_t port) : port(port) {} + explicit Axp2101(i2c_port_t port) : I2cDevice(port, AXP2101_ADDRESS) {} + + bool setRegisters(uint8_t* bytePairs, size_t bytePairsSize) const; bool getBatteryVoltage(float& vbatMillis) const; bool getChargeStatus(ChargeStatus& status) const; bool isChargingEnabled(bool& enabled) const; bool setChargingEnabled(bool enabled) const; + + bool isVBus() const; + bool getVBusVoltage(float& out) const; }; diff --git a/Boards/M5stackCoreS3/Source/I2cDevice/I2cDevice.cpp b/Boards/M5stackCoreS3/Source/I2cDevice/I2cDevice.cpp new file mode 100644 index 00000000..61302fdd --- /dev/null +++ b/Boards/M5stackCoreS3/Source/I2cDevice/I2cDevice.cpp @@ -0,0 +1,59 @@ +#include "I2cDevice.h" + +bool I2cDevice::readRegister12(uint8_t reg, float& out) const { + std::uint8_t data[2] = {0}; + if (tt::hal::i2c::masterReadRegister(port, address, reg, data, 2, DEFAULT_TIMEOUT) == ESP_OK) { + out = (data[0] & 0x0F) << 8 | data[1]; + return true; + } else { + return false; + } +} + +bool I2cDevice::readRegister14(uint8_t reg, float& out) const { + std::uint8_t data[2] = {0}; + if (tt::hal::i2c::masterReadRegister(port, address, reg, data, 2, DEFAULT_TIMEOUT) == ESP_OK) { + out = (data[0] & 0x3F) << 8 | data[1]; + return true; + } else { + return false; + } +} + +bool I2cDevice::readRegister16(uint8_t reg, uint16_t& out) const { + std::uint8_t data[2] = {0}; + if (tt::hal::i2c::masterReadRegister(port, address, reg, data, 2, DEFAULT_TIMEOUT) == ESP_OK) { + out = data[0] << 8 | data[1]; + return true; + } else { + return false; + } +} + +bool I2cDevice::readRegister8(uint8_t reg, uint8_t& result) const { + return tt::hal::i2c::masterWriteRead(port, address, ®, 1, &result, 1, DEFAULT_TIMEOUT); +} + +bool I2cDevice::writeRegister8(uint8_t reg, uint8_t value) const { + return tt::hal::i2c::masterWriteRegister(port, address, reg, &value, 1, DEFAULT_TIMEOUT); +} + +bool I2cDevice::bitOn(uint8_t reg, uint8_t bitmask) const { + uint8_t state; + if (readRegister8(reg, state)) { + state |= bitmask; + return writeRegister8(reg, state); + } else { + return false; + } +} + +bool I2cDevice::bitOff(uint8_t reg, uint8_t bitmask) const { + uint8_t state; + if (readRegister8(reg, state)) { + state &= ~bitmask; + return writeRegister8(reg, state); + } else { + return false; + } +} diff --git a/Boards/M5stackCoreS3/Source/I2cDevice/I2cDevice.h b/Boards/M5stackCoreS3/Source/I2cDevice/I2cDevice.h new file mode 100644 index 00000000..90c5635c --- /dev/null +++ b/Boards/M5stackCoreS3/Source/I2cDevice/I2cDevice.h @@ -0,0 +1,25 @@ +#pragma once + +#include "hal/i2c/I2c.h" + +class I2cDevice { + +protected: + + i2c_port_t port; + uint8_t address; + + static constexpr TickType_t DEFAULT_TIMEOUT = 1000 / portTICK_PERIOD_MS; + + bool readRegister8(uint8_t reg, uint8_t& result) const; + bool writeRegister8(uint8_t reg, uint8_t value) const; + bool readRegister12(uint8_t reg, float& out) const; + bool readRegister14(uint8_t reg, float& out) const; + bool readRegister16(uint8_t reg, uint16_t& out) const; + bool bitOn(uint8_t reg, uint8_t bitmask) const; + bool bitOff(uint8_t reg, uint8_t bitmask) const; + +public: + + explicit I2cDevice(i2c_port_t port, uint32_t address) : port(port), address(address) {} +}; diff --git a/Boards/M5stackCoreS3/Source/InitBoot.cpp b/Boards/M5stackCoreS3/Source/InitBoot.cpp index 9cb32dd4..4d5be8a0 100644 --- a/Boards/M5stackCoreS3/Source/InitBoot.cpp +++ b/Boards/M5stackCoreS3/Source/InitBoot.cpp @@ -3,8 +3,9 @@ #include #include "Log.h" #include "hal/CoreS3DisplayConstants.h" -#include "hal/i2c/I2c.h" -#include "CoreS3Constants.h" +#include "kernel/Kernel.h" +#include "Axp2101/Axp2101.h" +#include "Aw9523/Aw9523.h" #define TAG "core2" @@ -43,62 +44,141 @@ static bool initSpi3() { /** * For details see https://github.com/espressif/esp-bsp/blob/master/bsp/m5stack_core_s3/m5stack_core_s3.c + * and schematic: https://m5stack.oss-cn-shenzhen.aliyuncs.com/resource/docs/datasheet/core/K128%20CoreS3/Sch_M5_CoreS3_v1.0.pdf */ bool initGpioExpander() { - TT_LOG_I(TAG, "Init AW9523 GPIO expander"); - uint8_t aw9523_P0 = 0b10; - uint8_t aw9523_P1 = 0b10100000; + TT_LOG_I(TAG, "AW9523 init"); - // Enable LCD - aw9523_P1 |= (1 << 1); + /** + * P0 pins: + * 0: Touch reset + * 1: Bus out enable + * 2: AW88298 reset (I2S) + * 3: ES7210 interrupt (Audio ADC) + * 4: SD Card SW(itch on?) + * 5: USB OTG enable + * 6: / + * 7: / + */ + + /** + * P1 pins: + * 0: Cam reset + * 1: LCD reset + * 2: Touch interrupt + * 3: AW88298 interrupt (I2S) + * 4: / + * 5: / + * 6: / + * 7: Boost enable + */ + + uint8_t p0_state = 0U; + uint8_t p1_state = 0U; // Enable touch - aw9523_P0 |= (1); - + p0_state |= (1U); + // Bus out enable + p0_state |= (1U << 1U); + // I2S + p0_state |= (1U << 2U); // SD card - aw9523_P0 |= (1 << 4); + p0_state |= (1U << 4U); - if (!tt::hal::i2c::masterWrite(I2C_NUM_0, AW9523_ADDRESS, 0x02, &aw9523_P0, 1, 1000)) { - TT_LOG_E(TAG, "Failed to enable LCD"); + // Enable LCD + p1_state |= (1U << 1U); + // Boost enable + p1_state |= (1U << 7U); + + Aw9523 aw(I2C_NUM_0); + + if (!aw.writeP0(p0_state)) { + TT_LOG_E(TAG, "AW9523: Failed to set P0"); return false; } - if (!tt::hal::i2c::masterWrite(I2C_NUM_0, AW9523_ADDRESS, 0x03, &aw9523_P1, 1, 1000)) { - TT_LOG_E(TAG, "Failed to enable touch"); + if (!aw.writeP1(p1_state)) { + TT_LOG_E(TAG, "AW9523: Failed to set P1"); return false; } + Axp2101 axp(I2C_NUM_0); + if (axp.isVBus()) { + float voltage = 0.0f; + axp.getVBusVoltage(voltage); + TT_LOG_I(TAG, "AXP2101: VBus at %.2f", voltage); + } else { + TT_LOG_W(TAG, "AXP2101: VBus disabled"); + } + return true; } bool initPowerControl() { - TT_LOG_I(TAG, "Init power control"); + TT_LOG_I(TAG, "Init power control (AXP2101)"); - uint8_t sdcard_3v3 = 0b00011100; - // TODO: Refactor to use Axp2101 class with https://github.com/m5stack/M5Unified/blob/b8cfec7fed046242da7f7b8024a4e92004a51ff7/src/utility/AXP2101_Class.cpp#L62 - if (!tt::hal::i2c::masterWrite(I2C_NUM_0, AXP2101_ADDRESS, 0x95, &sdcard_3v3, 1, 1000)) { - TT_LOG_E(TAG, "Failed to enable SD card"); + Aw9523 aw(I2C_NUM_0); + // Source: https://github.com/m5stack/M5Unified/blob/b8cfec7fed046242da7f7b8024a4e92004a51ff7/src/utility/Power_Class.cpp#L61 + aw.bitOnP1(0b10000000); // SY7088 boost enable + + /** AXP2101 usage + Source: https://github.com/m5stack/M5Unified/blob/b8cfec7fed046242da7f7b8024a4e92004a51ff7/README.md?plain=1#L223 + | |M5Stack
CoreS3
CoreS3SE| | + |:---------:|:-----------------:|:---------:| + | ALDO1 |VDD 1v8 | ALDO1 | + | ALDO2 |VDDA 3v3 | ALDO2 | + | ALDO3 |CAM 3v3 | ALDO3 | + | ALDO4 |TF 3v3 | ALDO4 | + | BLDO1 |AVDD | BLDO1 | + | BLDO2 |DVDD | BLDO2 | + | DLDO1/DC1 |LCD BL | DLDO1/DC1 | + | DLDO2/DC2 | --- | DLDO2/DC2 | + | BACKUP |RTC BAT | BACKUP | + */ + + /** + * 0x92 = ALD01 + * 0x93 = ALD02 + * 0x94 = ALD03 + * 0x95 = ALD04 + * 0x96 = BLD01 + * 0x97 = BLD02 + * + * DCDC1 : 0.7-3.5V, 25mV/step 1200mA + * DCDC2 : 0.7-2.275V,25mV/step 1600mA + * DCDC3 : 0.7-3.5V, 25mV/step 700mA + + * LDOio0: 1.8-3.3V, 100mV/step 50mA + * LDO1 : 30mA always on + * LDO2 : 1.8-3.3V, 100mV/step 200mA + * LDO3 : 1.8-3.3V, 100mV/step 200mA + */ + // Source: https://github.com/m5stack/M5Unified/blob/b8cfec7fed046242da7f7b8024a4e92004a51ff7/src/utility/Power_Class.cpp#L64 + static constexpr uint8_t reg_data_array[] = { + 0x90U, 0xBFU, // LDOS ON/OFF control 0 (backlight) + 0x92U, 18U -5U, // ALDO1 set to 1.8v // for AW88298 + 0x93U, 33U -5U, // ALDO2 set to 3.3v // for ES7210 + 0x94U, 33U -5U, // ALDO3 set to 3.3v // for camera + 0x95U, 33U -5U, // ALDO3 set to 3.3v // for TF card slot + 0x27, 0x00, // PowerKey Hold=1sec / PowerOff=4sec + 0x69, 0x11, // CHGLED setting + 0x10, 0x30, // PMU common config + 0x30, 0x0F // ADC enabled (for voltage measurement) + }; + + Axp2101 axp(I2C_NUM_0); + if (axp.setRegisters((uint8_t*)reg_data_array, sizeof(reg_data_array))) { + TT_LOG_I(TAG, "AXP2101 initialized with %d registers", sizeof(reg_data_array) / 2); + return true; + } else { + TT_LOG_E(TAG, "AXP2101: Failed to set registers"); return false; } - - // TODO: Refactor to use Axp2102 class with https://github.com/m5stack/M5Unified/blob/b8cfec7fed046242da7f7b8024a4e92004a51ff7/src/utility/AXP2101_Class.cpp#L42 - uint8_t axp_dld01_enable = 0xBF; // For backlight - if (!tt::hal::i2c::masterWrite(I2C_NUM_0, AXP2101_ADDRESS, 0x90, &axp_dld01_enable, 1, 1000)) { - TT_LOG_E(TAG, "Failed to enable display backlight"); - return false; - } - - // TODO: Refactor to use Axp2101 class with https://github.com/m5stack/M5Unified/blob/b8cfec7fed046242da7f7b8024a4e92004a51ff7/src/utility/AXP2101_Class.cpp#L62 - uint8_t axp_dld01_voltage = 0b00011000; // For backlight - if (!tt::hal::i2c::masterWrite(I2C_NUM_0, AXP2101_ADDRESS, 0x99, &axp_dld01_voltage, 1, 1000)) { - TT_LOG_E(TAG, "Failed to set display backlight voltage"); - return false; - } - - return true; } bool initBoot() { - TT_LOG_I(TAG, "initBoot"); - return initPowerControl() && initGpioExpander() && initSpi3(); + TT_LOG_I(TAG, "initBoot()"); + return initPowerControl() && + initGpioExpander() && + initSpi3(); } \ No newline at end of file diff --git a/Boards/M5stackCoreS3/Source/M5stackCoreS3.cpp b/Boards/M5stackCoreS3/Source/M5stackCoreS3.cpp index 02bd4742..91b5572a 100644 --- a/Boards/M5stackCoreS3/Source/M5stackCoreS3.cpp +++ b/Boards/M5stackCoreS3/Source/M5stackCoreS3.cpp @@ -15,7 +15,7 @@ const tt::hal::Configuration m5stack_cores3 = { tt::hal::i2c::Configuration { .name = "Internal", .port = I2C_NUM_0, - .initMode = tt::hal::i2c::InitByTactility, + .initMode = tt::hal::i2c::InitMode::ByTactility, .canReinit = false, .hasMutableConfiguration = false, .config = (i2c_config_t) { @@ -33,7 +33,7 @@ const tt::hal::Configuration m5stack_cores3 = { tt::hal::i2c::Configuration { .name = "External", // Grove .port = I2C_NUM_1, - .initMode = tt::hal::i2c::InitByTactility, + .initMode = tt::hal::i2c::InitMode::ByTactility, .canReinit = true, .hasMutableConfiguration = true, .config = (i2c_config_t) { diff --git a/Boards/M5stackCoreS3/Source/hal/CoreS3Display.cpp b/Boards/M5stackCoreS3/Source/hal/CoreS3Display.cpp index d47b00d9..4078ab8f 100644 --- a/Boards/M5stackCoreS3/Source/hal/CoreS3Display.cpp +++ b/Boards/M5stackCoreS3/Source/hal/CoreS3Display.cpp @@ -175,7 +175,7 @@ void CoreS3Display::setGammaCurve(uint8_t index) { void CoreS3Display::setBacklightDuty(uint8_t backlightDuty) { const uint8_t voltage = 20 + ((8 * backlightDuty) / 255); // [0b00000, 0b11100] - under 20 is too dark // TODO: Refactor to use Axp2102 class with https://github.com/m5stack/M5Unified/blob/b8cfec7fed046242da7f7b8024a4e92004a51ff7/src/utility/AXP2101_Class.cpp#L42 - if (!tt::hal::i2c::masterWrite(I2C_NUM_0, AXP2101_ADDRESS, 0x99, &voltage, 1, 1000)) { + if (!tt::hal::i2c::masterWriteRegister(I2C_NUM_0, AXP2101_ADDRESS, 0x99, &voltage, 1, 1000)) { // Sets DLD01 TT_LOG_E(TAG, "Failed to set display backlight voltage"); } } diff --git a/Boards/M5stackCoreS3/Source/hal/CoreS3Power.cpp b/Boards/M5stackCoreS3/Source/hal/CoreS3Power.cpp index 52281d98..08d8fb23 100644 --- a/Boards/M5stackCoreS3/Source/hal/CoreS3Power.cpp +++ b/Boards/M5stackCoreS3/Source/hal/CoreS3Power.cpp @@ -5,11 +5,11 @@ bool CoreS3Power::supportsMetric(MetricType type) const { switch (type) { - case BATTERY_VOLTAGE: - case IS_CHARGING: - case CHARGE_LEVEL: + case MetricType::BatteryVoltage: + case MetricType::IsCharging: + case MetricType::ChargeLevel: return true; - case CURRENT: + case MetricType::Current: return false; } @@ -18,7 +18,7 @@ bool CoreS3Power::supportsMetric(MetricType type) const { bool CoreS3Power::getMetric(Power::MetricType type, Power::MetricData& data) { switch (type) { - case BATTERY_VOLTAGE: { + case MetricType::BatteryVoltage: { float milliVolt; if (axpDevice.getBatteryVoltage(milliVolt)) { data.valueAsUint32 = (uint32_t)milliVolt; @@ -27,7 +27,7 @@ bool CoreS3Power::getMetric(Power::MetricType type, Power::MetricData& data) { return false; } } - case CHARGE_LEVEL: { + case MetricType::ChargeLevel: { float vbatMillis; if (axpDevice.getBatteryVoltage(vbatMillis)) { float vbat = vbatMillis / 1000.f; @@ -44,7 +44,7 @@ bool CoreS3Power::getMetric(Power::MetricType type, Power::MetricData& data) { return false; } } - case IS_CHARGING: { + case MetricType::IsCharging: { Axp2101::ChargeStatus status; if (axpDevice.getChargeStatus(status)) { data.valueAsBool = (status == Axp2101::CHARGE_STATUS_CHARGING); @@ -53,7 +53,7 @@ bool CoreS3Power::getMetric(Power::MetricType type, Power::MetricData& data) { return false; } } - case CURRENT: + case MetricType::Current: return false; } diff --git a/Boards/M5stackCoreS3/Source/hal/CoreS3SdCard.cpp b/Boards/M5stackCoreS3/Source/hal/CoreS3SdCard.cpp index 47b266ab..a315fead 100644 --- a/Boards/M5stackCoreS3/Source/hal/CoreS3SdCard.cpp +++ b/Boards/M5stackCoreS3/Source/hal/CoreS3SdCard.cpp @@ -16,7 +16,7 @@ std::shared_ptr createSdCard() { GPIO_NUM_NC, GPIO_NUM_NC, GPIO_NUM_NC, - SdCard::MountBehaviourAtBoot, + SdCard::MountBehaviour::AtBoot, tt::lvgl::getLvglSyncLockable(), { CORES3_LCD_PIN_CS diff --git a/Boards/Simulator/Source/LvglTask.cpp b/Boards/Simulator/Source/LvglTask.cpp index e0189cf2..9375b6b4 100644 --- a/Boards/Simulator/Source/LvglTask.cpp +++ b/Boards/Simulator/Source/LvglTask.cpp @@ -10,8 +10,8 @@ #define TAG "lvgl_task" // Mutex for LVGL drawing -static tt::Mutex lvgl_mutex(tt::Mutex::TypeRecursive); -static tt::Mutex task_mutex(tt::Mutex::TypeRecursive); +static tt::Mutex lvgl_mutex(tt::Mutex::Type::Recursive); +static tt::Mutex task_mutex(tt::Mutex::Type::Recursive); static uint32_t task_max_sleep_ms = 10; // Mutex for LVGL task state (to modify task_running state) diff --git a/Boards/Simulator/Source/hal/Configuration.cpp b/Boards/Simulator/Source/hal/Configuration.cpp index 831de905..bd0d4ea5 100644 --- a/Boards/Simulator/Source/hal/Configuration.cpp +++ b/Boards/Simulator/Source/hal/Configuration.cpp @@ -36,7 +36,7 @@ extern const tt::hal::Configuration hardware = { tt::hal::i2c::Configuration { .name = "Internal", .port = I2C_NUM_0, - .initMode = tt::hal::i2c::InitByTactility, + .initMode = tt::hal::i2c::InitMode::ByTactility, .canReinit = false, .hasMutableConfiguration = false, .config = (i2c_config_t) { @@ -54,7 +54,7 @@ extern const tt::hal::Configuration hardware = { tt::hal::i2c::Configuration { .name = "External", .port = I2C_NUM_1, - .initMode = tt::hal::i2c::InitByTactility, + .initMode = tt::hal::i2c::InitMode::ByTactility, .canReinit = true, .hasMutableConfiguration = true, .config = (i2c_config_t) { diff --git a/Boards/Simulator/Source/hal/SimulatorPower.cpp b/Boards/Simulator/Source/hal/SimulatorPower.cpp index 186e3c11..1c43ae6f 100644 --- a/Boards/Simulator/Source/hal/SimulatorPower.cpp +++ b/Boards/Simulator/Source/hal/SimulatorPower.cpp @@ -4,10 +4,10 @@ bool SimulatorPower::supportsMetric(MetricType type) const { switch (type) { - case IS_CHARGING: - case CURRENT: - case BATTERY_VOLTAGE: - case CHARGE_LEVEL: + case MetricType::IsCharging: + case MetricType::Current: + case MetricType::BatteryVoltage: + case MetricType::ChargeLevel: return true; } @@ -16,16 +16,16 @@ bool SimulatorPower::supportsMetric(MetricType type) const { bool SimulatorPower::getMetric(Power::MetricType type, Power::MetricData& data) { switch (type) { - case IS_CHARGING: + case MetricType::IsCharging: data.valueAsBool = true; return true; - case CURRENT: + case MetricType::Current: data.valueAsInt32 = 42; return true; - case BATTERY_VOLTAGE: + case MetricType::BatteryVoltage: data.valueAsUint32 = 4032; return true; - case CHARGE_LEVEL: + case MetricType::ChargeLevel: data.valueAsUint8 = 100; return true; } diff --git a/Boards/Simulator/Source/hal/SimulatorSdCard.h b/Boards/Simulator/Source/hal/SimulatorSdCard.h index 23d8d7f4..cd07a127 100644 --- a/Boards/Simulator/Source/hal/SimulatorSdCard.h +++ b/Boards/Simulator/Source/hal/SimulatorSdCard.h @@ -8,14 +8,14 @@ class SimulatorSdCard : public SdCard { private: State state; public: - SimulatorSdCard() : SdCard(MountBehaviourAtBoot), state(StateUnmounted) {} + SimulatorSdCard() : SdCard(MountBehaviour::AtBoot), state(State::Unmounted) {} bool mount(const char* mountPath) override { - state = StateMounted; + state = State::Mounted; return true; } bool unmount() override { - state = StateUnmounted; + state = State::Unmounted; return true; } diff --git a/Boards/YellowBoard/Source/YellowBoard.cpp b/Boards/YellowBoard/Source/YellowBoard.cpp index c6f6161b..8a8aa9d5 100644 --- a/Boards/YellowBoard/Source/YellowBoard.cpp +++ b/Boards/YellowBoard/Source/YellowBoard.cpp @@ -15,7 +15,7 @@ const tt::hal::Configuration yellow_board_24inch_cap = { tt::hal::i2c::Configuration { .name = "First", .port = I2C_NUM_0, - .initMode = tt::hal::i2c::InitDisabled, + .initMode = tt::hal::i2c::InitMode::Disabled, .canReinit = true, .hasMutableConfiguration = true, .config = (i2c_config_t) { @@ -33,7 +33,7 @@ const tt::hal::Configuration yellow_board_24inch_cap = { tt::hal::i2c::Configuration { .name = "Second", .port = I2C_NUM_1, - .initMode = tt::hal::i2c::InitDisabled, + .initMode = tt::hal::i2c::InitMode::Disabled, .canReinit = true, .hasMutableConfiguration = true, .config = (i2c_config_t) { diff --git a/Boards/YellowBoard/Source/hal/YellowSdCard.cpp b/Boards/YellowBoard/Source/hal/YellowSdCard.cpp index 5f8db8f5..192cc7d0 100644 --- a/Boards/YellowBoard/Source/hal/YellowSdCard.cpp +++ b/Boards/YellowBoard/Source/hal/YellowSdCard.cpp @@ -16,7 +16,7 @@ std::shared_ptr createYellowSdCard() { GPIO_NUM_NC, GPIO_NUM_NC, GPIO_NUM_NC, - SdCard::MountBehaviourAtBoot, + SdCard::MountBehaviour::AtBoot, nullptr, std::vector(), SDCARD_SPI_HOST diff --git a/Tactility/Private/app/AppInstance.h b/Tactility/Private/app/AppInstance.h index e039a8fe..511fcc47 100644 --- a/Tactility/Private/app/AppInstance.h +++ b/Tactility/Private/app/AppInstance.h @@ -37,7 +37,7 @@ class AppInstance : public AppContext { private: - Mutex mutex = Mutex(Mutex::TypeNormal); + Mutex mutex = Mutex(Mutex::Type::Normal); const AppManifest& manifest; State state = StateInitial; Flags flags = { .showStatusbar = true }; diff --git a/Tactility/Source/app/crashdiagnostics/QrHelpers.h b/Tactility/Private/app/crashdiagnostics/QrHelpers.h similarity index 100% rename from Tactility/Source/app/crashdiagnostics/QrHelpers.h rename to Tactility/Private/app/crashdiagnostics/QrHelpers.h diff --git a/Tactility/Source/app/crashdiagnostics/QrUrl.h b/Tactility/Private/app/crashdiagnostics/QrUrl.h similarity index 100% rename from Tactility/Source/app/crashdiagnostics/QrUrl.h rename to Tactility/Private/app/crashdiagnostics/QrUrl.h diff --git a/Tactility/Source/app/files/FileUtils.h b/Tactility/Private/app/files/FileUtils.h similarity index 100% rename from Tactility/Source/app/files/FileUtils.h rename to Tactility/Private/app/files/FileUtils.h diff --git a/Tactility/Private/app/files/FilesPrivate.h b/Tactility/Private/app/files/FilesPrivate.h new file mode 100644 index 00000000..25d4c0b4 --- /dev/null +++ b/Tactility/Private/app/files/FilesPrivate.h @@ -0,0 +1,34 @@ +#pragma once + +#include "./View.h" +#include "./State.h" + +#include "app/AppManifest.h" + +#include +#include +#include + +namespace tt::app::files { + +class Files { + std::unique_ptr view; + std::shared_ptr state; + +public: + Files() { + state = std::make_shared(); + view = std::make_unique(state); + } + + void onShow(lv_obj_t* parent) { + view->init(parent); + } + + void onResult(Result result, const Bundle& bundle) { + view->onResult(result, bundle); + } +}; + + +} // namespace diff --git a/Tactility/Source/app/files/State.h b/Tactility/Private/app/files/State.h similarity index 96% rename from Tactility/Source/app/files/State.h rename to Tactility/Private/app/files/State.h index d39a09c6..ffefb92a 100644 --- a/Tactility/Source/app/files/State.h +++ b/Tactility/Private/app/files/State.h @@ -19,7 +19,7 @@ public: private: - Mutex mutex = Mutex(Mutex::TypeRecursive); + Mutex mutex = Mutex(Mutex::Type::Recursive); std::vector dir_entries; std::string current_path; std::string selected_child_entry; diff --git a/Tactility/Source/app/files/View.h b/Tactility/Private/app/files/View.h similarity index 97% rename from Tactility/Source/app/files/View.h rename to Tactility/Private/app/files/View.h index 862b7c7f..65839e43 100644 --- a/Tactility/Source/app/files/View.h +++ b/Tactility/Private/app/files/View.h @@ -1,6 +1,7 @@ #pragma once -#include "State.h" +#include "./State.h" + #include "app/AppManifest.h" #include #include diff --git a/Tactility/Source/app/i2cscanner/I2cHelpers.h b/Tactility/Private/app/i2cscanner/I2cHelpers.h similarity index 100% rename from Tactility/Source/app/i2cscanner/I2cHelpers.h rename to Tactility/Private/app/i2cscanner/I2cHelpers.h diff --git a/Tactility/Private/app/i2cscanner/I2cScannerPrivate.h b/Tactility/Private/app/i2cscanner/I2cScannerPrivate.h new file mode 100644 index 00000000..97761098 --- /dev/null +++ b/Tactility/Private/app/i2cscanner/I2cScannerPrivate.h @@ -0,0 +1,37 @@ +#pragma once + +#include +#include +#include +#include "lvgl.h" +#include "hal/i2c/I2c.h" +#include "Timer.h" +#include + +namespace tt::app::i2cscanner { + +#define TAG "i2cscanner" + +enum ScanState { + ScanStateInitial, + ScanStateScanning, + ScanStateStopped +}; + +struct Data { + // Core + Mutex mutex = Mutex(Mutex::Type::Recursive); + std::unique_ptr scanTimer = nullptr; + // State + ScanState scanState; + i2c_port_t port = I2C_NUM_0; + std::vector scannedAddresses; + // Widgets + lv_obj_t* scanButtonLabelWidget = nullptr; + lv_obj_t* portDropdownWidget = nullptr; + lv_obj_t* scanListWidget = nullptr; +}; + +void onScanTimerFinished(std::shared_ptr data); + +} diff --git a/Tactility/Source/app/i2cscanner/I2cScannerThread.h b/Tactility/Private/app/i2cscanner/I2cScannerThread.h similarity index 86% rename from Tactility/Source/app/i2cscanner/I2cScannerThread.h rename to Tactility/Private/app/i2cscanner/I2cScannerThread.h index c137e705..2593602a 100644 --- a/Tactility/Source/app/i2cscanner/I2cScannerThread.h +++ b/Tactility/Private/app/i2cscanner/I2cScannerThread.h @@ -1,6 +1,6 @@ #pragma once -#include "I2cScanner.h" +#include "./I2cScannerPrivate.h" #include namespace tt::app::i2cscanner { diff --git a/Tactility/Source/app/screenshot/ScreenshotUi.h b/Tactility/Private/app/screenshot/ScreenshotUi.h similarity index 100% rename from Tactility/Source/app/screenshot/ScreenshotUi.h rename to Tactility/Private/app/screenshot/ScreenshotUi.h diff --git a/Tactility/Source/app/wificonnect/Bindings.h b/Tactility/Private/app/wificonnect/Bindings.h similarity index 100% rename from Tactility/Source/app/wificonnect/Bindings.h rename to Tactility/Private/app/wificonnect/Bindings.h diff --git a/Tactility/Source/app/wificonnect/State.h b/Tactility/Private/app/wificonnect/State.h similarity index 100% rename from Tactility/Source/app/wificonnect/State.h rename to Tactility/Private/app/wificonnect/State.h diff --git a/Tactility/Source/app/wificonnect/View.h b/Tactility/Private/app/wificonnect/View.h similarity index 100% rename from Tactility/Source/app/wificonnect/View.h rename to Tactility/Private/app/wificonnect/View.h diff --git a/Tactility/Private/app/wificonnect/WifiConnectPrivate.h b/Tactility/Private/app/wificonnect/WifiConnectPrivate.h new file mode 100644 index 00000000..43df34da --- /dev/null +++ b/Tactility/Private/app/wificonnect/WifiConnectPrivate.h @@ -0,0 +1,45 @@ +#pragma once + +#include "app/wificonnect/Bindings.h" +#include "app/wificonnect/State.h" +#include "app/wificonnect/View.h" + +#include "Mutex.h" +#include "service/wifi/Wifi.h" + +namespace tt::app::wificonnect { + +class WifiConnect { + Mutex mutex; + State state; + Bindings bindings = { + .onConnectSsid = nullptr, + .onConnectSsidContext = nullptr + }; + View view = View(&bindings, &state); + PubSubSubscription* wifiSubscription; + bool view_enabled = false; + +public: + + WifiConnect(); + ~WifiConnect(); + + void lock(); + void unlock(); + + void onShow(AppContext& app, lv_obj_t* parent); + void onHide(AppContext& app); + + State& getState() { return state; } + Bindings& getBindings() { return bindings; } + View& getView() { return view; } + + + void requestViewUpdate(); +}; + +bool optSsidParameter(const std::shared_ptr& bundle, std::string& ssid); +bool optPasswordParameter(const std::shared_ptr& bundle, std::string& password); + +} // namespace diff --git a/Tactility/Source/app/wifimanage/Bindings.h b/Tactility/Private/app/wifimanage/Bindings.h similarity index 83% rename from Tactility/Source/app/wifimanage/Bindings.h rename to Tactility/Private/app/wifimanage/Bindings.h index 73b91d79..1921c903 100644 --- a/Tactility/Source/app/wifimanage/Bindings.h +++ b/Tactility/Private/app/wifimanage/Bindings.h @@ -6,12 +6,14 @@ typedef void (*OnWifiToggled)(bool enable); typedef void (*OnConnectSsid)(const char* ssid); typedef void (*OnDisconnect)(); typedef void (*OnShowApSettings)(const char* ssid); +typedef void (*OnConnectToHidden)(); struct Bindings{ OnWifiToggled onWifiToggled; OnConnectSsid onConnectSsid; OnDisconnect onDisconnect; OnShowApSettings onShowApSettings; + OnConnectToHidden onConnectToHidden; }; } // namespace diff --git a/Tactility/Source/app/wifimanage/State.h b/Tactility/Private/app/wifimanage/State.h similarity index 55% rename from Tactility/Source/app/wifimanage/State.h rename to Tactility/Private/app/wifimanage/State.h index 33cda253..5e676949 100644 --- a/Tactility/Source/app/wifimanage/State.h +++ b/Tactility/Private/app/wifimanage/State.h @@ -10,30 +10,30 @@ namespace tt::app::wifimanage { */ class State { - Mutex mutex = Mutex(Mutex::TypeRecursive); + Mutex mutex = Mutex(Mutex::Type::Recursive); bool scanning = false; bool scannedAfterRadioOn = false; - service::wifi::WifiRadioState radioState; - std::vector apRecords; + service::wifi::RadioState radioState; + std::vector apRecords; std::string connectSsid; public: - State() {} + State() = default; void setScanning(bool isScanning); bool isScanning() const; bool hasScannedAfterRadioOn() const { return scannedAfterRadioOn; } - void setRadioState(service::wifi::WifiRadioState state); - service::wifi::WifiRadioState getRadioState() const; + void setRadioState(service::wifi::RadioState state); + service::wifi::RadioState getRadioState() const; void updateApRecords(); - const std::vector& lockApRecords() const; + const std::vector& lockApRecords() const; void unlockApRecords() const; - void setConnectSsid(std::string ssid); + void setConnectSsid(const std::string& ssid); std::string getConnectSsid() const; }; diff --git a/Tactility/Source/app/wifimanage/View.h b/Tactility/Private/app/wifimanage/View.h similarity index 77% rename from Tactility/Source/app/wifimanage/View.h rename to Tactility/Private/app/wifimanage/View.h index bc436bfa..6281161e 100644 --- a/Tactility/Source/app/wifimanage/View.h +++ b/Tactility/Private/app/wifimanage/View.h @@ -1,8 +1,8 @@ #pragma once #include "app/AppContext.h" -#include "Bindings.h" -#include "State.h" +#include "./Bindings.h" +#include "./State.h" #include "lvgl.h" namespace tt::app::wifimanage { @@ -19,12 +19,14 @@ private: lv_obj_t* enable_on_boot_switch = nullptr; lv_obj_t* scanning_spinner = nullptr; lv_obj_t* networks_list = nullptr; + lv_obj_t* connect_to_hidden = nullptr; void updateWifiToggle(); void updateEnableOnBootToggle(); void updateScanning(); void updateNetworkList(); - void createSsidListItem(const service::wifi::WifiApRecord& record, bool isConnecting); + void updateConnectToHidden(); + void createSsidListItem(const service::wifi::ApRecord& record, bool isConnecting); public: diff --git a/Tactility/Private/app/wifimanage/WifiManagePrivate.h b/Tactility/Private/app/wifimanage/WifiManagePrivate.h new file mode 100644 index 00000000..b3941998 --- /dev/null +++ b/Tactility/Private/app/wifimanage/WifiManagePrivate.h @@ -0,0 +1,35 @@ +#pragma once + +#include "Mutex.h" +#include "./View.h" +#include "./State.h" +#include "service/wifi/Wifi.h" + +namespace tt::app::wifimanage { + +class WifiManage { + + PubSubSubscription* wifiSubscription = nullptr; + Mutex mutex; + Bindings bindings = { }; + State state; + View view = View(&bindings, &state); + bool isViewEnabled = false; + +public: + + WifiManage(); + + void lock(); + void unlock(); + + void onShow(AppContext& app, lv_obj_t* parent); + void onHide(AppContext& app); + + Bindings& getBindings() { return bindings; } + State& getState() { return state; } + + void requestViewUpdate(); +}; + +} // namespace diff --git a/Tactility/Private/service/gui/Gui_i.h b/Tactility/Private/service/gui/Gui_i.h index 7386d643..c8777afc 100644 --- a/Tactility/Private/service/gui/Gui_i.h +++ b/Tactility/Private/service/gui/Gui_i.h @@ -19,7 +19,7 @@ namespace tt::service::gui { struct Gui { // Thread and lock Thread* thread = nullptr; - Mutex mutex = Mutex(Mutex::TypeRecursive); + Mutex mutex = Mutex(Mutex::Type::Recursive); PubSubSubscription* loader_pubsub_subscription = nullptr; // Layers and Canvas diff --git a/Tactility/Private/service/loader/Loader_i.h b/Tactility/Private/service/loader/Loader_i.h index caab3a32..860415a0 100644 --- a/Tactility/Private/service/loader/Loader_i.h +++ b/Tactility/Private/service/loader/Loader_i.h @@ -57,17 +57,12 @@ typedef struct { class LoaderMessageAppStart { public: - // This lock blocks anyone from starting an app as long - // as an app is already running via loader_start() - // This lock's lifecycle is not owned by this class. - std::shared_ptr api_lock = std::make_shared(); std::string id; std::shared_ptr _Nullable parameters; LoaderMessageAppStart() = default; LoaderMessageAppStart(LoaderMessageAppStart& other) : - api_lock(other.api_lock), id(other.id), parameters(other.parameters) {} @@ -77,14 +72,6 @@ public: {} ~LoaderMessageAppStart() = default; - - std::shared_ptr getApiLockEventFlag() { return api_lock; } - - uint32_t getApiLockEventFlagValue() { return 1; } - - void onProcessed() { - api_lock->set(1); - } }; // endregion LoaderMessage @@ -92,7 +79,7 @@ public: struct Loader { std::shared_ptr pubsubInternal = std::make_shared(); std::shared_ptr pubsubExternal = std::make_shared(); - Mutex mutex = Mutex(Mutex::TypeRecursive); + Mutex mutex = Mutex(Mutex::Type::Recursive); std::stack appStack; /** The dispatcher thread needs a callstack large enough to accommodate all the dispatched methods. * This includes full LVGL redraw via Gui::redraw() diff --git a/Tactility/Source/app/ManifestRegistry.cpp b/Tactility/Source/app/ManifestRegistry.cpp index e4e59846..e7359594 100644 --- a/Tactility/Source/app/ManifestRegistry.cpp +++ b/Tactility/Source/app/ManifestRegistry.cpp @@ -10,7 +10,7 @@ namespace tt::app { typedef std::unordered_map AppManifestMap; static AppManifestMap app_manifest_map; -static Mutex hash_mutex(Mutex::TypeNormal); +static Mutex hash_mutex(Mutex::Type::Normal); void addApp(const AppManifest* manifest) { TT_LOG_I(TAG, "Registering manifest %s", manifest->id.c_str()); diff --git a/Tactility/Source/app/alertdialog/AlertDialog.cpp b/Tactility/Source/app/alertdialog/AlertDialog.cpp index a2901653..337babef 100644 --- a/Tactility/Source/app/alertdialog/AlertDialog.cpp +++ b/Tactility/Source/app/alertdialog/AlertDialog.cpp @@ -19,13 +19,13 @@ namespace tt::app::alertdialog { extern const AppManifest manifest; -void start(std::string title, std::string message, const std::vector& buttonLabels) { +void start(const std::string& title, const std::string& message, const std::vector& buttonLabels) { std::string items_joined = string::join(buttonLabels, PARAMETER_ITEM_CONCATENATION_TOKEN); auto bundle = std::make_shared(); bundle->putString(PARAMETER_BUNDLE_KEY_TITLE, title); bundle->putString(PARAMETER_BUNDLE_KEY_MESSAGE, message); bundle->putString(PARAMETER_BUNDLE_KEY_BUTTON_LABELS, items_joined); - service::loader::startApp(manifest.id, false, bundle); + service::loader::startApp(manifest.id, bundle); } int32_t getResultIndex(const Bundle& bundle) { diff --git a/Tactility/Source/app/alertdialog/AlertDialog.h b/Tactility/Source/app/alertdialog/AlertDialog.h index 057f84c7..4e805118 100644 --- a/Tactility/Source/app/alertdialog/AlertDialog.h +++ b/Tactility/Source/app/alertdialog/AlertDialog.h @@ -12,7 +12,13 @@ */ namespace tt::app::alertdialog { - void start(std::string title, std::string message, const std::vector& buttonLabels); + /** + * Show a dialog with the provided title, message and 0, 1 or more buttons. + * @param[in] title the title to show in the toolbar + * @param[in] message the message to display + * @param[in] buttonLabels the buttons to show + */ + void start(const std::string& title, const std::string& message, const std::vector& buttonLabels); /** * Get the index of the button that the user selected. diff --git a/Tactility/Source/app/applist/AppList.cpp b/Tactility/Source/app/applist/AppList.cpp index 61ae1938..1da03aef 100644 --- a/Tactility/Source/app/applist/AppList.cpp +++ b/Tactility/Source/app/applist/AppList.cpp @@ -10,7 +10,7 @@ namespace tt::app::applist { static void onAppPressed(lv_event_t* e) { const auto* manifest = static_cast(lv_event_get_user_data(e)); - service::loader::startApp(manifest->id, false); + service::loader::startApp(manifest->id); } static void createAppWidget(const AppManifest* manifest, void* parent) { diff --git a/Tactility/Source/app/crashdiagnostics/CrashDiagnostics.cpp b/Tactility/Source/app/crashdiagnostics/CrashDiagnostics.cpp index 397a4fae..88d46736 100644 --- a/Tactility/Source/app/crashdiagnostics/CrashDiagnostics.cpp +++ b/Tactility/Source/app/crashdiagnostics/CrashDiagnostics.cpp @@ -1,11 +1,11 @@ #ifdef ESP_TARGET +#include "app/crashdiagnostics/QrHelpers.h" +#include "app/crashdiagnostics/QrUrl.h" +#include "app/launcher/Launcher.h" #include "lvgl.h" #include "lvgl/Statusbar.h" -#include "app/launcher/Launcher.h" #include "qrcode.h" -#include "QrHelpers.h" -#include "QrUrl.h" #include "service/loader/Loader.h" #define TAG "crash_diagnostics" diff --git a/Tactility/Source/app/crashdiagnostics/QrHelpers.cpp b/Tactility/Source/app/crashdiagnostics/QrHelpers.cpp index e36935f9..3d36248d 100644 --- a/Tactility/Source/app/crashdiagnostics/QrHelpers.cpp +++ b/Tactility/Source/app/crashdiagnostics/QrHelpers.cpp @@ -1,6 +1,5 @@ +#include "app/crashdiagnostics/QrHelpers.h" #include -#include -#include "QrHelpers.h" /** * Maps QR version (starting at a fictitious 0) to the usable byte size for L(ow) CRC checking QR. diff --git a/Tactility/Source/app/crashdiagnostics/QrUrl.cpp b/Tactility/Source/app/crashdiagnostics/QrUrl.cpp index baa3eca2..f74204f3 100644 --- a/Tactility/Source/app/crashdiagnostics/QrUrl.cpp +++ b/Tactility/Source/app/crashdiagnostics/QrUrl.cpp @@ -1,6 +1,6 @@ #ifdef ESP_TARGET -#include "QrUrl.h" +#include "app/crashdiagnostics/QrUrl.h" #include "kernel/PanicHandler.h" #include "Log.h" diff --git a/Tactility/Source/app/files/FileUtils.cpp b/Tactility/Source/app/files/FileUtils.cpp index 28f1645e..2267cdf3 100644 --- a/Tactility/Source/app/files/FileUtils.cpp +++ b/Tactility/Source/app/files/FileUtils.cpp @@ -1,4 +1,5 @@ -#include "FileUtils.h" +#include "app/files/FileUtils.h" + #include "TactilityCore.h" #include #include diff --git a/Tactility/Source/app/files/Files.cpp b/Tactility/Source/app/files/Files.cpp index 3149a282..41ba5831 100644 --- a/Tactility/Source/app/files/Files.cpp +++ b/Tactility/Source/app/files/Files.cpp @@ -1,6 +1,8 @@ -#include "Files.h" +#include "app/files/FilesPrivate.h" + #include "app/AppContext.h" #include "Assets.h" +#include "service/loader/Loader.h" #include @@ -37,4 +39,8 @@ extern const AppManifest manifest = { .onResult = onResult }; +void start() { + service::loader::startApp(manifest.id); +} + } // namespace diff --git a/Tactility/Source/app/files/Files.h b/Tactility/Source/app/files/Files.h index eda259f8..51f8f16f 100644 --- a/Tactility/Source/app/files/Files.h +++ b/Tactility/Source/app/files/Files.h @@ -10,24 +10,6 @@ namespace tt::app::files { -class Files { - std::unique_ptr view; - std::shared_ptr state; - -public: - Files() { - state = std::make_shared(); - view = std::make_unique(state); - } - - void onShow(lv_obj_t* parent) { - view->init(parent); - } - - void onResult(Result result, const Bundle& bundle) { - view->onResult(result, bundle); - } -}; - +void start(); } // namespace diff --git a/Tactility/Source/app/files/State.cpp b/Tactility/Source/app/files/State.cpp index ed0f0601..46881aeb 100644 --- a/Tactility/Source/app/files/State.cpp +++ b/Tactility/Source/app/files/State.cpp @@ -1,7 +1,8 @@ -#include "State.h" +#include "app/files/State.h" +#include "app/files/FileUtils.h" + #include "kernel/Kernel.h" #include "Log.h" -#include "FileUtils.h" #include "Partitions.h" #include "hal/SdCard.h" diff --git a/Tactility/Source/app/files/View.cpp b/Tactility/Source/app/files/View.cpp index ec8c59d5..283552cd 100644 --- a/Tactility/Source/app/files/View.cpp +++ b/Tactility/Source/app/files/View.cpp @@ -1,3 +1,6 @@ +#include "app/files/FileUtils.h" +#include "app/files/View.h" + #include "app/alertdialog/AlertDialog.h" #include "app/imageviewer/ImageViewer.h" #include "app/inputdialog/InputDialog.h" @@ -6,9 +9,7 @@ #include "lvgl/Toolbar.h" #include "lvgl/LvglSync.h" #include "service/loader/Loader.h" -#include "FileUtils.h" #include "Tactility.h" -#include "View.h" #include "StringUtils.h" #include #include @@ -83,18 +84,14 @@ void View::viewFile(const std::string& path, const std::string& filename) { app::startElfApp(processed_filepath); #endif } else if (isSupportedImageFile(filename)) { - auto bundle = std::make_shared(); - bundle->putString(IMAGE_VIEWER_FILE_ARGUMENT, processed_filepath); - service::loader::startApp("ImageViewer", false, bundle); + app::imageviewer::start(processed_filepath); } else if (isSupportedTextFile(filename)) { - auto bundle = std::make_shared(); if (kernel::getPlatform() == kernel::PlatformEsp) { - bundle->putString(TEXT_VIEWER_FILE_ARGUMENT, processed_filepath); + app::textviewer::start(processed_filepath); } else { // Remove forward slash, because we need a relative path - bundle->putString(TEXT_VIEWER_FILE_ARGUMENT, processed_filepath.substr(1)); + app::textviewer::start(processed_filepath.substr(1)); } - service::loader::startApp("TextViewer", false, bundle); } else { TT_LOG_W(TAG, "opening files of this type is not supported"); } diff --git a/Tactility/Source/app/gpio/Gpio.cpp b/Tactility/Source/app/gpio/Gpio.cpp index 19225cfa..4a4ba7da 100644 --- a/Tactility/Source/app/gpio/Gpio.cpp +++ b/Tactility/Source/app/gpio/Gpio.cpp @@ -96,7 +96,7 @@ void Gpio::startTask(std::shared_ptr ptr) { lock(); tt_assert(timer == nullptr); timer = std::make_unique( - Timer::TypePeriodic, + Timer::Type::Periodic, &onTimer, ptr ); diff --git a/Tactility/Source/app/i2cscanner/I2cHelpers.cpp b/Tactility/Source/app/i2cscanner/I2cHelpers.cpp index bd57f706..95b2dbcd 100644 --- a/Tactility/Source/app/i2cscanner/I2cHelpers.cpp +++ b/Tactility/Source/app/i2cscanner/I2cHelpers.cpp @@ -1,4 +1,4 @@ -#include "I2cHelpers.h" +#include "app/i2cscanner/I2cHelpers.h" #include "Tactility.h" #include "StringUtils.h" #include diff --git a/Tactility/Source/app/i2cscanner/I2cScanner.cpp b/Tactility/Source/app/i2cscanner/I2cScanner.cpp index 002defeb..e4dad0c0 100644 --- a/Tactility/Source/app/i2cscanner/I2cScanner.cpp +++ b/Tactility/Source/app/i2cscanner/I2cScanner.cpp @@ -1,6 +1,6 @@ -#include "I2cScanner.h" -#include "I2cScannerThread.h" -#include "I2cHelpers.h" +#include "app/i2cscanner/I2cScannerPrivate.h" +#include "app/i2cscanner/I2cScannerThread.h" +#include "app/i2cscanner/I2cHelpers.h" #include "Assets.h" #include "Tactility.h" @@ -50,7 +50,7 @@ static void onSelectBus(lv_event_t* event) { TT_LOG_I(TAG, "Selected %ld", selected); } -static void onPressScan(lv_event_t* event) { +static void onPressScan(TT_UNUSED lv_event_t* event) { auto data = optData(); if (data != nullptr) { if (data->scanState == ScanStateScanning) { @@ -191,4 +191,8 @@ extern const AppManifest manifest = { .onHide = onHide }; +void start() { + service::loader::startApp(manifest.id); +} + } // namespace diff --git a/Tactility/Source/app/i2cscanner/I2cScanner.h b/Tactility/Source/app/i2cscanner/I2cScanner.h index 54028725..9ba5537f 100644 --- a/Tactility/Source/app/i2cscanner/I2cScanner.h +++ b/Tactility/Source/app/i2cscanner/I2cScanner.h @@ -10,28 +10,6 @@ namespace tt::app::i2cscanner { -#define TAG "i2cscanner" - -enum ScanState { - ScanStateInitial, - ScanStateScanning, - ScanStateStopped -}; - -struct Data { - // Core - Mutex mutex = Mutex(Mutex::TypeRecursive); - std::unique_ptr scanTimer = nullptr; - // State - ScanState scanState; - i2c_port_t port = I2C_NUM_0; - std::vector scannedAddresses; - // Widgets - lv_obj_t* scanButtonLabelWidget = nullptr; - lv_obj_t* portDropdownWidget = nullptr; - lv_obj_t* scanListWidget = nullptr; -}; - -void onScanTimerFinished(std::shared_ptr data); +void start(); } diff --git a/Tactility/Source/app/i2cscanner/I2cScannerThread.cpp b/Tactility/Source/app/i2cscanner/I2cScannerThread.cpp index 008dc411..8ca7037c 100644 --- a/Tactility/Source/app/i2cscanner/I2cScannerThread.cpp +++ b/Tactility/Source/app/i2cscanner/I2cScannerThread.cpp @@ -1,4 +1,4 @@ -#include "I2cScannerThread.h" +#include "app/i2cscanner/I2cScannerThread.h" #include "lvgl.h" #include "service/loader/Loader.h" @@ -100,7 +100,7 @@ void startScanning(std::shared_ptr data) { data->scanState = ScanStateScanning; data->scanTimer = std::make_unique( - Timer::TypeOnce, + Timer::Type::Once, onScanTimer, data ); diff --git a/Tactility/Source/app/imageviewer/ImageViewer.cpp b/Tactility/Source/app/imageviewer/ImageViewer.cpp index c62780ac..4dd38f67 100644 --- a/Tactility/Source/app/imageviewer/ImageViewer.cpp +++ b/Tactility/Source/app/imageviewer/ImageViewer.cpp @@ -1,15 +1,16 @@ #include -#include "ImageViewer.h" #include "lvgl.h" #include "lvgl/Style.h" #include "lvgl/Toolbar.h" #include "StringUtils.h" +#include "service/loader/Loader.h" namespace tt::app::imageviewer { extern const AppManifest manifest; #define TAG "image_viewer" +#define IMAGE_VIEWER_FILE_ARGUMENT "file" static void onShow(AppContext& app, lv_obj_t* parent) { auto wrapper = lv_obj_create(parent); @@ -57,4 +58,10 @@ extern const AppManifest manifest = { .onShow = onShow }; +void start(const std::string& file) { + auto parameters = std::make_shared(); + parameters->putString(IMAGE_VIEWER_FILE_ARGUMENT, file); + service::loader::startApp(manifest.id, parameters); +} + } // namespace diff --git a/Tactility/Source/app/imageviewer/ImageViewer.h b/Tactility/Source/app/imageviewer/ImageViewer.h index 18dd8ecc..a6a4c4da 100644 --- a/Tactility/Source/app/imageviewer/ImageViewer.h +++ b/Tactility/Source/app/imageviewer/ImageViewer.h @@ -1,3 +1,7 @@ #pragma once -#define IMAGE_VIEWER_FILE_ARGUMENT "file" \ No newline at end of file +namespace tt::app::imageviewer { + +void start(const std::string& file); + +}; \ No newline at end of file diff --git a/Tactility/Source/app/inputdialog/InputDialog.cpp b/Tactility/Source/app/inputdialog/InputDialog.cpp index 01a2caa7..413e0004 100644 --- a/Tactility/Source/app/inputdialog/InputDialog.cpp +++ b/Tactility/Source/app/inputdialog/InputDialog.cpp @@ -24,7 +24,7 @@ void start(const std::string& title, const std::string& message, const std::stri bundle->putString(PARAMETER_BUNDLE_KEY_TITLE, title); bundle->putString(PARAMETER_BUNDLE_KEY_MESSAGE, message); bundle->putString(PARAMETER_BUNDLE_KEY_PREFILLED, prefilled); - service::loader::startApp(manifest.id, false, bundle); + service::loader::startApp(manifest.id, bundle); } std::string getResult(const Bundle& bundle) { diff --git a/Tactility/Source/app/launcher/Launcher.cpp b/Tactility/Source/app/launcher/Launcher.cpp index d65927bb..53a1b86d 100644 --- a/Tactility/Source/app/launcher/Launcher.cpp +++ b/Tactility/Source/app/launcher/Launcher.cpp @@ -3,13 +3,12 @@ #include "Check.h" #include "lvgl.h" #include "service/loader/Loader.h" -#include "Assets.h" namespace tt::app::launcher { static void onAppPressed(TT_UNUSED lv_event_t* e) { auto* appId = (const char*)lv_event_get_user_data(e); - service::loader::startApp(appId, false); + service::loader::startApp(appId); } static lv_obj_t* createAppButton(lv_obj_t* parent, const char* title, const char* imageFile, const char* appId, int32_t buttonPaddingLeft) { diff --git a/Tactility/Source/app/log/Log.cpp b/Tactility/Source/app/log/Log.cpp index a518ed37..3a0d28b8 100644 --- a/Tactility/Source/app/log/Log.cpp +++ b/Tactility/Source/app/log/Log.cpp @@ -1,4 +1,3 @@ -#include #include #include #include "lvgl.h" @@ -13,12 +12,12 @@ namespace tt::app::log { struct LogAppData { - LogLevel filterLevel = LogLevelInfo; + LogLevel filterLevel = LogLevel::Info; lv_obj_t* labelWidget = nullptr; }; static bool shouldShowLog(LogLevel filterLevel, LogLevel logLevel) { - if (filterLevel == LogLevelNone || logLevel == LogLevelNone) { + if (filterLevel == LogLevel::None || logLevel == LogLevel::None) { return false; } else { return filterLevel >= logLevel; @@ -115,19 +114,19 @@ static void onResult(AppContext& app, Result result, const Bundle& bundle) { if (result == ResultOk) { switch (resultIndex) { case 0: - data->filterLevel = LogLevelVerbose; + data->filterLevel = LogLevel::Verbose; break; case 1: - data->filterLevel = LogLevelDebug; + data->filterLevel = LogLevel::Debug; break; case 2: - data->filterLevel = LogLevelInfo; + data->filterLevel = LogLevel::Info; break; case 3: - data->filterLevel = LogLevelWarning; + data->filterLevel = LogLevel::Warning; break; case 4: - data->filterLevel = LogLevelError; + data->filterLevel = LogLevel::Error; break; default: break; diff --git a/Tactility/Source/app/power/Power.cpp b/Tactility/Source/app/power/Power.cpp index 3006e9d6..655322ad 100644 --- a/Tactility/Source/app/power/Power.cpp +++ b/Tactility/Source/app/power/Power.cpp @@ -16,7 +16,7 @@ extern const AppManifest manifest; static void onTimer(TT_UNUSED std::shared_ptr context); struct Data { - Timer update_timer = Timer(Timer::TypePeriodic, &onTimer, nullptr); + Timer update_timer = Timer(Timer::Type::Periodic, &onTimer, nullptr); std::shared_ptr power = getConfiguration()->hardware->power(); lv_obj_t* enable_label = nullptr; lv_obj_t* enable_switch = nullptr; @@ -39,7 +39,7 @@ std::shared_ptr _Nullable optData() { static void updateUi(std::shared_ptr data) { const char* charge_state; hal::Power::MetricData metric_data; - if (data->power->getMetric(hal::Power::MetricType::IS_CHARGING, metric_data)) { + if (data->power->getMetric(hal::Power::MetricType::IsCharging, metric_data)) { charge_state = metric_data.valueAsBool ? "yes" : "no"; } else { charge_state = "N/A"; @@ -47,7 +47,7 @@ static void updateUi(std::shared_ptr data) { uint8_t charge_level; bool charge_level_scaled_set = false; - if (data->power->getMetric(hal::Power::MetricType::CHARGE_LEVEL, metric_data)) { + if (data->power->getMetric(hal::Power::MetricType::ChargeLevel, metric_data)) { charge_level = metric_data.valueAsUint8; charge_level_scaled_set = true; } @@ -57,14 +57,14 @@ static void updateUi(std::shared_ptr data) { int32_t current; bool current_set = false; - if (data->power->getMetric(hal::Power::MetricType::CURRENT, metric_data)) { + if (data->power->getMetric(hal::Power::MetricType::Current, metric_data)) { current = metric_data.valueAsInt32; current_set = true; } uint32_t battery_voltage; bool battery_voltage_set = false; - if (data->power->getMetric(hal::Power::MetricType::BATTERY_VOLTAGE, metric_data)) { + if (data->power->getMetric(hal::Power::MetricType::BatteryVoltage, metric_data)) { battery_voltage = metric_data.valueAsUint32; battery_voltage_set = true; } diff --git a/Tactility/Source/app/screenshot/Screenshot.cpp b/Tactility/Source/app/screenshot/Screenshot.cpp index e3f9c1d9..18689664 100644 --- a/Tactility/Source/app/screenshot/Screenshot.cpp +++ b/Tactility/Source/app/screenshot/Screenshot.cpp @@ -2,7 +2,7 @@ #if TT_FEATURE_SCREENSHOT_ENABLED -#include "ScreenshotUi.h" +#include "app/screenshot/ScreenshotUi.h" #include namespace tt::app::screenshot { diff --git a/Tactility/Source/app/screenshot/ScreenshotUi.cpp b/Tactility/Source/app/screenshot/ScreenshotUi.cpp index 4ff85935..f945ca20 100644 --- a/Tactility/Source/app/screenshot/ScreenshotUi.cpp +++ b/Tactility/Source/app/screenshot/ScreenshotUi.cpp @@ -2,7 +2,7 @@ #if TT_FEATURE_SCREENSHOT_ENABLED -#include "ScreenshotUi.h" +#include "app/screenshot/ScreenshotUi.h" #include "TactilityCore.h" #include "hal/SdCard.h" @@ -51,7 +51,7 @@ static void onTimerCallback(TT_UNUSED std::shared_ptr context) { } ScreenshotUi::ScreenshotUi() { - updateTimer = std::make_unique(Timer::TypePeriodic, onTimerCallback, nullptr); + updateTimer = std::make_unique(Timer::Type::Periodic, onTimerCallback, nullptr); } ScreenshotUi::~ScreenshotUi() { @@ -146,7 +146,7 @@ void ScreenshotUi::createModeSettingWidgets(lv_obj_t* parent) { lv_obj_align_to(modeDropdown, mode_label, LV_ALIGN_OUT_RIGHT_MID, 8, 0); lv_obj_add_event_cb(modeDropdown, onModeSetCallback, LV_EVENT_VALUE_CHANGED, nullptr); service::screenshot::Mode mode = service->getMode(); - if (mode == service::screenshot::ScreenshotModeApps) { + if (mode == service::screenshot::Mode::Apps) { lv_dropdown_set_selected(modeDropdown, 1); } @@ -177,7 +177,7 @@ void ScreenshotUi::createFilePathWidgets(lv_obj_t* parent) { lv_obj_set_flex_grow(pathTextArea, 1); if (kernel::getPlatform() == kernel::PlatformEsp) { auto sdcard = tt::hal::getConfiguration()->sdcard; - if (sdcard != nullptr && sdcard->getState() == hal::SdCard::StateMounted) { + if (sdcard != nullptr && sdcard->getState() == hal::SdCard::State::Mounted) { lv_textarea_set_text(pathTextArea, "A:/sdcard"); } else { lv_textarea_set_text(pathTextArea, "Error: no SD card"); diff --git a/Tactility/Source/app/selectiondialog/SelectionDialog.cpp b/Tactility/Source/app/selectiondialog/SelectionDialog.cpp index c88f152e..09034332 100644 --- a/Tactility/Source/app/selectiondialog/SelectionDialog.cpp +++ b/Tactility/Source/app/selectiondialog/SelectionDialog.cpp @@ -18,12 +18,12 @@ namespace tt::app::selectiondialog { extern const AppManifest manifest; -void start(std::string title, const std::vector& items) { +void start(const std::string& title, const std::vector& items) { std::string items_joined = string::join(items, PARAMETER_ITEM_CONCATENATION_TOKEN); auto bundle = std::make_shared(); bundle->putString(PARAMETER_BUNDLE_KEY_TITLE, title); bundle->putString(PARAMETER_BUNDLE_KEY_ITEMS, items_joined); - service::loader::startApp(manifest.id, false, bundle); + service::loader::startApp(manifest.id, bundle); } int32_t getResultIndex(const Bundle& bundle) { diff --git a/Tactility/Source/app/selectiondialog/SelectionDialog.h b/Tactility/Source/app/selectiondialog/SelectionDialog.h index 2cd82048..9dad7fc7 100644 --- a/Tactility/Source/app/selectiondialog/SelectionDialog.h +++ b/Tactility/Source/app/selectiondialog/SelectionDialog.h @@ -14,7 +14,7 @@ */ namespace tt::app::selectiondialog { - void start(std::string title, const std::vector& items); + void start(const std::string& title, const std::vector& items); /** * Get the index of the item that the user selected. diff --git a/Tactility/Source/app/textviewer/TextViewer.cpp b/Tactility/Source/app/textviewer/TextViewer.cpp index c0b2e006..f4d50d40 100644 --- a/Tactility/Source/app/textviewer/TextViewer.cpp +++ b/Tactility/Source/app/textviewer/TextViewer.cpp @@ -4,8 +4,10 @@ #include "lvgl/LabelUtils.h" #include "lvgl/Style.h" #include "lvgl/Toolbar.h" +#include "service/loader/Loader.h" #define TAG "text_viewer" +#define TEXT_VIEWER_FILE_ARGUMENT "file" namespace tt::app::textviewer { @@ -45,4 +47,11 @@ extern const AppManifest manifest = { .onShow = onShow }; +void start(const std::string& file) { + auto parameters = std::make_shared(); + parameters->putString(TEXT_VIEWER_FILE_ARGUMENT, file); + service::loader::startApp(manifest.id, parameters); +} + + } // namespace diff --git a/Tactility/Source/app/textviewer/TextViewer.h b/Tactility/Source/app/textviewer/TextViewer.h index de52710b..3f9fdd43 100644 --- a/Tactility/Source/app/textviewer/TextViewer.h +++ b/Tactility/Source/app/textviewer/TextViewer.h @@ -1,3 +1,7 @@ #pragma once -#define TEXT_VIEWER_FILE_ARGUMENT "file" \ No newline at end of file +namespace tt::app::textviewer { + +void start(const std::string&file); + +} diff --git a/Tactility/Source/app/timedatesettings/TimeDateSettings.cpp b/Tactility/Source/app/timedatesettings/TimeDateSettings.cpp index 7f29ae11..d0d2f311 100644 --- a/Tactility/Source/app/timedatesettings/TimeDateSettings.cpp +++ b/Tactility/Source/app/timedatesettings/TimeDateSettings.cpp @@ -4,7 +4,6 @@ #include "service/loader/Loader.h" #include "app/timezone/TimeZone.h" #include "Assets.h" -#include "Tactility.h" #include "time/Time.h" #include "lvgl/LvglSync.h" @@ -15,7 +14,7 @@ namespace tt::app::timedatesettings { extern const AppManifest manifest; struct Data { - Mutex mutex = Mutex(Mutex::TypeRecursive); + Mutex mutex = Mutex(Mutex::Type::Recursive); lv_obj_t* regionLabelWidget = nullptr; }; diff --git a/Tactility/Source/app/timezone/TimeZone.cpp b/Tactility/Source/app/timezone/TimeZone.cpp index 31abd562..1bd281e2 100644 --- a/Tactility/Source/app/timezone/TimeZone.cpp +++ b/Tactility/Source/app/timezone/TimeZone.cpp @@ -224,7 +224,7 @@ static void onShow(AppContext& app, lv_obj_t* parent) { static void onStart(AppContext& app) { auto data = std::make_shared(); - data->updateTimer = std::make_unique(Timer::TypeOnce, onUpdateTimer, data); + data->updateTimer = std::make_unique(Timer::Type::Once, onUpdateTimer, data); app.setData(data); } diff --git a/Tactility/Source/app/wifiapsettings/WifiApSettings.cpp b/Tactility/Source/app/wifiapsettings/WifiApSettings.cpp index f18e40d9..960bbf29 100644 --- a/Tactility/Source/app/wifiapsettings/WifiApSettings.cpp +++ b/Tactility/Source/app/wifiapsettings/WifiApSettings.cpp @@ -27,7 +27,7 @@ const AppContext* _Nullable optWifiApSettingsApp() { void start(const std::string& ssid) { auto bundle = std::make_shared(); bundle->putString("ssid", ssid); - service::loader::startApp(manifest.id, false, bundle); + service::loader::startApp(manifest.id, bundle); } static void onPressForget(TT_UNUSED lv_event_t* event) { @@ -135,7 +135,7 @@ void onResult(TT_UNUSED AppContext& app, TT_UNUSED Result result, const Bundle& TT_LOG_I(TAG, "Removed SSID"); if ( - service::wifi::getRadioState() == service::wifi::WIFI_RADIO_CONNECTION_ACTIVE && + service::wifi::getRadioState() == service::wifi::RadioState::ConnectionActive && service::wifi::getConnectionTarget() == ssid ) { service::wifi::disconnect(); diff --git a/Tactility/Source/app/wificonnect/Parameters.h b/Tactility/Source/app/wificonnect/Parameters.h deleted file mode 100644 index 88ab3af5..00000000 --- a/Tactility/Source/app/wificonnect/Parameters.h +++ /dev/null @@ -1,4 +0,0 @@ -#pragma once - -#define WIFI_CONNECT_PARAM_SSID "ssid" // String -#define WIFI_CONNECT_PARAM_PASSWORD "password" // String diff --git a/Tactility/Source/app/wificonnect/State.cpp b/Tactility/Source/app/wificonnect/State.cpp index 1c0cd077..47e11e41 100644 --- a/Tactility/Source/app/wificonnect/State.cpp +++ b/Tactility/Source/app/wificonnect/State.cpp @@ -1,4 +1,4 @@ -#include "State.h" +#include "app/wificonnect/State.h" #include "Check.h" #include diff --git a/Tactility/Source/app/wificonnect/View.cpp b/Tactility/Source/app/wificonnect/View.cpp index 33aad340..28a6b771 100644 --- a/Tactility/Source/app/wificonnect/View.cpp +++ b/Tactility/Source/app/wificonnect/View.cpp @@ -1,6 +1,5 @@ -#include "View.h" -#include "State.h" -#include "Parameters.h" +#include "app/wificonnect/View.h" +#include "app/wificonnect/WifiConnectPrivate.h" #include "WifiConnect.h" #include "lvgl.h" @@ -186,19 +185,19 @@ void View::init(AppContext& app, lv_obj_t* parent) { createBottomButtons(wrapper); // Keyboard bindings - service::gui::keyboardAddTextArea(ssid_textarea); - service::gui::keyboardAddTextArea(password_textarea); + service::gui::keyboardAddTextArea(ssid_textarea); + service::gui::keyboardAddTextArea(password_textarea); // Init from app parameters auto bundle = app.getParameters(); if (bundle != nullptr) { std::string ssid; - if (bundle->optString(WIFI_CONNECT_PARAM_SSID, ssid)) { + if (optSsidParameter(bundle, ssid)) { lv_textarea_set_text(ssid_textarea, ssid.c_str()); } std::string password; - if (bundle->optString(WIFI_CONNECT_PARAM_PASSWORD, password)) { + if (optPasswordParameter(bundle, ssid)) { lv_textarea_set_text(password_textarea, password.c_str()); } } diff --git a/Tactility/Source/app/wificonnect/WifiConnect.cpp b/Tactility/Source/app/wificonnect/WifiConnect.cpp index 959570fd..af8b9b62 100644 --- a/Tactility/Source/app/wificonnect/WifiConnect.cpp +++ b/Tactility/Source/app/wificonnect/WifiConnect.cpp @@ -1,4 +1,4 @@ -#include "WifiConnect.h" +#include "app/wificonnect/WifiConnectPrivate.h" #include "app/AppContext.h" #include "TactilityCore.h" @@ -9,6 +9,8 @@ namespace tt::app::wificonnect { #define TAG "wifi_connect" +#define WIFI_CONNECT_PARAM_SSID "ssid" // String +#define WIFI_CONNECT_PARAM_PASSWORD "password" // String extern const AppManifest manifest; @@ -23,18 +25,18 @@ std::shared_ptr _Nullable optWifiConnect() { } static void eventCallback(const void* message, void* context) { - auto* event = static_cast(message); + auto* event = static_cast(message); auto* wifi = static_cast(context); State& state = wifi->getState(); switch (event->type) { - case service::wifi::WifiEventTypeConnectionFailed: + case service::wifi::EventType::ConnectionFailed: if (state.isConnecting()) { state.setConnecting(false); state.setConnectionError(true); wifi->requestViewUpdate(); } break; - case service::wifi::WifiEventTypeConnectionSuccess: + case service::wifi::EventType::ConnectionSuccess: if (wifi->getState().isConnecting()) { state.setConnecting(false); service::loader::stopApp(); @@ -123,10 +125,25 @@ extern const AppManifest manifest = { .id = "WifiConnect", .name = "Wi-Fi Connect", .icon = LV_SYMBOL_WIFI, - .type = TypeSettings, + .type = TypeHidden, .onStart = &onStart, .onShow = &onShow, .onHide = &onHide }; +void start(const std::string& ssid, const std::string& password) { + auto parameters = std::make_shared(); + parameters->putString(WIFI_CONNECT_PARAM_SSID, ssid); + parameters->putString(WIFI_CONNECT_PARAM_PASSWORD, password); + service::loader::startApp(manifest.id, parameters); +} + +bool optSsidParameter(const std::shared_ptr& bundle, std::string& ssid) { + return bundle->optString(WIFI_CONNECT_PARAM_SSID, ssid); +} + +bool optPasswordParameter(const std::shared_ptr& bundle, std::string& password) { + return bundle->optString(WIFI_CONNECT_PARAM_PASSWORD, password); +} + } // namespace diff --git a/Tactility/Source/app/wificonnect/WifiConnect.h b/Tactility/Source/app/wificonnect/WifiConnect.h index c169d6d6..9891b4bf 100644 --- a/Tactility/Source/app/wificonnect/WifiConnect.h +++ b/Tactility/Source/app/wificonnect/WifiConnect.h @@ -1,48 +1,12 @@ #pragma once -#include "Bindings.h" -#include "State.h" -#include "View.h" - -#include "Mutex.h" -#include "service/wifi/Wifi.h" +#include namespace tt::app::wificonnect { -class WifiConnect { - Mutex mutex; - State state; - Bindings bindings = { - .onConnectSsid = nullptr, - .onConnectSsidContext = nullptr - }; - View view = View(&bindings, &state); - PubSubSubscription* wifiSubscription; - bool view_enabled = false; - -public: - - WifiConnect(); - ~WifiConnect(); - - void lock(); - void unlock(); - - void onShow(AppContext& app, lv_obj_t* parent); - void onHide(AppContext& app); - - State& getState() { return state; } - Bindings& getBindings() { return bindings; } - View& getView() { return view; } - - - void requestViewUpdate(); -}; - -void lock(WifiConnect* wifi); - -void unlock(WifiConnect* wifi); - -void view_update(WifiConnect* wifi); +/** + * Start the app with optional pre-filled fields. + */ +void start(const std::string& ssid = "", const std::string& password = ""); } // namespace diff --git a/Tactility/Source/app/wifimanage/State.cpp b/Tactility/Source/app/wifimanage/State.cpp index 2434f61d..083141ce 100644 --- a/Tactility/Source/app/wifimanage/State.cpp +++ b/Tactility/Source/app/wifimanage/State.cpp @@ -1,5 +1,5 @@ #include -#include "WifiManage.h" +#include "app/wifimanage/WifiManagePrivate.h" namespace tt::app::wifimanage { @@ -10,16 +10,16 @@ void State::setScanning(bool isScanning) { tt_check(mutex.release() == TtStatusOk); } -void State::setRadioState(service::wifi::WifiRadioState state) { +void State::setRadioState(service::wifi::RadioState state) { tt_check(mutex.acquire(TtWaitForever) == TtStatusOk); radioState = state; - if (radioState == service::wifi::WIFI_RADIO_OFF) { + if (radioState == service::wifi::RadioState::Off) { scannedAfterRadioOn = false; } tt_check(mutex.release() == TtStatusOk); } -service::wifi::WifiRadioState State::getRadioState() const { +service::wifi::RadioState State::getRadioState() const { tt_check(mutex.acquire(TtWaitForever) == TtStatusOk); auto result = radioState; tt_check(mutex.release() == TtStatusOk); @@ -33,7 +33,7 @@ bool State::isScanning() const { return result; } -const std::vector& State::lockApRecords() const { +const std::vector& State::lockApRecords() const { tt_check(mutex.acquire(TtWaitForever) == TtStatusOk); return apRecords; } @@ -48,7 +48,7 @@ void State::updateApRecords() { tt_check(mutex.release() == TtStatusOk); } -void State::setConnectSsid(std::string ssid) { +void State::setConnectSsid(const std::string& ssid) { tt_check(mutex.acquire(TtWaitForever) == TtStatusOk); connectSsid = ssid; tt_check(mutex.release() == TtStatusOk); diff --git a/Tactility/Source/app/wifimanage/View.cpp b/Tactility/Source/app/wifimanage/View.cpp index 827614dd..8534bd6a 100644 --- a/Tactility/Source/app/wifimanage/View.cpp +++ b/Tactility/Source/app/wifimanage/View.cpp @@ -1,5 +1,5 @@ -#include "View.h" -#include "WifiManage.h" +#include "app/wifimanage/View.h" +#include "app/wifimanage/WifiManagePrivate.h" #include "Log.h" #include "service/wifi/Wifi.h" @@ -48,6 +48,11 @@ static void on_enable_on_boot_switch_changed(lv_event_t* event) { } } +static void onConnectToHiddenClicked(lv_event_t* event) { + auto* bindings = (Bindings*)lv_event_get_user_data(event); + bindings->onConnectToHidden(); +} + // region Secondary updates static void connect(lv_event_t* event) { @@ -73,7 +78,7 @@ static void showDetails(lv_event_t* event) { bindings->onShowApSettings(ssid); } -void View::createSsidListItem(const service::wifi::WifiApRecord& record, bool isConnecting) { +void View::createSsidListItem(const service::wifi::ApRecord& record, bool isConnecting) { lv_obj_t* wrapper = lv_obj_create(networks_list); lv_obj_add_event_cb(wrapper, &connect, LV_EVENT_SHORT_CLICKED, bindings); lv_obj_set_user_data(wrapper, bindings); @@ -124,20 +129,36 @@ void View::createSsidListItem(const service::wifi::WifiApRecord& record, bool is } } +void View::updateConnectToHidden() { + switch (state->getRadioState()) { + case service::wifi::RadioState::On: + case service::wifi::RadioState::ConnectionPending: + case service::wifi::RadioState::ConnectionActive: + lv_obj_remove_flag(connect_to_hidden, LV_OBJ_FLAG_HIDDEN); + break; + + case service::wifi::RadioState::OnPending: + case service::wifi::RadioState::OffPending: + case service::wifi::RadioState::Off: + lv_obj_add_flag(connect_to_hidden, LV_OBJ_FLAG_HIDDEN); + break; + } +} + void View::updateNetworkList() { lv_obj_clean(networks_list); switch (state->getRadioState()) { - case service::wifi::WIFI_RADIO_ON_PENDING: - case service::wifi::WIFI_RADIO_ON: - case service::wifi::WIFI_RADIO_CONNECTION_PENDING: - case service::wifi::WIFI_RADIO_CONNECTION_ACTIVE: { + case service::wifi::RadioState::OnPending: + case service::wifi::RadioState::On: + case service::wifi::RadioState::ConnectionPending: + case service::wifi::RadioState::ConnectionActive: { std::string connection_target = service::wifi::getConnectionTarget(); auto& ap_records = state->lockApRecords(); bool is_connected = !connection_target.empty() && - state->getRadioState() == service::wifi::WIFI_RADIO_CONNECTION_ACTIVE; + state->getRadioState() == service::wifi::RadioState::ConnectionActive; bool added_connected = false; if (is_connected) { if (!ap_records.empty()) { @@ -159,8 +180,8 @@ void View::updateNetworkList() { if (used_ssids.find(record.ssid) == used_ssids.end()) { bool connection_target_match = (record.ssid == connection_target); bool is_connecting = connection_target_match - && state->getRadioState() == service::wifi::WIFI_RADIO_CONNECTION_PENDING && - !connection_target.empty(); + && state->getRadioState() == service::wifi::RadioState::ConnectionPending && + !connection_target.empty(); bool skip = connection_target_match && added_connected; if (!skip) { createSsidListItem(record, is_connecting); @@ -180,8 +201,8 @@ void View::updateNetworkList() { state->unlockApRecords(); break; } - case service::wifi::WIFI_RADIO_OFF_PENDING: - case service::wifi::WIFI_RADIO_OFF: { + case service::wifi::RadioState::OffPending: + case service::wifi::RadioState::Off: { lv_obj_add_flag(networks_list, LV_OBJ_FLAG_HIDDEN); break; } @@ -189,7 +210,7 @@ void View::updateNetworkList() { } void View::updateScanning() { - if (state->getRadioState() == service::wifi::WIFI_RADIO_ON && state->isScanning()) { + if (state->getRadioState() == service::wifi::RadioState::On && state->isScanning()) { lv_obj_clear_flag(scanning_spinner, LV_OBJ_FLAG_HIDDEN); } else { lv_obj_add_flag(scanning_spinner, LV_OBJ_FLAG_HIDDEN); @@ -199,18 +220,18 @@ void View::updateScanning() { void View::updateWifiToggle() { lv_obj_clear_state(enable_switch, LV_STATE_ANY); switch (state->getRadioState()) { - case service::wifi::WIFI_RADIO_ON: - case service::wifi::WIFI_RADIO_CONNECTION_PENDING: - case service::wifi::WIFI_RADIO_CONNECTION_ACTIVE: + case service::wifi::RadioState::On: + case service::wifi::RadioState::ConnectionPending: + case service::wifi::RadioState::ConnectionActive: lv_obj_add_state(enable_switch, LV_STATE_CHECKED); break; - case service::wifi::WIFI_RADIO_ON_PENDING: + case service::wifi::RadioState::OnPending: lv_obj_add_state(enable_switch, LV_STATE_CHECKED | LV_STATE_DISABLED); break; - case service::wifi::WIFI_RADIO_OFF: + case service::wifi::RadioState::Off: lv_obj_remove_state(enable_switch, LV_STATE_CHECKED | LV_STATE_DISABLED); break; - case service::wifi::WIFI_RADIO_OFF_PENDING: + case service::wifi::RadioState::OffPending: lv_obj_remove_state(enable_switch, LV_STATE_CHECKED); lv_obj_add_state(enable_switch, LV_STATE_DISABLED); break; @@ -233,7 +254,7 @@ void View::updateEnableOnBootToggle() { void View::init(const AppContext& app, lv_obj_t* parent) { root = parent; - paths = std::move(app.getPaths()); + paths = app.getPaths(); // Toolbar lv_obj_set_flex_flow(parent, LV_FLEX_FLOW_COLUMN); @@ -279,6 +300,14 @@ void View::init(const AppContext& app, lv_obj_t* parent) { lv_obj_set_style_pad_top(networks_list, 0, 0); lv_obj_set_style_pad_bottom(networks_list, 0, 0); lv_obj_align(networks_list, LV_ALIGN_TOP_LEFT, 0, 44); + + connect_to_hidden = lv_button_create(secondary_flex); + lv_obj_set_width(connect_to_hidden, LV_PCT(100)); + lv_obj_set_style_margin_bottom(connect_to_hidden, 8, 0); + lv_obj_set_style_margin_hor(connect_to_hidden, 12, 0); + lv_obj_add_event_cb(connect_to_hidden, onConnectToHiddenClicked, LV_EVENT_SHORT_CLICKED, bindings); + auto* connect_to_hidden_label = lv_label_create(connect_to_hidden); + lv_label_set_text(connect_to_hidden_label, "Connect to hidden SSID"); } void View::update() { @@ -286,6 +315,7 @@ void View::update() { updateEnableOnBootToggle(); updateScanning(); updateNetworkList(); + updateConnectToHidden(); } } // namespace diff --git a/Tactility/Source/app/wifimanage/WifiManage.cpp b/Tactility/Source/app/wifimanage/WifiManage.cpp index f91a2e25..a6bade85 100644 --- a/Tactility/Source/app/wifimanage/WifiManage.cpp +++ b/Tactility/Source/app/wifimanage/WifiManage.cpp @@ -1,14 +1,14 @@ -#include "WifiManage.h" -#include "View.h" -#include "State.h" +#include "app/wifimanage/WifiManagePrivate.h" +#include "app/wifimanage/View.h" +#include "app/wifimanage/State.h" #include "app/AppContext.h" -#include "app/wificonnect/Parameters.h" #include "app/wifiapsettings/WifiApSettings.h" #include "TactilityCore.h" #include "service/loader/Loader.h" #include "service/wifi/WifiSettings.h" #include "lvgl/LvglSync.h" +#include "app/wificonnect/WifiConnect.h" namespace tt::app::wifimanage { @@ -33,10 +33,7 @@ static void onConnect(const char* ssid) { service::wifi::connect(&settings, false); } else { TT_LOG_I(TAG, "Starting connection dialog"); - auto bundle = std::make_shared(); - bundle->putString(WIFI_CONNECT_PARAM_SSID, ssid); - bundle->putString(WIFI_CONNECT_PARAM_PASSWORD, ""); - service::loader::startApp("WifiConnect", false, bundle); + wificonnect::start(ssid); } } @@ -52,12 +49,17 @@ static void onWifiToggled(bool enabled) { service::wifi::setEnabled(enabled); } +static void onConnectToHidden() { + wificonnect::start(); +} + WifiManage::WifiManage() { bindings = (Bindings) { .onWifiToggled = onWifiToggled, .onConnectSsid = onConnect, .onDisconnect = onDisconnect, - .onShowApSettings = onShowApSettings + .onShowApSettings = onShowApSettings, + .onConnectToHidden = onConnectToHidden }; } @@ -83,19 +85,20 @@ void WifiManage::requestViewUpdate() { } static void wifiManageEventCallback(const void* message, void* context) { - auto* event = (service::wifi::WifiEvent*)message; + auto* event = (service::wifi::Event*)message; auto* wifi = (WifiManage*)context; - TT_LOG_I(TAG, "Update with state %d", service::wifi::getRadioState()); - wifi->getState().setRadioState(service::wifi::getRadioState()); + auto radio_state = service::wifi::getRadioState(); + TT_LOG_I(TAG, "Update with state %s", service::wifi::radioStateToString(radio_state)); + wifi->getState().setRadioState(radio_state); switch (event->type) { - case tt::service::wifi::WifiEventTypeScanStarted: + case tt::service::wifi::EventType::ScanStarted: wifi->getState().setScanning(true); break; - case tt::service::wifi::WifiEventTypeScanFinished: + case tt::service::wifi::EventType::ScanFinished: wifi->getState().setScanning(false); wifi->getState().updateApRecords(); break; - case tt::service::wifi::WifiEventTypeRadioStateOn: + case tt::service::wifi::EventType::RadioStateOn: if (!service::wifi::isScanning()) { service::wifi::scan(); } @@ -124,11 +127,11 @@ void WifiManage::onShow(AppContext& app, lv_obj_t* parent) { view.update(); unlock(); - service::wifi::WifiRadioState radio_state = service::wifi::getRadioState(); - bool can_scan = radio_state == service::wifi::WIFI_RADIO_ON || - radio_state == service::wifi::WIFI_RADIO_CONNECTION_PENDING || - radio_state == service::wifi::WIFI_RADIO_CONNECTION_ACTIVE; - TT_LOG_I(TAG, "%d %d", radio_state, service::wifi::isScanning()); + service::wifi::RadioState radio_state = service::wifi::getRadioState(); + bool can_scan = radio_state == service::wifi::RadioState::On || + radio_state == service::wifi::RadioState::ConnectionPending || + radio_state == service::wifi::RadioState::ConnectionActive; + TT_LOG_I(TAG, "%s %d", service::wifi::radioStateToString(radio_state), (int)service::wifi::isScanning()); if (can_scan && !service::wifi::isScanning()) { service::wifi::scan(); } @@ -172,4 +175,8 @@ extern const AppManifest manifest = { .onHide = onHide }; +void start() { + service::loader::startApp(manifest.id); +} + } // namespace diff --git a/Tactility/Source/app/wifimanage/WifiManage.h b/Tactility/Source/app/wifimanage/WifiManage.h index 51183834..f9902927 100644 --- a/Tactility/Source/app/wifimanage/WifiManage.h +++ b/Tactility/Source/app/wifimanage/WifiManage.h @@ -1,35 +1,12 @@ #pragma once #include "Mutex.h" -#include "View.h" -#include "State.h" +#include "app/wifimanage/View.h" +#include "app/wifimanage/State.h" #include "service/wifi/Wifi.h" namespace tt::app::wifimanage { -class WifiManage { - - PubSubSubscription* wifiSubscription = nullptr; - Mutex mutex; - Bindings bindings = { }; - State state; - View view = View(&bindings, &state); - bool isViewEnabled = false; - -public: - - WifiManage(); - - void lock(); - void unlock(); - - void onShow(AppContext& app, lv_obj_t* parent); - void onHide(AppContext& app); - - Bindings& getBindings() { return bindings; } - State& getState() { return state; } - - void requestViewUpdate(); -}; +void start(); } // namespace diff --git a/Tactility/Source/lvgl/Statusbar.cpp b/Tactility/Source/lvgl/Statusbar.cpp index 82328b28..8b789af8 100644 --- a/Tactility/Source/lvgl/Statusbar.cpp +++ b/Tactility/Source/lvgl/Statusbar.cpp @@ -26,10 +26,10 @@ struct StatusbarIcon { }; struct StatusbarData { - Mutex mutex = Mutex(Mutex::TypeRecursive); + Mutex mutex = Mutex(Mutex::Type::Recursive); std::shared_ptr pubsub = std::make_shared(); StatusbarIcon icons[STATUSBAR_ICON_LIMIT] = {}; - Timer* time_update_timer = new Timer(Timer::TypeOnce, onUpdateTime, nullptr); + Timer* time_update_timer = new Timer(Timer::Type::Once, onUpdateTime, nullptr); uint8_t time_hours = 0; uint8_t time_minutes = 0; bool time_set = false; diff --git a/Tactility/Source/service/loader/Loader.cpp b/Tactility/Source/service/loader/Loader.cpp index 8c9202f4..439a5290 100644 --- a/Tactility/Source/service/loader/Loader.cpp +++ b/Tactility/Source/service/loader/Loader.cpp @@ -17,6 +17,13 @@ namespace tt::service::loader { #define TAG "loader" +enum class LoaderStatus { + Ok, + ErrorAppStarted, + ErrorUnknownApp, + ErrorInternal, +}; + typedef struct { LoaderEventType type; } LoaderEventInternal; @@ -41,20 +48,11 @@ static void loader_free() { loader_singleton = nullptr; } -void startApp(const std::string& id, bool blocking, const std::shared_ptr& parameters) { +void startApp(const std::string& id, const std::shared_ptr& parameters) { TT_LOG_I(TAG, "Start app %s", id.c_str()); tt_assert(loader_singleton); - auto message = std::make_shared(id, parameters); loader_singleton->dispatcherThread->dispatch(onStartAppMessage, message); - - auto event_flag = message->getApiLockEventFlag(); - if (blocking) { - /* TODO: Check if task id is not the LVGL one, - because otherwise this fails as the apps starting logic will try to lock lvgl - to update the UI and fail. */ - event_flag->wait(message->getApiLockEventFlagValue()); - } } void stopApp() { @@ -163,7 +161,7 @@ static LoaderStatus startAppWithManifestInternal( auto scoped_lock = loader_singleton->mutex.scoped(); if (!scoped_lock->lock(50 / portTICK_PERIOD_MS)) { - return LoaderStatusErrorInternal; + return LoaderStatus::ErrorInternal; } auto previous_app = !loader_singleton->appStack.empty() ? loader_singleton->appStack.top() : nullptr; @@ -192,7 +190,7 @@ static LoaderStatus startAppWithManifestInternal( }; tt_pubsub_publish(loader_singleton->pubsubExternal, &event_external); - return LoaderStatusOk; + return LoaderStatus::Ok; } static void onStartAppMessage(std::shared_ptr message) { @@ -213,7 +211,7 @@ static LoaderStatus startAppInternal( const app::AppManifest* manifest = app::findAppById(id); if (manifest == nullptr) { TT_LOG_E(TAG, "App not found: %s", id.c_str()); - return LoaderStatusErrorUnknownApp; + return LoaderStatus::ErrorUnknownApp; } else { return startAppWithManifestInternal(manifest, parameters); } diff --git a/Tactility/Source/service/loader/Loader.h b/Tactility/Source/service/loader/Loader.h index bd206964..e770d058 100644 --- a/Tactility/Source/service/loader/Loader.h +++ b/Tactility/Source/service/loader/Loader.h @@ -10,21 +10,13 @@ namespace tt::service::loader { typedef struct Loader Loader; -typedef enum { - LoaderStatusOk, - LoaderStatusErrorAppStarted, - LoaderStatusErrorUnknownApp, - LoaderStatusErrorInternal, -} LoaderStatus; - /** * @brief Start an app * @param[in] id application name or id - * @param[in] blocking whether this call is blocking or not. You cannot call this from an LVGL thread. * @param[in] parameters optional parameters to pass onto the application */ -void startApp(const std::string& id, bool blocking = false, const std::shared_ptr& _Nullable parameters = nullptr); +void startApp(const std::string& id, const std::shared_ptr& _Nullable parameters = nullptr); /** @brief Stop the currently showing app. Show the previous app if any app was still running. */ void stopApp(); diff --git a/Tactility/Source/service/screenshot/Screenshot.cpp b/Tactility/Source/service/screenshot/Screenshot.cpp index 17af25b5..71c3ee53 100644 --- a/Tactility/Source/service/screenshot/Screenshot.cpp +++ b/Tactility/Source/service/screenshot/Screenshot.cpp @@ -32,7 +32,7 @@ void ScreenshotService::startApps(const char* path) { if (task == nullptr || task->isFinished()) { task = std::make_unique(); - mode = ScreenshotModeApps; + mode = Mode::Apps; task->startApps(path); } else { TT_LOG_W(TAG, "Screenshot task already running"); @@ -48,7 +48,7 @@ void ScreenshotService::startTimed(const char* path, uint8_t delayInSeconds, uin if (task == nullptr || task->isFinished()) { task = std::make_unique(); - mode = ScreenshotModeTimed; + mode = Mode::Timed; task->startTimed(path, delayInSeconds, amount); } else { TT_LOG_W(TAG, "Screenshot task already running"); @@ -64,17 +64,17 @@ void ScreenshotService::stop() { if (task != nullptr) { task = nullptr; - mode = ScreenshotModeNone; + mode = Mode::None; } else { TT_LOG_W(TAG, "Screenshot task not running"); } } -Mode ScreenshotService::getMode() { +Mode ScreenshotService::getMode() const { auto scoped_lockable = mutex.scoped(); if (!scoped_lockable->lock(50 / portTICK_PERIOD_MS)) { TT_LOG_W(TAG, LOG_MESSAGE_MUTEX_LOCK_FAILED); - return ScreenshotModeNone; + return Mode::None; } return mode; diff --git a/Tactility/Source/service/screenshot/Screenshot.h b/Tactility/Source/service/screenshot/Screenshot.h index c3418f88..c9850e2f 100644 --- a/Tactility/Source/service/screenshot/Screenshot.h +++ b/Tactility/Source/service/screenshot/Screenshot.h @@ -10,11 +10,11 @@ namespace tt::service::screenshot { -typedef enum { - ScreenshotModeNone, - ScreenshotModeTimed, - ScreenshotModeApps -} Mode; +enum class Mode { + None, + Timed, + Apps +}; class ScreenshotService { @@ -22,14 +22,14 @@ private: Mutex mutex; std::unique_ptr task; - Mode mode = ScreenshotModeNone; + Mode mode = Mode::None; public: bool isTaskStarted(); /** The state of the service. */ - Mode getMode(); + Mode getMode() const; /** @brief Start taking screenshot whenever an app is started * @param[in] path the path to store the screenshots at diff --git a/Tactility/Source/service/screenshot/ScreenshotTask.h b/Tactility/Source/service/screenshot/ScreenshotTask.h index 3683a008..3cb2291e 100644 --- a/Tactility/Source/service/screenshot/ScreenshotTask.h +++ b/Tactility/Source/service/screenshot/ScreenshotTask.h @@ -25,7 +25,7 @@ class ScreenshotTask { }; Thread* thread = nullptr; - Mutex mutex = Mutex(Mutex::TypeRecursive); + Mutex mutex = Mutex(Mutex::Type::Recursive); bool interrupted = false; bool finished = false; ScreenshotTaskWork work; diff --git a/Tactility/Source/service/statusbar/Statusbar.cpp b/Tactility/Source/service/statusbar/Statusbar.cpp index a2d74695..ae8e9577 100644 --- a/Tactility/Source/service/statusbar/Statusbar.cpp +++ b/Tactility/Source/service/statusbar/Statusbar.cpp @@ -80,17 +80,17 @@ const char* getWifiStatusIconForRssi(int rssi) { } } -static const char* getWifiStatusIcon(wifi::WifiRadioState state, bool secure) { +static const char* getWifiStatusIcon(wifi::RadioState state, bool secure) { int rssi; switch (state) { - case wifi::WIFI_RADIO_ON: - case wifi::WIFI_RADIO_ON_PENDING: - case wifi::WIFI_RADIO_CONNECTION_PENDING: + case wifi::RadioState::On: + case wifi::RadioState::OnPending: + case wifi::RadioState::ConnectionPending: return STATUSBAR_ICON_WIFI_SCAN_WHITE; - case wifi::WIFI_RADIO_OFF_PENDING: - case wifi::WIFI_RADIO_OFF: + case wifi::RadioState::OffPending: + case wifi::RadioState::Off: return STATUSBAR_ICON_WIFI_OFF_WHITE; - case wifi::WIFI_RADIO_CONNECTION_ACTIVE: + case wifi::RadioState::ConnectionActive: rssi = wifi::getRssi(); return getWifiStatusIconForRssi(rssi); default: @@ -99,7 +99,7 @@ static const char* getWifiStatusIcon(wifi::WifiRadioState state, bool secure) { } static void updateWifiIcon(const service::Paths* paths, const std::shared_ptr& data) { - wifi::WifiRadioState radio_state = wifi::getRadioState(); + wifi::RadioState radio_state = wifi::getRadioState(); bool is_secure = wifi::isConnectionSecure(); const char* desired_icon = getWifiStatusIcon(radio_state, is_secure); if (data->wifi_last_icon != desired_icon) { @@ -120,11 +120,11 @@ static void updateWifiIcon(const service::Paths* paths, const std::shared_ptrsdcard; if (sdcard != nullptr) { auto state = sdcard->getState(); - if (state != hal::SdCard::StateUnknown) { + if (state != hal::SdCard::State::Unknown) { auto* desired_icon = getSdCardStatusIcon(state); if (data->sdcard_last_icon != desired_icon) { auto icon_path = paths->getSystemPathLvgl(desired_icon); @@ -161,7 +161,7 @@ static _Nullable const char* getPowerStatusIcon() { auto power = get_power(); hal::Power::MetricData charge_level; - if (!power->getMetric(hal::Power::MetricType::CHARGE_LEVEL, charge_level)) { + if (!power->getMetric(hal::Power::MetricType::ChargeLevel, charge_level)) { return nullptr; } @@ -228,7 +228,7 @@ static void onStart(ServiceContext& service) { auto data = std::make_shared(); lvgl::unlock(); - data->paths = std::move(service.getPaths()); + data->paths = service.getPaths(); service.setData(data); @@ -238,7 +238,7 @@ static void onStart(ServiceContext& service) { updateSdCardIcon(data->paths.get(), data); // also updates visibility updatePowerStatusIcon(data->paths.get(), data); - data->updateTimer = std::make_unique(Timer::TypePeriodic, onUpdate, data); + data->updateTimer = std::make_unique(Timer::Type::Periodic, onUpdate, data); // We want to try and scan more often in case of startup or scan lock failure data->updateTimer->start(1000); } diff --git a/TactilityC/Source/tt_app_alertdialog.cpp b/TactilityC/Source/tt_app_alertdialog.cpp index ade85d35..7b967efc 100644 --- a/TactilityC/Source/tt_app_alertdialog.cpp +++ b/TactilityC/Source/tt_app_alertdialog.cpp @@ -6,8 +6,7 @@ extern "C" { void tt_app_alertdialog_start(const char* title, const char* message, const char* buttonLabels[], uint32_t buttonLabelCount) { std::vector list; for (int i = 0; i < buttonLabelCount; i++) { - const char* item = buttonLabels[i]; - list.push_back(item); + list.emplace_back(buttonLabels[i]); } tt::app::alertdialog::start(title, message, list); } diff --git a/TactilityC/Source/tt_app_alertdialog.h b/TactilityC/Source/tt_app_alertdialog.h index ac135034..0f7fd952 100644 --- a/TactilityC/Source/tt_app_alertdialog.h +++ b/TactilityC/Source/tt_app_alertdialog.h @@ -8,7 +8,18 @@ extern "C" { #include +/** + * Show a dialog with the provided title, message and 0, 1 or more buttons. + * @param[in] title the title to show in the toolbar + * @param[in] message the message to display + * @param[in] buttonLabels the buttons to show, or null when there are none to show + * @param[in] buttonLabelCount the amount of buttons (0 or more) + */ void tt_app_alertdialog_start(const char* title, const char* message, const char* buttonLabels[], uint32_t buttonLabelCount); + +/** + * @return the index of the button that was clicked (the index in the array when start() was called) + */ int32_t tt_app_alertdialog_get_result_index(BundleHandle handle); #ifdef __cplusplus diff --git a/TactilityC/Source/tt_app_context.h b/TactilityC/Source/tt_app_context.h index 1b609331..32311c0e 100644 --- a/TactilityC/Source/tt_app_context.h +++ b/TactilityC/Source/tt_app_context.h @@ -8,10 +8,30 @@ extern "C" { typedef void* AppContextHandle; +/** @return the data that was attached to this app context */ void* _Nullable tt_app_context_get_data(AppContextHandle handle); + +/** + * Attach data to an application context. + * Don't forget to manually delete allocated memory when onStopped() is called. + * @param[in] handle the app context handle + * @param[in] data the data to attach + */ void tt_app_context_set_data(AppContextHandle handle, void* _Nullable data); + +/** @return the bundle that belongs to this application, or null */ BundleHandle _Nullable tt_app_context_get_parameters(AppContextHandle handle); + +/** + * Set the result before closing an app. + * The result and bundle are passed along to the app that launched this app, when this app is closed. + * @param[in] handle the app context handle to set the result for + * @param[in] result the result state to set + * @param[in] bundle the result bundle to set + */ void tt_app_context_set_result(AppContextHandle handle, Result result, BundleHandle _Nullable bundle); + +/** @return true if a result was set for this app context */ bool tt_app_context_has_result(AppContextHandle handle); #ifdef __cplusplus diff --git a/TactilityC/Source/tt_app_manifest.h b/TactilityC/Source/tt_app_manifest.h index 4cee8716..9156bb27 100644 --- a/TactilityC/Source/tt_app_manifest.h +++ b/TactilityC/Source/tt_app_manifest.h @@ -21,6 +21,16 @@ typedef void (*AppOnShow)(AppContextHandle app, lv_obj_t* parent); typedef void (*AppOnHide)(AppContextHandle app); typedef void (*AppOnResult)(AppContextHandle app, Result result, BundleHandle resultData); +/** + * This is used to register the manifest of an external app. + * @param[in] name the application's human-readable name + * @param[in] icon the optional application icon (you can use LV_SYMBOL_* too) + * @param[in] onStart called when the app is launched (started) + * @param[in] onStop called when the app is exited (stopped) + * @param[in] onShow called when the app is about to be shown to the user (app becomes visible) + * @param[in] onHide called when the app is about to be invisible to the user (e.g. other app was launched by this app, and this app goes to the background) + * @param[in] onResult called when the app receives a result after launching another app + */ void tt_set_app_manifest( const char* name, const char* _Nullable icon, diff --git a/TactilityC/Source/tt_app_selectiondialog.cpp b/TactilityC/Source/tt_app_selectiondialog.cpp index 7c122554..7595b801 100644 --- a/TactilityC/Source/tt_app_selectiondialog.cpp +++ b/TactilityC/Source/tt_app_selectiondialog.cpp @@ -6,8 +6,7 @@ extern "C" { void tt_app_selectiondialog_start(const char* title, int argc, const char* argv[]) { std::vector list; for (int i = 0; i < argc; i++) { - const char* item = argv[i]; - list.push_back(item); + list.emplace_back(argv[i]); } tt::app::selectiondialog::start(title, list); } diff --git a/TactilityC/Source/tt_app_selectiondialog.h b/TactilityC/Source/tt_app_selectiondialog.h index 9aed6c35..66f71cdf 100644 --- a/TactilityC/Source/tt_app_selectiondialog.h +++ b/TactilityC/Source/tt_app_selectiondialog.h @@ -6,8 +6,15 @@ extern "C" { #endif +/** + * Start an app that displays a list of items and allows the user to select one. + * @param[in] title the title to show in the toolbar + * @param[in] argc the amount of items that the list contains + * @param[in] argv the labels of the items in the list + */ void tt_app_selectiondialog_start(const char* title, int argc, const char* argv[]); +/** @return the index of the item that was clicked by the user, or -1 when the user didn't select anything */ int32_t tt_app_selectiondialog_get_result_index(BundleHandle handle); #ifdef __cplusplus diff --git a/TactilityC/Source/tt_bundle.h b/TactilityC/Source/tt_bundle.h index a611d5bb..3c285071 100644 --- a/TactilityC/Source/tt_bundle.h +++ b/TactilityC/Source/tt_bundle.h @@ -7,21 +7,66 @@ extern "C" { #include #include +/** The handle that represents a bundle instance */ typedef void* BundleHandle; +/** @return a new bundle instance */ BundleHandle tt_bundle_alloc(); + +/** Dealloc an existing bundle instance */ void tt_bundle_free(BundleHandle handle); -bool tt_bundle_opt_bool(BundleHandle handle, const char* key, bool* out); -bool tt_bundle_opt_int32(BundleHandle handle, const char* key, int32_t* out); /** - * Note that outSize must be large enough to include null terminator. - * This means that your string has to be the expected text length + 1 extra character. + * Try to get a boolean value from a Bundle + * @param[in] handle the handle that represents the bundle + * @param[in] key the identifier that represents the stored value (~variable name) + * @param[out] out the output value (only set when return value is set to true) + * @return true if "out" was set + */ +bool tt_bundle_opt_bool(BundleHandle handle, const char* key, bool* out); + +/** + * Try to get an int32_t value from a Bundle + * @param[in] handle the handle that represents the bundle + * @param[in] key the identifier that represents the stored value (~variable name) + * @param[out] out the output value (only set when return value is set to true) + * @return true if "out" was set + */ +bool tt_bundle_opt_int32(BundleHandle handle, const char* key, int32_t* out); + +/** + * Try to get a string from a Bundle + * @warning outSize must be large enough to include null terminator. This means that your string has to be the expected text length + 1 extra character. + * @param[in] handle the handle that represents the bundle + * @param[in] key the identifier that represents the stored value (~variable name) + * @param[out] out the buffer to store the string in + * @param[in] outSize the size of the buffer + * @return true if "out" was set */ bool tt_bundle_opt_string(BundleHandle handle, const char* key, char* out, uint32_t outSize); +/** + * Store a boolean value in a Bundle + * @param[in] handle the handle that represents the bundle + * @param[in] key the identifier that represents the stored value (~variable name) + * @param[in] value the value to store + */ void tt_bundle_put_bool(BundleHandle handle, const char* key, bool value); + +/** + * Store an int32_t value in a Bundle + * @param[in] handle the handle that represents the bundle + * @param[in] key the identifier that represents the stored value (~variable name) + * @param[in] value the value to store + */ void tt_bundle_put_int32(BundleHandle handle, const char* key, int32_t value); + +/** + * Store a string value in a Bundle + * @param[in] handle the handle that represents the bundle + * @param[in] key the identifier that represents the stored value (~variable name) + * @param[in] value the value to store + */ void tt_bundle_put_string(BundleHandle handle, const char* key, const char* value); #ifdef __cplusplus diff --git a/TactilityC/Source/tt_hal_i2c.cpp b/TactilityC/Source/tt_hal_i2c.cpp index 85e7c4d6..a6186fee 100644 --- a/TactilityC/Source/tt_hal_i2c.cpp +++ b/TactilityC/Source/tt_hal_i2c.cpp @@ -20,15 +20,15 @@ bool tt_hal_i2c_master_read(i2c_port_t port, uint8_t address, uint8_t* data, siz } bool tt_hal_i2c_master_read_register(i2c_port_t port, uint8_t address, uint8_t reg, uint8_t* data, size_t dataSize, TickType_t timeout) { - return tt::hal::i2c::masterRead(port, address, reg, data, dataSize, timeout); + return tt::hal::i2c::masterReadRegister(port, address, reg, data, dataSize, timeout); } -bool tt_hal_i2c_master_write(i2c_port_t port, uint16_t address, const uint8_t* data, uint16_t dataSize, TickType_t timeout) { +bool tt_hal_i2c_master_write(i2c_port_t port, uint8_t address, const uint8_t* data, uint16_t dataSize, TickType_t timeout) { return tt::hal::i2c::masterWrite(port, address, data, dataSize, timeout); } -bool tt_hal_i2c_master_write_register(i2c_port_t port, uint16_t address, uint8_t reg, const uint8_t* data, uint16_t dataSize, TickType_t timeout) { - return tt::hal::i2c::masterWrite(port, address, reg, data, dataSize, timeout); +bool tt_hal_i2c_master_write_register(i2c_port_t port, uint8_t address, uint8_t reg, const uint8_t* data, uint16_t dataSize, TickType_t timeout) { + return tt::hal::i2c::masterWriteRegister(port, address, reg, data, dataSize, timeout); } bool tt_hal_i2c_master_write_read(i2c_port_t port, uint8_t address, const uint8_t* writeData, size_t writeDataSize, uint8_t* readData, size_t readDataSize, TickType_t timeout) { diff --git a/TactilityC/Source/tt_hal_i2c.h b/TactilityC/Source/tt_hal_i2c.h index e0696f20..389e7ef4 100644 --- a/TactilityC/Source/tt_hal_i2c.h +++ b/TactilityC/Source/tt_hal_i2c.h @@ -8,18 +8,102 @@ extern "C" { #endif +/** + * Start I2C communications for the specified port + * @param[in] port the I2C port to init + * @return true on success + */ bool tt_hal_i2c_start(i2c_port_t port); + +/** + * Stop I2C communications for the specified port + * @param[in] port the I2C port to deinit + * @return true on success + */ bool tt_hal_i2c_stop(i2c_port_t port); + +/** + * Check if the port was successfully started. + * @param[in] port the port to check + * @return true when the port was successfully started + */ bool tt_hal_i2c_is_started(i2c_port_t port); +/** + * Read from an I2C port in master mode. + * @param[in] port the I2C port to read from + * @param[in] address + * @param[in] data + * @param[in] dataSize + * @param[in] timeout + */ bool tt_hal_i2c_master_read(i2c_port_t port, uint8_t address, uint8_t* data, size_t dataSize, TickType_t timeout); + +/** + * Read a register from an I2C port in master mode. + * @param[in] port the I2C port to read from + * @param[in] address + * @param[in] reg + * @param[in] data + * @param[in] dataSize + * @param[in] timeout + */ bool tt_hal_i2c_master_read_register(i2c_port_t port, uint8_t address, uint8_t reg, uint8_t* data, size_t dataSize, TickType_t timeout); -bool tt_hal_i2c_master_write(i2c_port_t port, uint16_t address, const uint8_t* data, uint16_t dataSize, TickType_t timeout); -bool tt_hal_i2c_master_write_register(i2c_port_t port, uint16_t address, uint8_t reg, const uint8_t* data, uint16_t dataSize, TickType_t timeout); + +/** + * Write to an I2C port in master mode. + * @param[in] port the I2C port to write to + * @param[in] address + * @param[in] data + * @param[in] dataSize + * @param[in] timeout + */ +bool tt_hal_i2c_master_write(i2c_port_t port, uint8_t address, const uint8_t* data, uint16_t dataSize, TickType_t timeout); + +/** + * Write to a register of an I2C port in master mode. + * @param[in] port the I2C port to write to + * @param[in] address + * @param[in] reg + * @param[in] data + * @param[in] dataSize + * @param[in] timeout + */ +bool tt_hal_i2c_master_write_register(i2c_port_t port, uint8_t address, uint8_t reg, const uint8_t* data, uint16_t dataSize, TickType_t timeout); + +/** + * Write then read from an I2C port in master mode. + * @param[in] port the I2C port to communicate with + * @param[in] address + * @param[in] writeData + * @param[in] writeDataSize + * @param[in] readData + * @param[in] readDataSize + * @param[in] timeout + */ bool tt_hal_i2c_master_write_read(i2c_port_t port, uint8_t address, const uint8_t* writeData, size_t writeDataSize, uint8_t* readData, size_t readDataSize, TickType_t timeout); + +/** + * Check if an I2C port has a device at the specified address. + * @param[in] port the I2C port to communicate with + * @param[in] address + * @param[in] timeout + */ bool tt_hal_i2c_master_has_device_at_address(i2c_port_t port, uint8_t address, TickType_t timeout); +/** + * Used to lock an I2C port. + * This is useful for creating thread-safe I2C calls while calling ESP-IDF directly of third party I2C APIs. + * @param[in] port the I2C port to lock + * @param[in] timeout + */ bool tt_hal_i2c_lock(i2c_port_t port, TickType_t timeout); + +/** + * Used to unlock an I2C port. + * This is useful for creating thread-safe I2C calls while calling ESP-IDF directly of third party I2C APIs. + * @param[in] port the I2C port to unlock + */ bool tt_hal_i2c_unlock(i2c_port_t port); #ifdef __cplusplus diff --git a/TactilityC/Source/tt_init.h b/TactilityC/Source/tt_init.h index 319f9ecf..0439e733 100644 --- a/TactilityC/Source/tt_init.h +++ b/TactilityC/Source/tt_init.h @@ -4,6 +4,10 @@ extern "C" { #endif +/** + * Initialization method for TactilityC + * @warning This is called from the main firmware. Don't call this from an external app! + */ void tt_init_tactility_c(); #ifdef __cplusplus diff --git a/TactilityC/Source/tt_lvgl_spinner.h b/TactilityC/Source/tt_lvgl_spinner.h index 325aa95b..9136d0cc 100644 --- a/TactilityC/Source/tt_lvgl_spinner.h +++ b/TactilityC/Source/tt_lvgl_spinner.h @@ -6,6 +6,7 @@ extern "C" { #endif +/** Create a spinner widget. */ lv_obj_t* tt_lvgl_spinner_create(lv_obj_t* parent); #ifdef __cplusplus diff --git a/TactilityC/Source/tt_lvgl_toolbar.h b/TactilityC/Source/tt_lvgl_toolbar.h index 0c282c5e..65b11904 100644 --- a/TactilityC/Source/tt_lvgl_toolbar.h +++ b/TactilityC/Source/tt_lvgl_toolbar.h @@ -7,7 +7,10 @@ extern "C" { #endif +/** Create a toolbar widget that shows the app name as title */ lv_obj_t* tt_lvgl_toolbar_create(lv_obj_t* parent, AppContextHandle context); + +/** Create a toolbar widget with the provided title*/ lv_obj_t* tt_lvgl_toolbar_create_simple(lv_obj_t* parent, const char* title); #ifdef __cplusplus diff --git a/TactilityC/Source/tt_message_queue.cpp b/TactilityC/Source/tt_message_queue.cpp index 80d2867f..95bd4ab9 100644 --- a/TactilityC/Source/tt_message_queue.cpp +++ b/TactilityC/Source/tt_message_queue.cpp @@ -33,6 +33,10 @@ uint32_t tt_message_queue_get_count(MessageQueueHandle handle) { return HANDLE_TO_MESSAGE_QUEUE(handle)->getCount(); } +uint32_t tt_message_queue_get_space(MessageQueueHandle handle) { + return HANDLE_TO_MESSAGE_QUEUE(handle)->getSpace(); +} + bool tt_message_queue_reset(MessageQueueHandle handle) { return HANDLE_TO_MESSAGE_QUEUE(handle)->reset(); } diff --git a/TactilityC/Source/tt_message_queue.h b/TactilityC/Source/tt_message_queue.h index 53f92841..d9bd3732 100644 --- a/TactilityC/Source/tt_message_queue.h +++ b/TactilityC/Source/tt_message_queue.h @@ -9,15 +9,53 @@ extern "C" { #include #include +/** A handle that represents a message queue instance */ typedef void* MessageQueueHandle; +/** + * Allocate a new message queue in memory. + * @param[in] capacity how many messages this queue can contain before it starts blocking input + * @param[in] messageSize the size of a message + */ MessageQueueHandle tt_message_queue_alloc(uint32_t capacity, uint32_t messageSize); + +/** Free up the memory of a queue (dealloc) */ void tt_message_queue_free(MessageQueueHandle handle); + +/** + * Put (post) a message in the queue + * @param[in] handle the queue handle + * @param[in] message the message of the correct size - its data will be copied + * @param[timeout] timeout the amount of ticks to wait until the message is queued + * @return true if the item was successfully queued + */ bool tt_message_queue_put(MessageQueueHandle handle, const void* message, TickType_t timeout); + +/** + * Get the oldest message from the queue. + * @param[in] handle the queue handle + * @param[out] message a pointer to a message of the correct size + * @param[in] timeout the amount of ticks to wait until a message was copied + * @return true if a message was successfully copied + */ bool tt_message_queue_get(MessageQueueHandle handle, void* message, TickType_t timeout); + +/** @return the total amount of messages that this queue can hold */ uint32_t tt_message_queue_get_capacity(MessageQueueHandle handle); + +/** @return the size of a single message in the queue */ uint32_t tt_message_queue_get_message_size(MessageQueueHandle handle); + +/** @return the current amount of items in the queue */ uint32_t tt_message_queue_get_count(MessageQueueHandle handle); + +/** @return the remaining capacity in the queue */ +uint32_t tt_message_queue_get_space(MessageQueueHandle handle); + +/** + * Remove all items from the queue (if any) + * @return true on failure + */ bool tt_message_queue_reset(MessageQueueHandle handle); #ifdef __cplusplus diff --git a/TactilityC/Source/tt_mutex.cpp b/TactilityC/Source/tt_mutex.cpp index 119412e7..46b96d58 100644 --- a/TactilityC/Source/tt_mutex.cpp +++ b/TactilityC/Source/tt_mutex.cpp @@ -8,9 +8,9 @@ extern "C" { MutexHandle tt_mutex_alloc(enum TtMutexType type) { switch (type) { case TtMutexType::MUTEX_TYPE_NORMAL: - return new tt::Mutex(tt::Mutex::TypeNormal); + return new tt::Mutex(tt::Mutex::Type::Normal); case TtMutexType::MUTEX_TYPE_RECURSIVE: - return new tt::Mutex(tt::Mutex::TypeRecursive); + return new tt::Mutex(tt::Mutex::Type::Recursive); default: tt_crash("Type not supported"); } diff --git a/TactilityC/Source/tt_mutex.h b/TactilityC/Source/tt_mutex.h index 8f4b8e4e..f3ba3ddf 100644 --- a/TactilityC/Source/tt_mutex.h +++ b/TactilityC/Source/tt_mutex.h @@ -9,6 +9,7 @@ extern "C" { #include #include +/** A handle that represents a mutex instance */ typedef void* MutexHandle; enum TtMutexType { @@ -16,9 +17,30 @@ enum TtMutexType { MUTEX_TYPE_RECURSIVE }; -MutexHandle tt_mutex_alloc(enum TtMutexType); +/** + * Allocate a new mutex instance + * @param[in] type specify if the mutex is either a normal one, or whether it can recursively (re)lock + * @return the allocated instance + */ +MutexHandle tt_mutex_alloc(enum TtMutexType type); + +/** Free up the memory of the specified mutex instance. */ void tt_mutex_free(MutexHandle handle); -bool tt_mutex_lock(MutexHandle handle, TickType_t timeoutTicks); + +/** + * Attempt to lock a mutex. + * @param[in] handle the handle that represents the mutex instance + * @param[in] timeout the maximum amount of ticks to wait when trying to lock + * @return true when the lock was acquired + */ +bool tt_mutex_lock(MutexHandle handle, TickType_t timeout); + +/** + * Attempt to unlock a mutex. + * @param[in] handle the handle that represents the mutex instance + * @param[in] timeout the maximum amount of ticks to wait when trying to unlock + * @return true when the lock was unlocked + */ bool tt_mutex_unlock(MutexHandle handle); #ifdef __cplusplus diff --git a/TactilityC/Source/tt_semaphore.h b/TactilityC/Source/tt_semaphore.h index 0f3dd607..71dd4aa3 100644 --- a/TactilityC/Source/tt_semaphore.h +++ b/TactilityC/Source/tt_semaphore.h @@ -9,12 +9,40 @@ extern "C" { #include #include +/** A handle that represents a semaphore instance */ typedef void* SemaphoreHandle; +/** + * Allocate a new semaphore instance. + * @param[in] maxCount the maximum counter value + * @param[in] initialCount the initial counter value + * @return the handle that represents the new instance + */ SemaphoreHandle tt_semaphore_alloc(uint32_t maxCount, TickType_t initialCount); + +/** Free up the memory of a specified semaphore instance */ void tt_semaphore_free(SemaphoreHandle handle); -bool tt_semaphore_acquire(SemaphoreHandle handle, TickType_t timeoutTicks); + +/** + * Attempt to acquire a semaphore (increase counter) + * @param[in] handle the instance handle + * @param[in] timeout the maximum amount of ticks to wait while trying to acquire + * @return true on successfully acquiring the semaphore (counter is increased) + */ +bool tt_semaphore_acquire(SemaphoreHandle handle, TickType_t timeout); + +/** + * Release an acquired semaphore (decrease counter) + * @param[in] handle the instance handle + * @return true on successfully releasing the semaphore (counter is decreased) + */ bool tt_semaphore_release(SemaphoreHandle handle); + +/** + * Get the counter value of this semaphore instance + * @param[in] handle the instance handle + * @return the current counter value (acquisition count) + */ uint32_t tt_semaphore_get_count(SemaphoreHandle handle); #ifdef __cplusplus diff --git a/TactilityC/Source/tt_service_loader.cpp b/TactilityC/Source/tt_service_loader.cpp index 5f1fdbd7..801765be 100644 --- a/TactilityC/Source/tt_service_loader.cpp +++ b/TactilityC/Source/tt_service_loader.cpp @@ -4,9 +4,9 @@ extern "C" { -void tt_service_loader_start_app(const char* id, bool blocking, BundleHandle _Nullable bundle) { +void tt_service_loader_start_app(const char* id, BundleHandle _Nullable bundle) { auto shared_bundle = std::shared_ptr((tt::Bundle*)bundle); - tt::service::loader::startApp(id, blocking, std::move(shared_bundle)); + tt::service::loader::startApp(id, std::move(shared_bundle)); } void tt_service_loader_stop_app() { diff --git a/TactilityC/Source/tt_service_loader.h b/TactilityC/Source/tt_service_loader.h index f8b4a8ca..cbdd0bc6 100644 --- a/TactilityC/Source/tt_service_loader.h +++ b/TactilityC/Source/tt_service_loader.h @@ -8,12 +8,24 @@ extern "C" { #endif /** + * Start an application providing a manifest id and an optional bundle. + * Execution is always deferred. + * This function generally returns immediately unless the scheduler is blocked. * @param[in] id application manifest id - * @param[in] blocking whether this operation blocks until the application is started * @param[in] bundle an allocated bundle (or NULL) of which the memory ownership is handed over to this function */ -void tt_service_loader_start_app(const char* id, bool blocking, BundleHandle _Nullable bundle); +void tt_service_loader_start_app(const char* id, BundleHandle _Nullable bundle); + +/** + * Stop the currently active app. + * Execution is always deferred. + * This function generally returns immediately unless the scheduler is blocked. + */ void tt_service_loader_stop_app(); + +/** + * Get the context handle of the app that is currently shown on the screen. + */ AppContextHandle tt_service_loader_get_current_app(); #ifdef __cplusplus diff --git a/TactilityC/Source/tt_thread.cpp b/TactilityC/Source/tt_thread.cpp index ae87d46d..9c3ba85e 100644 --- a/TactilityC/Source/tt_thread.cpp +++ b/TactilityC/Source/tt_thread.cpp @@ -55,8 +55,8 @@ void tt_thread_start(ThreadHandle handle) { HANDLE_AS_THREAD(handle)->start(); } -bool tt_thread_join(ThreadHandle handle) { - return HANDLE_AS_THREAD(handle)->join(); +bool tt_thread_join(ThreadHandle handle, TickType_t timeout) { + return HANDLE_AS_THREAD(handle)->join(timeout); } ThreadId tt_thread_get_id(ThreadHandle handle) { diff --git a/TactilityC/Source/tt_thread.h b/TactilityC/Source/tt_thread.h index cb7164a3..e1dec737 100644 --- a/TactilityC/Source/tt_thread.h +++ b/TactilityC/Source/tt_thread.h @@ -16,14 +16,17 @@ extern "C" { #include #include +/** The handle that represents the thread insance */ typedef void* ThreadHandle; +/** The state of a thread instance */ typedef enum { ThreadStateStopped, ThreadStateStarting, ThreadStateRunning, } ThreadState; +/** The identifier that represents the thread */ typedef TaskHandle_t ThreadId; /** ThreadCallback Your callback to run in new thread @@ -48,23 +51,98 @@ typedef enum { ThreadPriorityHighest = 7U } ThreadPriority; +/** @return a thread handle that represents a newly allocated thread instance */ ThreadHandle tt_thread_alloc(); + +/** + * Allocate a thread and provide some common parameters so it's all ready to be started. + * @param[in] name the name of the thread + * @param[in] stackSize the size of the stack in bytes + * @param[in] callback the callback to call from the thread + * @param[in] callbackContext the data to pass to the callback + */ ThreadHandle tt_thread_alloc_ext( const char* name, uint32_t stackSize, ThreadCallback callback, void* _Nullable callbackContext ); + +/** + * Free up the memory of the thread that is represented by this handle + * @param[in] handle the thread instance handle + */ void tt_thread_free(ThreadHandle handle); + +/** + * Set the name of a thread + * @param[in] handle the thread instance handle + * @param[in] name the name to set + */ void tt_thread_set_name(ThreadHandle handle, const char* name); + +/** + * Set the stack size of the thread (in bytes) + * @param[in] handle the thread instance handle + * @param[in] the size of the thread in bytes + */ void tt_thread_set_stack_size(ThreadHandle handle, size_t size); + +/** + * Set the callback for a thread. This method is executed when the thread is started. + * @param[in] handle the thread instance handle + * @param[in] callback the callback to set + * @param[in] callbackContext the data to pass to the callback + */ void tt_thread_set_callback(ThreadHandle handle, ThreadCallback callback, void* _Nullable callbackContext); + +/** + * Set the priority of a thread + * @param[in] handle the thread instance handle + * @param[in] priority the priority to set + */ void tt_thread_set_priority(ThreadHandle handle, ThreadPriority priority); + +/** + * Set the state callback for a thread + * @param[in] handle the thread instance handle + * @param[in] callback the callback to set + * @param[in] callbackContext the data to pass to the callback + */ void tt_thread_set_state_callback(ThreadHandle handle, ThreadStateCallback callback, void* _Nullable callbackContext); + +/** + * @param[in] handle the thread instance handle + * @return the current state of a thread + */ ThreadState tt_thread_get_state(ThreadHandle handle); + +/** + * Start a thread + * @param[in] handle the thread instance handle + */ void tt_thread_start(ThreadHandle handle); -bool tt_thread_join(ThreadHandle handle); + +/** + * Wait (block) for the thread to finish. + * @param[in] handle the thread instance handle + * @warning make sure you manually interrupt any logic in your thread (e.g. by an EventFlag or boolean+Mutex) + */ +bool tt_thread_join(ThreadHandle handle, TickType_t timeout); + +/** + * Get thread id + * @param[in] handle the thread instance handle + * @return the ThreadId of a thread + * */ ThreadId tt_thread_get_id(ThreadHandle handle); + +/** + * Get the return code of a thread + * @warning crashes when state is not "stopped" + * @param[in] handle the thread instance handle + * @return the return code of a thread or + */ int32_t tt_thread_get_return_code(ThreadHandle handle); #ifdef __cplusplus diff --git a/TactilityC/Source/tt_timer.h b/TactilityC/Source/tt_timer.h index 8c1842ae..408f457c 100644 --- a/TactilityC/Source/tt_timer.h +++ b/TactilityC/Source/tt_timer.h @@ -10,8 +10,10 @@ extern "C" { #include #include +/** The handle that represents a timer instance */ typedef void* TimerHandle; +/** The behaviour of the timer */ typedef enum { TimerTypeOnce = 0, ///< One-shot timer. TimerTypePeriodic = 1 ///< Repeating timer. @@ -20,14 +22,68 @@ typedef enum { typedef void (*TimerCallback)(void* context); typedef void (*TimerPendingCallback)(void* context, uint32_t arg); +/** + * Create a new timer instance + * @param[in] callback the callback to call when the timer expires + * @param[in] callbackContext the data to pass to the callback + */ TimerHandle tt_timer_alloc(TimerType type, TimerCallback callback, void* callbackContext); + +/** Free up the memory of a timer instance */ void tt_timer_free(TimerHandle handle); -bool tt_timer_start(TimerHandle handle, TickType_t intervalTicks); -bool tt_timer_restart(TimerHandle handle, TickType_t intervalTicks); + +/** + * Start the timer + * @param[in] handle the timer instance handle + * @parma[in] interval the interval of the timer + * @return true when the timer was successfully started + */ +bool tt_timer_start(TimerHandle handle, TickType_t interval); + +/** + * Restart an already started timer + * @param[in] handle the timer instance handle + * @parma[in] interval the interval of the timer + * @return true when the timer was successfully restarted + */ +bool tt_timer_restart(TimerHandle handle, TickType_t interval); + +/** + * Stop a started timer + * @param[in] handle the timer instance handle + * @return true when the timer was successfully stopped + */ bool tt_timer_stop(TimerHandle handle); + +/** + * Check if a timer is started + * @param[in] handle the timer instance handle + * @return true when the timer is started (pending) + */ bool tt_timer_is_running(TimerHandle handle); + +/** + * Get the expire time of a timer + * @param[in] handle the timer instance handle + * @return the absolute timestamp at which the timer will expire + */ uint32_t tt_timer_get_expire_time(TimerHandle handle); -bool tt_timer_set_pending_callback(TimerHandle handle, TimerPendingCallback callback, void* callbackContext, uint32_t callbackArg, TickType_t timeoutTicks); + +/** + * Set the pending callback for a timer + * @param[in] handle the timer instance handle + * @param[in] callback the callback to set + * @param[in] callbackContext the context to pass to the callback + * @param[in] timeout the timeout for setting the callback + * @return when the callback was successfully set + */ +bool tt_timer_set_pending_callback(TimerHandle handle, TimerPendingCallback callback, void* callbackContext, uint32_t callbackArg, TickType_t timeout); + +/** + * Set the thread priority for the callback of the timer + * @param[in] handle the timer instance handle + * @param[in] priority the thread priority to set + */ void tt_timer_set_thread_priority(TimerHandle handle, ThreadPriority priority); #ifdef __cplusplus diff --git a/TactilityCore/Source/Bundle.cpp b/TactilityCore/Source/Bundle.cpp index c4185fa8..5f6c101b 100644 --- a/TactilityCore/Source/Bundle.cpp +++ b/TactilityCore/Source/Bundle.cpp @@ -16,22 +16,22 @@ std::string Bundle::getString(const std::string& key) const { bool Bundle::hasBool(const std::string& key) const { auto entry = this->entries.find(key); - return entry != std::end(this->entries) && entry->second.type == TypeBool; + return entry != std::end(this->entries) && entry->second.type == Type::Bool; } bool Bundle::hasInt32(const std::string& key) const { auto entry = this->entries.find(key); - return entry != std::end(this->entries) && entry->second.type == TypeInt32; + return entry != std::end(this->entries) && entry->second.type == Type::Int32; } bool Bundle::hasString(const std::string& key) const { auto entry = this->entries.find(key); - return entry != std::end(this->entries) && entry->second.type == TypeString; + return entry != std::end(this->entries) && entry->second.type == Type::String; } bool Bundle::optBool(const std::string& key, bool& out) const { auto entry = this->entries.find(key); - if (entry != std::end(this->entries) && entry->second.type == TypeBool) { + if (entry != std::end(this->entries) && entry->second.type == Type::Bool) { out = entry->second.value_bool; return true; } else { @@ -41,7 +41,7 @@ bool Bundle::optBool(const std::string& key, bool& out) const { bool Bundle::optInt32(const std::string& key, int32_t& out) const { auto entry = this->entries.find(key); - if (entry != std::end(this->entries) && entry->second.type == TypeInt32) { + if (entry != std::end(this->entries) && entry->second.type == Type::Int32) { out = entry->second.value_int32; return true; } else { @@ -51,7 +51,7 @@ bool Bundle::optInt32(const std::string& key, int32_t& out) const { bool Bundle::optString(const std::string& key, std::string& out) const { auto entry = this->entries.find(key); - if (entry != std::end(this->entries) && entry->second.type == TypeString) { + if (entry != std::end(this->entries) && entry->second.type == Type::String) { out = entry->second.value_string; return true; } else { @@ -61,7 +61,7 @@ bool Bundle::optString(const std::string& key, std::string& out) const { void Bundle::putBool(const std::string& key, bool value) { this->entries[key] = { - .type = TypeBool, + .type = Type::Bool, .value_bool = value, .value_string = "" }; @@ -69,7 +69,7 @@ void Bundle::putBool(const std::string& key, bool value) { void Bundle::putInt32(const std::string& key, int32_t value) { this->entries[key] = { - .type = TypeInt32, + .type = Type::Int32, .value_int32 = value, .value_string = "" }; @@ -77,7 +77,7 @@ void Bundle::putInt32(const std::string& key, int32_t value) { void Bundle::putString(const std::string& key, const std::string& value) { this->entries[key] = { - .type = TypeString, + .type = Type::String, .value_bool = false, .value_string = value }; diff --git a/TactilityCore/Source/Bundle.h b/TactilityCore/Source/Bundle.h index d0789dc9..559e658b 100644 --- a/TactilityCore/Source/Bundle.h +++ b/TactilityCore/Source/Bundle.h @@ -19,11 +19,11 @@ private: typedef uint32_t Hash; - typedef enum { - TypeBool, - TypeInt32, - TypeString, - } Type; + enum class Type { + Bool, + Int32, + String, + }; typedef struct { Type type; diff --git a/TactilityCore/Source/Dispatcher.cpp b/TactilityCore/Source/Dispatcher.cpp index 34e3d36d..57f0dee0 100644 --- a/TactilityCore/Source/Dispatcher.cpp +++ b/TactilityCore/Source/Dispatcher.cpp @@ -9,7 +9,7 @@ namespace tt { #define WAIT_FLAG 1 Dispatcher::Dispatcher() : - mutex(Mutex::TypeNormal) + mutex(Mutex::Type::Normal) {} Dispatcher::~Dispatcher() { diff --git a/TactilityCore/Source/Log.cpp b/TactilityCore/Source/Log.cpp index 05a51e04..17930613 100644 --- a/TactilityCore/Source/Log.cpp +++ b/TactilityCore/Source/Log.cpp @@ -61,15 +61,15 @@ namespace tt { static char toPrefix(LogLevel level) { switch (level) { - case LogLevelError: + case LogLevel::Error: return 'E'; - case LogLevelWarning: + case LogLevel::Warning: return 'W'; - case LogLevelInfo: + case LogLevel::Info: return 'I'; - case LogLevelDebug: + case LogLevel::Debug: return 'D'; - case LogLevelVerbose: + case LogLevel::Verbose: return 'T'; default: return '?'; @@ -78,15 +78,15 @@ static char toPrefix(LogLevel level) { static const char* toColour(LogLevel level) { switch (level) { - case LogLevelError: + case LogLevel::Error: return "\033[1;31m"; - case LogLevelWarning: + case LogLevel::Warning: return "\033[33m"; - case LogLevelInfo: + case LogLevel::Info: return "\033[32m"; - case LogLevelDebug: + case LogLevel::Debug: return "\033[1;37m"; - case LogLevelVerbose: + case LogLevel::Verbose: return "\033[37m"; default: return ""; diff --git a/TactilityCore/Source/Log.h b/TactilityCore/Source/Log.h index d87ee2bf..c6428d5b 100644 --- a/TactilityCore/Source/Log.h +++ b/TactilityCore/Source/Log.h @@ -13,17 +13,17 @@ namespace tt { /** Used for log output filtering */ -enum LogLevel { - LogLevelNone, /*!< No log output */ - LogLevelError, /*!< Critical errors, software module can not recover on its own */ - LogLevelWarning, /*!< Error conditions from which recovery measures have been taken */ - LogLevelInfo, /*!< Information messages which describe normal flow of events */ - LogLevelDebug, /*!< Extra information which is not necessary for normal use (values, pointers, sizes, etc). */ - LogLevelVerbose /*!< Bigger chunks of debugging information, or frequent messages which can potentially flood the output. */ +enum class LogLevel { + None, /*!< No log output */ + Error, /*!< Critical errors, software module can not recover on its own */ + Warning, /*!< Error conditions from which recovery measures have been taken */ + Info, /*!< Information messages which describe normal flow of events */ + Debug, /*!< Extra information which is not necessary for normal use (values, pointers, sizes, etc). */ + Verbose /*!< Bigger chunks of debugging information, or frequent messages which can potentially flood the output. */ }; struct LogEntry { - LogLevel level = LogLevelNone; + LogLevel level = LogLevel::None; char message[TT_LOG_MESSAGE_SIZE] = { 0 }; }; @@ -64,14 +64,14 @@ void log(LogLevel level, const char* tag, const char* format, ...); } // namespace #define TT_LOG_E(tag, format, ...) \ - tt::log(tt::LogLevelError, tag, format, ##__VA_ARGS__) + tt::log(tt::LogLevel::Error, tag, format, ##__VA_ARGS__) #define TT_LOG_W(tag, format, ...) \ - tt::log(tt::LogLevelWarning, tag, format, ##__VA_ARGS__) + tt::log(tt::LogLevel::Warning, tag, format, ##__VA_ARGS__) #define TT_LOG_I(tag, format, ...) \ - tt::log(tt::LogLevelInfo, tag, format, ##__VA_ARGS__) + tt::log(tt::LogLevel::Info, tag, format, ##__VA_ARGS__) #define TT_LOG_D(tag, format, ...) \ - tt::log(tt::LogLevelDebug, tag, format, ##__VA_ARGS__) + tt::log(tt::LogLevel::Debug, tag, format, ##__VA_ARGS__) #define TT_LOG_T(tag, format, ...) \ - tt::log(tt::LogLevelTrace, tag, format, ##__VA_ARGS__) + tt::log(tt::LogLevel::Trace, tag, format, ##__VA_ARGS__) #endif // ESP_TARGET diff --git a/TactilityCore/Source/Mutex.cpp b/TactilityCore/Source/Mutex.cpp index 1f170e4a..c8e44572 100644 --- a/TactilityCore/Source/Mutex.cpp +++ b/TactilityCore/Source/Mutex.cpp @@ -25,10 +25,10 @@ namespace tt { Mutex::Mutex(Type type) : type(type) { tt_mutex_info(data, "alloc"); switch (type) { - case TypeNormal: + case Type::Normal: semaphore = xSemaphoreCreateMutex(); break; - case TypeRecursive: + case Type::Recursive: semaphore = xSemaphoreCreateRecursiveMutex(); break; default: @@ -51,7 +51,7 @@ TtStatus Mutex::acquire(TickType_t timeout) const { tt_mutex_info(mutex, "acquire"); switch (type) { - case TypeNormal: + case Type::Normal: if (xSemaphoreTake(semaphore, timeout) != pdPASS) { if (timeout != 0U) { return TtStatusErrorTimeout; @@ -61,7 +61,7 @@ TtStatus Mutex::acquire(TickType_t timeout) const { } else { return TtStatusOk; } - case TypeRecursive: + case Type::Recursive: if (xSemaphoreTakeRecursive(semaphore, timeout) != pdPASS) { if (timeout != 0U) { return TtStatusErrorTimeout; @@ -82,14 +82,14 @@ TtStatus Mutex::release() const { tt_mutex_info(mutex, "release"); switch (type) { - case TypeNormal: { + case Type::Normal: { if (xSemaphoreGive(semaphore) != pdPASS) { return TtStatusErrorResource; } else { return TtStatusOk; } } - case TypeRecursive: + case Type::Recursive: if (xSemaphoreGiveRecursive(semaphore) != pdPASS) { return TtStatusErrorResource; } else { diff --git a/TactilityCore/Source/Mutex.h b/TactilityCore/Source/Mutex.h index 4109d1ab..1c0fd8ef 100644 --- a/TactilityCore/Source/Mutex.h +++ b/TactilityCore/Source/Mutex.h @@ -21,9 +21,9 @@ class Mutex : public Lockable { public: - enum Type { - TypeNormal, - TypeRecursive, + enum class Type { + Normal, + Recursive, }; private: @@ -33,7 +33,7 @@ private: public: - explicit Mutex(Type type = TypeNormal); + explicit Mutex(Type type = Type::Normal); ~Mutex() override; /** Attempt to lock the mutex. Blocks until timeout passes or lock is acquired. diff --git a/TactilityCore/Source/Semaphore.h b/TactilityCore/Source/Semaphore.h index da7f0497..a947ef62 100644 --- a/TactilityCore/Source/Semaphore.h +++ b/TactilityCore/Source/Semaphore.h @@ -32,7 +32,7 @@ public: ~Semaphore(); /** Acquire semaphore */ - bool acquire(uint32_t timeoutTicks) const; + bool acquire(uint32_t timeout) const; /** Release semaphore */ bool release() const; diff --git a/TactilityCore/Source/Thread.cpp b/TactilityCore/Source/Thread.cpp index abaeb539..06c06c9a 100644 --- a/TactilityCore/Source/Thread.cpp +++ b/TactilityCore/Source/Thread.cpp @@ -187,15 +187,19 @@ void Thread::start() { tt_check(data.state == State::Stopped || data.taskHandle); } -bool Thread::join() { +bool Thread::join(TickType_t timeout, TickType_t pollInterval) { tt_check(thread_get_current() != this); // !!! IMPORTANT NOTICE !!! // // If your thread exited, but your app stuck here: some other thread uses // all cpu time, which delays kernel from releasing task handle + TickType_t start_ticks = kernel::getTicks(); while (data.taskHandle) { - kernel::delayMillis(10); + kernel::delayTicks(pollInterval); + if ((kernel::getTicks() - start_ticks) > timeout) { + return false; + } } return true; diff --git a/TactilityCore/Source/Thread.h b/TactilityCore/Source/Thread.h index 8d6434e8..aa07fa3c 100644 --- a/TactilityCore/Source/Thread.h +++ b/TactilityCore/Source/Thread.h @@ -122,17 +122,22 @@ public: void start(); /** Join Thread - * @warning Use this method only when CPU is not busy (Idle task receives control), otherwise it will wait forever. + * @warning make sure you manually interrupt any logic in your thread (e.g. by an EventFlag or boolean+Mutex) + * @param[in] timeout the maximum amount of time to wait + * @param[in] pollInterval the amount of ticks to wait before we check again if the thread is finished * @return success result */ - bool join(); + bool join(TickType_t timeout = portMAX_DELAY, TickType_t pollInterval = 10); /** Get FreeRTOS ThreadId for Thread instance * @return ThreadId or nullptr */ ThreadId getId() const; - /** @return thread return code */ + /** + * @warning crashes when state is not "stopped" + * @return thread return code + */ int32_t getReturnCode() const; private: diff --git a/TactilityCore/Source/Timer.cpp b/TactilityCore/Source/Timer.cpp index 7fbf41e8..c8b7bc7c 100644 --- a/TactilityCore/Source/Timer.cpp +++ b/TactilityCore/Source/Timer.cpp @@ -21,7 +21,7 @@ Timer::Timer(Type type, Callback callback, std::shared_ptr callbackContext this->callbackContext = std::move(callbackContext); UBaseType_t reload; - if (type == TypeOnce) { + if (type == Type::Once) { reload = pdFALSE; } else { reload = pdTRUE; diff --git a/TactilityCore/Source/Timer.h b/TactilityCore/Source/Timer.h index 0534d6f1..3b2baf16 100644 --- a/TactilityCore/Source/Timer.h +++ b/TactilityCore/Source/Timer.h @@ -19,10 +19,15 @@ public: Callback callback; std::shared_ptr callbackContext; - typedef enum { - TypeOnce = 0, ///< One-shot timer. - TypePeriodic = 1 ///< Repeating timer. - } Type; + enum class Type { + Once = 0, ///< One-shot timer. + Periodic = 1 ///< Repeating timer. + }; + + enum class Priority{ + Normal, /**< Lower then other threads */ + Elevated, /**< Same as other threads */ + }; /** * @param[in] type The timer type @@ -74,11 +79,6 @@ public: */ bool setPendingCallback(PendingCallback callback, void* callbackContext, uint32_t callbackArg, TickType_t timeout); - enum class Priority{ - Normal, /**< Lower then other threads */ - Elevated, /**< Same as other threads */ - }; - /** Set Timer thread priority * @param[in] priority The priority */ diff --git a/TactilityHeadless/Private/service/ServiceInstance.h b/TactilityHeadless/Private/service/ServiceInstance.h index d50682fd..48ecadd0 100644 --- a/TactilityHeadless/Private/service/ServiceInstance.h +++ b/TactilityHeadless/Private/service/ServiceInstance.h @@ -8,7 +8,7 @@ class ServiceInstance : public ServiceContext { private: - Mutex mutex = Mutex(Mutex::TypeNormal); + Mutex mutex = Mutex(Mutex::Type::Normal); const service::ServiceManifest& manifest; std::shared_ptr data = nullptr; diff --git a/TactilityHeadless/Source/hal/Power.h b/TactilityHeadless/Source/hal/Power.h index 082e8035..fa048847 100644 --- a/TactilityHeadless/Source/hal/Power.h +++ b/TactilityHeadless/Source/hal/Power.h @@ -11,11 +11,11 @@ public: Power() = default; virtual ~Power() = default; - enum MetricType { - IS_CHARGING, // bool - CURRENT, // int32_t, mAh - battery current: either during charging (positive value) or discharging (negative value) - BATTERY_VOLTAGE, // uint32_t, mV - CHARGE_LEVEL, // uint8_t [0, 100] + enum class MetricType { + IsCharging, // bool + Current, // int32_t, mAh - battery current: either during charging (positive value) or discharging (negative value) + BatteryVoltage, // uint32_t, mV + ChargeLevel, // uint8_t [0, 100] }; union MetricData { diff --git a/TactilityHeadless/Source/hal/SdCard.h b/TactilityHeadless/Source/hal/SdCard.h index 3b7266dd..b2746d24 100644 --- a/TactilityHeadless/Source/hal/SdCard.h +++ b/TactilityHeadless/Source/hal/SdCard.h @@ -9,16 +9,16 @@ namespace tt::hal { class SdCard { public: - enum State { - StateMounted, - StateUnmounted, - StateError, - StateUnknown + enum class State { + Mounted, + Unmounted, + Error, + Unknown }; - enum MountBehaviour { - MountBehaviourAtBoot, /** Only mount at boot */ - MountBehaviourAnytime /** Mount/dismount any time */ + enum class MountBehaviour { + AtBoot, /** Only mount at boot */ + Anytime /** Mount/dismount any time */ }; private: @@ -33,7 +33,7 @@ public: virtual State getState() const = 0; virtual MountBehaviour getMountBehaviour() const { return mountBehaviour; } - bool isMounted() const { return getState() == StateMounted; } + bool isMounted() const { return getState() == State::Mounted; } }; } // namespace diff --git a/TactilityHeadless/Source/hal/SpiSdCard.cpp b/TactilityHeadless/Source/hal/SpiSdCard.cpp index e42aaafc..bb37ca26 100644 --- a/TactilityHeadless/Source/hal/SpiSdCard.cpp +++ b/TactilityHeadless/Source/hal/SpiSdCard.cpp @@ -127,7 +127,7 @@ bool SpiSdCard::unmount() { // TODO: Refactor to "bool getStatus(Status* status)" method so that it can fail when the lvgl lock fails tt::hal::SdCard::State SpiSdCard::getState() const { if (card == nullptr) { - return StateUnmounted; + return State::Unmounted; } /** @@ -139,7 +139,7 @@ tt::hal::SdCard::State SpiSdCard::getState() const { bool locked = config->lockable->lock(50); // TODO: Refactor to a more reliable locking mechanism if (!locked) { TT_LOG_E(TAG, LOG_MESSAGE_MUTEX_LOCK_FAILED_FMT, "LVGL"); - return StateUnknown; + return State::Unknown; } } @@ -150,9 +150,9 @@ tt::hal::SdCard::State SpiSdCard::getState() const { } if (result) { - return StateMounted; + return State::Mounted; } else { - return StateError; + return State::Error; } } diff --git a/TactilityHeadless/Source/hal/i2c/I2c.cpp b/TactilityHeadless/Source/hal/i2c/I2c.cpp index 4cfb9558..825de98a 100644 --- a/TactilityHeadless/Source/hal/i2c/I2c.cpp +++ b/TactilityHeadless/Source/hal/i2c/I2c.cpp @@ -21,11 +21,23 @@ static Data dataArray[I2C_NUM_MAX]; #define TAG "i2c" +const char* initModeToString(InitMode mode) { + switch (mode) { + case InitMode::ByTactility: + return TT_STRINGIFY(InitMode::ByTactility); + case InitMode::ByExternal: + return TT_STRINGIFY(InitMode::ByExternal); + case InitMode::Disabled: + return TT_STRINGIFY(InitMode::Disabled); + } + tt_crash("not implemented"); +} + void printInfo(const Data& data) { TT_LOG_V(TAG, "I2C info for port %d", data.configuration.port); TT_LOG_V(TAG, " isStarted: %d", data.isStarted); TT_LOG_V(TAG, " isConfigured: %d", data.isConfigured); - TT_LOG_V(TAG, " initMode: %d", data.configuration.initMode); + TT_LOG_V(TAG, " initMode: %s", initModeToString(data.configuration.initMode)); TT_LOG_V(TAG, " canReinit: %d", data.configuration.canReinit); TT_LOG_V(TAG, " hasMutableConfiguration: %d", data.configuration.hasMutableConfiguration); TT_LOG_V(TAG, " SDA pin: %d", data.configuration.config.sda_io_num); @@ -46,11 +58,11 @@ bool init(const std::vector& configurations) { for (const auto& config: configurations) { printInfo(dataArray[config.port]); - if (config.initMode == InitByTactility) { + if (config.initMode == InitMode::ByTactility) { if (!start(config.port)) { return false; } - } else if (config.initMode == InitByExternal) { + } else if (config.initMode == InitMode::ByExternal) { dataArray[config.port].isStarted = true; } } @@ -177,6 +189,7 @@ bool isStarted(i2c_port_t port) { bool masterRead(i2c_port_t port, uint8_t address, uint8_t* data, size_t dataSize, TickType_t timeout) { if (lock(port)) { + // TODO: We're passing an inaccurate timeout value as we already lost time with locking and previous writes in this loop esp_err_t result = i2c_master_read_from_device(port, address, data, dataSize, timeout); unlock(port); return result == ESP_OK; @@ -186,9 +199,7 @@ bool masterRead(i2c_port_t port, uint8_t address, uint8_t* data, size_t dataSize } } -bool masterRead(i2c_port_t port, uint8_t address, uint8_t reg, uint8_t* data, size_t dataSize, TickType_t timeout) { - tt_check(reg != 0); - +bool masterReadRegister(i2c_port_t port, uint8_t address, uint8_t reg, uint8_t* data, size_t dataSize, TickType_t timeout) { if (!lock(port)) { TT_LOG_E(TAG, "(%d) Mutex timeout", port); return false; @@ -207,6 +218,7 @@ bool masterRead(i2c_port_t port, uint8_t address, uint8_t reg, uint8_t* data, si } i2c_master_read_byte(cmd, data + dataSize - 1, I2C_MASTER_NACK); i2c_master_stop(cmd); + // TODO: We're passing an inaccurate timeout value as we already lost time with locking esp_err_t result = i2c_master_cmd_begin(port, cmd, timeout); i2c_cmd_link_delete(cmd); @@ -218,8 +230,9 @@ bool masterRead(i2c_port_t port, uint8_t address, uint8_t reg, uint8_t* data, si return result == ESP_OK; } -bool masterWrite(i2c_port_t port, uint16_t address, const uint8_t* data, uint16_t dataSize, TickType_t timeout) { +bool masterWrite(i2c_port_t port, uint8_t address, const uint8_t* data, uint16_t dataSize, TickType_t timeout) { if (lock(port)) { + // TODO: We're passing an inaccurate timeout value as we already lost time with locking esp_err_t result = i2c_master_write_to_device(port, address, data, dataSize, timeout); unlock(port); return result == ESP_OK; @@ -229,7 +242,7 @@ bool masterWrite(i2c_port_t port, uint16_t address, const uint8_t* data, uint16_ } } -bool masterWrite(i2c_port_t port, uint16_t address, uint8_t reg, const uint8_t* data, uint16_t dataSize, TickType_t timeout) { +bool masterWriteRegister(i2c_port_t port, uint8_t address, uint8_t reg, const uint8_t* data, uint16_t dataSize, TickType_t timeout) { tt_check(reg != 0); if (!lock(port)) { @@ -243,6 +256,7 @@ bool masterWrite(i2c_port_t port, uint16_t address, uint8_t reg, const uint8_t* i2c_master_write_byte(cmd, reg, ACK_CHECK_EN); i2c_master_write(cmd, (uint8_t*) data, dataSize, ACK_CHECK_EN); i2c_master_stop(cmd); + // TODO: We're passing an inaccurate timeout value as we already lost time with locking esp_err_t result = i2c_master_cmd_begin(port, cmd, timeout); i2c_cmd_link_delete(cmd); @@ -253,8 +267,21 @@ bool masterWrite(i2c_port_t port, uint16_t address, uint8_t reg, const uint8_t* return result == ESP_OK; } +bool masterWriteRegisterArray(i2c_port_t port, uint8_t address, const uint8_t* data, uint16_t dataSize, TickType_t timeout) { + assert(dataSize % 2 == 0); + bool result = true; + for (int i = 0; i < dataSize; i += 2) { + // TODO: We're passing an inaccurate timeout value as we already lost time with locking and previous writes in this loop + if (!masterWriteRegister(port, address, data[i], &data[i + 1], 1, timeout)) { + result = false; + } + } + return result; +} + bool masterWriteRead(i2c_port_t port, uint8_t address, const uint8_t* writeData, size_t writeDataSize, uint8_t* readData, size_t readDataSize, TickType_t timeout) { if (lock(port)) { + // TODO: We're passing an inaccurate timeout value as we already lost time with locking esp_err_t result = i2c_master_write_read_device(port, address, writeData, writeDataSize, readData, readDataSize, timeout); unlock(port); return result == ESP_OK; @@ -267,6 +294,7 @@ bool masterWriteRead(i2c_port_t port, uint8_t address, const uint8_t* writeData, bool masterHasDeviceAtAddress(i2c_port_t port, uint8_t address, TickType_t timeout) { if (lock(port)) { uint8_t message[2] = { 0, 0 }; + // TODO: We're passing an inaccurate timeout value as we already lost time with locking esp_err_t result = i2c_master_write_to_device(port, address, message, 2, timeout); unlock(port); return result == ESP_OK; diff --git a/TactilityHeadless/Source/hal/i2c/I2c.h b/TactilityHeadless/Source/hal/i2c/I2c.h index 648271c3..097a7c65 100644 --- a/TactilityHeadless/Source/hal/i2c/I2c.h +++ b/TactilityHeadless/Source/hal/i2c/I2c.h @@ -9,11 +9,11 @@ namespace tt::hal::i2c { -typedef enum { - InitByTactility, // Tactility will initialize it in the correct bootup phase - InitByExternal, // The device is already initialized and Tactility should assume it works - InitDisabled // Not initialized by default -} InitMode; +enum class InitMode { + ByTactility, // Tactility will initialize it in the correct bootup phase + ByExternal, // The device is already initialized and Tactility should assume it works + Disabled // Not initialized by default +}; struct Configuration { std::string name; @@ -35,7 +35,6 @@ enum Status { UNKNOWN }; - bool init(const std::vector& configurations); bool start(i2c_port_t port); @@ -43,9 +42,10 @@ bool stop(i2c_port_t port); bool isStarted(i2c_port_t port); bool masterRead(i2c_port_t port, uint8_t address, uint8_t* data, size_t dataSize, TickType_t timeout); -bool masterRead(i2c_port_t port, uint8_t address, uint8_t reg, uint8_t* data, size_t dataSize, TickType_t timeout); -bool masterWrite(i2c_port_t port, uint16_t address, const uint8_t* data, uint16_t dataSize, TickType_t timeout); -bool masterWrite(i2c_port_t port, uint16_t address, uint8_t reg, const uint8_t* data, uint16_t dataSize, TickType_t timeout); +bool masterReadRegister(i2c_port_t port, uint8_t address, uint8_t reg, uint8_t* data, size_t dataSize, TickType_t timeout); +bool masterWrite(i2c_port_t port, uint8_t address, const uint8_t* data, uint16_t dataSize, TickType_t timeout); +bool masterWriteRegister(i2c_port_t port, uint8_t address, uint8_t reg, const uint8_t* data, uint16_t dataSize, TickType_t timeout); +bool masterWriteRegisterArray(i2c_port_t port, uint8_t address, const uint8_t* data, uint16_t dataSize, TickType_t timeout); bool masterWriteRead(i2c_port_t port, uint8_t address, const uint8_t* writeData, size_t writeDataSize, uint8_t* readData, size_t readDataSize, TickType_t timeout); bool masterHasDeviceAtAddress(i2c_port_t port, uint8_t address, TickType_t timeout); diff --git a/TactilityHeadless/Source/hal/i2c/I2cMock.cpp b/TactilityHeadless/Source/hal/i2c/I2cMock.cpp index 1d6a3378..76ab7b01 100644 --- a/TactilityHeadless/Source/hal/i2c/I2cMock.cpp +++ b/TactilityHeadless/Source/hal/i2c/I2cMock.cpp @@ -28,9 +28,9 @@ bool init(const std::vector& configurations) { } for (const auto& config: configurations) { - if (config.initMode == InitByTactility && !start(config.port)) { + if (config.initMode == InitMode::ByTactility && !start(config.port)) { return false; - } else if (config.initMode == InitByExternal) { + } else if (config.initMode == InitMode::ByExternal) { dataArray[config.port].isStarted = true; } } diff --git a/TactilityHeadless/Source/hal/usb/Usb.cpp b/TactilityHeadless/Source/hal/usb/Usb.cpp index a48ae9bc..0c896d74 100644 --- a/TactilityHeadless/Source/hal/usb/Usb.cpp +++ b/TactilityHeadless/Source/hal/usb/Usb.cpp @@ -16,7 +16,7 @@ struct BootMode { uint32_t flag = 0; }; -static Mode currentMode = ModeDefault; +static Mode currentMode = Mode::Default; static RTC_NOINIT_ATTR BootMode bootMode; sdmmc_card_t* _Nullable getCard() { @@ -47,7 +47,7 @@ sdmmc_card_t* _Nullable getCard() { } static bool canStartNewMode() { - return isSupported() && (currentMode == ModeDefault || currentMode == ModeNone); + return isSupported() && (currentMode == Mode::Default || currentMode == Mode::None); } bool isSupported() { @@ -65,7 +65,7 @@ bool startMassStorageWithSdmmc() { TT_LOG_E(TAG, "Failed to init mass storage: %s", esp_err_to_name(result)); return false; } else { - currentMode = ModeMassStorageSdmmc; + currentMode = Mode::MassStorageSdmmc; return true; } } @@ -77,7 +77,7 @@ void stop() { tusbStop(); - currentMode = ModeNone; + currentMode = Mode::None; } Mode getMode() { diff --git a/TactilityHeadless/Source/hal/usb/Usb.h b/TactilityHeadless/Source/hal/usb/Usb.h index aab33d5c..e98f19e3 100644 --- a/TactilityHeadless/Source/hal/usb/Usb.h +++ b/TactilityHeadless/Source/hal/usb/Usb.h @@ -2,10 +2,10 @@ namespace tt::hal::usb { -enum Mode { - ModeDefault, // Default state of USB stack - ModeNone, // State after TinyUSB was used and (partially) deinitialized - ModeMassStorageSdmmc +enum class Mode { + Default, // Default state of USB stack + None, // State after TinyUSB was used and (partially) deinitialized + MassStorageSdmmc }; bool startMassStorageWithSdmmc(); diff --git a/TactilityHeadless/Source/hal/usb/UsbMock.cpp b/TactilityHeadless/Source/hal/usb/UsbMock.cpp index 431520db..94f881b8 100644 --- a/TactilityHeadless/Source/hal/usb/UsbMock.cpp +++ b/TactilityHeadless/Source/hal/usb/UsbMock.cpp @@ -8,7 +8,7 @@ namespace tt::hal::usb { bool startMassStorageWithSdmmc() { return false; } void stop() {} -Mode getMode() { return ModeDefault; } +Mode getMode() { return Mode::Default; } bool isSupported() { return false; } bool canRebootIntoMassStorageSdmmc() { return false; } diff --git a/TactilityHeadless/Source/service/ServiceRegistry.cpp b/TactilityHeadless/Source/service/ServiceRegistry.cpp index c3dd71dd..86793b76 100644 --- a/TactilityHeadless/Source/service/ServiceRegistry.cpp +++ b/TactilityHeadless/Source/service/ServiceRegistry.cpp @@ -17,8 +17,8 @@ typedef std::unordered_map ServiceInstanceMap; static ManifestMap service_manifest_map; static ServiceInstanceMap service_instance_map; -static Mutex manifest_mutex(Mutex::TypeNormal); -static Mutex instance_mutex(Mutex::TypeNormal); +static Mutex manifest_mutex(Mutex::Type::Normal); +static Mutex instance_mutex(Mutex::Type::Normal); void addService(const ServiceManifest* manifest) { TT_LOG_I(TAG, "Adding %s", manifest->id.c_str()); diff --git a/TactilityHeadless/Source/service/sdcard/Sdcard.cpp b/TactilityHeadless/Source/service/sdcard/Sdcard.cpp index 46dcf03a..8e16235d 100644 --- a/TactilityHeadless/Source/service/sdcard/Sdcard.cpp +++ b/TactilityHeadless/Source/service/sdcard/Sdcard.cpp @@ -17,7 +17,7 @@ extern const ServiceManifest manifest; struct ServiceData { Mutex mutex; std::unique_ptr updateTimer; - hal::SdCard::State lastState = hal::SdCard::StateUnmounted; + hal::SdCard::State lastState = hal::SdCard::State::Unmounted; bool lock(TickType_t timeout) const { return mutex.acquire(timeout) == TtStatusOk; @@ -44,7 +44,7 @@ static void onUpdate(std::shared_ptr context) { auto new_state = sdcard->getState(); - if (new_state == hal::SdCard::StateError) { + if (new_state == hal::SdCard::State::Error) { TT_LOG_W(TAG, "Sdcard error - unmounting. Did you eject the card in an unsafe manner?"); sdcard->unmount(); } @@ -61,7 +61,7 @@ static void onStart(ServiceContext& service) { auto data = std::make_shared(); service.setData(data); - data->updateTimer = std::make_unique(Timer::TypePeriodic, onUpdate, data); + data->updateTimer = std::make_unique(Timer::Type::Periodic, onUpdate, data); // We want to try and scan more often in case of startup or scan lock failure data->updateTimer->start(1000); } else { diff --git a/TactilityHeadless/Source/service/wifi/Wifi.cpp b/TactilityHeadless/Source/service/wifi/Wifi.cpp new file mode 100644 index 00000000..20715312 --- /dev/null +++ b/TactilityHeadless/Source/service/wifi/Wifi.cpp @@ -0,0 +1,23 @@ +#include "./Wifi.h" + +namespace tt::service::wifi { + +const char* radioStateToString(RadioState state) { + switch (state) { + case RadioState::OnPending: + return TT_STRINGIFY(RadioState::OnPending); + case RadioState::On: + return TT_STRINGIFY(RadioState::On); + case RadioState::ConnectionPending: + return TT_STRINGIFY(RadioState::ConnectionPending); + case RadioState::ConnectionActive: + return TT_STRINGIFY(RadioState::ConnectionActive); + case RadioState::OffPending: + return TT_STRINGIFY(RadioState::OnPending); + case RadioState::Off: + return TT_STRINGIFY(RadioState::Off); + } + tt_crash("not implemented"); +} + +} diff --git a/TactilityHeadless/Source/service/wifi/Wifi.h b/TactilityHeadless/Source/service/wifi/Wifi.h index c49765f0..2ffa65b4 100644 --- a/TactilityHeadless/Source/service/wifi/Wifi.h +++ b/TactilityHeadless/Source/service/wifi/Wifi.h @@ -34,39 +34,39 @@ typedef enum { namespace tt::service::wifi { -enum WifiEventType { +enum class EventType { /** Radio was turned on */ - WifiEventTypeRadioStateOn, + RadioStateOn, /** Radio is turning on. */ - WifiEventTypeRadioStateOnPending, + RadioStateOnPending, /** Radio is turned off */ - WifiEventTypeRadioStateOff, + RadioStateOff, /** Radio is turning off */ - WifiEventTypeRadioStateOffPending, + RadioStateOffPending, /** Started scanning for access points */ - WifiEventTypeScanStarted, + ScanStarted, /** Finished scanning for access points */ // TODO: 1 second validity - WifiEventTypeScanFinished, - WifiEventTypeDisconnected, - WifiEventTypeConnectionPending, - WifiEventTypeConnectionSuccess, - WifiEventTypeConnectionFailed + ScanFinished, + Disconnected, + ConnectionPending, + ConnectionSuccess, + ConnectionFailed }; -enum WifiRadioState { - WIFI_RADIO_ON_PENDING, - WIFI_RADIO_ON, - WIFI_RADIO_CONNECTION_PENDING, - WIFI_RADIO_CONNECTION_ACTIVE, - WIFI_RADIO_OFF_PENDING, - WIFI_RADIO_OFF, +enum class RadioState { + OnPending, + On, + ConnectionPending, + ConnectionActive, + OffPending, + Off, }; -struct WifiEvent { - WifiEventType type; +struct Event { + EventType type; }; -struct WifiApRecord { +struct ApRecord { std::string ssid; int8_t rssi; wifi_auth_mode_t auth_mode; @@ -78,7 +78,12 @@ struct WifiApRecord { */ std::shared_ptr getPubsub(); -WifiRadioState getRadioState(); +/** @return Get the current radio state */ +RadioState getRadioState(); + +/** For logging purposes */ +const char* radioStateToString(RadioState state); + /** * @brief Request scanning update. Returns immediately. Results are through pubsub. */ @@ -91,7 +96,7 @@ bool isScanning(); std::string getConnectionTarget(); /** @return the access points from the last scan (if any). It only contains public APs. */ -std::vector getScanResults(); +std::vector getScanResults(); /** * @brief Overrides the default scan result size of 16. diff --git a/TactilityHeadless/Source/service/wifi/WifiEsp.cpp b/TactilityHeadless/Source/service/wifi/WifiEsp.cpp index 2efd7782..75089b4b 100644 --- a/TactilityHeadless/Source/service/wifi/WifiEsp.cpp +++ b/TactilityHeadless/Source/service/wifi/WifiEsp.cpp @@ -35,15 +35,15 @@ class Wifi { private: - std::atomic radio_state = WIFI_RADIO_OFF; + std::atomic radio_state = RadioState::Off; bool scan_active = false; bool secure_connection = false; public: /** @brief Locking mechanism for modifying the Wifi instance */ - Mutex radioMutex = Mutex(Mutex::TypeRecursive); - Mutex dataMutex = Mutex(Mutex::TypeRecursive); + Mutex radioMutex = Mutex(Mutex::Type::Recursive); + Mutex dataMutex = Mutex(Mutex::Type::Recursive); std::unique_ptr autoConnectTimer; /** @brief The public event bus */ std::shared_ptr pubsub = std::make_shared(); @@ -71,14 +71,14 @@ public: bool pause_auto_connect = false; // Pause when manually disconnecting until manually connecting again bool connection_target_remember = false; // Whether to store the connection_target on successful connection or not - WifiRadioState getRadioState() const { + RadioState getRadioState() const { auto lockable = dataMutex.scoped(); lockable->lock(TtWaitForever); // TODO: Handle lock failure return radio_state; } - void setRadioState(WifiRadioState newState) { + void setRadioState(RadioState newState) { auto lockable = dataMutex.scoped(); lockable->lock(TtWaitForever); // TODO: Handle lock failure @@ -89,7 +89,7 @@ public: auto lockable = dataMutex.scoped(); lockable->lock(TtWaitForever); // TODO: Handle lock failure - return radio_state; + return scan_active; } void setScanning(bool newState) { @@ -138,12 +138,12 @@ std::shared_ptr getPubsub() { return wifi->pubsub; } -WifiRadioState getRadioState() { +RadioState getRadioState() { auto wifi = wifi_singleton; if (wifi != nullptr) { return wifi->getRadioState(); } else { - return WIFI_RADIO_OFF; + return RadioState::Off; } } @@ -153,10 +153,10 @@ std::string getConnectionTarget() { return ""; } - WifiRadioState state = wifi->getRadioState(); + RadioState state = wifi->getRadioState(); if ( - state != WIFI_RADIO_CONNECTION_PENDING && - state != WIFI_RADIO_CONNECTION_ACTIVE + state != RadioState::ConnectionPending && + state != RadioState::ConnectionActive ) { return ""; } @@ -199,6 +199,11 @@ void connect(const settings::WifiApSettings* ap, bool remember) { wifi->pause_auto_connect = true; memcpy(&wifi->connection_target, ap, sizeof(settings::WifiApSettings)); wifi->connection_target_remember = remember; + + if (wifi->getRadioState() == RadioState::Off) { + getMainDispatcher().dispatch(dispatchEnable, wifi); + } + getMainDispatcher().dispatch(dispatchConnect, wifi); } @@ -242,11 +247,11 @@ void setScanRecords(uint16_t records) { } } -std::vector getScanResults() { +std::vector getScanResults() { TT_LOG_I(TAG, "getScanResults()"); auto wifi = wifi_singleton; - std::vector records; + std::vector records; if (wifi == nullptr) { return records; @@ -260,7 +265,7 @@ std::vector getScanResults() { if (wifi->scan_list_count > 0) { uint16_t i = 0; for (; i < wifi->scan_list_count; ++i) { - records.push_back((WifiApRecord) { + records.push_back((ApRecord) { .ssid = (const char*)wifi->scan_list[i].ssid, .rssi = wifi->scan_list[i].rssi, .auth_mode = wifi->scan_list[i].authmode @@ -355,18 +360,18 @@ static void scan_list_free_safely(std::shared_ptr wifi) { } } -static void publish_event_simple(std::shared_ptr wifi, WifiEventType type) { +static void publish_event_simple(std::shared_ptr wifi, EventType type) { auto lockable = wifi->dataMutex.scoped(); if (lockable->lock(TtWaitForever)) { - WifiEvent turning_on_event = {.type = type}; + Event turning_on_event = {.type = type}; tt_pubsub_publish(wifi->pubsub, &turning_on_event); } } static bool copy_scan_list(std::shared_ptr wifi) { auto state = wifi->getRadioState(); - bool can_fetch_results = (state == WIFI_RADIO_ON || state == WIFI_RADIO_CONNECTION_ACTIVE) && - wifi->isScanActive(); + bool can_fetch_results = (state == RadioState::On || state == RadioState::ConnectionActive) && + wifi->isScanActive(); if (!can_fetch_results) { TT_LOG_I(TAG, "Skip scan result fetching"); @@ -443,20 +448,20 @@ static void eventHandler(TT_UNUSED void* arg, esp_event_base_t event_base, int32 if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_START) { TT_LOG_I(TAG, "eventHandler: sta start"); - if (wifi->getRadioState() == WIFI_RADIO_CONNECTION_PENDING) { + if (wifi->getRadioState() == RadioState::ConnectionPending) { esp_wifi_connect(); } } else if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_DISCONNECTED) { TT_LOG_I(TAG, "eventHandler: disconnected"); - if (wifi->getRadioState() == WIFI_RADIO_CONNECTION_PENDING) { + if (wifi->getRadioState() == RadioState::ConnectionPending) { wifi->connection_wait_flags.set(WIFI_FAIL_BIT); } - wifi->setRadioState(WIFI_RADIO_ON); - publish_event_simple(wifi, WifiEventTypeDisconnected); + wifi->setRadioState(RadioState::On); + publish_event_simple(wifi, EventType::Disconnected); } else if (event_base == IP_EVENT && event_id == IP_EVENT_STA_GOT_IP) { auto* event = static_cast(event_data); TT_LOG_I(TAG, "eventHandler: got ip:" IPSTR, IP2STR(&event->ip_info.ip)); - if (wifi->getRadioState() == WIFI_RADIO_CONNECTION_PENDING) { + if (wifi->getRadioState() == RadioState::ConnectionPending) { wifi->connection_wait_flags.set(WIFI_CONNECTED_BIT); // We resume auto-connecting only when there was an explicit request by the user for the connection // TODO: Make thread-safe @@ -469,17 +474,17 @@ static void eventHandler(TT_UNUSED void* arg, esp_event_base_t event_base, int32 auto state = wifi->getRadioState(); if ( - state != WIFI_RADIO_OFF && - state != WIFI_RADIO_OFF_PENDING + state != RadioState::Off && + state != RadioState::OffPending ) { wifi->setScanActive(false); esp_wifi_scan_stop(); } - publish_event_simple(wifi_singleton, WifiEventTypeScanFinished); + publish_event_simple(wifi_singleton, EventType::ScanFinished); TT_LOG_I(TAG, "eventHandler: Finished scan"); - if (copied_list && wifi_singleton->getRadioState() == WIFI_RADIO_ON && !wifi->pause_auto_connect) { + if (copied_list && wifi_singleton->getRadioState() == RadioState::On && !wifi->pause_auto_connect) { getMainDispatcher().dispatch(dispatchAutoConnect, wifi); } } @@ -489,12 +494,12 @@ static void dispatchEnable(std::shared_ptr context) { TT_LOG_I(TAG, "dispatchEnable()"); auto wifi = std::static_pointer_cast(context); - WifiRadioState state = wifi->getRadioState(); + RadioState state = wifi->getRadioState(); if ( - state == WIFI_RADIO_ON || - state == WIFI_RADIO_ON_PENDING || - state == WIFI_RADIO_OFF_PENDING - ) { + state == RadioState::On || + state == RadioState::OnPending || + state == RadioState::OffPending + ) { TT_LOG_W(TAG, "Can't enable from current state"); return; } @@ -503,8 +508,8 @@ static void dispatchEnable(std::shared_ptr context) { if (lockable->lock(50 / portTICK_PERIOD_MS)) { TT_LOG_I(TAG, "Enabling"); - wifi->setRadioState(WIFI_RADIO_ON_PENDING); - publish_event_simple(wifi, WifiEventTypeRadioStateOnPending); + wifi->setRadioState(RadioState::OnPending); + publish_event_simple(wifi, EventType::RadioStateOnPending); if (wifi->netif != nullptr) { esp_netif_destroy(wifi->netif); @@ -520,8 +525,8 @@ static void dispatchEnable(std::shared_ptr context) { if (init_result == ESP_ERR_NO_MEM) { TT_LOG_E(TAG, "Insufficient memory"); } - wifi->setRadioState(WIFI_RADIO_OFF); - publish_event_simple(wifi, WifiEventTypeRadioStateOff); + wifi->setRadioState(RadioState::Off); + publish_event_simple(wifi, EventType::RadioStateOff); return; } @@ -547,9 +552,9 @@ static void dispatchEnable(std::shared_ptr context) { if (esp_wifi_set_mode(WIFI_MODE_STA) != ESP_OK) { TT_LOG_E(TAG, "Wifi mode setting failed"); - wifi->setRadioState(WIFI_RADIO_OFF); + wifi->setRadioState(RadioState::Off); esp_wifi_deinit(); - publish_event_simple(wifi, WifiEventTypeRadioStateOff); + publish_event_simple(wifi, EventType::RadioStateOff); return; } @@ -559,15 +564,15 @@ static void dispatchEnable(std::shared_ptr context) { if (start_result == ESP_ERR_NO_MEM) { TT_LOG_E(TAG, "Insufficient memory"); } - wifi->setRadioState(WIFI_RADIO_OFF); + wifi->setRadioState(RadioState::Off); esp_wifi_set_mode(WIFI_MODE_NULL); esp_wifi_deinit(); - publish_event_simple(wifi, WifiEventTypeRadioStateOff); + publish_event_simple(wifi, EventType::RadioStateOff); return; } - wifi->setRadioState(WIFI_RADIO_ON); - publish_event_simple(wifi, WifiEventTypeRadioStateOn); + wifi->setRadioState(RadioState::On); + publish_event_simple(wifi, EventType::RadioStateOn); TT_LOG_I(TAG, "Enabled"); } else { TT_LOG_E(TAG, LOG_MESSAGE_MUTEX_LOCK_FAILED); @@ -584,27 +589,27 @@ static void dispatchDisable(std::shared_ptr context) { return; } - WifiRadioState state = wifi->getRadioState(); + RadioState state = wifi->getRadioState(); if ( - state == WIFI_RADIO_OFF || - state == WIFI_RADIO_OFF_PENDING || - state == WIFI_RADIO_ON_PENDING - ) { + state == RadioState::Off || + state == RadioState::OffPending || + state == RadioState::OnPending + ) { TT_LOG_W(TAG, "Can't disable from current state"); return; } TT_LOG_I(TAG, "Disabling"); - wifi->setRadioState(WIFI_RADIO_OFF_PENDING); - publish_event_simple(wifi, WifiEventTypeRadioStateOffPending); + wifi->setRadioState(RadioState::OffPending); + publish_event_simple(wifi, EventType::RadioStateOffPending); // Free up scan list memory scan_list_free_safely(wifi_singleton); if (esp_wifi_stop() != ESP_OK) { TT_LOG_E(TAG, "Failed to stop radio"); - wifi->setRadioState(WIFI_RADIO_ON); - publish_event_simple(wifi, WifiEventTypeRadioStateOn); + wifi->setRadioState(RadioState::On); + publish_event_simple(wifi, EventType::RadioStateOn); return; } @@ -636,8 +641,8 @@ static void dispatchDisable(std::shared_ptr context) { esp_netif_destroy(wifi->netif); wifi->netif = nullptr; wifi->setScanActive(false); - wifi->setRadioState(WIFI_RADIO_OFF); - publish_event_simple(wifi, WifiEventTypeRadioStateOff); + wifi->setRadioState(RadioState::Off); + publish_event_simple(wifi, EventType::RadioStateOff); TT_LOG_I(TAG, "Disabled"); } @@ -651,8 +656,8 @@ static void dispatchScan(std::shared_ptr context) { return; } - WifiRadioState state = wifi->getRadioState(); - if (state != WIFI_RADIO_ON && state != WIFI_RADIO_CONNECTION_ACTIVE && state != WIFI_RADIO_CONNECTION_PENDING) { + RadioState state = wifi->getRadioState(); + if (state != RadioState::On && state != RadioState::ConnectionActive && state != RadioState::ConnectionPending) { TT_LOG_W(TAG, "Scan unavailable: wifi not enabled"); return; } @@ -672,7 +677,7 @@ static void dispatchScan(std::shared_ptr context) { TT_LOG_I(TAG, "Starting scan"); wifi->setScanActive(true); - publish_event_simple(wifi, WifiEventTypeScanStarted); + publish_event_simple(wifi, EventType::ScanStarted); } static void dispatchConnect(std::shared_ptr context) { @@ -688,12 +693,12 @@ static void dispatchConnect(std::shared_ptr context) { TT_LOG_I(TAG, "Connecting to %s", wifi->connection_target.ssid); // Stop radio first, if needed - WifiRadioState radio_state = wifi->getRadioState(); + RadioState radio_state = wifi->getRadioState(); if ( - radio_state == WIFI_RADIO_ON || - radio_state == WIFI_RADIO_CONNECTION_ACTIVE || - radio_state == WIFI_RADIO_CONNECTION_PENDING - ) { + radio_state == RadioState::On || + radio_state == RadioState::ConnectionActive || + radio_state == RadioState::ConnectionPending + ) { TT_LOG_I(TAG, "Connecting: Stopping radio first"); esp_err_t stop_result = esp_wifi_stop(); wifi->setScanActive(false); @@ -703,9 +708,9 @@ static void dispatchConnect(std::shared_ptr context) { } } - wifi->setRadioState(WIFI_RADIO_CONNECTION_PENDING); + wifi->setRadioState(RadioState::ConnectionPending); - publish_event_simple(wifi, WifiEventTypeConnectionPending); + publish_event_simple(wifi, EventType::ConnectionPending); wifi_config_t wifi_config = { .sta = { @@ -759,17 +764,17 @@ static void dispatchConnect(std::shared_ptr context) { esp_err_t set_config_result = esp_wifi_set_config(WIFI_IF_STA, &wifi_config); if (set_config_result != ESP_OK) { - wifi->setRadioState(WIFI_RADIO_ON); + wifi->setRadioState(RadioState::On); TT_LOG_E(TAG, "Failed to set wifi config (%s)", esp_err_to_name(set_config_result)); - publish_event_simple(wifi, WifiEventTypeConnectionFailed); + publish_event_simple(wifi, EventType::ConnectionFailed); return; } esp_err_t wifi_start_result = esp_wifi_start(); if (wifi_start_result != ESP_OK) { - wifi->setRadioState(WIFI_RADIO_ON); + wifi->setRadioState(RadioState::On); TT_LOG_E(TAG, "Failed to start wifi to begin connecting (%s)", esp_err_to_name(wifi_start_result)); - publish_event_simple(wifi, WifiEventTypeConnectionFailed); + publish_event_simple(wifi, EventType::ConnectionFailed); return; } @@ -781,8 +786,8 @@ static void dispatchConnect(std::shared_ptr context) { if (bits & WIFI_CONNECTED_BIT) { wifi->setSecureConnection(wifi_config.sta.password[0] != 0x00U); - wifi->setRadioState(WIFI_RADIO_CONNECTION_ACTIVE); - publish_event_simple(wifi, WifiEventTypeConnectionSuccess); + wifi->setRadioState(RadioState::ConnectionActive); + publish_event_simple(wifi, EventType::ConnectionSuccess); TT_LOG_I(TAG, "Connected to %s", wifi->connection_target.ssid); if (wifi->connection_target_remember) { if (!settings::save(&wifi->connection_target)) { @@ -792,12 +797,12 @@ static void dispatchConnect(std::shared_ptr context) { } } } else if (bits & WIFI_FAIL_BIT) { - wifi->setRadioState(WIFI_RADIO_ON); - publish_event_simple(wifi, WifiEventTypeConnectionFailed); + wifi->setRadioState(RadioState::On); + publish_event_simple(wifi, EventType::ConnectionFailed); TT_LOG_I(TAG, "Failed to connect to %s", wifi->connection_target.ssid); } else { - wifi->setRadioState(WIFI_RADIO_ON); - publish_event_simple(wifi, WifiEventTypeConnectionFailed); + wifi->setRadioState(RadioState::On); + publish_event_simple(wifi, EventType::ConnectionFailed); TT_LOG_E(TAG, "UNEXPECTED EVENT"); } @@ -864,23 +869,23 @@ static void dispatchDisconnectButKeepActive(std::shared_ptr context) { esp_err_t set_config_result = esp_wifi_set_config(WIFI_IF_STA, &wifi_config); if (set_config_result != ESP_OK) { // TODO: disable radio, because radio state is in limbo between off and on - wifi->setRadioState(WIFI_RADIO_OFF); + wifi->setRadioState(RadioState::Off); TT_LOG_E(TAG, "failed to set wifi config (%s)", esp_err_to_name(set_config_result)); - publish_event_simple(wifi, WifiEventTypeRadioStateOff); + publish_event_simple(wifi, EventType::RadioStateOff); return; } esp_err_t wifi_start_result = esp_wifi_start(); if (wifi_start_result != ESP_OK) { // TODO: disable radio, because radio state is in limbo between off and on - wifi->setRadioState(WIFI_RADIO_OFF); + wifi->setRadioState(RadioState::Off); TT_LOG_E(TAG, "failed to start wifi to begin connecting (%s)", esp_err_to_name(wifi_start_result)); - publish_event_simple(wifi, WifiEventTypeRadioStateOff); + publish_event_simple(wifi, EventType::RadioStateOff); return; } - wifi->setRadioState(WIFI_RADIO_ON); - publish_event_simple(wifi, WifiEventTypeDisconnected); + wifi->setRadioState(RadioState::On); + publish_event_simple(wifi, EventType::Disconnected); TT_LOG_I(TAG, "Disconnected"); } @@ -891,7 +896,7 @@ static bool shouldScanForAutoConnect(std::shared_ptr wifi) { return false; } - bool is_radio_in_scannable_state = wifi->getRadioState() == WIFI_RADIO_ON && + bool is_radio_in_scannable_state = wifi->getRadioState() == RadioState::On && !wifi->isScanActive() && !wifi->pause_auto_connect; @@ -921,7 +926,7 @@ static void onStart(ServiceContext& service) { service.setData(wifi_singleton); - wifi_singleton->autoConnectTimer = std::make_unique(Timer::TypePeriodic, onAutoConnectTimer, wifi_singleton); + wifi_singleton->autoConnectTimer = std::make_unique(Timer::Type::Periodic, onAutoConnectTimer, wifi_singleton); // We want to try and scan more often in case of startup or scan lock failure wifi_singleton->autoConnectTimer->start(TT_MIN(2000, AUTO_SCAN_INTERVAL)); @@ -935,8 +940,8 @@ static void onStop(ServiceContext& service) { auto wifi = wifi_singleton; tt_assert(wifi != nullptr); - WifiRadioState state = wifi->getRadioState(); - if (state != WIFI_RADIO_OFF) { + RadioState state = wifi->getRadioState(); + if (state != RadioState::Off) { dispatchDisable(wifi); } diff --git a/TactilityHeadless/Source/service/wifi/WifiMock.cpp b/TactilityHeadless/Source/service/wifi/WifiMock.cpp index b2fc87cd..e19c46e9 100644 --- a/TactilityHeadless/Source/service/wifi/WifiMock.cpp +++ b/TactilityHeadless/Source/service/wifi/WifiMock.cpp @@ -20,13 +20,13 @@ struct Wifi { ~Wifi() = default; /** @brief Locking mechanism for modifying the Wifi instance */ - Mutex mutex = Mutex(Mutex::TypeRecursive); + Mutex mutex = Mutex(Mutex::Type::Recursive); /** @brief The public event bus */ std::shared_ptr pubsub = std::make_shared(); /** @brief The internal message queue */ bool scan_active = false; bool secure_connection = false; - WifiRadioState radio_state = WIFI_RADIO_CONNECTION_ACTIVE; + RadioState radio_state = RadioState::ConnectionActive; }; @@ -34,8 +34,8 @@ static Wifi* wifi = nullptr; // region Static -static void publish_event_simple(Wifi* wifi, WifiEventType type) { - WifiEvent turning_on_event = {.type = type}; +static void publish_event_simple(Wifi* wifi, EventType type) { + Event turning_on_event = { .type = type }; tt_pubsub_publish(wifi->pubsub, &turning_on_event); } @@ -48,7 +48,7 @@ std::shared_ptr getPubsub() { return wifi->pubsub; } -WifiRadioState getRadioState() { +RadioState getRadioState() { return wifi->radio_state; } @@ -80,31 +80,31 @@ void setScanRecords(uint16_t records) { // TODO: implement } -std::vector getScanResults() { +std::vector getScanResults() { tt_check(wifi); - std::vector records; - records.push_back((WifiApRecord) { + std::vector records; + records.push_back((ApRecord) { .ssid = "Home Wifi", .rssi = -30, .auth_mode = WIFI_AUTH_WPA2_PSK }); - records.push_back((WifiApRecord) { + records.push_back((ApRecord) { .ssid = "No place like 127.0.0.1", .rssi = -67, .auth_mode = WIFI_AUTH_WPA2_PSK }); - records.push_back((WifiApRecord) { + records.push_back((ApRecord) { .ssid = "Pretty fly for a Wi-Fi", .rssi = -70, .auth_mode = WIFI_AUTH_WPA2_PSK }); - records.push_back((WifiApRecord) { + records.push_back((ApRecord) { .ssid = "An AP with a really, really long name", .rssi = -80, .auth_mode = WIFI_AUTH_WPA2_PSK }); - records.push_back((WifiApRecord) { + records.push_back((ApRecord) { .ssid = "Bad Reception", .rssi = -90, .auth_mode = WIFI_AUTH_OPEN @@ -116,10 +116,10 @@ std::vector getScanResults() { void setEnabled(bool enabled) { tt_assert(wifi != nullptr); if (enabled) { - wifi->radio_state = WIFI_RADIO_ON; + wifi->radio_state = RadioState::On; wifi->secure_connection = true; } else { - wifi->radio_state = WIFI_RADIO_OFF; + wifi->radio_state = RadioState::Off; } } @@ -128,7 +128,7 @@ bool isConnectionSecure() { } int getRssi() { - if (wifi->radio_state == WIFI_RADIO_CONNECTION_ACTIVE) { + if (wifi->radio_state == RadioState::ConnectionActive) { return -30; } else { return 0; diff --git a/TactilityHeadless/Source/service/wifi/WifiSettings.h b/TactilityHeadless/Source/service/wifi/WifiSettings.h index 285226b6..468370fa 100644 --- a/TactilityHeadless/Source/service/wifi/WifiSettings.h +++ b/TactilityHeadless/Source/service/wifi/WifiSettings.h @@ -11,9 +11,9 @@ namespace tt::service::wifi::settings { * This makes it easier to use the char array as a string in various places. */ struct WifiApSettings { - char ssid[TT_WIFI_SSID_LIMIT + 1]; - char password[TT_WIFI_CREDENTIALS_PASSWORD_LIMIT + 1]; - bool auto_connect; + char ssid[TT_WIFI_SSID_LIMIT + 1] = { 0 }; + char password[TT_WIFI_CREDENTIALS_PASSWORD_LIMIT + 1] = { 0 }; + bool auto_connect = true; }; bool contains(const char* ssid); diff --git a/Tests/TactilityCore/MutexTest.cpp b/Tests/TactilityCore/MutexTest.cpp index 6a461485..908a5adf 100644 --- a/Tests/TactilityCore/MutexTest.cpp +++ b/Tests/TactilityCore/MutexTest.cpp @@ -11,7 +11,7 @@ static int32_t thread_with_mutex_parameter(void* parameter) { } TEST_CASE("a mutex can block a thread") { - auto mutex = Mutex(Mutex::TypeNormal); + auto mutex = Mutex(Mutex::Type::Normal); mutex.lock(portMAX_DELAY); Thread thread = Thread( diff --git a/Tests/TactilityCore/TimerTest.cpp b/Tests/TactilityCore/TimerTest.cpp index ef3d86f7..95df2af7 100644 --- a/Tests/TactilityCore/TimerTest.cpp +++ b/Tests/TactilityCore/TimerTest.cpp @@ -18,7 +18,7 @@ static void timer_callback_with_counter(std::shared_ptr context) { TEST_CASE("a timer passes the context correctly") { auto foo = std::make_shared(1); - auto* timer = new Timer(Timer::TypeOnce, &timer_callback_with_context, foo); + auto* timer = new Timer(Timer::Type::Once, &timer_callback_with_context, foo); timer->start(1); kernel::delayTicks(10); timer->stop(); @@ -27,9 +27,9 @@ TEST_CASE("a timer passes the context correctly") { CHECK_EQ(*std::static_pointer_cast(timer_callback_context), *foo); } -TEST_CASE("TimerTypePeriodic timers can be stopped and restarted") { +TEST_CASE("TimerType::Periodic timers can be stopped and restarted") { auto counter = std::make_shared(0); - auto* timer = new Timer(Timer::TypePeriodic, &timer_callback_with_counter, counter); + auto* timer = new Timer(Timer::Type::Periodic, &timer_callback_with_counter, counter); timer->start(1); kernel::delayTicks(10); timer->stop(); @@ -41,10 +41,10 @@ TEST_CASE("TimerTypePeriodic timers can be stopped and restarted") { CHECK_GE(*counter, 2); } -TEST_CASE("TimerTypePeriodic calls the callback periodically") { +TEST_CASE("TimerType::Periodic calls the callback periodically") { auto counter = std::make_shared(0); int ticks_to_run = 10; - auto* timer = new Timer(Timer::TypePeriodic, &timer_callback_with_counter, counter); + auto* timer = new Timer(Timer::Type::Periodic, &timer_callback_with_counter, counter); timer->start(1); kernel::delayTicks(ticks_to_run); timer->stop(); @@ -53,9 +53,9 @@ TEST_CASE("TimerTypePeriodic calls the callback periodically") { CHECK_EQ(*counter, ticks_to_run); } -TEST_CASE("restarting TimerTypeOnce timers calls the callback again") { +TEST_CASE("restarting TimerType::Once timers calls the callback again") { auto counter = std::make_shared(0); - auto* timer = new Timer(Timer::TypeOnce, &timer_callback_with_counter, counter); + auto* timer = new Timer(Timer::Type::Once, &timer_callback_with_counter, counter); timer->start(1); kernel::delayTicks(10); timer->stop();