Merge develop into main (#307)

## Launcher

- Launcher now has optional power button to show
- Launcher layout improvements
- Removed text from Launcher (translations with larger amounts of text did not fit small device formats)

## T-Lora Pager

- Implement power off (created `BQ25896` driver)
- Implemented haptics (created `DRV2605` driver project) and buzz on startup
- Reversed scroll wheel
- Created `TloraEncoder` device and relocated its logic from `TloraKeyboard`
- Disabled SPIRAM test to save 0.5 seconds of boot time (current boot time is very slow)
- Update `ST7796` esp_lcd driver to v1.3.4
- Fixed keyboard bug: delete queue in destructor
- Fixed driver dependencies: Avoiding usage of global static shared_ptr. Properly constructor-inject everywhere, or use `tt::hal::findDevices()`
- I2C configuration is now immutable (you cannot disable it anymore from the I2C Settings app, as it would break crucial drivers)
- Renamed I2C and UART subsystems to "Internal"

## Drivers

- On/off interface added to `PowerDevice`
- Created `tt::hal::Configuration.createDevices`, which is intended to replace all custom create calls for display, keyboard, etc.
- Created `EncoderDevice` as a `Device` subtype

## Other Improvements

- Changed `findDevices(type, function)` into a templatized function.
- Improved SD card mounting

## Fixes

- Show Screenshot app again
- Fixed Statusbar: some updates were allowed to time out and fail silently: When the Statusbar service would do a state update, the LVGL statusbar would never get updated due to this timeout.
- Fixed memory leaks in all `createSdCard()` functions (in most board implementations)
This commit is contained in:
Ken Van Hoeylandt
2025-08-30 21:54:55 +02:00
committed by GitHub
parent e9f72490fc
commit 50007ea9ed
69 changed files with 957 additions and 577 deletions
-9
View File
@@ -88,15 +88,6 @@ std::vector<std::shared_ptr<Device>> findDevices(Device::Type type) {
});
}
void findDevices(Device::Type type, std::function<bool(const std::shared_ptr<Device>&)> onDeviceFound) {
auto devices_view = findDevices(type);
for (auto& device : devices_view) {
if (!onDeviceFound(device)) {
break;
}
}
}
std::vector<std::shared_ptr<Device>> getDevices() {
return devices;
}
+28 -16
View File
@@ -8,12 +8,35 @@
#include <Tactility/kernel/SystemEvents.h>
#define TAG "hal"
#define TT_SDCARD_MOUNT_POINT "/sdcard"
namespace tt::hal {
constexpr auto* TAG = "hal";
void registerDevices(const Configuration& configuration) {
TT_LOG_I(TAG, "Registering devices");
if (configuration.sdcard != nullptr) {
registerDevice(configuration.sdcard);
}
if (configuration.power != nullptr) {
std::shared_ptr<power::PowerDevice> power = configuration.power();
registerDevice(power);
}
if (configuration.createKeyboard) {
auto keyboard = configuration.createKeyboard();
if (keyboard != nullptr) {
registerDevice(std::reinterpret_pointer_cast<Device>(keyboard));
}
}
auto devices = configuration.createDevices();
for (auto& device : devices) {
registerDevice(device);
}
}
void init(const Configuration& configuration) {
kernel::publishSystemEvent(kernel::SystemEvent::BootInitHalBegin);
@@ -34,18 +57,7 @@ void init(const Configuration& configuration) {
tt_check(configuration.initBoot(), "Init power failed");
}
if (configuration.sdcard != nullptr) {
TT_LOG_I(TAG, "Mounting sdcard");
if (!configuration.sdcard->mount(TT_SDCARD_MOUNT_POINT)) {
TT_LOG_W(TAG, "SD card mount failed (init can continue)");
}
registerDevice(configuration.sdcard);
}
if (configuration.power != nullptr) {
std::shared_ptr<power::PowerDevice> power = configuration.power();
registerDevice(power);
}
registerDevices(configuration);
kernel::publishSystemEvent(kernel::SystemEvent::BootInitHalEnd);
}
+7 -7
View File
@@ -5,11 +5,11 @@
namespace tt::hal::i2c {
bool I2cDevice::read(uint8_t* data, size_t dataSize, TickType_t timeout) {
return tt::hal::i2c::masterRead(port, address, data, dataSize, timeout);
return masterRead(port, address, data, dataSize, timeout);
}
bool I2cDevice::write(const uint8_t* data, uint16_t dataSize, TickType_t timeout) {
return tt::hal::i2c::masterWrite(port, address, data, dataSize, timeout);
return masterWrite(port, address, data, dataSize, timeout);
}
bool I2cDevice::writeRead(const uint8_t* writeData, size_t writeDataSize, uint8_t* readData, size_t readDataSize, TickType_t timeout) {
@@ -22,7 +22,7 @@ bool I2cDevice::writeRegister(uint8_t reg, const uint8_t* data, uint16_t dataSiz
bool I2cDevice::readRegister12(uint8_t reg, float& out) const {
std::uint8_t data[2] = {0};
if (tt::hal::i2c::masterReadRegister(port, address, reg, data, 2, DEFAULT_TIMEOUT)) {
if (masterReadRegister(port, address, reg, data, 2, DEFAULT_TIMEOUT)) {
out = (data[0] & 0x0F) << 8 | data[1];
return true;
} else {
@@ -32,7 +32,7 @@ bool I2cDevice::readRegister12(uint8_t reg, float& out) const {
bool I2cDevice::readRegister14(uint8_t reg, float& out) const {
std::uint8_t data[2] = {0};
if (tt::hal::i2c::masterReadRegister(port, address, reg, data, 2, DEFAULT_TIMEOUT)) {
if (masterReadRegister(port, address, reg, data, 2, DEFAULT_TIMEOUT)) {
out = (data[0] & 0x3F) << 8 | data[1];
return true;
} else {
@@ -42,7 +42,7 @@ bool I2cDevice::readRegister14(uint8_t reg, float& out) const {
bool I2cDevice::readRegister16(uint8_t reg, uint16_t& out) const {
std::uint8_t data[2] = {0};
if (tt::hal::i2c::masterReadRegister(port, address, reg, data, 2, DEFAULT_TIMEOUT)) {
if (masterReadRegister(port, address, reg, data, 2, DEFAULT_TIMEOUT)) {
out = data[0] << 8 | data[1];
return true;
} else {
@@ -51,11 +51,11 @@ bool I2cDevice::readRegister16(uint8_t reg, uint16_t& out) const {
}
bool I2cDevice::readRegister8(uint8_t reg, uint8_t& result) const {
return tt::hal::i2c::masterWriteRead(port, address, &reg, 1, &result, 1, DEFAULT_TIMEOUT);
return masterWriteRead(port, address, &reg, 1, &result, 1, DEFAULT_TIMEOUT);
}
bool I2cDevice::writeRegister8(uint8_t reg, uint8_t value) const {
return tt::hal::i2c::masterWriteRegister(port, address, reg, &value, 1, DEFAULT_TIMEOUT);
return masterWriteRegister(port, address, reg, &value, 1, DEFAULT_TIMEOUT);
}
bool I2cDevice::bitOn(uint8_t reg, uint8_t bitmask) const {
@@ -0,0 +1,40 @@
#include <Tactility/hal/sdcard/SdCardMounting.h>
#include <Tactility/hal/sdcard/SdCardDevice.h>
namespace tt::hal::sdcard {
constexpr auto* TAG = "SdCardMounting";
constexpr auto* TT_SDCARD_MOUNT_POINT = "/sdcard";
static void mount(const std::shared_ptr<SdCardDevice>& sdcard, const std::string& path) {
sdcard->getLock()->withLock([&sdcard, &path] {
TT_LOG_I(TAG, "Mounting sdcard at %s", path.c_str());
if (!sdcard->mount(path)) {
TT_LOG_W(TAG, "SD card mount failed for %s (init can continue)", path.c_str());
}
});
}
void mountAll() {
auto sdcards = hal::findDevices<SdCardDevice>(Device::Type::SdCard);
if (!sdcards.empty()) {
if (sdcards.size() == 1) {
// Fixed mount path name
auto sdcard = sdcards[0];
if (!sdcard->isMounted()) {
mount(sdcard, TT_SDCARD_MOUNT_POINT);
}
} else {
// Numbered mount path name
for (int i = 0; i < sdcards.size(); i++) {
auto sdcard = sdcards[i];
if (!sdcard->isMounted()) {
std::string mount_path = TT_SDCARD_MOUNT_POINT + std::to_string(i);
mount(sdcard, mount_path);
}
}
}
}
}
}
+16 -17
View File
@@ -21,30 +21,29 @@ static Mode currentMode = Mode::Default;
static RTC_NOINIT_ATTR BootMode bootMode;
sdmmc_card_t* _Nullable getCard() {
auto sdcard = getConfiguration()->sdcard;
if (sdcard == nullptr) {
TT_LOG_W(TAG, "No SD card configuration found");
auto sdcards = findDevices<sdcard::SpiSdCardDevice>(Device::Type::SdCard);
std::shared_ptr<sdcard::SpiSdCardDevice> usable_sdcard;
for (auto& sdcard : sdcards) {
auto sdcard_candidate = std::static_pointer_cast<sdcard::SpiSdCardDevice>(sdcard);
if (sdcard_candidate != nullptr && sdcard_candidate->isMounted() && sdcard_candidate->getCard() != nullptr) {
usable_sdcard = sdcard_candidate;
break;
}
}
if (usable_sdcard == nullptr) {
TT_LOG_W(TAG, "Couldn't find a mounted SpiSdCard");
return nullptr;
}
if (!sdcard->isMounted()) {
TT_LOG_W(TAG, "SD card not mounted");
return nullptr;
}
auto spi_sdcard = std::static_pointer_cast<sdcard::SpiSdCardDevice>(sdcard);
if (spi_sdcard == nullptr) {
TT_LOG_W(TAG, "SD card interface is not supported (must be SpiSdCard)");
return nullptr;
}
auto* card = spi_sdcard->getCard();
if (card == nullptr) {
auto* sdmmc_card = usable_sdcard->getCard();
if (sdmmc_card == nullptr) {
TT_LOG_W(TAG, "SD card has no card object available");
return nullptr;
}
return card;
return sdmmc_card;
}
static bool canStartNewMode() {