mirror of
https://github.com/ByteWelder/Tactility.git
synced 2026-04-23 11:55:05 +00:00
Merge develop into main (#313)
- Add app path get() functions to `TactilityC` - Improved `Dispatcher` and `DispatcherThread` - Improved `PubSub` (type safety) - Created test for `DispatcherThread` and `PubSub` - Save properties files on app exit (various apps) by posting it to the main dispatcher (fixes UI hanging briefly on app exit) - Fixed bug with `SystemSettings` being read from the wrong file path. - `loadPropertiesFile()` now uses `file::readLines()` instead of doing that manually - Increased timer task stack size (required due to issues when reading a properties file for the very first time) - General cleanup - Created `EstimatedPower` driver that uses an ADC pin to measure voltage and estimate the battery charge that is left. - Cleanup of T-Deck board (updated to new style)
This commit is contained in:
parent
5cc5b50694
commit
0f8380e8fe
@ -3,5 +3,5 @@ file(GLOB_RECURSE SOURCE_FILES Source/*.c*)
|
|||||||
idf_component_register(
|
idf_component_register(
|
||||||
SRCS ${SOURCE_FILES}
|
SRCS ${SOURCE_FILES}
|
||||||
INCLUDE_DIRS "Source"
|
INCLUDE_DIRS "Source"
|
||||||
REQUIRES Tactility EspLcdCompat ST7789 GT911 PwmBacklight driver esp_adc
|
REQUIRES Tactility EspLcdCompat ST7789 GT911 PwmBacklight EstimatedPower driver
|
||||||
)
|
)
|
||||||
|
|||||||
@ -30,7 +30,7 @@ static bool powerOn() {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool tdeckInit() {
|
bool initBoot() {
|
||||||
ESP_LOGI(TAG, LOG_MESSAGE_POWER_ON_START);
|
ESP_LOGI(TAG, LOG_MESSAGE_POWER_ON_START);
|
||||||
if (!powerOn()) {
|
if (!powerOn()) {
|
||||||
TT_LOG_E(TAG, LOG_MESSAGE_POWER_ON_FAILED);
|
TT_LOG_E(TAG, LOG_MESSAGE_POWER_ON_FAILED);
|
||||||
|
|||||||
@ -1,24 +1,29 @@
|
|||||||
#include "Tactility/lvgl/LvglSync.h"
|
|
||||||
#include "hal/TdeckDisplay.h"
|
|
||||||
#include "hal/TdeckDisplayConstants.h"
|
|
||||||
#include "hal/TdeckKeyboard.h"
|
|
||||||
#include "hal/TdeckPower.h"
|
|
||||||
#include "hal/TdeckSdCard.h"
|
|
||||||
|
|
||||||
#include <Tactility/hal/Configuration.h>
|
#include <Tactility/hal/Configuration.h>
|
||||||
|
#include <Tactility/lvgl/LvglSync.h>
|
||||||
|
|
||||||
#define TDECK_SPI_TRANSFER_SIZE_LIMIT (TDECK_LCD_HORIZONTAL_RESOLUTION * TDECK_LCD_SPI_TRANSFER_HEIGHT * (LV_COLOR_DEPTH / 8))
|
#include "devices/Display.h"
|
||||||
|
#include "devices/Power.h"
|
||||||
|
#include "devices/Sdcard.h"
|
||||||
|
#include "devices/TdeckKeyboard.h"
|
||||||
|
|
||||||
bool tdeckInit();
|
#define TDECK_SPI_TRANSFER_SIZE_LIMIT (320 * 240 * (LV_COLOR_DEPTH / 8))
|
||||||
|
|
||||||
|
bool initBoot();
|
||||||
|
|
||||||
using namespace tt::hal;
|
using namespace tt::hal;
|
||||||
|
|
||||||
|
static std::vector<std::shared_ptr<Device>> createDevices() {
|
||||||
|
return {
|
||||||
|
createPower(),
|
||||||
|
createDisplay(),
|
||||||
|
std::make_shared<TdeckKeyboard>(),
|
||||||
|
createSdCard()
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
extern const Configuration lilygo_tdeck = {
|
extern const Configuration lilygo_tdeck = {
|
||||||
.initBoot = tdeckInit,
|
.initBoot = initBoot,
|
||||||
.createDisplay = createDisplay,
|
.createDevices = createDevices,
|
||||||
.createKeyboard = createKeyboard,
|
|
||||||
.sdcard = createTdeckSdCard(),
|
|
||||||
.power = tdeck_get_power,
|
|
||||||
.i2c = {
|
.i2c = {
|
||||||
i2c::Configuration {
|
i2c::Configuration {
|
||||||
.name = "Internal",
|
.name = "Internal",
|
||||||
|
|||||||
@ -1,13 +1,15 @@
|
|||||||
#include "TdeckDisplay.h"
|
#include "Display.h"
|
||||||
#include "TdeckDisplayConstants.h"
|
|
||||||
|
|
||||||
#include <Gt911Touch.h>
|
#include <Gt911Touch.h>
|
||||||
#include <PwmBacklight.h>
|
#include <PwmBacklight.h>
|
||||||
#include <St7789Display.h>
|
#include <St7789Display.h>
|
||||||
|
|
||||||
#include <driver/spi_master.h>
|
#define TDECK_LCD_SPI_HOST SPI2_HOST
|
||||||
|
#define TDECK_LCD_PIN_CS GPIO_NUM_12
|
||||||
#define TAG "tdeck_display"
|
#define TDECK_LCD_PIN_DC GPIO_NUM_11 // RS
|
||||||
|
#define TDECK_LCD_HORIZONTAL_RESOLUTION 320
|
||||||
|
#define TDECK_LCD_VERTICAL_RESOLUTION 240
|
||||||
|
#define TDECK_LCD_SPI_TRANSFER_HEIGHT (TDECK_LCD_VERTICAL_RESOLUTION / 10)
|
||||||
|
|
||||||
static std::shared_ptr<tt::hal::touch::TouchDevice> createTouch() {
|
static std::shared_ptr<tt::hal::touch::TouchDevice> createTouch() {
|
||||||
// Note for future changes: Reset pin is 48 and interrupt pin is 47
|
// Note for future changes: Reset pin is 48 and interrupt pin is 47
|
||||||
@ -1,5 +1,5 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "Tactility/hal/display/DisplayDevice.h"
|
#include <Tactility/hal/display/DisplayDevice.h>
|
||||||
|
|
||||||
std::shared_ptr<tt::hal::display::DisplayDevice> createDisplay();
|
std::shared_ptr<tt::hal::display::DisplayDevice> createDisplay();
|
||||||
10
Boards/LilygoTdeck/Source/devices/Power.cpp
Normal file
10
Boards/LilygoTdeck/Source/devices/Power.cpp
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
#include <ChargeFromAdcVoltage.h>
|
||||||
|
#include <EstimatedPower.h>
|
||||||
|
|
||||||
|
std::shared_ptr<PowerDevice> createPower() {
|
||||||
|
ChargeFromAdcVoltage::Configuration configuration;
|
||||||
|
// 2.0 ratio, but +.11 added as display voltage sag compensation.
|
||||||
|
configuration.adcMultiplier = 2.11;
|
||||||
|
|
||||||
|
return std::make_shared<EstimatedPower>(configuration);
|
||||||
|
}
|
||||||
5
Boards/LilygoTdeck/Source/devices/Power.h
Normal file
5
Boards/LilygoTdeck/Source/devices/Power.h
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <Tactility/hal/power/PowerDevice.h>
|
||||||
|
|
||||||
|
std::shared_ptr<tt::hal::power::PowerDevice> createPower();
|
||||||
@ -1,17 +1,15 @@
|
|||||||
#include "TdeckSdCard.h"
|
#include "Sdcard.h"
|
||||||
|
|
||||||
#include <Tactility/lvgl/LvglSync.h>
|
#include <Tactility/lvgl/LvglSync.h>
|
||||||
#include <Tactility/hal/sdcard/SpiSdCardDevice.h>
|
#include <Tactility/hal/sdcard/SpiSdCardDevice.h>
|
||||||
|
|
||||||
#include <esp_vfs_fat.h>
|
|
||||||
|
|
||||||
using tt::hal::sdcard::SpiSdCardDevice;
|
using tt::hal::sdcard::SpiSdCardDevice;
|
||||||
|
|
||||||
constexpr auto TDECK_SDCARD_PIN_CS = GPIO_NUM_39;
|
constexpr auto TDECK_SDCARD_PIN_CS = GPIO_NUM_39;
|
||||||
constexpr auto TDECK_LCD_PIN_CS = GPIO_NUM_12;
|
constexpr auto TDECK_LCD_PIN_CS = GPIO_NUM_12;
|
||||||
constexpr auto TDECK_RADIO_PIN_CS = GPIO_NUM_9;
|
constexpr auto TDECK_RADIO_PIN_CS = GPIO_NUM_9;
|
||||||
|
|
||||||
std::shared_ptr<SdCardDevice> createTdeckSdCard() {
|
std::shared_ptr<SdCardDevice> createSdCard() {
|
||||||
auto configuration = std::make_unique<SpiSdCardDevice::Config>(
|
auto configuration = std::make_unique<SpiSdCardDevice::Config>(
|
||||||
TDECK_SDCARD_PIN_CS,
|
TDECK_SDCARD_PIN_CS,
|
||||||
GPIO_NUM_NC,
|
GPIO_NUM_NC,
|
||||||
@ -4,4 +4,4 @@
|
|||||||
|
|
||||||
using tt::hal::sdcard::SdCardDevice;
|
using tt::hal::sdcard::SdCardDevice;
|
||||||
|
|
||||||
std::shared_ptr<SdCardDevice> createTdeckSdCard();
|
std::shared_ptr<SdCardDevice> createSdCard();
|
||||||
@ -2,10 +2,9 @@
|
|||||||
#include <Tactility/hal/i2c/I2c.h>
|
#include <Tactility/hal/i2c/I2c.h>
|
||||||
#include <driver/i2c.h>
|
#include <driver/i2c.h>
|
||||||
|
|
||||||
#define TAG "tdeck_keyboard"
|
constexpr auto* TAG = "TdeckKeyboard";
|
||||||
|
constexpr auto TDECK_KEYBOARD_I2C_BUS_HANDLE = I2C_NUM_0;
|
||||||
#define TDECK_KEYBOARD_I2C_BUS_HANDLE I2C_NUM_0
|
constexpr auto TDECK_KEYBOARD_SLAVE_ADDRESS = 0x55;
|
||||||
#define TDECK_KEYBOARD_SLAVE_ADDRESS 0x55
|
|
||||||
|
|
||||||
static bool keyboard_i2c_read(uint8_t* output) {
|
static bool keyboard_i2c_read(uint8_t* output) {
|
||||||
return tt::hal::i2c::masterRead(TDECK_KEYBOARD_I2C_BUS_HANDLE, TDECK_KEYBOARD_SLAVE_ADDRESS, output, 1, 100 / portTICK_PERIOD_MS);
|
return tt::hal::i2c::masterRead(TDECK_KEYBOARD_I2C_BUS_HANDLE, TDECK_KEYBOARD_SLAVE_ADDRESS, output, 1, 100 / portTICK_PERIOD_MS);
|
||||||
@ -61,7 +60,3 @@ bool TdeckKeyboard::stopLvgl() {
|
|||||||
bool TdeckKeyboard::isAttached() const {
|
bool TdeckKeyboard::isAttached() const {
|
||||||
return tt::hal::i2c::masterHasDeviceAtAddress(TDECK_KEYBOARD_I2C_BUS_HANDLE, TDECK_KEYBOARD_SLAVE_ADDRESS, 100);
|
return tt::hal::i2c::masterHasDeviceAtAddress(TDECK_KEYBOARD_I2C_BUS_HANDLE, TDECK_KEYBOARD_SLAVE_ADDRESS, 100);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<tt::hal::keyboard::KeyboardDevice> createKeyboard() {
|
|
||||||
return std::make_shared<TdeckKeyboard>();
|
|
||||||
}
|
|
||||||
@ -2,8 +2,6 @@
|
|||||||
|
|
||||||
#include <Tactility/hal/keyboard/KeyboardDevice.h>
|
#include <Tactility/hal/keyboard/KeyboardDevice.h>
|
||||||
#include <Tactility/TactilityCore.h>
|
#include <Tactility/TactilityCore.h>
|
||||||
#include <esp_lcd_panel_io_interface.h>
|
|
||||||
#include <esp_lcd_touch.h>
|
|
||||||
|
|
||||||
class TdeckKeyboard final : public tt::hal::keyboard::KeyboardDevice {
|
class TdeckKeyboard final : public tt::hal::keyboard::KeyboardDevice {
|
||||||
|
|
||||||
@ -19,5 +17,3 @@ public:
|
|||||||
bool isAttached() const override;
|
bool isAttached() const override;
|
||||||
lv_indev_t* _Nullable getLvglIndev() override { return deviceHandle; }
|
lv_indev_t* _Nullable getLvglIndev() override { return deviceHandle; }
|
||||||
};
|
};
|
||||||
|
|
||||||
std::shared_ptr<tt::hal::keyboard::KeyboardDevice> createKeyboard();
|
|
||||||
@ -1,8 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#define TDECK_LCD_SPI_HOST SPI2_HOST
|
|
||||||
#define TDECK_LCD_PIN_CS GPIO_NUM_12
|
|
||||||
#define TDECK_LCD_PIN_DC GPIO_NUM_11 // RS
|
|
||||||
#define TDECK_LCD_HORIZONTAL_RESOLUTION 320
|
|
||||||
#define TDECK_LCD_VERTICAL_RESOLUTION 240
|
|
||||||
#define TDECK_LCD_SPI_TRANSFER_HEIGHT (TDECK_LCD_VERTICAL_RESOLUTION / 10)
|
|
||||||
@ -1,130 +0,0 @@
|
|||||||
#include "TdeckPower.h"
|
|
||||||
|
|
||||||
#include <Tactility/Log.h>
|
|
||||||
|
|
||||||
#define TAG "power"
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 2.0 ratio, but +.11 added as display voltage sag compensation.
|
|
||||||
*/
|
|
||||||
#define ADC_MULTIPLIER 2.11
|
|
||||||
|
|
||||||
#define ADC_REF_VOLTAGE 3.3f
|
|
||||||
#define BATTERY_VOLTAGE_MIN 3.2f
|
|
||||||
#define BATTERY_VOLTAGE_MAX 4.2f
|
|
||||||
|
|
||||||
static adc_oneshot_unit_init_cfg_t adcConfig = {
|
|
||||||
.unit_id = ADC_UNIT_1,
|
|
||||||
.clk_src = ADC_RTC_CLK_SRC_DEFAULT,
|
|
||||||
.ulp_mode = ADC_ULP_MODE_DISABLE,
|
|
||||||
};
|
|
||||||
|
|
||||||
static adc_oneshot_chan_cfg_t adcChannelConfig = {
|
|
||||||
.atten = ADC_ATTEN_DB_12,
|
|
||||||
.bitwidth = ADC_BITWIDTH_DEFAULT,
|
|
||||||
};
|
|
||||||
|
|
||||||
static uint8_t estimateChargeLevelFromVoltage(uint32_t milliVolt) {
|
|
||||||
float volts = std::min((float)milliVolt / 1000.f, BATTERY_VOLTAGE_MAX);
|
|
||||||
float voltage_percentage = (volts - BATTERY_VOLTAGE_MIN) / (BATTERY_VOLTAGE_MAX - BATTERY_VOLTAGE_MIN);
|
|
||||||
float voltage_factor = std::min(1.0f, voltage_percentage);
|
|
||||||
auto charge_level = (uint8_t) (voltage_factor * 100.f);
|
|
||||||
TT_LOG_V(TAG, "mV = %lu, scaled = %.2f, factor = %.2f, result = %d", milliVolt, volts, voltage_factor, charge_level);
|
|
||||||
return charge_level;
|
|
||||||
}
|
|
||||||
|
|
||||||
TdeckPower::TdeckPower() {
|
|
||||||
if (adc_oneshot_new_unit(&adcConfig, &adcHandle) != ESP_OK) {
|
|
||||||
TT_LOG_E(TAG, "ADC config failed");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (adc_oneshot_config_channel(adcHandle, ADC_CHANNEL_3, &adcChannelConfig) != ESP_OK) {
|
|
||||||
TT_LOG_E(TAG, "ADC channel config failed");
|
|
||||||
|
|
||||||
adc_oneshot_del_unit(adcHandle);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
TdeckPower::~TdeckPower() {
|
|
||||||
if (adcHandle) {
|
|
||||||
adc_oneshot_del_unit(adcHandle);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool TdeckPower::supportsMetric(MetricType type) const {
|
|
||||||
switch (type) {
|
|
||||||
using enum MetricType;
|
|
||||||
case BatteryVoltage:
|
|
||||||
case ChargeLevel:
|
|
||||||
return true;
|
|
||||||
default:
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false; // Safety guard for when new enum values are introduced
|
|
||||||
}
|
|
||||||
|
|
||||||
bool TdeckPower::getMetric(MetricType type, MetricData& data) {
|
|
||||||
switch (type) {
|
|
||||||
using enum MetricType;
|
|
||||||
case BatteryVoltage:
|
|
||||||
return readBatteryVoltageSampled(data.valueAsUint32);
|
|
||||||
case ChargeLevel:
|
|
||||||
if (readBatteryVoltageSampled(data.valueAsUint32)) {
|
|
||||||
data.valueAsUint32 = estimateChargeLevelFromVoltage(data.valueAsUint32);
|
|
||||||
return true;
|
|
||||||
} else {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false; // Safety guard for when new enum values are introduced
|
|
||||||
}
|
|
||||||
|
|
||||||
bool TdeckPower::readBatteryVoltageOnce(uint32_t& output) {
|
|
||||||
int raw;
|
|
||||||
if (adc_oneshot_read(adcHandle, ADC_CHANNEL_3, &raw) == ESP_OK) {
|
|
||||||
output = ADC_MULTIPLIER * ((1000.f * ADC_REF_VOLTAGE) / 4096.f) * (float)raw;
|
|
||||||
TT_LOG_V(TAG, "Raw = %d, voltage = %lu", raw, output);
|
|
||||||
return true;
|
|
||||||
} else {
|
|
||||||
TT_LOG_E(TAG, "Read failed");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#define MAX_VOLTAGE_SAMPLES 15
|
|
||||||
|
|
||||||
bool TdeckPower::readBatteryVoltageSampled(uint32_t& output) {
|
|
||||||
size_t samples_read = 0;
|
|
||||||
uint32_t sample_accumulator = 0;
|
|
||||||
uint32_t sample_read_buffer;
|
|
||||||
|
|
||||||
for (size_t i = 0; i < MAX_VOLTAGE_SAMPLES; ++i) {
|
|
||||||
if (readBatteryVoltageOnce(sample_read_buffer)) {
|
|
||||||
sample_accumulator += sample_read_buffer;
|
|
||||||
samples_read++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (samples_read > 0) {
|
|
||||||
output = sample_accumulator / samples_read;
|
|
||||||
return true;
|
|
||||||
} else {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static std::shared_ptr<PowerDevice> power;
|
|
||||||
|
|
||||||
std::shared_ptr<PowerDevice> tdeck_get_power() {
|
|
||||||
if (power == nullptr) {
|
|
||||||
power = std::make_shared<TdeckPower>();
|
|
||||||
}
|
|
||||||
return power;
|
|
||||||
}
|
|
||||||
|
|
||||||
@ -1,30 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include "Tactility/hal/power/PowerDevice.h"
|
|
||||||
#include <esp_adc/adc_oneshot.h>
|
|
||||||
#include <memory>
|
|
||||||
|
|
||||||
using tt::hal::power::PowerDevice;
|
|
||||||
|
|
||||||
class TdeckPower : public PowerDevice {
|
|
||||||
|
|
||||||
adc_oneshot_unit_handle_t adcHandle = nullptr;
|
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
TdeckPower();
|
|
||||||
~TdeckPower();
|
|
||||||
|
|
||||||
std::string getName() const final { return "ADC Power Measurement"; }
|
|
||||||
std::string getDescription() const final { return "Power measurement interface via ADC pin"; }
|
|
||||||
|
|
||||||
bool supportsMetric(MetricType type) const override;
|
|
||||||
bool getMetric(MetricType type, MetricData& data) override;
|
|
||||||
|
|
||||||
private:
|
|
||||||
|
|
||||||
bool readBatteryVoltageSampled(uint32_t& output);
|
|
||||||
bool readBatteryVoltageOnce(uint32_t& output);
|
|
||||||
};
|
|
||||||
|
|
||||||
std::shared_ptr<PowerDevice> tdeck_get_power();
|
|
||||||
@ -2,19 +2,18 @@
|
|||||||
|
|
||||||
## Higher Priority
|
## Higher Priority
|
||||||
|
|
||||||
- Move Display settings from flash to `/data/apps/display/display.properties`
|
|
||||||
- Expose app::Paths to TactilityC
|
|
||||||
- Call tt::lvgl::isSyncSet after HAL init and show an error (and crash?) when it is not set.
|
|
||||||
- External app loading: Check the version of Tactility and check ESP target hardware to check for compatibility.
|
- External app loading: Check the version of Tactility and check ESP target hardware to check for compatibility.
|
||||||
- App packaging
|
|
||||||
- Create more unit tests for `tactility-core`
|
|
||||||
- Make a URL handler. Use it for handling local files. Match file types with apps.
|
|
||||||
- Fix Development service: when no SD card is present, the app fails to install. Consider installing to `/data`
|
- Fix Development service: when no SD card is present, the app fails to install. Consider installing to `/data`
|
||||||
- Refactor `PropertiesFile.cpp` to use `tt::file::readLines()` (see TODO in code)
|
Note: Change app install to "transfer file" functionality. We can have a proper install when we have app packaging.
|
||||||
- Localize all apps
|
- Make a URL handler. Use it for handling local files. Match file types with apps.
|
||||||
|
Create some kind of "intent" handler like on Android.
|
||||||
|
The intent can have an action (e.g. view), a URL and an optional bundle.
|
||||||
|
The manifest can provide the intent handler
|
||||||
|
- App packaging
|
||||||
|
|
||||||
## Lower Priority
|
## Lower Priority
|
||||||
|
|
||||||
|
- Localize all apps
|
||||||
- Support hot-plugging SD card (note: this is not possible if they require the CS pin hack)
|
- Support hot-plugging SD card (note: this is not possible if they require the CS pin hack)
|
||||||
- Create more unit tests for `tactility`
|
- Create more unit tests for `tactility`
|
||||||
- Explore LVGL9's FreeRTOS functionality
|
- Explore LVGL9's FreeRTOS functionality
|
||||||
|
|||||||
5
Drivers/EstimatedPower/CMakeLists.txt
Normal file
5
Drivers/EstimatedPower/CMakeLists.txt
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
idf_component_register(
|
||||||
|
SRC_DIRS "Source"
|
||||||
|
INCLUDE_DIRS "Source"
|
||||||
|
REQUIRES Tactility esp_adc
|
||||||
|
)
|
||||||
3
Drivers/EstimatedPower/README.md
Normal file
3
Drivers/EstimatedPower/README.md
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
# EstimatedPower
|
||||||
|
|
||||||
|
Use ADC measurements to read voltage and estimate the available power that is left in the battery.
|
||||||
67
Drivers/EstimatedPower/Source/ChargeFromAdcVoltage.cpp
Normal file
67
Drivers/EstimatedPower/Source/ChargeFromAdcVoltage.cpp
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
#include "ChargeFromAdcVoltage.h"
|
||||||
|
#include <Tactility/Log.h>
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
|
constexpr auto TAG = "EstimatePower";
|
||||||
|
constexpr auto MAX_VOLTAGE_SAMPLES = 15;
|
||||||
|
|
||||||
|
uint8_t ChargeFromAdcVoltage::estimateChargeLevelFromVoltage(uint32_t milliVolt) const {
|
||||||
|
const float volts = std::min((float)milliVolt / 1000.f, configuration.batteryVoltageMax);
|
||||||
|
const float voltage_percentage = (volts - configuration.batteryVoltageMin) / (configuration.batteryVoltageMax - configuration.batteryVoltageMin);
|
||||||
|
const float voltage_factor = std::min(1.0f, voltage_percentage);
|
||||||
|
const auto charge_level = (uint8_t) (voltage_factor * 100.f);
|
||||||
|
TT_LOG_V(TAG, "mV = %lu, scaled = %.2f, factor = %.2f, result = %d", milliVolt, volts, voltage_factor, charge_level);
|
||||||
|
return charge_level;
|
||||||
|
}
|
||||||
|
|
||||||
|
ChargeFromAdcVoltage::ChargeFromAdcVoltage(const Configuration& configuration) : configuration(configuration) {
|
||||||
|
if (adc_oneshot_new_unit(&configuration.adcConfig, &adcHandle) != ESP_OK) {
|
||||||
|
TT_LOG_E(TAG, "ADC config failed");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (adc_oneshot_config_channel(adcHandle, configuration.adcChannel, &configuration.adcChannelConfig) != ESP_OK) {
|
||||||
|
TT_LOG_E(TAG, "ADC channel config failed");
|
||||||
|
|
||||||
|
adc_oneshot_del_unit(adcHandle);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ChargeFromAdcVoltage::~ChargeFromAdcVoltage() {
|
||||||
|
if (adcHandle) {
|
||||||
|
adc_oneshot_del_unit(adcHandle);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ChargeFromAdcVoltage::readBatteryVoltageOnce(uint32_t& output) const {
|
||||||
|
int raw;
|
||||||
|
if (adc_oneshot_read(adcHandle, configuration.adcChannel, &raw) == ESP_OK) {
|
||||||
|
output = configuration.adcMultiplier * ((1000.f * configuration.adcRefVoltage) / 4096.f) * (float)raw;
|
||||||
|
TT_LOG_V(TAG, "Raw = %d, voltage = %lu", raw, output);
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
TT_LOG_E(TAG, "Read failed");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ChargeFromAdcVoltage::readBatteryVoltageSampled(uint32_t& output) const {
|
||||||
|
size_t samples_read = 0;
|
||||||
|
uint32_t sample_accumulator = 0;
|
||||||
|
uint32_t sample_read_buffer;
|
||||||
|
|
||||||
|
for (size_t i = 0; i < MAX_VOLTAGE_SAMPLES; ++i) {
|
||||||
|
if (readBatteryVoltageOnce(sample_read_buffer)) {
|
||||||
|
sample_accumulator += sample_read_buffer;
|
||||||
|
samples_read++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (samples_read == 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
output = sample_accumulator / samples_read;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
42
Drivers/EstimatedPower/Source/ChargeFromAdcVoltage.h
Normal file
42
Drivers/EstimatedPower/Source/ChargeFromAdcVoltage.h
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <esp_adc/adc_oneshot.h>
|
||||||
|
|
||||||
|
class ChargeFromAdcVoltage {
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
struct Configuration {
|
||||||
|
adc_channel_t adcChannel = ADC_CHANNEL_3;
|
||||||
|
float adcMultiplier = 1.0f;
|
||||||
|
float adcRefVoltage = 3.3f;
|
||||||
|
float batteryVoltageMin = 3.2f;
|
||||||
|
float batteryVoltageMax = 4.2f;
|
||||||
|
adc_oneshot_unit_init_cfg_t adcConfig = {
|
||||||
|
.unit_id = ADC_UNIT_1,
|
||||||
|
.clk_src = ADC_RTC_CLK_SRC_DEFAULT,
|
||||||
|
.ulp_mode = ADC_ULP_MODE_DISABLE,
|
||||||
|
};
|
||||||
|
adc_oneshot_chan_cfg_t adcChannelConfig = {
|
||||||
|
.atten = ADC_ATTEN_DB_12,
|
||||||
|
.bitwidth = ADC_BITWIDTH_DEFAULT,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
adc_oneshot_unit_handle_t adcHandle = nullptr;
|
||||||
|
Configuration configuration;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
explicit ChargeFromAdcVoltage(const Configuration& configuration);
|
||||||
|
|
||||||
|
~ChargeFromAdcVoltage();
|
||||||
|
|
||||||
|
uint8_t estimateChargeLevelFromVoltage(uint32_t milliVolt) const;
|
||||||
|
|
||||||
|
bool readBatteryVoltageSampled(uint32_t& output) const;
|
||||||
|
|
||||||
|
bool readBatteryVoltageOnce(uint32_t& output) const;
|
||||||
|
};
|
||||||
30
Drivers/EstimatedPower/Source/EstimatedPower.cpp
Normal file
30
Drivers/EstimatedPower/Source/EstimatedPower.cpp
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
#include "EstimatedPower.h"
|
||||||
|
|
||||||
|
bool EstimatedPower::supportsMetric(MetricType type) const {
|
||||||
|
switch (type) {
|
||||||
|
using enum MetricType;
|
||||||
|
case BatteryVoltage:
|
||||||
|
case ChargeLevel:
|
||||||
|
return true;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool EstimatedPower::getMetric(MetricType type, MetricData& data) {
|
||||||
|
switch (type) {
|
||||||
|
using enum MetricType;
|
||||||
|
case BatteryVoltage:
|
||||||
|
return chargeFromAdcVoltage->readBatteryVoltageSampled(data.valueAsUint32);
|
||||||
|
case ChargeLevel:
|
||||||
|
if (chargeFromAdcVoltage->readBatteryVoltageSampled(data.valueAsUint32)) {
|
||||||
|
data.valueAsUint32 = chargeFromAdcVoltage->estimateChargeLevelFromVoltage(data.valueAsUint32);
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
27
Drivers/EstimatedPower/Source/EstimatedPower.h
Normal file
27
Drivers/EstimatedPower/Source/EstimatedPower.h
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <ChargeFromAdcVoltage.h>
|
||||||
|
#include <Tactility/hal/power/PowerDevice.h>
|
||||||
|
|
||||||
|
using tt::hal::power::PowerDevice;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Uses Voltage measurements to estimate charge.
|
||||||
|
* Supports voltage and charge level metrics.
|
||||||
|
* Can be overridden to further extend supported metrics.
|
||||||
|
*/
|
||||||
|
class EstimatedPower final : public PowerDevice {
|
||||||
|
|
||||||
|
std::unique_ptr<ChargeFromAdcVoltage> chargeFromAdcVoltage;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
EstimatedPower(ChargeFromAdcVoltage::Configuration configuration) :
|
||||||
|
chargeFromAdcVoltage(std::make_unique<ChargeFromAdcVoltage>(std::move(configuration))) {}
|
||||||
|
|
||||||
|
std::string getName() const override { return "ADC Power Measurement"; }
|
||||||
|
std::string getDescription() const override { return "Power measurement interface via ADC pin"; }
|
||||||
|
|
||||||
|
bool supportsMetric(MetricType type) const override;
|
||||||
|
bool getMetric(MetricType type, MetricData& data) override;
|
||||||
|
};
|
||||||
@ -1,13 +1,13 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "Tactility/app/AppManifest.h"
|
#include <Tactility/app/AppManifest.h>
|
||||||
|
#include <Tactility/Dispatcher.h>
|
||||||
#include <Tactility/hal/Configuration.h>
|
#include <Tactility/hal/Configuration.h>
|
||||||
#include <Tactility/service/ServiceManifest.h>
|
#include <Tactility/service/ServiceManifest.h>
|
||||||
|
|
||||||
namespace tt {
|
namespace tt {
|
||||||
|
|
||||||
namespace app::launcher { extern const app::AppManifest manifest; }
|
namespace app::launcher { extern const AppManifest manifest; }
|
||||||
|
|
||||||
/** @brief The configuration for the operating system
|
/** @brief The configuration for the operating system
|
||||||
* It contains the hardware configuration, apps and services
|
* It contains the hardware configuration, apps and services
|
||||||
@ -33,4 +33,7 @@ void run(const Configuration& config);
|
|||||||
*/
|
*/
|
||||||
const Configuration* _Nullable getConfiguration();
|
const Configuration* _Nullable getConfiguration();
|
||||||
|
|
||||||
|
|
||||||
|
Dispatcher& getMainDispatcher();
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|||||||
@ -1,8 +1,8 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "Tactility/hal/sdcard/SdCardDevice.h"
|
#include <Tactility/hal/sdcard/SdCardDevice.h>
|
||||||
#include "Tactility/hal/spi/Spi.h"
|
#include <Tactility/hal/spi/Spi.h>
|
||||||
#include "Tactility/hal/uart/Uart.h"
|
#include <Tactility/hal/uart/Uart.h>
|
||||||
#include "i2c/I2c.h"
|
#include "i2c/I2c.h"
|
||||||
|
|
||||||
namespace tt::hal {
|
namespace tt::hal {
|
||||||
|
|||||||
@ -11,8 +11,6 @@ namespace tt::service::gps {
|
|||||||
|
|
||||||
class GpsService final : public Service {
|
class GpsService final : public Service {
|
||||||
|
|
||||||
private:
|
|
||||||
|
|
||||||
struct GpsDeviceRecord {
|
struct GpsDeviceRecord {
|
||||||
std::shared_ptr<hal::gps::GpsDevice> device = nullptr;
|
std::shared_ptr<hal::gps::GpsDevice> device = nullptr;
|
||||||
hal::gps::GpsDevice::GgaSubscriptionId satelliteSubscriptionId = -1;
|
hal::gps::GpsDevice::GgaSubscriptionId satelliteSubscriptionId = -1;
|
||||||
@ -25,7 +23,7 @@ private:
|
|||||||
Mutex mutex = Mutex(Mutex::Type::Recursive);
|
Mutex mutex = Mutex(Mutex::Type::Recursive);
|
||||||
Mutex stateMutex;
|
Mutex stateMutex;
|
||||||
std::vector<GpsDeviceRecord> deviceRecords;
|
std::vector<GpsDeviceRecord> deviceRecords;
|
||||||
std::shared_ptr<PubSub> statePubSub = std::make_shared<PubSub>();
|
std::shared_ptr<PubSub<State>> statePubSub = std::make_shared<PubSub<State>>();
|
||||||
std::unique_ptr<Paths> paths;
|
std::unique_ptr<Paths> paths;
|
||||||
State state = State::Off;
|
State state = State::Off;
|
||||||
|
|
||||||
@ -46,8 +44,8 @@ private:
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
void onStart(tt::service::ServiceContext &serviceContext) final;
|
void onStart(ServiceContext &serviceContext) override;
|
||||||
void onStop(tt::service::ServiceContext &serviceContext) final;
|
void onStop(ServiceContext &serviceContext) override;
|
||||||
|
|
||||||
bool addGpsConfiguration(hal::gps::GpsConfiguration configuration);
|
bool addGpsConfiguration(hal::gps::GpsConfiguration configuration);
|
||||||
bool removeGpsConfiguration(hal::gps::GpsConfiguration configuration);
|
bool removeGpsConfiguration(hal::gps::GpsConfiguration configuration);
|
||||||
@ -61,7 +59,7 @@ public:
|
|||||||
bool getCoordinates(minmea_sentence_rmc& rmc) const;
|
bool getCoordinates(minmea_sentence_rmc& rmc) const;
|
||||||
|
|
||||||
/** @return GPS service pubsub that broadcasts State* objects */
|
/** @return GPS service pubsub that broadcasts State* objects */
|
||||||
std::shared_ptr<PubSub> getStatePubsub() const { return statePubSub; }
|
std::shared_ptr<PubSub<State>> getStatePubsub() const { return statePubSub; }
|
||||||
};
|
};
|
||||||
|
|
||||||
std::shared_ptr<GpsService> findGpsService();
|
std::shared_ptr<GpsService> findGpsService();
|
||||||
|
|||||||
@ -11,15 +11,11 @@ namespace tt::service::loader {
|
|||||||
|
|
||||||
// region LoaderEvent for PubSub
|
// region LoaderEvent for PubSub
|
||||||
|
|
||||||
typedef enum {
|
enum class LoaderEvent{
|
||||||
LoaderEventTypeApplicationStarted,
|
ApplicationStarted,
|
||||||
LoaderEventTypeApplicationShowing,
|
ApplicationShowing,
|
||||||
LoaderEventTypeApplicationHiding,
|
ApplicationHiding,
|
||||||
LoaderEventTypeApplicationStopped
|
ApplicationStopped
|
||||||
} LoaderEventType;
|
|
||||||
|
|
||||||
struct LoaderEvent {
|
|
||||||
LoaderEventType type;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// endregion LoaderEvent for PubSub
|
// endregion LoaderEvent for PubSub
|
||||||
@ -43,6 +39,6 @@ std::shared_ptr<app::App> _Nullable getCurrentApp();
|
|||||||
/**
|
/**
|
||||||
* @brief PubSub for LoaderEvent
|
* @brief PubSub for LoaderEvent
|
||||||
*/
|
*/
|
||||||
std::shared_ptr<PubSub> getPubsub();
|
std::shared_ptr<PubSub<LoaderEvent>> getPubsub();
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|||||||
@ -33,7 +33,7 @@ typedef enum {
|
|||||||
|
|
||||||
namespace tt::service::wifi {
|
namespace tt::service::wifi {
|
||||||
|
|
||||||
enum class EventType {
|
enum class WifiEvent {
|
||||||
/** Radio was turned on */
|
/** Radio was turned on */
|
||||||
RadioStateOn,
|
RadioStateOn,
|
||||||
/** Radio is turning on. */
|
/** Radio is turning on. */
|
||||||
@ -61,10 +61,6 @@ enum class RadioState {
|
|||||||
Off,
|
Off,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Event {
|
|
||||||
EventType type;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct ApRecord {
|
struct ApRecord {
|
||||||
std::string ssid;
|
std::string ssid;
|
||||||
int8_t rssi;
|
int8_t rssi;
|
||||||
@ -76,7 +72,7 @@ struct ApRecord {
|
|||||||
* @brief Get wifi pubsub that broadcasts Event objects
|
* @brief Get wifi pubsub that broadcasts Event objects
|
||||||
* @return PubSub
|
* @return PubSub
|
||||||
*/
|
*/
|
||||||
std::shared_ptr<PubSub> getPubsub();
|
std::shared_ptr<PubSub<WifiEvent>> getPubsub();
|
||||||
|
|
||||||
/** @return Get the current radio state */
|
/** @return Get the current radio state */
|
||||||
RadioState getRadioState();
|
RadioState getRadioState();
|
||||||
|
|||||||
@ -19,9 +19,11 @@ class WifiConnect : public App {
|
|||||||
.onConnectSsidContext = nullptr
|
.onConnectSsidContext = nullptr
|
||||||
};
|
};
|
||||||
View view = View(&bindings, &state);
|
View view = View(&bindings, &state);
|
||||||
PubSub::SubscriptionHandle wifiSubscription;
|
PubSub<service::wifi::WifiEvent>::SubscriptionHandle wifiSubscription;
|
||||||
bool view_enabled = false;
|
bool view_enabled = false;
|
||||||
|
|
||||||
|
void onWifiEvent(service::wifi::WifiEvent event);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
WifiConnect();
|
WifiConnect();
|
||||||
|
|||||||
@ -13,15 +13,15 @@ namespace tt::app::wifimanage {
|
|||||||
|
|
||||||
class WifiManage : public App {
|
class WifiManage : public App {
|
||||||
|
|
||||||
private:
|
PubSub<service::wifi::WifiEvent>::SubscriptionHandle wifiSubscription = nullptr;
|
||||||
|
|
||||||
PubSub::SubscriptionHandle wifiSubscription = nullptr;
|
|
||||||
Mutex mutex;
|
Mutex mutex;
|
||||||
Bindings bindings = { };
|
Bindings bindings = { };
|
||||||
State state;
|
State state;
|
||||||
View view = View(&bindings, &state);
|
View view = View(&bindings, &state);
|
||||||
bool isViewEnabled = false;
|
bool isViewEnabled = false;
|
||||||
|
|
||||||
|
void onWifiEvent(service::wifi::WifiEvent event);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
WifiManage();
|
WifiManage();
|
||||||
|
|||||||
@ -1,14 +1,13 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <Tactility/app/AppContext.h>
|
||||||
#include <Tactility/MessageQueue.h>
|
#include <Tactility/MessageQueue.h>
|
||||||
#include <Tactility/Mutex.h>
|
#include <Tactility/Mutex.h>
|
||||||
#include <Tactility/PubSub.h>
|
#include <Tactility/PubSub.h>
|
||||||
#include <Tactility/service/Service.h>
|
#include <Tactility/service/Service.h>
|
||||||
|
#include <Tactility/service/loader/Loader.h>
|
||||||
#include "Tactility/app/AppContext.h"
|
|
||||||
|
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
|
|
||||||
#include <lvgl.h>
|
#include <lvgl.h>
|
||||||
|
|
||||||
namespace tt::service::gui {
|
namespace tt::service::gui {
|
||||||
@ -23,7 +22,7 @@ class GuiService : public Service {
|
|||||||
// Thread and lock
|
// Thread and lock
|
||||||
Thread* thread = nullptr;
|
Thread* thread = nullptr;
|
||||||
Mutex mutex = Mutex(Mutex::Type::Recursive);
|
Mutex mutex = Mutex(Mutex::Type::Recursive);
|
||||||
PubSub::SubscriptionHandle loader_pubsub_subscription = nullptr;
|
PubSub<loader::LoaderEvent>::SubscriptionHandle loader_pubsub_subscription = nullptr;
|
||||||
|
|
||||||
// Layers and Canvas
|
// Layers and Canvas
|
||||||
lv_obj_t* appRootWidget = nullptr;
|
lv_obj_t* appRootWidget = nullptr;
|
||||||
@ -37,10 +36,10 @@ class GuiService : public Service {
|
|||||||
|
|
||||||
bool isStarted = false;
|
bool isStarted = false;
|
||||||
|
|
||||||
static void onLoaderMessage(const void* message, TT_UNUSED void* context);
|
|
||||||
|
|
||||||
static int32_t guiMain();
|
static int32_t guiMain();
|
||||||
|
|
||||||
|
void onLoaderEvent(loader::LoaderEvent event);
|
||||||
|
|
||||||
lv_obj_t* createAppViews(lv_obj_t* parent);
|
lv_obj_t* createAppViews(lv_obj_t* parent);
|
||||||
|
|
||||||
void redraw();
|
void redraw();
|
||||||
|
|||||||
@ -1,28 +1,46 @@
|
|||||||
#include <Tactility/Tactility.h>
|
#include <Tactility/Tactility.h>
|
||||||
|
#include <Tactility/TactilityConfig.h>
|
||||||
|
|
||||||
#include <Tactility/app/AppRegistration.h>
|
#include <Tactility/app/AppRegistration.h>
|
||||||
#include <Tactility/TactilityConfig.h>
|
#include <Tactility/DispatcherThread.h>
|
||||||
#include <Tactility/TactilityHeadless.h>
|
#include <Tactility/hal/HalPrivate.h>
|
||||||
|
#include <Tactility/hal/sdcard/SdCardMounting.h>
|
||||||
#include <Tactility/lvgl/LvglPrivate.h>
|
#include <Tactility/lvgl/LvglPrivate.h>
|
||||||
|
#include <Tactility/network/NtpPrivate.h>
|
||||||
#include <Tactility/service/ServiceManifest.h>
|
#include <Tactility/service/ServiceManifest.h>
|
||||||
#include <Tactility/service/ServiceRegistration.h>
|
#include <Tactility/service/ServiceRegistration.h>
|
||||||
#include <Tactility/service/loader/Loader.h>
|
#include <Tactility/service/loader/Loader.h>
|
||||||
|
#include <Tactility/settings/TimePrivate.h>
|
||||||
|
|
||||||
|
#ifdef ESP_PLATFORM
|
||||||
|
#include <Tactility/InitEsp.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace tt {
|
namespace tt {
|
||||||
|
|
||||||
#define TAG "Tactility"
|
constexpr auto* TAG = "Tactility";
|
||||||
|
|
||||||
static const Configuration* config_instance = nullptr;
|
static const Configuration* config_instance = nullptr;
|
||||||
|
static Dispatcher mainDispatcher;
|
||||||
|
|
||||||
// region Default services
|
// region Default services
|
||||||
|
|
||||||
namespace service {
|
namespace service {
|
||||||
|
// Primary
|
||||||
|
namespace gps { extern const ServiceManifest manifest; }
|
||||||
|
namespace wifi { extern const ServiceManifest manifest; }
|
||||||
|
namespace sdcard { extern const ServiceManifest manifest; }
|
||||||
|
#ifdef ESP_PLATFORM
|
||||||
|
namespace development { extern const ServiceManifest manifest; }
|
||||||
|
namespace espnow { extern const ServiceManifest manifest; }
|
||||||
|
#endif
|
||||||
|
// Secondary (UI)
|
||||||
namespace gui { extern const ServiceManifest manifest; }
|
namespace gui { extern const ServiceManifest manifest; }
|
||||||
namespace loader { extern const ServiceManifest manifest; }
|
namespace loader { extern const ServiceManifest manifest; }
|
||||||
namespace statusbar { extern const ServiceManifest manifest; }
|
namespace statusbar { extern const ServiceManifest manifest; }
|
||||||
#if TT_FEATURE_SCREENSHOT_ENABLED
|
#if TT_FEATURE_SCREENSHOT_ENABLED
|
||||||
namespace screenshot { extern const ServiceManifest manifest; }
|
namespace screenshot { extern const ServiceManifest manifest; }
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// endregion
|
// endregion
|
||||||
@ -127,7 +145,7 @@ static void registerUserApps(const std::vector<const app::AppManifest*>& apps) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void registerAndStartSystemServices() {
|
static void registerAndStartSecondaryServices() {
|
||||||
TT_LOG_I(TAG, "Registering and starting system services");
|
TT_LOG_I(TAG, "Registering and starting system services");
|
||||||
addService(service::loader::manifest);
|
addService(service::loader::manifest);
|
||||||
addService(service::gui::manifest);
|
addService(service::gui::manifest);
|
||||||
@ -137,6 +155,17 @@ static void registerAndStartSystemServices() {
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void registerAndStartPrimaryServices() {
|
||||||
|
TT_LOG_I(TAG, "Registering and starting system services");
|
||||||
|
addService(service::gps::manifest);
|
||||||
|
addService(service::sdcard::manifest);
|
||||||
|
addService(service::wifi::manifest);
|
||||||
|
#ifdef ESP_PLATFORM
|
||||||
|
addService(service::development::manifest);
|
||||||
|
addService(service::espnow::manifest);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
static void registerAndStartUserServices(const std::vector<const service::ServiceManifest*>& manifests) {
|
static void registerAndStartUserServices(const std::vector<const service::ServiceManifest*>& manifests) {
|
||||||
TT_LOG_I(TAG, "Registering and starting user services");
|
TT_LOG_I(TAG, "Registering and starting user services");
|
||||||
for (auto* manifest : manifests) {
|
for (auto* manifest : manifests) {
|
||||||
@ -165,11 +194,18 @@ void run(const Configuration& config) {
|
|||||||
// Assign early so starting services can use it
|
// Assign early so starting services can use it
|
||||||
config_instance = &config;
|
config_instance = &config;
|
||||||
|
|
||||||
initHeadless(hardware);
|
TT_LOG_I(TAG, "Tactility v%s on %s (%s)", TT_VERSION, CONFIG_TT_BOARD_NAME, CONFIG_TT_BOARD_ID);
|
||||||
|
#ifdef ESP_PLATFORM
|
||||||
|
initEsp();
|
||||||
|
#endif
|
||||||
|
settings::initTimeZone();
|
||||||
|
hal::init(*config.hardware);
|
||||||
|
hal::sdcard::mountAll();
|
||||||
|
network::ntp::init();
|
||||||
|
|
||||||
|
registerAndStartPrimaryServices();
|
||||||
lvgl::init(hardware);
|
lvgl::init(hardware);
|
||||||
|
registerAndStartSecondaryServices();
|
||||||
registerAndStartSystemServices();
|
|
||||||
|
|
||||||
TT_LOG_I(TAG, "starting boot app");
|
TT_LOG_I(TAG, "starting boot app");
|
||||||
// The boot app takes care of registering system apps, user services and user apps
|
// The boot app takes care of registering system apps, user services and user apps
|
||||||
@ -180,7 +216,7 @@ void run(const Configuration& config) {
|
|||||||
|
|
||||||
TT_LOG_I(TAG, "Processing main dispatcher");
|
TT_LOG_I(TAG, "Processing main dispatcher");
|
||||||
while (true) {
|
while (true) {
|
||||||
getMainDispatcher().consume();
|
mainDispatcher.consume();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -188,4 +224,8 @@ const Configuration* _Nullable getConfiguration() {
|
|||||||
return config_instance;
|
return config_instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Dispatcher& getMainDispatcher() {
|
||||||
|
return mainDispatcher;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|||||||
@ -1,68 +0,0 @@
|
|||||||
#include "Tactility/TactilityHeadless.h"
|
|
||||||
#include "Tactility/hal/Configuration.h"
|
|
||||||
#include "Tactility/hal/Hal_i.h"
|
|
||||||
#include "Tactility/network/NtpPrivate.h"
|
|
||||||
#include "Tactility/service/ServiceManifest.h"
|
|
||||||
#include "Tactility/service/ServiceRegistration.h"
|
|
||||||
|
|
||||||
#include <Tactility/Dispatcher.h>
|
|
||||||
#include <Tactility/hal/sdcard/SdCardMounting.h>
|
|
||||||
#include <Tactility/settings/TimePrivate.h>
|
|
||||||
|
|
||||||
#ifdef ESP_PLATFORM
|
|
||||||
#include "Tactility/InitEsp.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
namespace tt {
|
|
||||||
|
|
||||||
constexpr auto* TAG = "Tactility";
|
|
||||||
|
|
||||||
namespace service::gps { extern const ServiceManifest manifest; }
|
|
||||||
namespace service::wifi { extern const ServiceManifest manifest; }
|
|
||||||
namespace service::sdcard { extern const ServiceManifest manifest; }
|
|
||||||
#ifdef ESP_PLATFORM
|
|
||||||
namespace service::development { extern const ServiceManifest manifest; }
|
|
||||||
namespace service::espnow { extern const ServiceManifest manifest; }
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static Dispatcher mainDispatcher;
|
|
||||||
|
|
||||||
static const hal::Configuration* hardwareConfig = nullptr;
|
|
||||||
|
|
||||||
static void registerAndStartSystemServices() {
|
|
||||||
TT_LOG_I(TAG, "Registering and starting system services");
|
|
||||||
addService(service::gps::manifest);
|
|
||||||
addService(service::sdcard::manifest);
|
|
||||||
addService(service::wifi::manifest);
|
|
||||||
#ifdef ESP_PLATFORM
|
|
||||||
addService(service::development::manifest);
|
|
||||||
addService(service::espnow::manifest);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
void initHeadless(const hal::Configuration& config) {
|
|
||||||
TT_LOG_I(TAG, "Tactility v%s on %s (%s)", TT_VERSION, CONFIG_TT_BOARD_NAME, CONFIG_TT_BOARD_ID);
|
|
||||||
#ifdef ESP_PLATFORM
|
|
||||||
initEsp();
|
|
||||||
#endif
|
|
||||||
hardwareConfig = &config;
|
|
||||||
settings::initTimeZone();
|
|
||||||
hal::init(config);
|
|
||||||
hal::sdcard::mountAll();
|
|
||||||
network::ntp::init();
|
|
||||||
registerAndStartSystemServices();
|
|
||||||
}
|
|
||||||
|
|
||||||
Dispatcher& getMainDispatcher() {
|
|
||||||
return mainDispatcher;
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace hal {
|
|
||||||
|
|
||||||
const Configuration* getConfiguration() {
|
|
||||||
return hardwareConfig;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace hal
|
|
||||||
|
|
||||||
} // namespace tt
|
|
||||||
@ -32,7 +32,7 @@ class BootApp : public App {
|
|||||||
|
|
||||||
Thread thread = Thread(
|
Thread thread = Thread(
|
||||||
"boot",
|
"boot",
|
||||||
4096,
|
5120,
|
||||||
[] { return bootThreadCallback(); },
|
[] { return bootThreadCallback(); },
|
||||||
getCpuAffinityConfiguration().system
|
getCpuAffinityConfiguration().system
|
||||||
);
|
);
|
||||||
|
|||||||
@ -1,17 +1,19 @@
|
|||||||
#ifdef ESP_PLATFORM
|
#ifdef ESP_PLATFORM
|
||||||
|
|
||||||
|
#include <Tactility/Tactility.h>
|
||||||
|
|
||||||
#include <Tactility/app/AppManifest.h>
|
#include <Tactility/app/AppManifest.h>
|
||||||
#include <Tactility/lvgl/LvglSync.h>
|
#include <Tactility/lvgl/LvglSync.h>
|
||||||
#include <Tactility/lvgl/Style.h>
|
#include <Tactility/lvgl/Style.h>
|
||||||
#include <Tactility/lvgl/Toolbar.h>
|
#include <Tactility/lvgl/Toolbar.h>
|
||||||
#include <Tactility/service/development/DevelopmentService.h>
|
#include <Tactility/service/development/DevelopmentService.h>
|
||||||
|
#include <Tactility/service/development/DevelopmentSettings.h>
|
||||||
#include <Tactility/service/loader/Loader.h>
|
#include <Tactility/service/loader/Loader.h>
|
||||||
#include <Tactility/service/wifi/Wifi.h>
|
#include <Tactility/service/wifi/Wifi.h>
|
||||||
#include <Tactility/Timer.h>
|
#include <Tactility/Timer.h>
|
||||||
|
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <lvgl.h>
|
#include <lvgl.h>
|
||||||
#include <Tactility/service/development/DevelopmentSettings.h>
|
|
||||||
|
|
||||||
namespace tt::app::development {
|
namespace tt::app::development {
|
||||||
|
|
||||||
@ -51,7 +53,10 @@ class DevelopmentApp final : public App {
|
|||||||
bool is_on = lv_obj_has_state(widget, LV_STATE_CHECKED);
|
bool is_on = lv_obj_has_state(widget, LV_STATE_CHECKED);
|
||||||
bool is_changed = is_on != service::development::shouldEnableOnBoot();
|
bool is_changed = is_on != service::development::shouldEnableOnBoot();
|
||||||
if (is_changed) {
|
if (is_changed) {
|
||||||
|
// Dispatch it, so file IO doesn't block the UI
|
||||||
|
getMainDispatcher().dispatch([is_on] {
|
||||||
service::development::setEnableOnBoot(is_on);
|
service::development::setEnableOnBoot(is_on);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,8 +1,9 @@
|
|||||||
|
#include <Tactility/Tactility.h>
|
||||||
|
|
||||||
#include <Tactility/settings/DisplaySettings.h>
|
#include <Tactility/settings/DisplaySettings.h>
|
||||||
#include <Tactility/Assets.h>
|
#include <Tactility/Assets.h>
|
||||||
#include <Tactility/hal/display/DisplayDevice.h>
|
#include <Tactility/hal/display/DisplayDevice.h>
|
||||||
#include <Tactility/lvgl/Toolbar.h>
|
#include <Tactility/lvgl/Toolbar.h>
|
||||||
#include <Tactility/Tactility.h>
|
|
||||||
|
|
||||||
#include <lvgl.h>
|
#include <lvgl.h>
|
||||||
|
|
||||||
@ -139,7 +140,11 @@ public:
|
|||||||
|
|
||||||
void onHide(TT_UNUSED AppContext& app) override {
|
void onHide(TT_UNUSED AppContext& app) override {
|
||||||
if (displaySettingsUpdated) {
|
if (displaySettingsUpdated) {
|
||||||
settings::display::save(displaySettings);
|
// Dispatch it, so file IO doesn't block the UI
|
||||||
|
const settings::display::DisplaySettings settings_to_save = displaySettings;
|
||||||
|
getMainDispatcher().dispatch([settings_to_save] {
|
||||||
|
settings::display::save(settings_to_save);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@ -1,12 +1,13 @@
|
|||||||
#include "Tactility/TactilityHeadless.h"
|
#include <Tactility/Tactility.h>
|
||||||
#include "Tactility/Timer.h"
|
|
||||||
#include "Tactility/app/AppManifest.h"
|
#include <Tactility/app/AppManifest.h>
|
||||||
#include "Tactility/app/alertdialog/AlertDialog.h"
|
#include <Tactility/app/alertdialog/AlertDialog.h>
|
||||||
#include "Tactility/lvgl/LvglSync.h"
|
#include <Tactility/lvgl/LvglSync.h>
|
||||||
#include "Tactility/lvgl/Toolbar.h"
|
#include <Tactility/lvgl/Toolbar.h>
|
||||||
#include "Tactility/service/gps/GpsUtil.h"
|
|
||||||
#include "Tactility/service/loader/Loader.h"
|
|
||||||
#include <Tactility/service/gps/GpsService.h>
|
#include <Tactility/service/gps/GpsService.h>
|
||||||
|
#include <Tactility/service/gps/GpsState.h>
|
||||||
|
#include <Tactility/service/loader/Loader.h>
|
||||||
|
#include <Tactility/Timer.h>
|
||||||
|
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <format>
|
#include <format>
|
||||||
@ -34,14 +35,9 @@ class GpsSettingsApp final : public App {
|
|||||||
lv_obj_t* gpsConfigWrapper = nullptr;
|
lv_obj_t* gpsConfigWrapper = nullptr;
|
||||||
lv_obj_t* addGpsWrapper = nullptr;
|
lv_obj_t* addGpsWrapper = nullptr;
|
||||||
bool hasSetInfo = false;
|
bool hasSetInfo = false;
|
||||||
PubSub::SubscriptionHandle serviceStateSubscription = nullptr;
|
PubSub<service::gps::State>::SubscriptionHandle serviceStateSubscription = nullptr;
|
||||||
std::shared_ptr<service::gps::GpsService> service;
|
std::shared_ptr<service::gps::GpsService> service;
|
||||||
|
|
||||||
static void onServiceStateChangedCallback(const void* data, void* context) {
|
|
||||||
auto* app = (GpsSettingsApp*)context;
|
|
||||||
app->onServiceStateChanged();
|
|
||||||
}
|
|
||||||
|
|
||||||
void onServiceStateChanged() {
|
void onServiceStateChanged() {
|
||||||
auto lock = lvgl::getSyncLock()->asScopedLock();
|
auto lock = lvgl::getSyncLock()->asScopedLock();
|
||||||
if (lock.lock(100 / portTICK_PERIOD_MS)) {
|
if (lock.lock(100 / portTICK_PERIOD_MS)) {
|
||||||
@ -313,7 +309,9 @@ public:
|
|||||||
lv_obj_set_style_pad_all(infoContainerWidget, 0, 0);
|
lv_obj_set_style_pad_all(infoContainerWidget, 0, 0);
|
||||||
hasSetInfo = false;
|
hasSetInfo = false;
|
||||||
|
|
||||||
serviceStateSubscription = service->getStatePubsub()->subscribe(onServiceStateChangedCallback, this);
|
serviceStateSubscription = service->getStatePubsub()->subscribe([this](auto) {
|
||||||
|
onServiceStateChanged();
|
||||||
|
});
|
||||||
|
|
||||||
gpsConfigWrapper = lv_obj_create(main_wrapper);
|
gpsConfigWrapper = lv_obj_create(main_wrapper);
|
||||||
lv_obj_set_size(gpsConfigWrapper, LV_PCT(100), LV_SIZE_CONTENT);
|
lv_obj_set_size(gpsConfigWrapper, LV_PCT(100), LV_SIZE_CONTENT);
|
||||||
|
|||||||
@ -1,19 +1,18 @@
|
|||||||
#include "Tactility/TactilityConfig.h"
|
#include <Tactility/Tactility.h>
|
||||||
|
#include <Tactility/TactilityConfig.h>
|
||||||
|
|
||||||
#include <Tactility/Timer.h>
|
#include <Tactility/Timer.h>
|
||||||
#include <Tactility/kernel/Kernel.h>
|
#include <Tactility/kernel/Kernel.h>
|
||||||
|
|
||||||
#if TT_FEATURE_SCREENSHOT_ENABLED
|
#if TT_FEATURE_SCREENSHOT_ENABLED
|
||||||
|
|
||||||
#include "Tactility/app/App.h"
|
#include <Tactility/app/App.h>
|
||||||
#include "Tactility/app/AppManifest.h"
|
#include <Tactility/app/AppManifest.h>
|
||||||
#include "Tactility/lvgl/LvglSync.h"
|
#include <Tactility/lvgl/LvglSync.h>
|
||||||
#include "Tactility/lvgl/Toolbar.h"
|
#include <Tactility/lvgl/Toolbar.h>
|
||||||
#include "Tactility/service/screenshot/Screenshot.h"
|
#include <Tactility/service/screenshot/Screenshot.h>
|
||||||
|
|
||||||
#include <Tactility/TactilityHeadless.h>
|
constexpr auto* TAG = "Screenshot";
|
||||||
|
|
||||||
#define TAG "screenshot"
|
|
||||||
|
|
||||||
namespace tt::app::screenshot {
|
namespace tt::app::screenshot {
|
||||||
|
|
||||||
|
|||||||
@ -1,6 +1,4 @@
|
|||||||
#include "Tactility/app/wificonnect/State.h"
|
#include <Tactility/app/wificonnect/State.h>
|
||||||
|
|
||||||
#include <cstring>
|
|
||||||
|
|
||||||
namespace tt::app::wificonnect {
|
namespace tt::app::wificonnect {
|
||||||
|
|
||||||
|
|||||||
@ -1,19 +1,18 @@
|
|||||||
#include "Tactility/app/wificonnect/View.h"
|
|
||||||
#include "Tactility/app/wificonnect/WifiConnect.h"
|
|
||||||
|
|
||||||
#include "Tactility/lvgl/Toolbar.h"
|
|
||||||
#include "Tactility/lvgl/Spinner.h"
|
|
||||||
|
|
||||||
#include <Tactility/TactilityCore.h>
|
#include <Tactility/TactilityCore.h>
|
||||||
|
|
||||||
#include <lvgl.h>
|
#include <Tactility/app/wificonnect/View.h>
|
||||||
#include <cstring>
|
#include <Tactility/app/wificonnect/WifiConnect.h>
|
||||||
|
#include <Tactility/lvgl/Toolbar.h>
|
||||||
|
#include <Tactility/lvgl/Spinner.h>
|
||||||
#include <Tactility/service/wifi/WifiApSettings.h>
|
#include <Tactility/service/wifi/WifiApSettings.h>
|
||||||
#include <Tactility/service/wifi/WifiGlobals.h>
|
#include <Tactility/service/wifi/WifiGlobals.h>
|
||||||
|
|
||||||
|
#include <lvgl.h>
|
||||||
|
#include <cstring>
|
||||||
|
|
||||||
namespace tt::app::wificonnect {
|
namespace tt::app::wificonnect {
|
||||||
|
|
||||||
#define TAG "wifi_connect"
|
constexpr auto* TAG = "WifiConnect";
|
||||||
|
|
||||||
void View::resetErrors() {
|
void View::resetErrors() {
|
||||||
lv_obj_add_flag(password_error, LV_OBJ_FLAG_HIDDEN);
|
lv_obj_add_flag(password_error, LV_OBJ_FLAG_HIDDEN);
|
||||||
|
|||||||
@ -1,41 +1,18 @@
|
|||||||
#include "Tactility/app/wificonnect/WifiConnect.h"
|
#include <Tactility/app/wificonnect/WifiConnect.h>
|
||||||
|
|
||||||
#include "Tactility/app/AppContext.h"
|
#include <Tactility/app/AppContext.h>
|
||||||
#include "Tactility/service/loader/Loader.h"
|
#include <Tactility/service/loader/Loader.h>
|
||||||
#include "Tactility/service/wifi/Wifi.h"
|
#include <Tactility/service/wifi/Wifi.h>
|
||||||
#include "Tactility/lvgl/LvglSync.h"
|
#include <Tactility/lvgl/LvglSync.h>
|
||||||
|
|
||||||
namespace tt::app::wificonnect {
|
namespace tt::app::wificonnect {
|
||||||
#define TAG "wifi_connect"
|
|
||||||
#define WIFI_CONNECT_PARAM_SSID "ssid" // String
|
constexpr auto* TAG = "WifiConnect";
|
||||||
#define WIFI_CONNECT_PARAM_PASSWORD "password" // String
|
constexpr auto* WIFI_CONNECT_PARAM_SSID = "ssid"; // String
|
||||||
|
constexpr auto* WIFI_CONNECT_PARAM_PASSWORD = "password"; // String
|
||||||
|
|
||||||
extern const AppManifest manifest;
|
extern const AppManifest manifest;
|
||||||
|
|
||||||
static void eventCallback(const void* message, void* context) {
|
|
||||||
auto* event = static_cast<const service::wifi::Event*>(message);
|
|
||||||
auto* wifi = static_cast<WifiConnect*>(context);
|
|
||||||
State& state = wifi->getState();
|
|
||||||
switch (event->type) {
|
|
||||||
case service::wifi::EventType::ConnectionFailed:
|
|
||||||
if (state.isConnecting()) {
|
|
||||||
state.setConnecting(false);
|
|
||||||
state.setConnectionError(true);
|
|
||||||
wifi->requestViewUpdate();
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case service::wifi::EventType::ConnectionSuccess:
|
|
||||||
if (wifi->getState().isConnecting()) {
|
|
||||||
state.setConnecting(false);
|
|
||||||
service::loader::stopApp();
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
wifi->requestViewUpdate();
|
|
||||||
}
|
|
||||||
|
|
||||||
static void onConnect(const service::wifi::settings::WifiApSettings& ap_settings, bool remember, TT_UNUSED void* parameter) {
|
static void onConnect(const service::wifi::settings::WifiApSettings& ap_settings, bool remember, TT_UNUSED void* parameter) {
|
||||||
auto* wifi = static_cast<WifiConnect*>(parameter);
|
auto* wifi = static_cast<WifiConnect*>(parameter);
|
||||||
wifi->getState().setApSettings(ap_settings);
|
wifi->getState().setApSettings(ap_settings);
|
||||||
@ -43,8 +20,33 @@ static void onConnect(const service::wifi::settings::WifiApSettings& ap_settings
|
|||||||
service::wifi::connect(ap_settings, remember);
|
service::wifi::connect(ap_settings, remember);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void WifiConnect::onWifiEvent(service::wifi::WifiEvent event) {
|
||||||
|
State& state = getState();
|
||||||
|
switch (event) {
|
||||||
|
case service::wifi::WifiEvent::ConnectionFailed:
|
||||||
|
if (state.isConnecting()) {
|
||||||
|
state.setConnecting(false);
|
||||||
|
state.setConnectionError(true);
|
||||||
|
requestViewUpdate();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case service::wifi::WifiEvent::ConnectionSuccess:
|
||||||
|
if (getState().isConnecting()) {
|
||||||
|
state.setConnecting(false);
|
||||||
|
service::loader::stopApp();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
requestViewUpdate();
|
||||||
|
}
|
||||||
|
|
||||||
WifiConnect::WifiConnect() {
|
WifiConnect::WifiConnect() {
|
||||||
wifiSubscription = service::wifi::getPubsub()->subscribe(&eventCallback, this);
|
wifiSubscription = service::wifi::getPubsub()->subscribe([this](auto event) {
|
||||||
|
onWifiEvent(event);
|
||||||
|
});
|
||||||
|
|
||||||
bindings = (Bindings) {
|
bindings = (Bindings) {
|
||||||
.onConnectSsid = onConnect,
|
.onConnectSsid = onConnect,
|
||||||
.onConnectSsidContext = this,
|
.onConnectSsidContext = this,
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
#include "Tactility/app/wifimanage/WifiManagePrivate.h"
|
#include <Tactility/app/wifimanage/WifiManagePrivate.h>
|
||||||
|
|
||||||
namespace tt::app::wifimanage {
|
namespace tt::app::wifimanage {
|
||||||
|
|
||||||
|
|||||||
@ -1,9 +1,11 @@
|
|||||||
#include "Tactility/app/wifimanage/View.h"
|
#include <Tactility/app/wifimanage/View.h>
|
||||||
#include "Tactility/app/wifimanage/WifiManagePrivate.h"
|
|
||||||
|
|
||||||
#include "Tactility/lvgl/Style.h"
|
#include <Tactility/Tactility.h>
|
||||||
#include "Tactility/lvgl/Toolbar.h"
|
#include <Tactility/app/wifimanage/WifiManagePrivate.h>
|
||||||
#include "Tactility/lvgl/Spinner.h"
|
|
||||||
|
#include <Tactility/lvgl/Style.h>
|
||||||
|
#include <Tactility/lvgl/Toolbar.h>
|
||||||
|
#include <Tactility/lvgl/Spinner.h>
|
||||||
|
|
||||||
#include <Tactility/Log.h>
|
#include <Tactility/Log.h>
|
||||||
#include <Tactility/service/wifi/Wifi.h>
|
#include <Tactility/service/wifi/Wifi.h>
|
||||||
@ -15,7 +17,7 @@
|
|||||||
|
|
||||||
namespace tt::app::wifimanage {
|
namespace tt::app::wifimanage {
|
||||||
|
|
||||||
#define TAG "wifi_main_view"
|
constexpr auto* TAG = "WifiManageView";
|
||||||
|
|
||||||
std::shared_ptr<WifiManage> _Nullable optWifiManage();
|
std::shared_ptr<WifiManage> _Nullable optWifiManage();
|
||||||
|
|
||||||
@ -49,7 +51,10 @@ static void on_enable_on_boot_switch_changed(lv_event_t* event) {
|
|||||||
auto* enable_switch = static_cast<lv_obj_t*>(lv_event_get_target(event));
|
auto* enable_switch = static_cast<lv_obj_t*>(lv_event_get_target(event));
|
||||||
if (code == LV_EVENT_VALUE_CHANGED) {
|
if (code == LV_EVENT_VALUE_CHANGED) {
|
||||||
bool is_on = lv_obj_has_state(enable_switch, LV_STATE_CHECKED);
|
bool is_on = lv_obj_has_state(enable_switch, LV_STATE_CHECKED);
|
||||||
|
// Dispatch it, so file IO doesn't block the UI
|
||||||
|
getMainDispatcher().dispatch([is_on] {
|
||||||
service::wifi::settings::setEnableOnBoot(is_on);
|
service::wifi::settings::setEnableOnBoot(is_on);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,16 +1,15 @@
|
|||||||
#include "Tactility/app/wifimanage/WifiManagePrivate.h"
|
#include <Tactility/app/wifimanage/WifiManagePrivate.h>
|
||||||
#include "Tactility/app/wifimanage/View.h"
|
#include <Tactility/app/wifimanage/View.h>
|
||||||
|
|
||||||
#include "Tactility/app/AppContext.h"
|
#include <Tactility/app/AppContext.h>
|
||||||
#include "Tactility/app/wifiapsettings/WifiApSettings.h"
|
#include <Tactility/app/wifiapsettings/WifiApSettings.h>
|
||||||
#include "Tactility/service/loader/Loader.h"
|
#include <Tactility/app/wificonnect/WifiConnect.h>
|
||||||
#include "Tactility/service/wifi/WifiSettings.h"
|
#include <Tactility/lvgl/LvglSync.h>
|
||||||
#include "Tactility/lvgl/LvglSync.h"
|
#include <Tactility/service/loader/Loader.h>
|
||||||
#include "Tactility/app/wificonnect/WifiConnect.h"
|
|
||||||
|
|
||||||
namespace tt::app::wifimanage {
|
namespace tt::app::wifimanage {
|
||||||
|
|
||||||
#define TAG "wifi_manage"
|
constexpr auto TAG = "WifiManage";
|
||||||
|
|
||||||
extern const AppManifest manifest;
|
extern const AppManifest manifest;
|
||||||
|
|
||||||
@ -72,20 +71,18 @@ void WifiManage::requestViewUpdate() {
|
|||||||
unlock();
|
unlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void wifiManageEventCallback(const void* message, void* context) {
|
void WifiManage::onWifiEvent(service::wifi::WifiEvent event) {
|
||||||
auto* event = (service::wifi::Event*)message;
|
|
||||||
auto* wifi = (WifiManage*)context;
|
|
||||||
auto radio_state = service::wifi::getRadioState();
|
auto radio_state = service::wifi::getRadioState();
|
||||||
TT_LOG_I(TAG, "Update with state %s", service::wifi::radioStateToString(radio_state));
|
TT_LOG_I(TAG, "Update with state %s", service::wifi::radioStateToString(radio_state));
|
||||||
wifi->getState().setRadioState(radio_state);
|
getState().setRadioState(radio_state);
|
||||||
switch (event->type) {
|
switch (event) {
|
||||||
using enum tt::service::wifi::EventType;
|
using enum service::wifi::WifiEvent;
|
||||||
case ScanStarted:
|
case ScanStarted:
|
||||||
wifi->getState().setScanning(true);
|
getState().setScanning(true);
|
||||||
break;
|
break;
|
||||||
case ScanFinished:
|
case ScanFinished:
|
||||||
wifi->getState().setScanning(false);
|
getState().setScanning(false);
|
||||||
wifi->getState().updateApRecords();
|
getState().updateApRecords();
|
||||||
break;
|
break;
|
||||||
case RadioStateOn:
|
case RadioStateOn:
|
||||||
if (!service::wifi::isScanning()) {
|
if (!service::wifi::isScanning()) {
|
||||||
@ -96,11 +93,13 @@ static void wifiManageEventCallback(const void* message, void* context) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
wifi->requestViewUpdate();
|
requestViewUpdate();
|
||||||
}
|
}
|
||||||
|
|
||||||
void WifiManage::onShow(AppContext& app, lv_obj_t* parent) {
|
void WifiManage::onShow(AppContext& app, lv_obj_t* parent) {
|
||||||
wifiSubscription = service::wifi::getPubsub()->subscribe(&wifiManageEventCallback, this);
|
wifiSubscription = service::wifi::getPubsub()->subscribe([this](auto event) {
|
||||||
|
onWifiEvent(event);
|
||||||
|
});
|
||||||
|
|
||||||
// State update (it has its own locking)
|
// State update (it has its own locking)
|
||||||
state.setRadioState(service::wifi::getRadioState());
|
state.setRadioState(service::wifi::getRadioState());
|
||||||
|
|||||||
@ -21,31 +21,21 @@ bool getKeyValuePair(const std::string& input, std::string& key, std::string& va
|
|||||||
bool loadPropertiesFile(const std::string& filePath, std::function<void(const std::string& key, const std::string& value)> callback) {
|
bool loadPropertiesFile(const std::string& filePath, std::function<void(const std::string& key, const std::string& value)> callback) {
|
||||||
return file::withLock<bool>(filePath, [&filePath, &callback] {
|
return file::withLock<bool>(filePath, [&filePath, &callback] {
|
||||||
TT_LOG_I(TAG, "Reading properties file %s", filePath.c_str());
|
TT_LOG_I(TAG, "Reading properties file %s", filePath.c_str());
|
||||||
const auto input = readString(filePath);
|
|
||||||
if (input == nullptr) {
|
|
||||||
TT_LOG_E(TAG, "Failed to read file contents of %s", filePath.c_str());
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
const auto* input_start = reinterpret_cast<const char*>(input.get());
|
|
||||||
const std::string input_string = input_start;
|
|
||||||
|
|
||||||
uint16_t line_count = 0;
|
uint16_t line_count = 0;
|
||||||
// TODO: Rewrite to use file::readLines()
|
return readLines(filePath, true, [&line_count, &filePath, &callback](const std::string& line) {
|
||||||
string::split(input_string, "\n", [&line_count, &filePath, &callback](auto token) {
|
|
||||||
line_count++;
|
line_count++;
|
||||||
std::string key, value;
|
std::string key, value;
|
||||||
auto trimmed_token = string::trim(token, " \t");
|
auto trimmed_line = string::trim(line, " \t");
|
||||||
if (!trimmed_token.starts_with("#")) {
|
if (!trimmed_line.starts_with("#")) {
|
||||||
if (getKeyValuePair(token, key, value)) {
|
if (getKeyValuePair(trimmed_line, key, value)) {
|
||||||
std::string trimmed_key = string::trim(key, " \t");
|
std::string trimmed_key = string::trim(key, " \t");
|
||||||
std::string trimmed_value = string::trim(value, " \t");
|
std::string trimmed_value = string::trim(value, " \t");
|
||||||
callback(trimmed_key, trimmed_value);
|
callback(trimmed_key, trimmed_value);
|
||||||
} else { TT_LOG_E(TAG, "Failed to parse line %d of %s", line_count, filePath.c_str()); }
|
} else {
|
||||||
|
TT_LOG_E(TAG, "Failed to parse line %d of %s", line_count, filePath.c_str());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
return true;
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,3 +1,4 @@
|
|||||||
|
#include "Tactility/Tactility.h"
|
||||||
#include "Tactility/hal/Configuration.h"
|
#include "Tactility/hal/Configuration.h"
|
||||||
#include "Tactility/hal/Device.h"
|
#include "Tactility/hal/Device.h"
|
||||||
#include "Tactility/hal/gps/GpsInit.h"
|
#include "Tactility/hal/gps/GpsInit.h"
|
||||||
@ -10,7 +11,7 @@
|
|||||||
|
|
||||||
namespace tt::hal {
|
namespace tt::hal {
|
||||||
|
|
||||||
constexpr auto* TAG = "hal";
|
constexpr auto* TAG = "Hal";
|
||||||
|
|
||||||
void registerDevices(const Configuration& configuration) {
|
void registerDevices(const Configuration& configuration) {
|
||||||
TT_LOG_I(TAG, "Registering devices");
|
TT_LOG_I(TAG, "Registering devices");
|
||||||
@ -62,4 +63,8 @@ void init(const Configuration& configuration) {
|
|||||||
kernel::publishSystemEvent(kernel::SystemEvent::BootInitHalEnd);
|
kernel::publishSystemEvent(kernel::SystemEvent::BootInitHalEnd);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const Configuration* getConfiguration() {
|
||||||
|
return tt::getConfiguration()->hardware;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|||||||
@ -5,13 +5,13 @@
|
|||||||
|
|
||||||
#include <ranges>
|
#include <ranges>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
#include <Tactility/TactilityHeadless.h>
|
||||||
|
|
||||||
#ifdef ESP_PLATFORM
|
#ifdef ESP_PLATFORM
|
||||||
#include "Tactility/TactilityHeadless.h"
|
#include <Tactility/hal/uart/UartEsp.h>
|
||||||
#include "Tactility/hal/uart/UartEsp.h"
|
|
||||||
#include <esp_check.h>
|
#include <esp_check.h>
|
||||||
#else
|
#else
|
||||||
#include "Tactility/hal/uart/UartPosix.h"
|
#include <Tactility/hal/uart/UartPosix.h>
|
||||||
#include <dirent.h>
|
#include <dirent.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -29,7 +29,7 @@ struct UartEntry {
|
|||||||
static std::vector<UartEntry> uartEntries = {};
|
static std::vector<UartEntry> uartEntries = {};
|
||||||
static uint32_t lastUartId = uartIdNotInUse;
|
static uint32_t lastUartId = uartIdNotInUse;
|
||||||
|
|
||||||
bool init(const std::vector<uart::Configuration>& configurations) {
|
bool init(const std::vector<Configuration>& configurations) {
|
||||||
TT_LOG_I(TAG, "Init");
|
TT_LOG_I(TAG, "Init");
|
||||||
for (const auto& configuration: configurations) {
|
for (const auto& configuration: configurations) {
|
||||||
uartEntries.push_back({
|
uartEntries.push_back({
|
||||||
@ -142,7 +142,7 @@ void close(uint32_t uartId) {
|
|||||||
std::vector<std::string> getNames() {
|
std::vector<std::string> getNames() {
|
||||||
std::vector<std::string> names;
|
std::vector<std::string> names;
|
||||||
#ifdef ESP_PLATFORM
|
#ifdef ESP_PLATFORM
|
||||||
for (auto& config : getConfiguration()->uart) {
|
for (auto& config : hal::getConfiguration()->uart) {
|
||||||
names.push_back(config.name);
|
names.push_back(config.name);
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
|
|||||||
@ -1,17 +1,15 @@
|
|||||||
#ifdef ESP_PLATFORM
|
#ifdef ESP_PLATFORM
|
||||||
|
|
||||||
#include "Tactility/hal/usb/Usb.h"
|
#include <Tactility/hal/usb/Usb.h>
|
||||||
#include "Tactility/TactilityHeadless.h"
|
#include <Tactility/hal/sdcard/SpiSdCardDevice.h>
|
||||||
#include "Tactility/hal/sdcard/SpiSdCardDevice.h"
|
#include <Tactility/hal/usb/UsbTusb.h>
|
||||||
#include "Tactility/hal/usb/UsbTusb.h"
|
|
||||||
|
|
||||||
#include <Tactility/Log.h>
|
#include <Tactility/Log.h>
|
||||||
|
|
||||||
namespace tt::hal::usb {
|
namespace tt::hal::usb {
|
||||||
|
|
||||||
#define TAG "usb"
|
constexpr auto* TAG = "usb";
|
||||||
|
constexpr auto BOOT_FLAG = 42;
|
||||||
#define BOOT_FLAG 42
|
|
||||||
|
|
||||||
struct BootMode {
|
struct BootMode {
|
||||||
uint32_t flag = 0;
|
uint32_t flag = 0;
|
||||||
|
|||||||
@ -9,7 +9,6 @@
|
|||||||
#include <Tactility/kernel/SystemEvents.h>
|
#include <Tactility/kernel/SystemEvents.h>
|
||||||
#include <Tactility/service/ServiceRegistration.h>
|
#include <Tactility/service/ServiceRegistration.h>
|
||||||
#include <Tactility/settings/DisplaySettings.h>
|
#include <Tactility/settings/DisplaySettings.h>
|
||||||
#include <Tactility/TactilityHeadless.h>
|
|
||||||
|
|
||||||
#ifdef ESP_PLATFORM
|
#ifdef ESP_PLATFORM
|
||||||
#include <Tactility/lvgl/EspLvglPort.h>
|
#include <Tactility/lvgl/EspLvglPort.h>
|
||||||
|
|||||||
@ -28,9 +28,9 @@ struct StatusbarIcon {
|
|||||||
|
|
||||||
struct StatusbarData {
|
struct StatusbarData {
|
||||||
Mutex mutex = Mutex(Mutex::Type::Recursive);
|
Mutex mutex = Mutex(Mutex::Type::Recursive);
|
||||||
std::shared_ptr<PubSub> pubsub = std::make_shared<PubSub>();
|
std::shared_ptr<PubSub<void*>> pubsub = std::make_shared<PubSub<void*>>();
|
||||||
StatusbarIcon icons[STATUSBAR_ICON_LIMIT] = {};
|
StatusbarIcon icons[STATUSBAR_ICON_LIMIT] = {};
|
||||||
Timer* time_update_timer = new Timer(Timer::Type::Once, []() { onUpdateTime(); });
|
Timer* time_update_timer = new Timer(Timer::Type::Once, [] { onUpdateTime(); });
|
||||||
uint8_t time_hours = 0;
|
uint8_t time_hours = 0;
|
||||||
uint8_t time_minutes = 0;
|
uint8_t time_minutes = 0;
|
||||||
bool time_set = false;
|
bool time_set = false;
|
||||||
@ -44,7 +44,7 @@ typedef struct {
|
|||||||
lv_obj_t* time;
|
lv_obj_t* time;
|
||||||
lv_obj_t* icons[STATUSBAR_ICON_LIMIT];
|
lv_obj_t* icons[STATUSBAR_ICON_LIMIT];
|
||||||
lv_obj_t* battery_icon;
|
lv_obj_t* battery_icon;
|
||||||
PubSub::SubscriptionHandle pubsub_subscription;
|
PubSub<void*>::SubscriptionHandle pubsub_subscription;
|
||||||
} Statusbar;
|
} Statusbar;
|
||||||
|
|
||||||
static bool statusbar_lock(TickType_t timeoutTicks = portMAX_DELAY) {
|
static bool statusbar_lock(TickType_t timeoutTicks = portMAX_DELAY) {
|
||||||
@ -108,9 +108,8 @@ static const lv_obj_class_t statusbar_class = {
|
|||||||
.theme_inheritable = false
|
.theme_inheritable = false
|
||||||
};
|
};
|
||||||
|
|
||||||
static void statusbar_pubsub_event(TT_UNUSED const void* message, void* obj) {
|
static void statusbar_pubsub_event(Statusbar* statusbar) {
|
||||||
TT_LOG_D(TAG, "event");
|
TT_LOG_D(TAG, "Update event");
|
||||||
auto* statusbar = static_cast<Statusbar*>(obj);
|
|
||||||
if (lock(portMAX_DELAY)) {
|
if (lock(portMAX_DELAY)) {
|
||||||
update_main(statusbar);
|
update_main(statusbar);
|
||||||
lv_obj_invalidate(&statusbar->obj);
|
lv_obj_invalidate(&statusbar->obj);
|
||||||
@ -133,7 +132,9 @@ static void statusbar_constructor(const lv_obj_class_t* class_p, lv_obj_t* obj)
|
|||||||
lv_obj_remove_flag(obj, LV_OBJ_FLAG_SCROLLABLE);
|
lv_obj_remove_flag(obj, LV_OBJ_FLAG_SCROLLABLE);
|
||||||
LV_TRACE_OBJ_CREATE("finished");
|
LV_TRACE_OBJ_CREATE("finished");
|
||||||
auto* statusbar = (Statusbar*)obj;
|
auto* statusbar = (Statusbar*)obj;
|
||||||
statusbar->pubsub_subscription = statusbar_data.pubsub->subscribe(&statusbar_pubsub_event, statusbar);
|
statusbar->pubsub_subscription = statusbar_data.pubsub->subscribe([statusbar](auto) {
|
||||||
|
statusbar_pubsub_event(statusbar);
|
||||||
|
});
|
||||||
|
|
||||||
if (!statusbar_data.time_update_timer->isRunning()) {
|
if (!statusbar_data.time_update_timer->isRunning()) {
|
||||||
statusbar_data.time_update_timer->start(200 / portTICK_PERIOD_MS);
|
statusbar_data.time_update_timer->start(200 / portTICK_PERIOD_MS);
|
||||||
|
|||||||
@ -13,7 +13,6 @@
|
|||||||
#include <Tactility/service/ServiceRegistration.h>
|
#include <Tactility/service/ServiceRegistration.h>
|
||||||
#include <Tactility/service/wifi/Wifi.h>
|
#include <Tactility/service/wifi/Wifi.h>
|
||||||
#include <Tactility/StringUtils.h>
|
#include <Tactility/StringUtils.h>
|
||||||
#include <Tactility/TactilityHeadless.h>
|
|
||||||
|
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <esp_wifi.h>
|
#include <esp_wifi.h>
|
||||||
|
|||||||
@ -1,10 +1,11 @@
|
|||||||
#ifdef ESP_PLATFORM
|
#ifdef ESP_PLATFORM
|
||||||
|
|
||||||
#include "Tactility/service/espnow/EspNowService.h"
|
#include <Tactility/Tactility.h>
|
||||||
#include "Tactility/TactilityHeadless.h"
|
#include <Tactility/service/espnow/EspNowService.h>
|
||||||
#include "Tactility/service/ServiceManifest.h"
|
#include <Tactility/service/ServiceManifest.h>
|
||||||
#include "Tactility/service/ServiceRegistration.h"
|
#include <Tactility/service/ServiceRegistration.h>
|
||||||
#include "Tactility/service/espnow/EspNowWifi.h"
|
#include <Tactility/service/espnow/EspNowWifi.h>
|
||||||
|
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <esp_now.h>
|
#include <esp_now.h>
|
||||||
#include <esp_random.h>
|
#include <esp_random.h>
|
||||||
|
|||||||
@ -208,7 +208,7 @@ void GpsService::setState(State newState) {
|
|||||||
lock.lock();
|
lock.lock();
|
||||||
state = newState;
|
state = newState;
|
||||||
lock.unlock();
|
lock.unlock();
|
||||||
statePubSub->publish(&state);
|
statePubSub->publish(state);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GpsService::hasCoordinates() const {
|
bool GpsService::hasCoordinates() const {
|
||||||
|
|||||||
@ -12,22 +12,16 @@ namespace tt::service::gui {
|
|||||||
|
|
||||||
extern const ServiceManifest manifest;
|
extern const ServiceManifest manifest;
|
||||||
|
|
||||||
constexpr const char* TAG = "gui";
|
constexpr auto* TAG = "GuiService";
|
||||||
|
|
||||||
// region AppManifest
|
// region AppManifest
|
||||||
|
|
||||||
void GuiService::onLoaderMessage(const void* message, TT_UNUSED void* context) {
|
void GuiService::onLoaderEvent(loader::LoaderEvent event) {
|
||||||
auto service = findService();
|
if (event == loader::LoaderEvent::ApplicationShowing) {
|
||||||
if (service == nullptr) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto* event = static_cast<const loader::LoaderEvent*>(message);
|
|
||||||
if (event->type == loader::LoaderEventTypeApplicationShowing) {
|
|
||||||
auto app_instance = app::getCurrentAppContext();
|
auto app_instance = app::getCurrentAppContext();
|
||||||
service->showApp(app_instance);
|
showApp(app_instance);
|
||||||
} else if (event->type == loader::LoaderEventTypeApplicationHiding) {
|
} else if (event == loader::LoaderEvent::ApplicationHiding) {
|
||||||
service->hideApp();
|
hideApp();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -124,7 +118,12 @@ void GuiService::onStart(TT_UNUSED ServiceContext& service) {
|
|||||||
4096, // Last known minimum was 2800 for launching desktop
|
4096, // Last known minimum was 2800 for launching desktop
|
||||||
[]() { return guiMain(); }
|
[]() { return guiMain(); }
|
||||||
);
|
);
|
||||||
loader_pubsub_subscription = loader::getPubsub()->subscribe(&onLoaderMessage, nullptr);
|
|
||||||
|
loader_pubsub_subscription = loader::getPubsub()->subscribe([this](auto event) {
|
||||||
|
onLoaderEvent(event);
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
tt_check(lvgl::lock(1000 / portTICK_PERIOD_MS));
|
tt_check(lvgl::lock(1000 / portTICK_PERIOD_MS));
|
||||||
keyboardGroup = lv_group_create();
|
keyboardGroup = lv_group_create();
|
||||||
auto* screen_root = lv_screen_active();
|
auto* screen_root = lv_screen_active();
|
||||||
|
|||||||
@ -3,7 +3,6 @@
|
|||||||
#include "Tactility/app/AppManifest.h"
|
#include "Tactility/app/AppManifest.h"
|
||||||
#include "Tactility/app/AppRegistration.h"
|
#include "Tactility/app/AppRegistration.h"
|
||||||
|
|
||||||
#include <Tactility/RtosCompat.h>
|
|
||||||
#include <Tactility/DispatcherThread.h>
|
#include <Tactility/DispatcherThread.h>
|
||||||
#include <Tactility/service/ServiceManifest.h>
|
#include <Tactility/service/ServiceManifest.h>
|
||||||
#include <Tactility/service/ServiceRegistration.h>
|
#include <Tactility/service/ServiceRegistration.h>
|
||||||
@ -11,7 +10,6 @@
|
|||||||
#include <stack>
|
#include <stack>
|
||||||
|
|
||||||
#ifdef ESP_PLATFORM
|
#ifdef ESP_PLATFORM
|
||||||
#include <Tactility/TactilityHeadless.h>
|
|
||||||
#include <esp_heap_caps.h>
|
#include <esp_heap_caps.h>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
#else
|
#else
|
||||||
@ -20,8 +18,8 @@
|
|||||||
|
|
||||||
namespace tt::service::loader {
|
namespace tt::service::loader {
|
||||||
|
|
||||||
#define TAG "loader"
|
constexpr auto* TAG = "Loader";
|
||||||
#define LOADER_TIMEOUT (100 / portTICK_PERIOD_MS)
|
constexpr auto LOADER_TIMEOUT = (100 / portTICK_PERIOD_MS);
|
||||||
|
|
||||||
extern const ServiceManifest manifest;
|
extern const ServiceManifest manifest;
|
||||||
|
|
||||||
@ -47,7 +45,7 @@ static const char* appStateToString(app::State state) {
|
|||||||
|
|
||||||
class LoaderService final : public Service {
|
class LoaderService final : public Service {
|
||||||
|
|
||||||
std::shared_ptr<PubSub> pubsubExternal = std::make_shared<PubSub>();
|
std::shared_ptr<PubSub<LoaderEvent>> pubsubExternal = std::make_shared<PubSub<LoaderEvent>>();
|
||||||
Mutex mutex = Mutex(Mutex::Type::Recursive);
|
Mutex mutex = Mutex(Mutex::Type::Recursive);
|
||||||
std::stack<std::shared_ptr<app::AppInstance>> appStack;
|
std::stack<std::shared_ptr<app::AppInstance>> appStack;
|
||||||
app::LaunchId nextLaunchId = 0;
|
app::LaunchId nextLaunchId = 0;
|
||||||
@ -64,13 +62,13 @@ class LoaderService final : public Service {
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
void onStart(TT_UNUSED ServiceContext& service) final {
|
void onStart(TT_UNUSED ServiceContext& service) override {
|
||||||
dispatcherThread->start();
|
dispatcherThread->start();
|
||||||
}
|
}
|
||||||
|
|
||||||
void onStop(TT_UNUSED ServiceContext& service) final {
|
void onStop(TT_UNUSED ServiceContext& service) override {
|
||||||
// Send stop signal to thread and wait for thread to finish
|
// Send stop signal to thread and wait for thread to finish
|
||||||
mutex.withLock([this]() {
|
mutex.withLock([this] {
|
||||||
dispatcherThread->stop();
|
dispatcherThread->stop();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -79,7 +77,7 @@ public:
|
|||||||
void stopApp();
|
void stopApp();
|
||||||
std::shared_ptr<app::AppContext> _Nullable getCurrentAppContext();
|
std::shared_ptr<app::AppContext> _Nullable getCurrentAppContext();
|
||||||
|
|
||||||
std::shared_ptr<PubSub> getPubsub() const { return pubsubExternal; }
|
std::shared_ptr<PubSub<LoaderEvent>> getPubsub() const { return pubsubExternal; }
|
||||||
};
|
};
|
||||||
|
|
||||||
std::shared_ptr<LoaderService> _Nullable optScreenshotService() {
|
std::shared_ptr<LoaderService> _Nullable optScreenshotService() {
|
||||||
@ -117,8 +115,7 @@ void LoaderService::onStartAppMessage(const std::string& id, app::LaunchId launc
|
|||||||
|
|
||||||
transitionAppToState(new_app, app::State::Showing);
|
transitionAppToState(new_app, app::State::Showing);
|
||||||
|
|
||||||
LoaderEvent event_external = { .type = LoaderEventTypeApplicationStarted };
|
pubsubExternal->publish(LoaderEvent::ApplicationStarted);
|
||||||
pubsubExternal->publish(&event_external);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void LoaderService::onStopAppMessage(const std::string& id) {
|
void LoaderService::onStopAppMessage(const std::string& id) {
|
||||||
@ -188,8 +185,7 @@ void LoaderService::onStopAppMessage(const std::string& id) {
|
|||||||
lock.unlock();
|
lock.unlock();
|
||||||
// WARNING: After this point we cannot change the app states from this method directly anymore as we don't have a lock!
|
// WARNING: After this point we cannot change the app states from this method directly anymore as we don't have a lock!
|
||||||
|
|
||||||
LoaderEvent event_external = { .type = LoaderEventTypeApplicationStopped };
|
pubsubExternal->publish(LoaderEvent::ApplicationStopped);
|
||||||
pubsubExternal->publish(&event_external);
|
|
||||||
|
|
||||||
if (instance_to_resume != nullptr) {
|
if (instance_to_resume != nullptr) {
|
||||||
if (result_set) {
|
if (result_set) {
|
||||||
@ -240,13 +236,11 @@ void LoaderService::transitionAppToState(const std::shared_ptr<app::AppInstance>
|
|||||||
app->getApp()->onCreate(*app);
|
app->getApp()->onCreate(*app);
|
||||||
break;
|
break;
|
||||||
case Showing: {
|
case Showing: {
|
||||||
LoaderEvent event_showing = { .type = LoaderEventTypeApplicationShowing };
|
pubsubExternal->publish(LoaderEvent::ApplicationShowing);
|
||||||
pubsubExternal->publish(&event_showing);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case Hiding: {
|
case Hiding: {
|
||||||
LoaderEvent event_hiding = { .type = LoaderEventTypeApplicationHiding };
|
pubsubExternal->publish(LoaderEvent::ApplicationHiding);
|
||||||
pubsubExternal->publish(&event_hiding);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case Stopped:
|
case Stopped:
|
||||||
@ -307,7 +301,7 @@ std::shared_ptr<app::App> _Nullable getCurrentApp() {
|
|||||||
return app_context != nullptr ? app_context->getApp() : nullptr;
|
return app_context != nullptr ? app_context->getApp() : nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<PubSub> getPubsub() {
|
std::shared_ptr<PubSub<LoaderEvent>> getPubsub() {
|
||||||
auto service = optScreenshotService();
|
auto service = optScreenshotService();
|
||||||
assert(service);
|
assert(service);
|
||||||
return service->getPubsub();
|
return service->getPubsub();
|
||||||
|
|||||||
@ -1,14 +1,14 @@
|
|||||||
#include "Tactility/service/ServiceContext.h"
|
#include <Tactility/service/ServiceContext.h>
|
||||||
#include "Tactility/TactilityHeadless.h"
|
#include <Tactility/service/ServiceRegistration.h>
|
||||||
#include "Tactility/service/ServiceRegistration.h"
|
|
||||||
|
|
||||||
#include <Tactility/Mutex.h>
|
#include <Tactility/Mutex.h>
|
||||||
#include <Tactility/Timer.h>
|
#include <Tactility/Timer.h>
|
||||||
|
#include <Tactility/hal/sdcard/SdCardDevice.h>
|
||||||
#define TAG "sdcard_service"
|
|
||||||
|
|
||||||
namespace tt::service::sdcard {
|
namespace tt::service::sdcard {
|
||||||
|
|
||||||
|
constexpr auto* TAG = "SdcardService";
|
||||||
|
|
||||||
extern const ServiceManifest manifest;
|
extern const ServiceManifest manifest;
|
||||||
|
|
||||||
class SdCardService final : public Service {
|
class SdCardService final : public Service {
|
||||||
|
|||||||
@ -6,7 +6,6 @@
|
|||||||
#include "Tactility/service/gps/GpsService.h"
|
#include "Tactility/service/gps/GpsService.h"
|
||||||
#include <Tactility/Mutex.h>
|
#include <Tactility/Mutex.h>
|
||||||
#include <Tactility/Tactility.h>
|
#include <Tactility/Tactility.h>
|
||||||
#include <Tactility/TactilityHeadless.h>
|
|
||||||
#include <Tactility/Timer.h>
|
#include <Tactility/Timer.h>
|
||||||
#include <Tactility/service/ServiceContext.h>
|
#include <Tactility/service/ServiceContext.h>
|
||||||
#include <Tactility/service/ServiceRegistration.h>
|
#include <Tactility/service/ServiceRegistration.h>
|
||||||
@ -14,7 +13,7 @@
|
|||||||
|
|
||||||
namespace tt::service::statusbar {
|
namespace tt::service::statusbar {
|
||||||
|
|
||||||
#define TAG "statusbar_service"
|
constexpr auto* TAG = "StatusbarService";
|
||||||
|
|
||||||
// SD card status
|
// SD card status
|
||||||
#define STATUSBAR_ICON_SDCARD "sdcard.png"
|
#define STATUSBAR_ICON_SDCARD "sdcard.png"
|
||||||
|
|||||||
@ -1,14 +1,14 @@
|
|||||||
#ifdef ESP_PLATFORM
|
#ifdef ESP_PLATFORM
|
||||||
|
|
||||||
#include "Tactility/service/wifi/Wifi.h"
|
#include <Tactility/service/wifi/Wifi.h>
|
||||||
|
|
||||||
#include "Tactility/TactilityHeadless.h"
|
|
||||||
#include "Tactility/service/ServiceContext.h"
|
|
||||||
#include "Tactility/service/wifi/WifiGlobals.h"
|
|
||||||
#include "Tactility/service/wifi/WifiSettings.h"
|
|
||||||
#include "Tactility/service/wifi/WifiBootSplashInit.h"
|
|
||||||
|
|
||||||
|
#include <Tactility/EventFlag.h>
|
||||||
|
#include <Tactility/Tactility.h>
|
||||||
#include <Tactility/kernel/SystemEvents.h>
|
#include <Tactility/kernel/SystemEvents.h>
|
||||||
|
#include <Tactility/service/ServiceContext.h>
|
||||||
|
#include <Tactility/service/wifi/WifiGlobals.h>
|
||||||
|
#include <Tactility/service/wifi/WifiSettings.h>
|
||||||
|
#include <Tactility/service/wifi/WifiBootSplashInit.h>
|
||||||
#include <Tactility/Timer.h>
|
#include <Tactility/Timer.h>
|
||||||
|
|
||||||
#include <lwip/esp_netif_net_stack.h>
|
#include <lwip/esp_netif_net_stack.h>
|
||||||
@ -19,10 +19,10 @@
|
|||||||
|
|
||||||
namespace tt::service::wifi {
|
namespace tt::service::wifi {
|
||||||
|
|
||||||
#define TAG "wifi_service"
|
constexpr auto* TAG = "WifiService";
|
||||||
#define WIFI_CONNECTED_BIT BIT0
|
constexpr auto WIFI_CONNECTED_BIT = BIT0;
|
||||||
#define WIFI_FAIL_BIT BIT1
|
constexpr auto WIFI_FAIL_BIT = BIT1;
|
||||||
#define AUTO_SCAN_INTERVAL 10000 // ms
|
constexpr auto AUTO_SCAN_INTERVAL = 10000; // ms
|
||||||
|
|
||||||
// Forward declarations
|
// Forward declarations
|
||||||
class Wifi;
|
class Wifi;
|
||||||
@ -48,7 +48,7 @@ public:
|
|||||||
Mutex dataMutex = Mutex(Mutex::Type::Recursive);
|
Mutex dataMutex = Mutex(Mutex::Type::Recursive);
|
||||||
std::unique_ptr<Timer> autoConnectTimer;
|
std::unique_ptr<Timer> autoConnectTimer;
|
||||||
/** @brief The public event bus */
|
/** @brief The public event bus */
|
||||||
std::shared_ptr<PubSub> pubsub = std::make_shared<PubSub>();
|
std::shared_ptr<PubSub<WifiEvent>> pubsub = std::make_shared<PubSub<WifiEvent>>();
|
||||||
// TODO: Deal with messages that come in while an action is ongoing
|
// TODO: Deal with messages that come in while an action is ongoing
|
||||||
// for example: when scanning and you turn off the radio, the scan should probably stop or turning off
|
// for example: when scanning and you turn off the radio, the scan should probably stop or turning off
|
||||||
// the radio should disable the on/off button in the app as it is pending.
|
// the radio should disable the on/off button in the app as it is pending.
|
||||||
@ -129,7 +129,7 @@ static std::shared_ptr<Wifi> wifi_singleton;
|
|||||||
|
|
||||||
// region Public functions
|
// region Public functions
|
||||||
|
|
||||||
std::shared_ptr<PubSub> getPubsub() {
|
std::shared_ptr<PubSub<WifiEvent>> getPubsub() {
|
||||||
auto wifi = wifi_singleton;
|
auto wifi = wifi_singleton;
|
||||||
if (wifi == nullptr) {
|
if (wifi == nullptr) {
|
||||||
tt_crash("Service not running");
|
tt_crash("Service not running");
|
||||||
@ -371,11 +371,10 @@ static void scan_list_free_safely(std::shared_ptr<Wifi> wifi) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void publish_event_simple(std::shared_ptr<Wifi> wifi, EventType type) {
|
static void publish_event(std::shared_ptr<Wifi> wifi, WifiEvent event) {
|
||||||
auto lock = wifi->dataMutex.asScopedLock();
|
auto lock = wifi->dataMutex.asScopedLock();
|
||||||
if (lock.lock()) {
|
if (lock.lock()) {
|
||||||
Event turning_on_event = {.type = type};
|
wifi->pubsub->publish(event);
|
||||||
wifi->pubsub->publish(&turning_on_event);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -484,7 +483,7 @@ static void eventHandler(TT_UNUSED void* arg, esp_event_base_t event_base, int32
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
wifi->setRadioState(RadioState::On);
|
wifi->setRadioState(RadioState::On);
|
||||||
publish_event_simple(wifi, EventType::Disconnected);
|
publish_event(wifi, WifiEvent::Disconnected);
|
||||||
kernel::publishSystemEvent(kernel::SystemEvent::NetworkDisconnected);
|
kernel::publishSystemEvent(kernel::SystemEvent::NetworkDisconnected);
|
||||||
} else if (event_base == IP_EVENT && event_id == IP_EVENT_STA_GOT_IP) {
|
} else if (event_base == IP_EVENT && event_id == IP_EVENT_STA_GOT_IP) {
|
||||||
auto* event = static_cast<ip_event_got_ip_t*>(event_data);
|
auto* event = static_cast<ip_event_got_ip_t*>(event_data);
|
||||||
@ -511,7 +510,7 @@ static void eventHandler(TT_UNUSED void* arg, esp_event_base_t event_base, int32
|
|||||||
esp_wifi_scan_stop();
|
esp_wifi_scan_stop();
|
||||||
}
|
}
|
||||||
|
|
||||||
publish_event_simple(wifi_singleton, EventType::ScanFinished);
|
publish_event(wifi_singleton, WifiEvent::ScanFinished);
|
||||||
TT_LOG_I(TAG, "eventHandler: Finished scan");
|
TT_LOG_I(TAG, "eventHandler: Finished scan");
|
||||||
|
|
||||||
if (copied_list && wifi_singleton->getRadioState() == RadioState::On && !wifi->pause_auto_connect) {
|
if (copied_list && wifi_singleton->getRadioState() == RadioState::On && !wifi->pause_auto_connect) {
|
||||||
@ -537,7 +536,7 @@ static void dispatchEnable(std::shared_ptr<Wifi> wifi) {
|
|||||||
if (lock.lock(50 / portTICK_PERIOD_MS)) {
|
if (lock.lock(50 / portTICK_PERIOD_MS)) {
|
||||||
TT_LOG_I(TAG, "Enabling");
|
TT_LOG_I(TAG, "Enabling");
|
||||||
wifi->setRadioState(RadioState::OnPending);
|
wifi->setRadioState(RadioState::OnPending);
|
||||||
publish_event_simple(wifi, EventType::RadioStateOnPending);
|
publish_event(wifi, WifiEvent::RadioStateOnPending);
|
||||||
|
|
||||||
if (wifi->netif != nullptr) {
|
if (wifi->netif != nullptr) {
|
||||||
esp_netif_destroy(wifi->netif);
|
esp_netif_destroy(wifi->netif);
|
||||||
@ -554,7 +553,7 @@ static void dispatchEnable(std::shared_ptr<Wifi> wifi) {
|
|||||||
TT_LOG_E(TAG, "Insufficient memory");
|
TT_LOG_E(TAG, "Insufficient memory");
|
||||||
}
|
}
|
||||||
wifi->setRadioState(RadioState::Off);
|
wifi->setRadioState(RadioState::Off);
|
||||||
publish_event_simple(wifi, EventType::RadioStateOff);
|
publish_event(wifi, WifiEvent::RadioStateOff);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -582,7 +581,7 @@ static void dispatchEnable(std::shared_ptr<Wifi> wifi) {
|
|||||||
TT_LOG_E(TAG, "Wifi mode setting failed");
|
TT_LOG_E(TAG, "Wifi mode setting failed");
|
||||||
wifi->setRadioState(RadioState::Off);
|
wifi->setRadioState(RadioState::Off);
|
||||||
esp_wifi_deinit();
|
esp_wifi_deinit();
|
||||||
publish_event_simple(wifi, EventType::RadioStateOff);
|
publish_event(wifi, WifiEvent::RadioStateOff);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -595,12 +594,12 @@ static void dispatchEnable(std::shared_ptr<Wifi> wifi) {
|
|||||||
wifi->setRadioState(RadioState::Off);
|
wifi->setRadioState(RadioState::Off);
|
||||||
esp_wifi_set_mode(WIFI_MODE_NULL);
|
esp_wifi_set_mode(WIFI_MODE_NULL);
|
||||||
esp_wifi_deinit();
|
esp_wifi_deinit();
|
||||||
publish_event_simple(wifi, EventType::RadioStateOff);
|
publish_event(wifi, WifiEvent::RadioStateOff);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
wifi->setRadioState(RadioState::On);
|
wifi->setRadioState(RadioState::On);
|
||||||
publish_event_simple(wifi, EventType::RadioStateOn);
|
publish_event(wifi, WifiEvent::RadioStateOn);
|
||||||
|
|
||||||
wifi->pause_auto_connect = false;
|
wifi->pause_auto_connect = false;
|
||||||
|
|
||||||
@ -631,7 +630,7 @@ static void dispatchDisable(std::shared_ptr<Wifi> wifi) {
|
|||||||
|
|
||||||
TT_LOG_I(TAG, "Disabling");
|
TT_LOG_I(TAG, "Disabling");
|
||||||
wifi->setRadioState(RadioState::OffPending);
|
wifi->setRadioState(RadioState::OffPending);
|
||||||
publish_event_simple(wifi, EventType::RadioStateOffPending);
|
publish_event(wifi, WifiEvent::RadioStateOffPending);
|
||||||
|
|
||||||
// Free up scan list memory
|
// Free up scan list memory
|
||||||
scan_list_free_safely(wifi_singleton);
|
scan_list_free_safely(wifi_singleton);
|
||||||
@ -639,7 +638,7 @@ static void dispatchDisable(std::shared_ptr<Wifi> wifi) {
|
|||||||
if (esp_wifi_stop() != ESP_OK) {
|
if (esp_wifi_stop() != ESP_OK) {
|
||||||
TT_LOG_E(TAG, "Failed to stop radio");
|
TT_LOG_E(TAG, "Failed to stop radio");
|
||||||
wifi->setRadioState(RadioState::On);
|
wifi->setRadioState(RadioState::On);
|
||||||
publish_event_simple(wifi, EventType::RadioStateOn);
|
publish_event(wifi, WifiEvent::RadioStateOn);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -672,7 +671,7 @@ static void dispatchDisable(std::shared_ptr<Wifi> wifi) {
|
|||||||
wifi->netif = nullptr;
|
wifi->netif = nullptr;
|
||||||
wifi->setScanActive(false);
|
wifi->setScanActive(false);
|
||||||
wifi->setRadioState(RadioState::Off);
|
wifi->setRadioState(RadioState::Off);
|
||||||
publish_event_simple(wifi, EventType::RadioStateOff);
|
publish_event(wifi, WifiEvent::RadioStateOff);
|
||||||
TT_LOG_I(TAG, "Disabled");
|
TT_LOG_I(TAG, "Disabled");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -706,7 +705,7 @@ static void dispatchScan(std::shared_ptr<Wifi> wifi) {
|
|||||||
|
|
||||||
TT_LOG_I(TAG, "Starting scan");
|
TT_LOG_I(TAG, "Starting scan");
|
||||||
wifi->setScanActive(true);
|
wifi->setScanActive(true);
|
||||||
publish_event_simple(wifi, EventType::ScanStarted);
|
publish_event(wifi, WifiEvent::ScanStarted);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void dispatchConnect(std::shared_ptr<Wifi> wifi) {
|
static void dispatchConnect(std::shared_ptr<Wifi> wifi) {
|
||||||
@ -740,7 +739,7 @@ static void dispatchConnect(std::shared_ptr<Wifi> wifi) {
|
|||||||
|
|
||||||
wifi->setRadioState(RadioState::ConnectionPending);
|
wifi->setRadioState(RadioState::ConnectionPending);
|
||||||
|
|
||||||
publish_event_simple(wifi, EventType::ConnectionPending);
|
publish_event(wifi, WifiEvent::ConnectionPending);
|
||||||
|
|
||||||
wifi_config_t config;
|
wifi_config_t config;
|
||||||
memset(&config, 0, sizeof(wifi_config_t));
|
memset(&config, 0, sizeof(wifi_config_t));
|
||||||
@ -762,7 +761,7 @@ static void dispatchConnect(std::shared_ptr<Wifi> wifi) {
|
|||||||
if (set_config_result != ESP_OK) {
|
if (set_config_result != ESP_OK) {
|
||||||
wifi->setRadioState(RadioState::On);
|
wifi->setRadioState(RadioState::On);
|
||||||
TT_LOG_E(TAG, "Failed to set wifi config (%s)", esp_err_to_name(set_config_result));
|
TT_LOG_E(TAG, "Failed to set wifi config (%s)", esp_err_to_name(set_config_result));
|
||||||
publish_event_simple(wifi, EventType::ConnectionFailed);
|
publish_event(wifi, WifiEvent::ConnectionFailed);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -771,7 +770,7 @@ static void dispatchConnect(std::shared_ptr<Wifi> wifi) {
|
|||||||
if (wifi_start_result != ESP_OK) {
|
if (wifi_start_result != ESP_OK) {
|
||||||
wifi->setRadioState(RadioState::On);
|
wifi->setRadioState(RadioState::On);
|
||||||
TT_LOG_E(TAG, "Failed to start wifi to begin connecting (%s)", esp_err_to_name(wifi_start_result));
|
TT_LOG_E(TAG, "Failed to start wifi to begin connecting (%s)", esp_err_to_name(wifi_start_result));
|
||||||
publish_event_simple(wifi, EventType::ConnectionFailed);
|
publish_event(wifi, WifiEvent::ConnectionFailed);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -784,7 +783,7 @@ static void dispatchConnect(std::shared_ptr<Wifi> wifi) {
|
|||||||
if (bits & WIFI_CONNECTED_BIT) {
|
if (bits & WIFI_CONNECTED_BIT) {
|
||||||
wifi->setSecureConnection(config.sta.password[0] != 0x00U);
|
wifi->setSecureConnection(config.sta.password[0] != 0x00U);
|
||||||
wifi->setRadioState(RadioState::ConnectionActive);
|
wifi->setRadioState(RadioState::ConnectionActive);
|
||||||
publish_event_simple(wifi, EventType::ConnectionSuccess);
|
publish_event(wifi, WifiEvent::ConnectionSuccess);
|
||||||
TT_LOG_I(TAG, "Connected to %s", wifi->connection_target.ssid.c_str());
|
TT_LOG_I(TAG, "Connected to %s", wifi->connection_target.ssid.c_str());
|
||||||
if (wifi->connection_target_remember) {
|
if (wifi->connection_target_remember) {
|
||||||
if (!settings::save(wifi->connection_target)) {
|
if (!settings::save(wifi->connection_target)) {
|
||||||
@ -795,11 +794,11 @@ static void dispatchConnect(std::shared_ptr<Wifi> wifi) {
|
|||||||
}
|
}
|
||||||
} else if (bits & WIFI_FAIL_BIT) {
|
} else if (bits & WIFI_FAIL_BIT) {
|
||||||
wifi->setRadioState(RadioState::On);
|
wifi->setRadioState(RadioState::On);
|
||||||
publish_event_simple(wifi, EventType::ConnectionFailed);
|
publish_event(wifi, WifiEvent::ConnectionFailed);
|
||||||
TT_LOG_I(TAG, "Failed to connect to %s", wifi->connection_target.ssid.c_str());
|
TT_LOG_I(TAG, "Failed to connect to %s", wifi->connection_target.ssid.c_str());
|
||||||
} else {
|
} else {
|
||||||
wifi->setRadioState(RadioState::On);
|
wifi->setRadioState(RadioState::On);
|
||||||
publish_event_simple(wifi, EventType::ConnectionFailed);
|
publish_event(wifi, WifiEvent::ConnectionFailed);
|
||||||
TT_LOG_E(TAG, "UNEXPECTED EVENT");
|
TT_LOG_E(TAG, "UNEXPECTED EVENT");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -834,7 +833,7 @@ static void dispatchDisconnectButKeepActive(std::shared_ptr<Wifi> wifi) {
|
|||||||
// TODO: disable radio, because radio state is in limbo between off and on
|
// TODO: disable radio, because radio state is in limbo between off and on
|
||||||
wifi->setRadioState(RadioState::Off);
|
wifi->setRadioState(RadioState::Off);
|
||||||
TT_LOG_E(TAG, "failed to set wifi config (%s)", esp_err_to_name(set_config_result));
|
TT_LOG_E(TAG, "failed to set wifi config (%s)", esp_err_to_name(set_config_result));
|
||||||
publish_event_simple(wifi, EventType::RadioStateOff);
|
publish_event(wifi, WifiEvent::RadioStateOff);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -843,12 +842,12 @@ static void dispatchDisconnectButKeepActive(std::shared_ptr<Wifi> wifi) {
|
|||||||
// TODO: disable radio, because radio state is in limbo between off and on
|
// TODO: disable radio, because radio state is in limbo between off and on
|
||||||
wifi->setRadioState(RadioState::Off);
|
wifi->setRadioState(RadioState::Off);
|
||||||
TT_LOG_E(TAG, "failed to start wifi to begin connecting (%s)", esp_err_to_name(wifi_start_result));
|
TT_LOG_E(TAG, "failed to start wifi to begin connecting (%s)", esp_err_to_name(wifi_start_result));
|
||||||
publish_event_simple(wifi, EventType::RadioStateOff);
|
publish_event(wifi, WifiEvent::RadioStateOff);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
wifi->setRadioState(RadioState::On);
|
wifi->setRadioState(RadioState::On);
|
||||||
publish_event_simple(wifi, EventType::Disconnected);
|
publish_event(wifi, WifiEvent::Disconnected);
|
||||||
TT_LOG_I(TAG, "Disconnected");
|
TT_LOG_I(TAG, "Disconnected");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -22,7 +22,7 @@ struct Wifi {
|
|||||||
/** @brief Locking mechanism for modifying the Wifi instance */
|
/** @brief Locking mechanism for modifying the Wifi instance */
|
||||||
Mutex mutex = Mutex(Mutex::Type::Recursive);
|
Mutex mutex = Mutex(Mutex::Type::Recursive);
|
||||||
/** @brief The public event bus */
|
/** @brief The public event bus */
|
||||||
std::shared_ptr<PubSub> pubsub = std::make_shared<PubSub>();
|
std::shared_ptr<PubSub<WifiEvent>> pubsub = std::make_shared<PubSub<WifiEvent>>();
|
||||||
/** @brief The internal message queue */
|
/** @brief The internal message queue */
|
||||||
bool scan_active = false;
|
bool scan_active = false;
|
||||||
bool secure_connection = false;
|
bool secure_connection = false;
|
||||||
@ -34,16 +34,15 @@ static Wifi* wifi = nullptr;
|
|||||||
|
|
||||||
// region Static
|
// region Static
|
||||||
|
|
||||||
static void publish_event_simple(Wifi* wifi, EventType type) {
|
static void publish_event(WifiEvent event) {
|
||||||
Event turning_on_event = { .type = type };
|
wifi->pubsub->publish(event);
|
||||||
wifi->pubsub->publish(&turning_on_event);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// endregion Static
|
// endregion Static
|
||||||
|
|
||||||
// region Public functions
|
// region Public functions
|
||||||
|
|
||||||
std::shared_ptr<PubSub> getPubsub() {
|
std::shared_ptr<PubSub<WifiEvent>> getPubsub() {
|
||||||
assert(wifi);
|
assert(wifi);
|
||||||
return wifi->pubsub;
|
return wifi->pubsub;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,9 +1,8 @@
|
|||||||
#include "Tactility/service/wifi/WifiSettings.h"
|
#include <Tactility/service/wifi/WifiSettings.h>
|
||||||
#include "Tactility/Preferences.h"
|
|
||||||
#include "Tactility/file/PropertiesFile.h"
|
|
||||||
|
|
||||||
#include <Tactility/Log.h>
|
|
||||||
#include <Tactility/file/File.h>
|
#include <Tactility/file/File.h>
|
||||||
|
#include <Tactility/file/PropertiesFile.h>
|
||||||
|
#include <Tactility/Log.h>
|
||||||
|
|
||||||
namespace tt::service::wifi::settings {
|
namespace tt::service::wifi::settings {
|
||||||
|
|
||||||
@ -15,6 +14,12 @@ struct WifiSettings {
|
|||||||
bool enableOnBoot;
|
bool enableOnBoot;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static WifiSettings cachedSettings {
|
||||||
|
.enableOnBoot = false
|
||||||
|
};
|
||||||
|
|
||||||
|
static bool cached = false;
|
||||||
|
|
||||||
static bool load(WifiSettings& settings) {
|
static bool load(WifiSettings& settings) {
|
||||||
std::map<std::string, std::string> map;
|
std::map<std::string, std::string> map;
|
||||||
if (!file::loadPropertiesFile(SETTINGS_FILE, map)) {
|
if (!file::loadPropertiesFile(SETTINGS_FILE, map)) {
|
||||||
@ -36,19 +41,27 @@ static bool save(const WifiSettings& settings) {
|
|||||||
return file::savePropertiesFile(SETTINGS_FILE, map);
|
return file::savePropertiesFile(SETTINGS_FILE, map);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
WifiSettings getCachedOrLoad() {
|
||||||
|
if (!cached) {
|
||||||
|
if (!load(cachedSettings)) {
|
||||||
|
TT_LOG_E(TAG, "Failed to load %s", SETTINGS_FILE);
|
||||||
|
} else {
|
||||||
|
cached = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return cachedSettings;
|
||||||
|
}
|
||||||
|
|
||||||
void setEnableOnBoot(bool enable) {
|
void setEnableOnBoot(bool enable) {
|
||||||
WifiSettings settings { .enableOnBoot = enable };
|
cachedSettings.enableOnBoot = enable;
|
||||||
if (!save(settings)) {
|
if (!save(cachedSettings)) {
|
||||||
TT_LOG_E(TAG, "Failed to save %s", SETTINGS_FILE);
|
TT_LOG_E(TAG, "Failed to save %s", SETTINGS_FILE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool shouldEnableOnBoot() {
|
bool shouldEnableOnBoot() {
|
||||||
WifiSettings settings;
|
return getCachedOrLoad().enableOnBoot;
|
||||||
if (!load(settings)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return settings.enableOnBoot;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|||||||
@ -7,11 +7,11 @@
|
|||||||
namespace tt::settings {
|
namespace tt::settings {
|
||||||
|
|
||||||
constexpr auto* TAG = "SystemSettings";
|
constexpr auto* TAG = "SystemSettings";
|
||||||
constexpr auto* FILE_PATH = "/data/system.properties";
|
constexpr auto* FILE_PATH = "/data/settings/system.properties";
|
||||||
|
|
||||||
static Mutex mutex = Mutex();
|
static Mutex mutex = Mutex();
|
||||||
static bool cached = false;
|
static bool cached = false;
|
||||||
static SystemSettings cachedProperties;
|
static SystemSettings cachedSettings;
|
||||||
|
|
||||||
static bool loadSystemSettingsFromFile(SystemSettings& properties) {
|
static bool loadSystemSettingsFromFile(SystemSettings& properties) {
|
||||||
std::map<std::string, std::string> map;
|
std::map<std::string, std::string> map;
|
||||||
@ -44,13 +44,13 @@ bool loadSystemSettings(SystemSettings& properties) {
|
|||||||
scoped_lock.lock();
|
scoped_lock.lock();
|
||||||
|
|
||||||
if (!cached) {
|
if (!cached) {
|
||||||
if (!loadSystemSettingsFromFile(cachedProperties)) {
|
if (!loadSystemSettingsFromFile(cachedSettings)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
cached = true;
|
cached = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
properties = cachedProperties;
|
properties = cachedSettings;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -68,7 +68,7 @@ bool saveSystemSettings(const SystemSettings& properties) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
cachedProperties = properties;
|
cachedSettings = properties;
|
||||||
cached = true;
|
cached = true;
|
||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
|
|||||||
@ -7,6 +7,7 @@ extern "C" {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
typedef void* AppHandle;
|
typedef void* AppHandle;
|
||||||
|
typedef void* AppPathsHandle;
|
||||||
|
|
||||||
/** @return the bundle that belongs to this application, or null if it wasn't started with parameters. */
|
/** @return the bundle that belongs to this application, or null if it wasn't started with parameters. */
|
||||||
BundleHandle _Nullable tt_app_get_parameters(AppHandle handle);
|
BundleHandle _Nullable tt_app_get_parameters(AppHandle handle);
|
||||||
@ -14,7 +15,7 @@ BundleHandle _Nullable tt_app_get_parameters(AppHandle handle);
|
|||||||
/**
|
/**
|
||||||
* Set the result before closing an app.
|
* 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.
|
* 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] handle the app handle to set the result for
|
||||||
* @param[in] result the result state to set
|
* @param[in] result the result state to set
|
||||||
* @param[in] bundle the result bundle to set
|
* @param[in] bundle the result bundle to set
|
||||||
*/
|
*/
|
||||||
@ -23,6 +24,21 @@ void tt_app_set_result(AppHandle handle, AppResult result, BundleHandle _Nullabl
|
|||||||
/** @return true if a result was set for this app context */
|
/** @return true if a result was set for this app context */
|
||||||
bool tt_app_has_result(AppHandle handle);
|
bool tt_app_has_result(AppHandle handle);
|
||||||
|
|
||||||
|
/** Get the path to the data directory of this app.
|
||||||
|
* @param[in] handle the app handle
|
||||||
|
* @param[out] buffer the output buffer (recommended size is 256 bytes)
|
||||||
|
* @param[inout] size used as input for maximum buffer size (including null terminator) and is set with the path string length by this function
|
||||||
|
*/
|
||||||
|
void tt_app_get_data_directory(AppPathsHandle handle, char* buffer, size_t& size);
|
||||||
|
|
||||||
|
/** Get the path to the data directory of this app, with LVGL drive letter prefix applied.
|
||||||
|
* The recommended buffer size is 256 bytes.
|
||||||
|
* @param[in] handle the app handle
|
||||||
|
* @param[out] buffer the output buffer (recommended size is 256 bytes)
|
||||||
|
* @param[inout] size used as input for maximum buffer size (including null terminator) and is set with the path string length by this function
|
||||||
|
*/
|
||||||
|
void tt_app_get_data_directory_lvgl(AppPathsHandle handle, char* buffer, size_t& size);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Start an app by id.
|
* Start an app by id.
|
||||||
* @param[in] appId the app manifest id
|
* @param[in] appId the app manifest id
|
||||||
|
|||||||
@ -4,6 +4,8 @@
|
|||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
|
|
||||||
|
constexpr auto* TAG = "tt_app";
|
||||||
|
|
||||||
#define HANDLE_AS_APP_CONTEXT(handle) ((tt::app::AppContext*)(handle))
|
#define HANDLE_AS_APP_CONTEXT(handle) ((tt::app::AppContext*)(handle))
|
||||||
|
|
||||||
BundleHandle _Nullable tt_app_get_parameters(AppHandle handle) {
|
BundleHandle _Nullable tt_app_get_parameters(AppHandle handle) {
|
||||||
@ -31,4 +33,38 @@ void tt_app_stop() {
|
|||||||
tt::app::stop();
|
tt::app::stop();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void tt_app_get_data_directory(AppPathsHandle handle, char* buffer, size_t& size) {
|
||||||
|
assert(buffer != nullptr);
|
||||||
|
assert(size > 0);
|
||||||
|
auto paths = HANDLE_AS_APP_CONTEXT(handle)->getPaths();
|
||||||
|
auto data_path = paths->getDataDirectory();
|
||||||
|
auto expected_length = data_path.length() + 1;
|
||||||
|
if (size < expected_length) {
|
||||||
|
TT_LOG_E(TAG, "Path buffer not large enough (%d < %d)", size, expected_length);
|
||||||
|
size = 0;
|
||||||
|
buffer[0] = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
strcpy(buffer, data_path.c_str());
|
||||||
|
size = data_path.length();
|
||||||
|
}
|
||||||
|
|
||||||
|
void tt_app_get_data_directory_lvgl(AppPathsHandle handle, char* buffer, size_t& size) {
|
||||||
|
assert(buffer != nullptr);
|
||||||
|
assert(size > 0);
|
||||||
|
auto paths = HANDLE_AS_APP_CONTEXT(handle)->getPaths();
|
||||||
|
auto data_path = paths->getDataDirectoryLvgl();
|
||||||
|
auto expected_length = data_path.length() + 1;
|
||||||
|
if (size < expected_length) {
|
||||||
|
TT_LOG_E(TAG, "Path buffer not large enough (%d < %d)", size, expected_length);
|
||||||
|
size = 0;
|
||||||
|
buffer[0] = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
strcpy(buffer, data_path.c_str());
|
||||||
|
size = data_path.length();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -119,6 +119,8 @@ const esp_elfsym elf_symbols[] {
|
|||||||
ESP_ELFSYM_EXPORT(tt_app_selectiondialog_get_result_index),
|
ESP_ELFSYM_EXPORT(tt_app_selectiondialog_get_result_index),
|
||||||
ESP_ELFSYM_EXPORT(tt_app_alertdialog_start),
|
ESP_ELFSYM_EXPORT(tt_app_alertdialog_start),
|
||||||
ESP_ELFSYM_EXPORT(tt_app_alertdialog_get_result_index),
|
ESP_ELFSYM_EXPORT(tt_app_alertdialog_get_result_index),
|
||||||
|
ESP_ELFSYM_EXPORT(tt_app_get_data_directory),
|
||||||
|
ESP_ELFSYM_EXPORT(tt_app_get_data_directory_lvgl),
|
||||||
ESP_ELFSYM_EXPORT(tt_bundle_alloc),
|
ESP_ELFSYM_EXPORT(tt_bundle_alloc),
|
||||||
ESP_ELFSYM_EXPORT(tt_bundle_free),
|
ESP_ELFSYM_EXPORT(tt_bundle_free),
|
||||||
ESP_ELFSYM_EXPORT(tt_bundle_opt_bool),
|
ESP_ELFSYM_EXPORT(tt_bundle_opt_bool),
|
||||||
|
|||||||
@ -13,9 +13,7 @@ namespace tt {
|
|||||||
/**
|
/**
|
||||||
* A dictionary that maps keys (strings) onto several atomary types.
|
* A dictionary that maps keys (strings) onto several atomary types.
|
||||||
*/
|
*/
|
||||||
class Bundle {
|
class Bundle final {
|
||||||
|
|
||||||
private:
|
|
||||||
|
|
||||||
typedef uint32_t Hash;
|
typedef uint32_t Hash;
|
||||||
|
|
||||||
|
|||||||
@ -19,7 +19,8 @@ namespace tt {
|
|||||||
* Generally, one task would dispatch the execution,
|
* Generally, one task would dispatch the execution,
|
||||||
* while the other thread consumes and executes the work.
|
* while the other thread consumes and executes the work.
|
||||||
*/
|
*/
|
||||||
class Dispatcher {
|
class Dispatcher final {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
typedef std::function<void()> Function;
|
typedef std::function<void()> Function;
|
||||||
@ -38,8 +39,10 @@ public:
|
|||||||
/**
|
/**
|
||||||
* Queue a function to be consumed elsewhere.
|
* Queue a function to be consumed elsewhere.
|
||||||
* @param[in] function the function to execute elsewhere
|
* @param[in] function the function to execute elsewhere
|
||||||
|
* @param[in] timeout lock acquisition timeout
|
||||||
|
* @return true if dispatching was successful (timeout not reached)
|
||||||
*/
|
*/
|
||||||
void dispatch(Function function, TickType_t timeout = portMAX_DELAY);
|
bool dispatch(Function function, TickType_t timeout = portMAX_DELAY);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Consume 1 or more dispatched function (if any) until the queue is empty.
|
* Consume 1 or more dispatched function (if any) until the queue is empty.
|
||||||
|
|||||||
@ -5,11 +5,11 @@
|
|||||||
namespace tt {
|
namespace tt {
|
||||||
|
|
||||||
/** Starts a Thread to process dispatched messages */
|
/** Starts a Thread to process dispatched messages */
|
||||||
class DispatcherThread {
|
class DispatcherThread final {
|
||||||
|
|
||||||
Dispatcher dispatcher;
|
Dispatcher dispatcher;
|
||||||
std::unique_ptr<Thread> thread;
|
std::unique_ptr<Thread> thread;
|
||||||
bool interruptThread = false;
|
bool interruptThread = true;
|
||||||
|
|
||||||
int32_t threadMain();
|
int32_t threadMain();
|
||||||
|
|
||||||
@ -21,13 +21,16 @@ public:
|
|||||||
/**
|
/**
|
||||||
* Dispatch a message.
|
* Dispatch a message.
|
||||||
*/
|
*/
|
||||||
void dispatch(Dispatcher::Function function, TickType_t timeout = portMAX_DELAY);
|
bool dispatch(Dispatcher::Function function, TickType_t timeout = portMAX_DELAY);
|
||||||
|
|
||||||
/** Start the thread (blocking). */
|
/** Start the thread (blocking). */
|
||||||
void start();
|
void start();
|
||||||
|
|
||||||
/** Stop the thread (blocking). */
|
/** Stop the thread (blocking). */
|
||||||
void stop();
|
void stop();
|
||||||
|
|
||||||
|
/** @return true of the thread is started */
|
||||||
|
bool isStarted() const { return thread != nullptr && !interruptThread; }
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -8,8 +8,7 @@ namespace tt {
|
|||||||
/**
|
/**
|
||||||
* Wrapper for FreeRTOS xEventGroup.
|
* Wrapper for FreeRTOS xEventGroup.
|
||||||
*/
|
*/
|
||||||
class EventFlag {
|
class EventFlag final {
|
||||||
private:
|
|
||||||
|
|
||||||
struct EventGroupHandleDeleter {
|
struct EventGroupHandleDeleter {
|
||||||
void operator()(EventGroupHandle_t handleToDelete) {
|
void operator()(EventGroupHandle_t handleToDelete) {
|
||||||
|
|||||||
@ -1,7 +1,3 @@
|
|||||||
/**
|
|
||||||
* @file pubsub.h
|
|
||||||
* PubSub
|
|
||||||
*/
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "Mutex.h"
|
#include "Mutex.h"
|
||||||
@ -9,18 +5,13 @@
|
|||||||
|
|
||||||
namespace tt {
|
namespace tt {
|
||||||
|
|
||||||
/** PubSub Callback type */
|
|
||||||
typedef void (*PubSubCallback)(const void* message, void* context);
|
|
||||||
|
|
||||||
/** Publish and subscribe to messages in a thread-safe manner. */
|
/** Publish and subscribe to messages in a thread-safe manner. */
|
||||||
class PubSub {
|
template<typename DataType>
|
||||||
|
class PubSub final {
|
||||||
private:
|
|
||||||
|
|
||||||
struct Subscription {
|
struct Subscription {
|
||||||
uint64_t id;
|
uint64_t id;
|
||||||
PubSubCallback callback;
|
std::function<void(DataType)> callback;
|
||||||
void* callbackParameter;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef std::list<Subscription> Subscriptions;
|
typedef std::list<Subscription> Subscriptions;
|
||||||
@ -42,21 +33,55 @@ public:
|
|||||||
|
|
||||||
/** Start receiving messages at the specified handle (Threadsafe, Re-entrable)
|
/** Start receiving messages at the specified handle (Threadsafe, Re-entrable)
|
||||||
* @param[in] callback
|
* @param[in] callback
|
||||||
* @param[in] callbackParameter the data to pass to the callback
|
|
||||||
* @return subscription instance
|
* @return subscription instance
|
||||||
*/
|
*/
|
||||||
SubscriptionHandle subscribe(PubSubCallback callback, void* callbackParameter);
|
SubscriptionHandle subscribe(std::function<void(DataType)> callback) {
|
||||||
|
mutex.lock();
|
||||||
|
items.push_back({
|
||||||
|
.id = (++lastId),
|
||||||
|
.callback = std::move(callback)
|
||||||
|
});
|
||||||
|
|
||||||
|
mutex.unlock();
|
||||||
|
|
||||||
|
return reinterpret_cast<SubscriptionHandle>(lastId);
|
||||||
|
}
|
||||||
|
|
||||||
/** Stop receiving messages at the specified handle (Threadsafe, Re-entrable.)
|
/** Stop receiving messages at the specified handle (Threadsafe, Re-entrable.)
|
||||||
* No use of `tt_pubsub_subscription` allowed after call of this method
|
* No use of `tt_pubsub_subscription` allowed after call of this method
|
||||||
* @param[in] subscription
|
* @param[in] subscription
|
||||||
*/
|
*/
|
||||||
void unsubscribe(SubscriptionHandle subscription);
|
void unsubscribe(SubscriptionHandle subscription) {
|
||||||
|
assert(subscription);
|
||||||
|
|
||||||
/** Publish message to all subscribers (Threadsafe, Re-entrable.)
|
mutex.lock();
|
||||||
* @param[in] message message pointer to publish - it is passed as-is to the callback
|
bool result = false;
|
||||||
|
auto id = reinterpret_cast<uint64_t>(subscription);
|
||||||
|
for (auto it = items.begin(); it != items.end(); ++it) {
|
||||||
|
if (it->id == id) {
|
||||||
|
items.erase(it);
|
||||||
|
result = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mutex.unlock();
|
||||||
|
tt_check(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Publish something to all subscribers (Threadsafe, Re-entrable.)
|
||||||
|
* @param[in] data the data to publish
|
||||||
*/
|
*/
|
||||||
void publish(void* message);
|
void publish(DataType data) {
|
||||||
|
mutex.lock();
|
||||||
|
|
||||||
|
// Iterate over subscribers
|
||||||
|
for (auto& it : items) {
|
||||||
|
it.callback(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
mutex.unlock();
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -21,8 +21,6 @@ namespace tt {
|
|||||||
*/
|
*/
|
||||||
class Semaphore final : public Lock {
|
class Semaphore final : public Lock {
|
||||||
|
|
||||||
private:
|
|
||||||
|
|
||||||
struct SemaphoreHandleDeleter {
|
struct SemaphoreHandleDeleter {
|
||||||
void operator()(QueueHandle_t handleToDelete) {
|
void operator()(QueueHandle_t handleToDelete) {
|
||||||
assert(!kernel::isIsr());
|
assert(!kernel::isIsr());
|
||||||
|
|||||||
@ -22,9 +22,7 @@ namespace tt {
|
|||||||
* interrupt that will write to the buffer (the writer), and only one task or
|
* interrupt that will write to the buffer (the writer), and only one task or
|
||||||
* interrupt that will read from the buffer (the reader).
|
* interrupt that will read from the buffer (the reader).
|
||||||
*/
|
*/
|
||||||
class StreamBuffer {
|
class StreamBuffer final {
|
||||||
|
|
||||||
private:
|
|
||||||
|
|
||||||
struct StreamBufferHandleDeleter {
|
struct StreamBufferHandleDeleter {
|
||||||
void operator()(StreamBufferHandle_t handleToDelete) {
|
void operator()(StreamBufferHandle_t handleToDelete) {
|
||||||
|
|||||||
@ -1,6 +1,5 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "CoreDefines.h"
|
|
||||||
#include "RtosCompatTask.h"
|
#include "RtosCompatTask.h"
|
||||||
|
|
||||||
#include <functional>
|
#include <functional>
|
||||||
@ -11,7 +10,7 @@ namespace tt {
|
|||||||
|
|
||||||
typedef TaskHandle_t ThreadId;
|
typedef TaskHandle_t ThreadId;
|
||||||
|
|
||||||
class Thread {
|
class Thread final {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
@ -184,8 +183,8 @@ public:
|
|||||||
static uint32_t awaitFlags(uint32_t flags, uint32_t options, uint32_t timeout);
|
static uint32_t awaitFlags(uint32_t flags, uint32_t options, uint32_t timeout);
|
||||||
};
|
};
|
||||||
|
|
||||||
#define THREAD_PRIORITY_SERVICE Thread::Priority::High
|
constexpr auto THREAD_PRIORITY_SERVICE = Thread::Priority::High;
|
||||||
#define THREAD_PRIORITY_RENDER Thread::Priority::Higher
|
constexpr auto THREAD_PRIORITY_RENDER = Thread::Priority::Higher;
|
||||||
#define THREAD_PRIORITY_ISR Thread::Priority::Critical
|
constexpr auto THREAD_PRIORITY_ISR = Thread::Priority::Critical;
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|||||||
@ -15,7 +15,7 @@ Dispatcher::~Dispatcher() {
|
|||||||
mutex.unlock();
|
mutex.unlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Dispatcher::dispatch(Function function, TickType_t timeout) {
|
bool Dispatcher::dispatch(Function function, TickType_t timeout) {
|
||||||
// Mutate
|
// Mutate
|
||||||
if (mutex.lock(timeout)) {
|
if (mutex.lock(timeout)) {
|
||||||
queue.push(std::move(function));
|
queue.push(std::move(function));
|
||||||
@ -25,8 +25,10 @@ void Dispatcher::dispatch(Function function, TickType_t timeout) {
|
|||||||
tt_check(mutex.unlock());
|
tt_check(mutex.unlock());
|
||||||
// Signal
|
// Signal
|
||||||
eventFlag.set(WAIT_FLAG);
|
eventFlag.set(WAIT_FLAG);
|
||||||
|
return true;
|
||||||
} else {
|
} else {
|
||||||
TT_LOG_E(TAG, LOG_MESSAGE_MUTEX_LOCK_FAILED);
|
TT_LOG_E(TAG, LOG_MESSAGE_MUTEX_LOCK_FAILED);
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -6,7 +6,7 @@ DispatcherThread::DispatcherThread(const std::string& threadName, size_t threadS
|
|||||||
thread = std::make_unique<Thread>(
|
thread = std::make_unique<Thread>(
|
||||||
threadName,
|
threadName,
|
||||||
threadStackSize,
|
threadStackSize,
|
||||||
[this]() {
|
[this] {
|
||||||
return threadMain();
|
return threadMain();
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
@ -30,8 +30,8 @@ int32_t DispatcherThread::threadMain() {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void DispatcherThread::dispatch(Dispatcher::Function function, TickType_t timeout) {
|
bool DispatcherThread::dispatch(Dispatcher::Function function, TickType_t timeout) {
|
||||||
dispatcher.dispatch(function, timeout);
|
return dispatcher.dispatch(function, timeout);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DispatcherThread::start() {
|
void DispatcherThread::start() {
|
||||||
|
|||||||
@ -1,47 +0,0 @@
|
|||||||
#include "Tactility/PubSub.h"
|
|
||||||
#include "Tactility/Check.h"
|
|
||||||
|
|
||||||
namespace tt {
|
|
||||||
|
|
||||||
PubSub::SubscriptionHandle PubSub::subscribe(PubSubCallback callback, void* callbackParameter) {
|
|
||||||
mutex.lock();
|
|
||||||
items.push_back({
|
|
||||||
.id = (++lastId),
|
|
||||||
.callback = callback,
|
|
||||||
.callbackParameter = callbackParameter});
|
|
||||||
|
|
||||||
mutex.unlock();
|
|
||||||
|
|
||||||
return (Subscription*)lastId;
|
|
||||||
}
|
|
||||||
|
|
||||||
void PubSub::unsubscribe(SubscriptionHandle subscription) {
|
|
||||||
assert(subscription);
|
|
||||||
|
|
||||||
mutex.lock();
|
|
||||||
bool result = false;
|
|
||||||
auto id = (uint64_t)subscription;
|
|
||||||
for (auto it = items.begin(); it != items.end(); it++) {
|
|
||||||
if (it->id == id) {
|
|
||||||
items.erase(it);
|
|
||||||
result = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
mutex.unlock();
|
|
||||||
tt_check(result);
|
|
||||||
}
|
|
||||||
|
|
||||||
void PubSub::publish(void* message) {
|
|
||||||
mutex.lock();
|
|
||||||
|
|
||||||
// Iterate over subscribers
|
|
||||||
for (auto& it : items) {
|
|
||||||
it.callback(message, it.callbackParameter);
|
|
||||||
}
|
|
||||||
|
|
||||||
mutex.unlock();
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace
|
|
||||||
@ -5,7 +5,7 @@
|
|||||||
|
|
||||||
namespace tt {
|
namespace tt {
|
||||||
|
|
||||||
inline static StreamBufferHandle_t createStreamBuffer(size_t size, size_t triggerLevel) {
|
static StreamBufferHandle_t createStreamBuffer(size_t size, size_t triggerLevel) {
|
||||||
assert(size != 0);
|
assert(size != 0);
|
||||||
return xStreamBufferCreate(size, triggerLevel);
|
return xStreamBufferCreate(size, triggerLevel);
|
||||||
}
|
}
|
||||||
|
|||||||
29
Tests/TactilityCore/DispatcherThreadTest.cpp
Normal file
29
Tests/TactilityCore/DispatcherThreadTest.cpp
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
#include "doctest.h"
|
||||||
|
#include <Tactility/TactilityCore.h>
|
||||||
|
#include <Tactility/DispatcherThread.h>
|
||||||
|
|
||||||
|
using namespace tt;
|
||||||
|
|
||||||
|
TEST_CASE("DispatcherThread state test") {
|
||||||
|
DispatcherThread thread("test");
|
||||||
|
CHECK_EQ(thread.isStarted(), false);
|
||||||
|
|
||||||
|
thread.start();
|
||||||
|
CHECK_EQ(thread.isStarted(), true);
|
||||||
|
|
||||||
|
thread.stop();
|
||||||
|
CHECK_EQ(thread.isStarted(), false);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("DispatcherThread should consume jobs") {
|
||||||
|
DispatcherThread thread("test");
|
||||||
|
thread.start();
|
||||||
|
int counter = 0;
|
||||||
|
|
||||||
|
thread.dispatch([&counter]() { counter++; });
|
||||||
|
|
||||||
|
tt::kernel::delayTicks(10);
|
||||||
|
|
||||||
|
CHECK_EQ(counter, 1);
|
||||||
|
thread.stop();
|
||||||
|
}
|
||||||
35
Tests/TactilityCore/PubSubTest.cpp
Normal file
35
Tests/TactilityCore/PubSubTest.cpp
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
#include "doctest.h"
|
||||||
|
#include <Tactility/TactilityCore.h>
|
||||||
|
#include <Tactility/PubSub.h>
|
||||||
|
|
||||||
|
using namespace tt;
|
||||||
|
|
||||||
|
TEST_CASE("PubSub publishing with no subscriptions should not crash") {
|
||||||
|
PubSub<int> pubsub;
|
||||||
|
pubsub.publish(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("PubSub subscription receives published data") {
|
||||||
|
PubSub<int> pubsub;
|
||||||
|
int value = 0;
|
||||||
|
|
||||||
|
auto subscription = pubsub.subscribe([&value](auto newValue) {
|
||||||
|
value = newValue;
|
||||||
|
});
|
||||||
|
pubsub.publish(1);
|
||||||
|
|
||||||
|
CHECK_EQ(value, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("PubSub unsubscribed subscription does not receive published data") {
|
||||||
|
PubSub<int> pubsub;
|
||||||
|
int value = 0;
|
||||||
|
|
||||||
|
auto subscription = pubsub.subscribe([&value](auto newValue) {
|
||||||
|
value = newValue;
|
||||||
|
});
|
||||||
|
pubsub.unsubscribe(subscription);
|
||||||
|
pubsub.publish(1);
|
||||||
|
|
||||||
|
CHECK_EQ(value, 0);
|
||||||
|
}
|
||||||
@ -19,7 +19,7 @@ CONFIG_FREERTOS_HZ=1000
|
|||||||
CONFIG_FREERTOS_TASK_NOTIFICATION_ARRAY_ENTRIES=2
|
CONFIG_FREERTOS_TASK_NOTIFICATION_ARRAY_ENTRIES=2
|
||||||
CONFIG_FREERTOS_SMP=n
|
CONFIG_FREERTOS_SMP=n
|
||||||
CONFIG_FREERTOS_UNICORE=n
|
CONFIG_FREERTOS_UNICORE=n
|
||||||
CONFIG_FREERTOS_TIMER_TASK_STACK_DEPTH=4096
|
CONFIG_FREERTOS_TIMER_TASK_STACK_DEPTH=5120
|
||||||
CONFIG_FREERTOS_USE_TRACE_FACILITY=y
|
CONFIG_FREERTOS_USE_TRACE_FACILITY=y
|
||||||
CONFIG_PARTITION_TABLE_CUSTOM=y
|
CONFIG_PARTITION_TABLE_CUSTOM=y
|
||||||
CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions.csv"
|
CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions.csv"
|
||||||
|
|||||||
@ -19,7 +19,7 @@ CONFIG_FREERTOS_HZ=1000
|
|||||||
CONFIG_FREERTOS_TASK_NOTIFICATION_ARRAY_ENTRIES=2
|
CONFIG_FREERTOS_TASK_NOTIFICATION_ARRAY_ENTRIES=2
|
||||||
CONFIG_FREERTOS_SMP=n
|
CONFIG_FREERTOS_SMP=n
|
||||||
CONFIG_FREERTOS_UNICORE=n
|
CONFIG_FREERTOS_UNICORE=n
|
||||||
CONFIG_FREERTOS_TIMER_TASK_STACK_DEPTH=4096
|
CONFIG_FREERTOS_TIMER_TASK_STACK_DEPTH=5120
|
||||||
CONFIG_FREERTOS_USE_TRACE_FACILITY=y
|
CONFIG_FREERTOS_USE_TRACE_FACILITY=y
|
||||||
CONFIG_PARTITION_TABLE_CUSTOM=y
|
CONFIG_PARTITION_TABLE_CUSTOM=y
|
||||||
CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions.csv"
|
CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions.csv"
|
||||||
|
|||||||
@ -19,7 +19,7 @@ CONFIG_FREERTOS_HZ=1000
|
|||||||
CONFIG_FREERTOS_TASK_NOTIFICATION_ARRAY_ENTRIES=2
|
CONFIG_FREERTOS_TASK_NOTIFICATION_ARRAY_ENTRIES=2
|
||||||
CONFIG_FREERTOS_SMP=n
|
CONFIG_FREERTOS_SMP=n
|
||||||
CONFIG_FREERTOS_UNICORE=n
|
CONFIG_FREERTOS_UNICORE=n
|
||||||
CONFIG_FREERTOS_TIMER_TASK_STACK_DEPTH=4096
|
CONFIG_FREERTOS_TIMER_TASK_STACK_DEPTH=5120
|
||||||
CONFIG_FREERTOS_USE_TRACE_FACILITY=y
|
CONFIG_FREERTOS_USE_TRACE_FACILITY=y
|
||||||
CONFIG_PARTITION_TABLE_CUSTOM=y
|
CONFIG_PARTITION_TABLE_CUSTOM=y
|
||||||
CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions.csv"
|
CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions.csv"
|
||||||
|
|||||||
@ -19,7 +19,7 @@ CONFIG_FREERTOS_HZ=1000
|
|||||||
CONFIG_FREERTOS_TASK_NOTIFICATION_ARRAY_ENTRIES=2
|
CONFIG_FREERTOS_TASK_NOTIFICATION_ARRAY_ENTRIES=2
|
||||||
CONFIG_FREERTOS_SMP=n
|
CONFIG_FREERTOS_SMP=n
|
||||||
CONFIG_FREERTOS_UNICORE=n
|
CONFIG_FREERTOS_UNICORE=n
|
||||||
CONFIG_FREERTOS_TIMER_TASK_STACK_DEPTH=4096
|
CONFIG_FREERTOS_TIMER_TASK_STACK_DEPTH=5120
|
||||||
CONFIG_FREERTOS_USE_TRACE_FACILITY=y
|
CONFIG_FREERTOS_USE_TRACE_FACILITY=y
|
||||||
CONFIG_PARTITION_TABLE_CUSTOM=y
|
CONFIG_PARTITION_TABLE_CUSTOM=y
|
||||||
CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions.csv"
|
CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions.csv"
|
||||||
|
|||||||
@ -19,7 +19,7 @@ CONFIG_FREERTOS_HZ=1000
|
|||||||
CONFIG_FREERTOS_TASK_NOTIFICATION_ARRAY_ENTRIES=2
|
CONFIG_FREERTOS_TASK_NOTIFICATION_ARRAY_ENTRIES=2
|
||||||
CONFIG_FREERTOS_SMP=n
|
CONFIG_FREERTOS_SMP=n
|
||||||
CONFIG_FREERTOS_UNICORE=n
|
CONFIG_FREERTOS_UNICORE=n
|
||||||
CONFIG_FREERTOS_TIMER_TASK_STACK_DEPTH=4096
|
CONFIG_FREERTOS_TIMER_TASK_STACK_DEPTH=5120
|
||||||
CONFIG_FREERTOS_USE_TRACE_FACILITY=y
|
CONFIG_FREERTOS_USE_TRACE_FACILITY=y
|
||||||
CONFIG_PARTITION_TABLE_CUSTOM=y
|
CONFIG_PARTITION_TABLE_CUSTOM=y
|
||||||
CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions.csv"
|
CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions.csv"
|
||||||
|
|||||||
@ -19,7 +19,7 @@ CONFIG_FREERTOS_HZ=1000
|
|||||||
CONFIG_FREERTOS_TASK_NOTIFICATION_ARRAY_ENTRIES=2
|
CONFIG_FREERTOS_TASK_NOTIFICATION_ARRAY_ENTRIES=2
|
||||||
CONFIG_FREERTOS_SMP=n
|
CONFIG_FREERTOS_SMP=n
|
||||||
CONFIG_FREERTOS_UNICORE=n
|
CONFIG_FREERTOS_UNICORE=n
|
||||||
CONFIG_FREERTOS_TIMER_TASK_STACK_DEPTH=4096
|
CONFIG_FREERTOS_TIMER_TASK_STACK_DEPTH=5120
|
||||||
CONFIG_FREERTOS_USE_TRACE_FACILITY=y
|
CONFIG_FREERTOS_USE_TRACE_FACILITY=y
|
||||||
CONFIG_PARTITION_TABLE_CUSTOM=y
|
CONFIG_PARTITION_TABLE_CUSTOM=y
|
||||||
CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions.csv"
|
CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions.csv"
|
||||||
|
|||||||
@ -19,7 +19,7 @@ CONFIG_FREERTOS_HZ=1000
|
|||||||
CONFIG_FREERTOS_TASK_NOTIFICATION_ARRAY_ENTRIES=2
|
CONFIG_FREERTOS_TASK_NOTIFICATION_ARRAY_ENTRIES=2
|
||||||
CONFIG_FREERTOS_SMP=n
|
CONFIG_FREERTOS_SMP=n
|
||||||
CONFIG_FREERTOS_UNICORE=n
|
CONFIG_FREERTOS_UNICORE=n
|
||||||
CONFIG_FREERTOS_TIMER_TASK_STACK_DEPTH=4096
|
CONFIG_FREERTOS_TIMER_TASK_STACK_DEPTH=5120
|
||||||
CONFIG_FREERTOS_USE_TRACE_FACILITY=y
|
CONFIG_FREERTOS_USE_TRACE_FACILITY=y
|
||||||
CONFIG_PARTITION_TABLE_CUSTOM=y
|
CONFIG_PARTITION_TABLE_CUSTOM=y
|
||||||
CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions.csv"
|
CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions.csv"
|
||||||
|
|||||||
@ -19,7 +19,7 @@ CONFIG_FREERTOS_HZ=1000
|
|||||||
CONFIG_FREERTOS_TASK_NOTIFICATION_ARRAY_ENTRIES=2
|
CONFIG_FREERTOS_TASK_NOTIFICATION_ARRAY_ENTRIES=2
|
||||||
CONFIG_FREERTOS_SMP=n
|
CONFIG_FREERTOS_SMP=n
|
||||||
CONFIG_FREERTOS_UNICORE=n
|
CONFIG_FREERTOS_UNICORE=n
|
||||||
CONFIG_FREERTOS_TIMER_TASK_STACK_DEPTH=4096
|
CONFIG_FREERTOS_TIMER_TASK_STACK_DEPTH=5120
|
||||||
CONFIG_FREERTOS_USE_TRACE_FACILITY=y
|
CONFIG_FREERTOS_USE_TRACE_FACILITY=y
|
||||||
CONFIG_PARTITION_TABLE_CUSTOM=y
|
CONFIG_PARTITION_TABLE_CUSTOM=y
|
||||||
CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions.csv"
|
CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions.csv"
|
||||||
|
|||||||
@ -19,7 +19,7 @@ CONFIG_FREERTOS_HZ=1000
|
|||||||
CONFIG_FREERTOS_TASK_NOTIFICATION_ARRAY_ENTRIES=2
|
CONFIG_FREERTOS_TASK_NOTIFICATION_ARRAY_ENTRIES=2
|
||||||
CONFIG_FREERTOS_SMP=n
|
CONFIG_FREERTOS_SMP=n
|
||||||
CONFIG_FREERTOS_UNICORE=n
|
CONFIG_FREERTOS_UNICORE=n
|
||||||
CONFIG_FREERTOS_TIMER_TASK_STACK_DEPTH=4096
|
CONFIG_FREERTOS_TIMER_TASK_STACK_DEPTH=5120
|
||||||
CONFIG_FREERTOS_USE_TRACE_FACILITY=y
|
CONFIG_FREERTOS_USE_TRACE_FACILITY=y
|
||||||
CONFIG_PARTITION_TABLE_CUSTOM=y
|
CONFIG_PARTITION_TABLE_CUSTOM=y
|
||||||
CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions.csv"
|
CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions.csv"
|
||||||
|
|||||||
@ -19,7 +19,7 @@ CONFIG_FREERTOS_HZ=1000
|
|||||||
CONFIG_FREERTOS_TASK_NOTIFICATION_ARRAY_ENTRIES=2
|
CONFIG_FREERTOS_TASK_NOTIFICATION_ARRAY_ENTRIES=2
|
||||||
CONFIG_FREERTOS_SMP=n
|
CONFIG_FREERTOS_SMP=n
|
||||||
CONFIG_FREERTOS_UNICORE=n
|
CONFIG_FREERTOS_UNICORE=n
|
||||||
CONFIG_FREERTOS_TIMER_TASK_STACK_DEPTH=4096
|
CONFIG_FREERTOS_TIMER_TASK_STACK_DEPTH=5120
|
||||||
CONFIG_FREERTOS_USE_TRACE_FACILITY=y
|
CONFIG_FREERTOS_USE_TRACE_FACILITY=y
|
||||||
CONFIG_PARTITION_TABLE_CUSTOM=y
|
CONFIG_PARTITION_TABLE_CUSTOM=y
|
||||||
CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions.csv"
|
CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions.csv"
|
||||||
|
|||||||
@ -19,7 +19,7 @@ CONFIG_FREERTOS_HZ=1000
|
|||||||
CONFIG_FREERTOS_TASK_NOTIFICATION_ARRAY_ENTRIES=2
|
CONFIG_FREERTOS_TASK_NOTIFICATION_ARRAY_ENTRIES=2
|
||||||
CONFIG_FREERTOS_SMP=n
|
CONFIG_FREERTOS_SMP=n
|
||||||
CONFIG_FREERTOS_UNICORE=n
|
CONFIG_FREERTOS_UNICORE=n
|
||||||
CONFIG_FREERTOS_TIMER_TASK_STACK_DEPTH=4096
|
CONFIG_FREERTOS_TIMER_TASK_STACK_DEPTH=5120
|
||||||
CONFIG_FREERTOS_USE_TRACE_FACILITY=y
|
CONFIG_FREERTOS_USE_TRACE_FACILITY=y
|
||||||
CONFIG_PARTITION_TABLE_CUSTOM=y
|
CONFIG_PARTITION_TABLE_CUSTOM=y
|
||||||
CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions.csv"
|
CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions.csv"
|
||||||
|
|||||||
@ -19,7 +19,7 @@ CONFIG_FREERTOS_HZ=1000
|
|||||||
CONFIG_FREERTOS_TASK_NOTIFICATION_ARRAY_ENTRIES=2
|
CONFIG_FREERTOS_TASK_NOTIFICATION_ARRAY_ENTRIES=2
|
||||||
CONFIG_FREERTOS_SMP=n
|
CONFIG_FREERTOS_SMP=n
|
||||||
CONFIG_FREERTOS_UNICORE=n
|
CONFIG_FREERTOS_UNICORE=n
|
||||||
CONFIG_FREERTOS_TIMER_TASK_STACK_DEPTH=4096
|
CONFIG_FREERTOS_TIMER_TASK_STACK_DEPTH=5120
|
||||||
CONFIG_FREERTOS_USE_TRACE_FACILITY=y
|
CONFIG_FREERTOS_USE_TRACE_FACILITY=y
|
||||||
CONFIG_PARTITION_TABLE_CUSTOM=y
|
CONFIG_PARTITION_TABLE_CUSTOM=y
|
||||||
CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions.csv"
|
CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions.csv"
|
||||||
|
|||||||
@ -19,7 +19,7 @@ CONFIG_FREERTOS_HZ=1000
|
|||||||
CONFIG_FREERTOS_TASK_NOTIFICATION_ARRAY_ENTRIES=2
|
CONFIG_FREERTOS_TASK_NOTIFICATION_ARRAY_ENTRIES=2
|
||||||
CONFIG_FREERTOS_SMP=n
|
CONFIG_FREERTOS_SMP=n
|
||||||
CONFIG_FREERTOS_UNICORE=n
|
CONFIG_FREERTOS_UNICORE=n
|
||||||
CONFIG_FREERTOS_TIMER_TASK_STACK_DEPTH=4096
|
CONFIG_FREERTOS_TIMER_TASK_STACK_DEPTH=5120
|
||||||
CONFIG_FREERTOS_USE_TRACE_FACILITY=y
|
CONFIG_FREERTOS_USE_TRACE_FACILITY=y
|
||||||
CONFIG_PARTITION_TABLE_CUSTOM=y
|
CONFIG_PARTITION_TABLE_CUSTOM=y
|
||||||
CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions.csv"
|
CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions.csv"
|
||||||
|
|||||||
@ -19,7 +19,7 @@ CONFIG_FREERTOS_HZ=1000
|
|||||||
CONFIG_FREERTOS_TASK_NOTIFICATION_ARRAY_ENTRIES=2
|
CONFIG_FREERTOS_TASK_NOTIFICATION_ARRAY_ENTRIES=2
|
||||||
CONFIG_FREERTOS_SMP=n
|
CONFIG_FREERTOS_SMP=n
|
||||||
CONFIG_FREERTOS_UNICORE=n
|
CONFIG_FREERTOS_UNICORE=n
|
||||||
CONFIG_FREERTOS_TIMER_TASK_STACK_DEPTH=4096
|
CONFIG_FREERTOS_TIMER_TASK_STACK_DEPTH=5120
|
||||||
CONFIG_FREERTOS_USE_TRACE_FACILITY=y
|
CONFIG_FREERTOS_USE_TRACE_FACILITY=y
|
||||||
CONFIG_PARTITION_TABLE_CUSTOM=y
|
CONFIG_PARTITION_TABLE_CUSTOM=y
|
||||||
CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions.csv"
|
CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions.csv"
|
||||||
|
|||||||
@ -19,7 +19,7 @@ CONFIG_FREERTOS_HZ=1000
|
|||||||
CONFIG_FREERTOS_TASK_NOTIFICATION_ARRAY_ENTRIES=2
|
CONFIG_FREERTOS_TASK_NOTIFICATION_ARRAY_ENTRIES=2
|
||||||
CONFIG_FREERTOS_SMP=n
|
CONFIG_FREERTOS_SMP=n
|
||||||
CONFIG_FREERTOS_UNICORE=n
|
CONFIG_FREERTOS_UNICORE=n
|
||||||
CONFIG_FREERTOS_TIMER_TASK_STACK_DEPTH=4096
|
CONFIG_FREERTOS_TIMER_TASK_STACK_DEPTH=5120
|
||||||
CONFIG_FREERTOS_USE_TRACE_FACILITY=y
|
CONFIG_FREERTOS_USE_TRACE_FACILITY=y
|
||||||
CONFIG_PARTITION_TABLE_CUSTOM=y
|
CONFIG_PARTITION_TABLE_CUSTOM=y
|
||||||
CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions.csv"
|
CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions.csv"
|
||||||
|
|||||||
@ -19,7 +19,7 @@ CONFIG_FREERTOS_HZ=1000
|
|||||||
CONFIG_FREERTOS_TASK_NOTIFICATION_ARRAY_ENTRIES=2
|
CONFIG_FREERTOS_TASK_NOTIFICATION_ARRAY_ENTRIES=2
|
||||||
CONFIG_FREERTOS_SMP=n
|
CONFIG_FREERTOS_SMP=n
|
||||||
CONFIG_FREERTOS_UNICORE=n
|
CONFIG_FREERTOS_UNICORE=n
|
||||||
CONFIG_FREERTOS_TIMER_TASK_STACK_DEPTH=4096
|
CONFIG_FREERTOS_TIMER_TASK_STACK_DEPTH=5120
|
||||||
CONFIG_FREERTOS_USE_TRACE_FACILITY=y
|
CONFIG_FREERTOS_USE_TRACE_FACILITY=y
|
||||||
CONFIG_PARTITION_TABLE_CUSTOM=y
|
CONFIG_PARTITION_TABLE_CUSTOM=y
|
||||||
CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions.csv"
|
CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions.csv"
|
||||||
|
|||||||
@ -19,7 +19,7 @@ CONFIG_FREERTOS_HZ=1000
|
|||||||
CONFIG_FREERTOS_TASK_NOTIFICATION_ARRAY_ENTRIES=2
|
CONFIG_FREERTOS_TASK_NOTIFICATION_ARRAY_ENTRIES=2
|
||||||
CONFIG_FREERTOS_SMP=n
|
CONFIG_FREERTOS_SMP=n
|
||||||
CONFIG_FREERTOS_UNICORE=n
|
CONFIG_FREERTOS_UNICORE=n
|
||||||
CONFIG_FREERTOS_TIMER_TASK_STACK_DEPTH=4096
|
CONFIG_FREERTOS_TIMER_TASK_STACK_DEPTH=5120
|
||||||
CONFIG_FREERTOS_USE_TRACE_FACILITY=y
|
CONFIG_FREERTOS_USE_TRACE_FACILITY=y
|
||||||
CONFIG_PARTITION_TABLE_CUSTOM=y
|
CONFIG_PARTITION_TABLE_CUSTOM=y
|
||||||
CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions.csv"
|
CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions.csv"
|
||||||
|
|||||||
@ -19,7 +19,7 @@ CONFIG_FREERTOS_HZ=1000
|
|||||||
CONFIG_FREERTOS_TASK_NOTIFICATION_ARRAY_ENTRIES=2
|
CONFIG_FREERTOS_TASK_NOTIFICATION_ARRAY_ENTRIES=2
|
||||||
CONFIG_FREERTOS_SMP=n
|
CONFIG_FREERTOS_SMP=n
|
||||||
CONFIG_FREERTOS_UNICORE=n
|
CONFIG_FREERTOS_UNICORE=n
|
||||||
CONFIG_FREERTOS_TIMER_TASK_STACK_DEPTH=4096
|
CONFIG_FREERTOS_TIMER_TASK_STACK_DEPTH=5120
|
||||||
CONFIG_FREERTOS_USE_TRACE_FACILITY=y
|
CONFIG_FREERTOS_USE_TRACE_FACILITY=y
|
||||||
CONFIG_PARTITION_TABLE_CUSTOM=y
|
CONFIG_PARTITION_TABLE_CUSTOM=y
|
||||||
CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions.csv"
|
CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions.csv"
|
||||||
|
|||||||
@ -19,7 +19,7 @@ CONFIG_FREERTOS_HZ=1000
|
|||||||
CONFIG_FREERTOS_TASK_NOTIFICATION_ARRAY_ENTRIES=2
|
CONFIG_FREERTOS_TASK_NOTIFICATION_ARRAY_ENTRIES=2
|
||||||
CONFIG_FREERTOS_SMP=n
|
CONFIG_FREERTOS_SMP=n
|
||||||
CONFIG_FREERTOS_UNICORE=n
|
CONFIG_FREERTOS_UNICORE=n
|
||||||
CONFIG_FREERTOS_TIMER_TASK_STACK_DEPTH=4096
|
CONFIG_FREERTOS_TIMER_TASK_STACK_DEPTH=5120
|
||||||
CONFIG_FREERTOS_USE_TRACE_FACILITY=y
|
CONFIG_FREERTOS_USE_TRACE_FACILITY=y
|
||||||
CONFIG_PARTITION_TABLE_CUSTOM=y
|
CONFIG_PARTITION_TABLE_CUSTOM=y
|
||||||
CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions.csv"
|
CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions.csv"
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user