From 457c21ffd8d69d61340a36a54ca8e599e4a787aa Mon Sep 17 00:00:00 2001 From: Ken Van Hoeylandt Date: Sat, 6 Sep 2025 17:17:39 +0200 Subject: [PATCH] Merge develop into main (#321) - Implemented `TouchDriver` for `Xpt2046SoftSpi` - Refactored system initialization --- Documentation/ideas.md | 24 ++- Drivers/EspLcdCompat/Source/EspLcdDisplay.cpp | 2 +- .../XPT2046SoftSPI/Source/Xpt2046SoftSpi.cpp | 198 +++++++++--------- .../XPT2046SoftSPI/Source/Xpt2046SoftSpi.h | 28 ++- Tactility/Source/PartitionsEsp.cpp | 3 +- Tactility/Source/Tactility.cpp | 12 +- Tactility/Source/TactilityHeadlessEsp.cpp | 7 +- Tactility/Source/hal/Hal.cpp | 35 ++++ Tactility/Source/lvgl/Lvgl.cpp | 75 ++----- 9 files changed, 208 insertions(+), 176 deletions(-) diff --git a/Documentation/ideas.md b/Documentation/ideas.md index 6c256004..6b0a9dc3 100644 --- a/Documentation/ideas.md +++ b/Documentation/ideas.md @@ -17,9 +17,17 @@ Scan these paths on startup. Make the AppList use the scan results. +## Medium Priority + +- Unify the way displays are dimmed. Some implementations turn off the display when it's fully dimmed. Make this a separate functionality. +- Try out ILI9342 https://github.com/jbrilha/esp_lcd_ili9342 +- All drivers (e.g. display, touch, etc.) should call stop() in their destructor, or at least assert that they should not be running. +- Create different partition files for different ESP flash size targets (N4, N8, N16, N32) + Consider a dev variant for quick flashing. +- Bug: Turn on WiFi (when testing it wasn't connected/connecting - just active). Open chat. Observe crash. + ## Lower Priority -- Try out ILI9342 https://github.com/jbrilha/esp_lcd_ili9342 - Localize all apps - Support hot-plugging SD card (note: this is not possible if they require the CS pin hack) - Create more unit tests for `tactility` @@ -28,22 +36,16 @@ - CrashHandler: process other types of crashes (WDT?) - Add a Keyboard setting in `keyboard.properties` to override the behaviour of soft keyboard hiding (e.g. keyboard hardware is present, but the user wants to use a soft keyboard) - Use GPS time to set/update the current time -- All drivers (e.g. display, touch, etc.) should call stop() in their destructor, or at least assert that they should not be running. - Fix bug in T-Deck/etc: esp_lvgl_port settings has a large stack size (~9kB) to fix an issue where the T-Deck would get a stackoverflow. This sometimes happens when WiFi is auto-enabled and you open the app while it is still connecting. -- Start using non_null (either via MS GSL, or custom) -- `hal/Configuration.h` defines C function types: Use C++ std::function instead +- Consider using non_null (either via MS GSL, or custom) - Fix system time to not be 1980 (use build year as a minimum). Consider keeping track of the last known time. - Use std::span or string_view in StringUtils https://youtu.be/FRkJCvHWdwQ?t=2754 - Mutex: Implement give/take from ISR support (works only for non-recursive ones) - Extend unPhone power driver: add charging status, usb connection status, etc. -- Create different partition files for different ESP flash size targets (N4, N8, N16, N32) -- T-Deck: Clear screen before turning on blacklight -- T-Deck: Use knob for UI selection? +- Clear screen before turning on blacklight (e.g. T-Deck, CYD 2432S028R, etc.) +- T-Deck: Use trackball as input device (with optional mouse functionality for LVGL) - Show a warning screen if firmware encryption or secure boot are off when saving WiFi credentials. -- Show a warning screen when a user plugs in the SD card on a device that only supports mounting at boot. -- Scanning SD card for external apps and auto-register them (in a temporary register?) - Remove flex_flow from app_container in Gui.cpp -- Bug: Turn on WiFi (when testing it wasn't connected/connecting - just active). Open chat. Observe crash. # Nice-to-haves @@ -82,3 +84,5 @@ - Todo list - Calendar - Display touch calibration +- RSS reader +- Static file web server (with option to specify path and port) diff --git a/Drivers/EspLcdCompat/Source/EspLcdDisplay.cpp b/Drivers/EspLcdCompat/Source/EspLcdDisplay.cpp index bcc3e6e1..87a39e8e 100644 --- a/Drivers/EspLcdCompat/Source/EspLcdDisplay.cpp +++ b/Drivers/EspLcdCompat/Source/EspLcdDisplay.cpp @@ -68,7 +68,7 @@ bool EspLcdDisplay::startLvgl() { } auto touch_device = getTouchDevice(); - if (touch_device != nullptr) { + if (touch_device != nullptr && touch_device->supportsLvgl()) { touch_device->startLvgl(lvglDisplay); } diff --git a/Drivers/XPT2046SoftSPI/Source/Xpt2046SoftSpi.cpp b/Drivers/XPT2046SoftSPI/Source/Xpt2046SoftSpi.cpp index 785937d6..174d916c 100644 --- a/Drivers/XPT2046SoftSPI/Source/Xpt2046SoftSpi.cpp +++ b/Drivers/XPT2046SoftSPI/Source/Xpt2046SoftSpi.cpp @@ -52,20 +52,63 @@ static void ensureNvsInitialized() { initialized = (result == ESP_OK); } -bool Xpt2046SoftSpi::startLvgl(lv_display_t* display) { +bool Xpt2046SoftSpi::start() { + ensureNvsInitialized(); - // Create LVGL input device - deviceHandle = lv_indev_create(); - if (!deviceHandle) { - TT_LOG_E(TAG, "Failed to create LVGL input device"); + TT_LOG_I(TAG, "Starting Xpt2046SoftSpi touch driver"); + + // Configure GPIO pins + gpio_config_t io_conf = {}; + + // Configure MOSI, CLK, CS as outputs + io_conf.intr_type = GPIO_INTR_DISABLE; + io_conf.mode = GPIO_MODE_OUTPUT; + io_conf.pin_bit_mask = (1ULL << configuration->mosiPin) | + (1ULL << configuration->clkPin) | + (1ULL << configuration->csPin); + io_conf.pull_down_en = GPIO_PULLDOWN_DISABLE; + io_conf.pull_up_en = GPIO_PULLUP_DISABLE; + + if (gpio_config(&io_conf) != ESP_OK) { + TT_LOG_E(TAG, "Failed to configure output pins"); return false; } - lv_indev_set_type(deviceHandle, LV_INDEV_TYPE_POINTER); - lv_indev_set_read_cb(deviceHandle, touchReadCallback); - lv_indev_set_user_data(deviceHandle, this); + // Configure MISO as input + io_conf.mode = GPIO_MODE_INPUT; + io_conf.pin_bit_mask = (1ULL << configuration->misoPin); + io_conf.pull_up_en = GPIO_PULLUP_ENABLE; + + if (gpio_config(&io_conf) != ESP_OK) { + TT_LOG_E(TAG, "Failed to configure input pin"); + return false; + } + + // Initialize pin states + gpio_set_level(configuration->csPin, 1); // CS high + gpio_set_level(configuration->clkPin, 0); // CLK low + gpio_set_level(configuration->mosiPin, 0); // MOSI low + + TT_LOG_I(TAG, "GPIO configured: MOSI=%d, MISO=%d, CLK=%d, CS=%d", configuration->mosiPin, configuration->misoPin, configuration->clkPin, configuration->csPin); + + // Load or perform calibration + bool calibrationValid = true; //loadCalibration() && !RERUN_CALIBRATE; + if (calibrationValid) { + // Check if calibration values are valid (xMin != xMax, yMin != yMax) + if (cal.xMin == cal.xMax || cal.yMin == cal.yMax) { + TT_LOG_W(TAG, "Invalid calibration detected: xMin=%d, xMax=%d, yMin=%d, yMax=%d", cal.xMin, cal.xMax, cal.yMin, cal.yMax); + calibrationValid = false; + } + } + + if (!calibrationValid) { + TT_LOG_W(TAG, "Calibration data not found, invalid, or forced recalibration"); + calibrate(); + saveCalibration(); + } else { + TT_LOG_I(TAG, "Loaded calibration: xMin=%d, yMin=%d, xMax=%d, yMax=%d", cal.xMin, cal.yMin, cal.xMax, cal.yMax); + } - TT_LOG_I(TAG, "Xpt2046SoftSpi touch driver started successfully"); return true; } @@ -73,13 +116,41 @@ bool Xpt2046SoftSpi::stop() { TT_LOG_I(TAG, "Stopping Xpt2046SoftSpi touch driver"); // Stop LVLG if needed - if (deviceHandle != nullptr) { + if (lvglDevice != nullptr) { stopLvgl(); } return true; } +bool Xpt2046SoftSpi::startLvgl(lv_display_t* display) { + if (lvglDevice != nullptr) { + TT_LOG_E(TAG, "LVGL was already started"); + return false; + } + + lvglDevice = lv_indev_create(); + if (!lvglDevice) { + TT_LOG_E(TAG, "Failed to create LVGL input device"); + return false; + } + + lv_indev_set_type(lvglDevice, LV_INDEV_TYPE_POINTER); + lv_indev_set_read_cb(lvglDevice, touchReadCallback); + lv_indev_set_user_data(lvglDevice, this); + + TT_LOG_I(TAG, "Xpt2046SoftSpi touch driver started successfully"); + return true; +} + +bool Xpt2046SoftSpi::stopLvgl() { + if (lvglDevice != nullptr) { + lv_indev_delete(lvglDevice); + lvglDevice = nullptr; + } + return true; +} + int Xpt2046SoftSpi::readSPI(uint8_t command) { int result = 0; @@ -186,12 +257,14 @@ void Xpt2046SoftSpi::setCalibration(int xMin, int yMin, int xMax, int yMax) { TT_LOG_I(TAG, "Manual calibration set: xMin=%d, yMin=%d, xMax=%d, yMax=%d", xMin, yMin, xMax, yMax); } -Point Xpt2046SoftSpi::getTouch() { +bool Xpt2046SoftSpi::getTouchPoint(Point& point) { const int samples = 8; // More samples for better accuracy int totalX = 0, totalY = 0; int validSamples = 0; + gpio_set_level(configuration->csPin, 0); + for (int i = 0; i < samples; i++) { int rawX = readSPI(CMD_READ_X); int rawY = readSPI(CMD_READ_Y); @@ -206,8 +279,10 @@ Point Xpt2046SoftSpi::getTouch() { vTaskDelay(pdMS_TO_TICKS(1)); } + gpio_set_level(configuration->csPin, 1); + if (validSamples == 0) { - return Point {0, 0}; + return false; } int rawX = totalX / validSamples; @@ -218,7 +293,7 @@ Point Xpt2046SoftSpi::getTouch() { if (xRange <= 0 || yRange <= 0) { TT_LOG_W(TAG, "Invalid calibration: xRange=%d, yRange=%d", xRange, yRange); - return Point {0, 0}; + return false; } int x = (rawX - cal.xMin) * configuration->xMax / xRange; @@ -228,17 +303,20 @@ Point Xpt2046SoftSpi::getTouch() { if (configuration->mirrorX) x = configuration->xMax - x; if (configuration->mirrorY) y = configuration->yMax - y; - x = std::clamp(x, 0, (int)configuration->xMax); - y = std::clamp(y, 0, (int)configuration->yMax); + point.x = std::clamp(x, 0, (int)configuration->xMax); + point.y = std::clamp(y, 0, (int)configuration->yMax); - return Point {x, y}; + return true; } +// TODO: Merge isTouched() and getTouchPoint() into 1 method bool Xpt2046SoftSpi::isTouched() { const int samples = 3; int xTotal = 0, yTotal = 0; int validSamples = 0; + gpio_set_level(configuration->csPin, 0); + for (int i = 0; i < samples; i++) { int x = readSPI(CMD_READ_X); int y = readSPI(CMD_READ_Y); @@ -259,7 +337,7 @@ bool Xpt2046SoftSpi::isTouched() { // Debug logging (remove this once working) if (touched) { - TT_LOG_I(TAG, "Touch detected: validSamples=%d, avgX=%d, avgY=%d", validSamples, xTotal / validSamples, yTotal / validSamples); + TT_LOG_D(TAG, "Touch detected: validSamples=%d, avgX=%d, avgY=%d", validSamples, xTotal / validSamples, yTotal / validSamples); } return touched; @@ -268,8 +346,8 @@ bool Xpt2046SoftSpi::isTouched() { void Xpt2046SoftSpi::touchReadCallback(lv_indev_t* indev, lv_indev_data_t* data) { Xpt2046SoftSpi* touch = static_cast(lv_indev_get_user_data(indev)); - if (touch && touch->isTouched()) { - Point point = touch->getTouch(); + Point point; + if (touch && touch->isTouched() && touch->getTouchPoint(point)) { data->point.x = point.x; data->point.y = point.y; data->state = LV_INDEV_STATE_PRESSED; @@ -278,81 +356,13 @@ void Xpt2046SoftSpi::touchReadCallback(lv_indev_t* indev, lv_indev_data_t* data) } } -bool Xpt2046SoftSpi::start() { - ensureNvsInitialized();; - - TT_LOG_I(TAG, "Starting Xpt2046SoftSpi touch driver"); - - // Configure GPIO pins - gpio_config_t io_conf = {}; - - // Configure MOSI, CLK, CS as outputs - io_conf.intr_type = GPIO_INTR_DISABLE; - io_conf.mode = GPIO_MODE_OUTPUT; - io_conf.pin_bit_mask = (1ULL << configuration->mosiPin) | - (1ULL << configuration->clkPin) | - (1ULL << configuration->csPin); - io_conf.pull_down_en = GPIO_PULLDOWN_DISABLE; - io_conf.pull_up_en = GPIO_PULLUP_DISABLE; - - if (gpio_config(&io_conf) != ESP_OK) { - TT_LOG_E(TAG, "Failed to configure output pins"); - return false; - } - - // Configure MISO as input - io_conf.mode = GPIO_MODE_INPUT; - io_conf.pin_bit_mask = (1ULL << configuration->misoPin); - io_conf.pull_up_en = GPIO_PULLUP_ENABLE; - - if (gpio_config(&io_conf) != ESP_OK) { - TT_LOG_E(TAG, "Failed to configure input pin"); - return false; - } - - // Initialize pin states - gpio_set_level(configuration->csPin, 1); // CS high - gpio_set_level(configuration->clkPin, 0); // CLK low - gpio_set_level(configuration->mosiPin, 0); // MOSI low - - TT_LOG_I(TAG, "GPIO configured: MOSI=%d, MISO=%d, CLK=%d, CS=%d", configuration->mosiPin, configuration->misoPin, configuration->clkPin, configuration->csPin); - - // Load or perform calibration - bool calibrationValid = true; //loadCalibration() && !RERUN_CALIBRATE; - if (calibrationValid) { - // Check if calibration values are valid (xMin != xMax, yMin != yMax) - if (cal.xMin == cal.xMax || cal.yMin == cal.yMax) { - TT_LOG_W(TAG, "Invalid calibration detected: xMin=%d, xMax=%d, yMin=%d, yMax=%d", cal.xMin, cal.xMax, cal.yMin, cal.yMax); - calibrationValid = false; - } - } - - if (!calibrationValid) { - TT_LOG_W(TAG, "Calibration data not found, invalid, or forced recalibration"); - calibrate(); - saveCalibration(); - } else { - TT_LOG_I(TAG, "Loaded calibration: xMin=%d, yMin=%d, xMax=%d, yMax=%d", cal.xMin, cal.yMin, cal.xMax, cal.yMax); - } - - return true; -} - -// Whether this device supports LVGL -bool Xpt2046SoftSpi::supportsLvgl() const { - return true; -} - -// Stop LVGL -bool Xpt2046SoftSpi::stopLvgl() { - if (deviceHandle != nullptr) { - lv_indev_delete(deviceHandle); - deviceHandle = nullptr; - } - return true; -} - // Return driver instance if any std::shared_ptr Xpt2046SoftSpi::getTouchDriver() { - return nullptr; // replace with actual driver later + assert(lvglDevice == nullptr); // Still attached to LVGL context. Call stopLvgl() first. + + if (touchDriver == nullptr) { + touchDriver = std::make_shared(this); + } + + return touchDriver; } diff --git a/Drivers/XPT2046SoftSPI/Source/Xpt2046SoftSpi.h b/Drivers/XPT2046SoftSPI/Source/Xpt2046SoftSpi.h index ae571354..a861b009 100644 --- a/Drivers/XPT2046SoftSPI/Source/Xpt2046SoftSpi.h +++ b/Drivers/XPT2046SoftSPI/Source/Xpt2046SoftSpi.h @@ -57,8 +57,28 @@ public: }; private: + + class Xpt2046SoftSpiDriver final : public tt::hal::touch::TouchDriver { + Xpt2046SoftSpi* device; + public: + Xpt2046SoftSpiDriver(Xpt2046SoftSpi* device) : device(device) {} + bool getTouchedPoints(uint16_t* x, uint16_t* y, uint16_t* strength, uint8_t* pointCount, uint8_t maxPointCount) override { + Point point; + if (device->isTouched() && device->getTouchPoint(point)) { + *x = point.x; + *y = point.y; + *pointCount = 1; + return true; + } else { + *pointCount = 0; + return false; + } + } + }; + std::unique_ptr configuration; - lv_indev_t* deviceHandle = nullptr; + lv_indev_t* lvglDevice = nullptr; + std::shared_ptr touchDriver; int readSPI(uint8_t command); bool loadCalibration(); @@ -75,16 +95,16 @@ public: bool start() override; bool stop() override; - bool supportsLvgl() const override; + bool supportsLvgl() const override { return true; } bool startLvgl(lv_display_t* display) override; bool stopLvgl() override; bool supportsTouchDriver() override { return true; } std::shared_ptr getTouchDriver() override; - lv_indev_t* getLvglIndev() override { return deviceHandle; } + lv_indev_t* getLvglIndev() override { return lvglDevice; } // XPT2046-specific methods - Point getTouch(); + bool getTouchPoint(Point& point); void calibrate(); void setCalibration(int xMin, int yMin, int xMax, int yMax); bool isTouched(); diff --git a/Tactility/Source/PartitionsEsp.cpp b/Tactility/Source/PartitionsEsp.cpp index 51225ba8..ec8f0895 100644 --- a/Tactility/Source/PartitionsEsp.cpp +++ b/Tactility/Source/PartitionsEsp.cpp @@ -9,7 +9,7 @@ namespace tt { -static const char* TAG = "Partitions"; +constexpr auto* TAG = "Partitions"; static esp_err_t initNvsFlashSafely() { esp_err_t result = nvs_flash_init(); @@ -37,6 +37,7 @@ size_t getSectorSize() { } esp_err_t initPartitionsEsp() { + TT_LOG_I(TAG, "Init partitions"); ESP_ERROR_CHECK(initNvsFlashSafely()); const esp_vfs_fat_mount_config_t mount_config = { diff --git a/Tactility/Source/Tactility.cpp b/Tactility/Source/Tactility.cpp index 735ceb67..87f93a58 100644 --- a/Tactility/Source/Tactility.cpp +++ b/Tactility/Source/Tactility.cpp @@ -186,7 +186,7 @@ void initFromBootApp() { } void run(const Configuration& config) { - TT_LOG_D(TAG, "run"); + TT_LOG_I(TAG, "Tactility v%s on %s (%s)", TT_VERSION, CONFIG_TT_BOARD_NAME, CONFIG_TT_BOARD_ID); assert(config.hardware); const hal::Configuration& hardware = *config.hardware; @@ -194,27 +194,25 @@ void run(const Configuration& config) { // Assign early so starting services can use it config_instance = &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 settings::initTimeZone(); hal::init(*config.hardware); - hal::sdcard::mountAll(); network::ntp::init(); registerAndStartPrimaryServices(); lvgl::init(hardware); registerAndStartSecondaryServices(); - TT_LOG_I(TAG, "starting boot app"); + TT_LOG_I(TAG, "Core systems ready"); + + TT_LOG_I(TAG, "Starting boot app"); // The boot app takes care of registering system apps, user services and user apps addApp(app::boot::manifest); service::loader::startApp(app::boot::manifest.id); - TT_LOG_I(TAG, "init complete"); - - TT_LOG_I(TAG, "Processing main dispatcher"); + TT_LOG_I(TAG, "Main dispatcher ready"); while (true) { mainDispatcher.consume(); } diff --git a/Tactility/Source/TactilityHeadlessEsp.cpp b/Tactility/Source/TactilityHeadlessEsp.cpp index a8a145cb..32e64769 100644 --- a/Tactility/Source/TactilityHeadlessEsp.cpp +++ b/Tactility/Source/TactilityHeadlessEsp.cpp @@ -9,21 +9,22 @@ namespace tt { -#define TAG "tactility" +constexpr auto* TAG = "Tactility"; // Initialize NVS static void initNvs() { + TT_LOG_I(TAG, "Init NVS"); esp_err_t ret = nvs_flash_init(); if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) { - TT_LOG_I(TAG, "nvs erasing"); + TT_LOG_I(TAG, "NVS erasing"); ESP_ERROR_CHECK(nvs_flash_erase()); ret = nvs_flash_init(); } ESP_ERROR_CHECK(ret); - TT_LOG_I(TAG, "nvs initialized"); } static void initNetwork() { + TT_LOG_I(TAG, "Init network"); ESP_ERROR_CHECK(esp_netif_init()); ESP_ERROR_CHECK(esp_event_loop_create_default()); } diff --git a/Tactility/Source/hal/Hal.cpp b/Tactility/Source/hal/Hal.cpp index eb20185f..8b379fff 100644 --- a/Tactility/Source/hal/Hal.cpp +++ b/Tactility/Source/hal/Hal.cpp @@ -8,6 +8,7 @@ #include "Tactility/hal/uart/UartInit.h" #include +#include #include #include @@ -34,6 +35,13 @@ void registerDevices(const Configuration& configuration) { } } + if (configuration.createDisplay != nullptr) { + auto display = configuration.createDisplay(); + if (display != nullptr) { + registerDevice(display); + } + } + auto devices = configuration.createDevices(); for (auto& device : devices) { registerDevice(device); @@ -50,6 +58,29 @@ void registerDevices(const Configuration& configuration) { } } +static void startDisplays() { + TT_LOG_I(TAG, "Start displays"); + auto displays = hal::findDevices(Device::Type::Display); + for (auto& display : displays) { + if (!display->start()) { + TT_LOG_E(TAG, "Display start failed"); + } else { + TT_LOG_I(TAG, "Started %s", display->getName().c_str()); + + if (display->supportsBacklightDuty()) { + display->setBacklightDuty(0); + } + + auto touch = display->getTouchDevice(); + if (touch != nullptr && !touch->start()) { + TT_LOG_E(TAG, "Touch start failed"); + } else { + TT_LOG_I(TAG, "Started %s", touch->getName().c_str()); + } + } + } +} + void init(const Configuration& configuration) { kernel::publishSystemEvent(kernel::SystemEvent::BootInitHalBegin); @@ -72,6 +103,10 @@ void init(const Configuration& configuration) { registerDevices(configuration); + sdcard::mountAll(); // Warning: This needs to happen BEFORE displays are initialized on the SPI bus + + startDisplays(); // Warning: SPI displays need to start after SPI SD cards are mounted + kernel::publishSystemEvent(kernel::SystemEvent::BootInitHalEnd); } diff --git a/Tactility/Source/lvgl/Lvgl.cpp b/Tactility/Source/lvgl/Lvgl.cpp index c280cb10..52c284c0 100644 --- a/Tactility/Source/lvgl/Lvgl.cpp +++ b/Tactility/Source/lvgl/Lvgl.cpp @@ -22,35 +22,6 @@ constexpr auto* TAG = "Lvgl"; static bool started = false; -// TODO: Move to hal init -static void initDisplays(const hal::Configuration& config) { - TT_LOG_I(TAG, "Init displays"); - if (config.createDisplay != nullptr) { - auto display = config.createDisplay(); - if (display != nullptr) { - hal::registerDevice(display); - } - } - - TT_LOG_I(TAG, "Start displays"); - auto displays = hal::findDevices(hal::Device::Type::Display); - for (auto& display : displays) { - if (!display->start()) { - TT_LOG_E(TAG, "Display start failed"); - } - - if (display->supportsBacklightDuty()) { - display->setBacklightDuty(0); - } - - auto touch = display->getTouchDevice(); - if (touch != nullptr) { - hal::registerDevice(touch); - touch->start(); - } - } -} - void init(const hal::Configuration& config) { TT_LOG_I(TAG, "Init started"); @@ -60,8 +31,6 @@ void init(const hal::Configuration& config) { } #endif - initDisplays(config); - start(); TT_LOG_I(TAG, "Init finished"); @@ -105,32 +74,30 @@ void start() { // Start touch - TT_LOG_I(TAG, "Start touch devices"); - auto touch_devices = hal::findDevices(hal::Device::Type::Touch); - for (auto touch_device : touch_devices) { - if (displays.size() > 0) { - // TODO: Consider implementing support for multiple displays - auto display = displays[0]; + // TODO: Consider implementing support for multiple displays + auto primary_display = !displays.empty() ? displays[0] : nullptr; + + // Start display-related peripherals + if (primary_display != nullptr) { + TT_LOG_I(TAG, "Start touch devices"); + auto touch_devices = hal::findDevices(hal::Device::Type::Touch); + for (auto touch_device : touch_devices) { // Start any touch devices that haven't been started yet if (touch_device->supportsLvgl() && touch_device->getLvglIndev() == nullptr) { - if (touch_device->startLvgl(display->getLvglDisplay())) { + if (touch_device->startLvgl(primary_display->getLvglDisplay())) { TT_LOG_I(TAG, "Started %s", touch_device->getName().c_str()); } else { TT_LOG_E(TAG, "Start failed for %s", touch_device->getName().c_str()); } } } - } - // Start keyboards - TT_LOG_I(TAG, "Start keyboards"); - auto keyboards = hal::findDevices(hal::Device::Type::Keyboard); - for (auto keyboard : keyboards) { - if (displays.size() > 0) { - // TODO: Consider implementing support for multiple displays - auto display = displays[0]; + // Start keyboards + TT_LOG_I(TAG, "Start keyboards"); + auto keyboards = hal::findDevices(hal::Device::Type::Keyboard); + for (auto keyboard : keyboards) { if (keyboard->isAttached()) { - if (keyboard->startLvgl(display->getLvglDisplay())) { + if (keyboard->startLvgl(primary_display->getLvglDisplay())) { lv_indev_t* keyboard_indev = keyboard->getLvglIndev(); hardware_keyboard_set_indev(keyboard_indev); TT_LOG_I(TAG, "Started %s", keyboard->getName().c_str()); @@ -139,16 +106,12 @@ void start() { } } } - } - // Start encoders - TT_LOG_I(TAG, "Start encoders"); - auto encoders = hal::findDevices(hal::Device::Type::Encoder); - for (auto encoder : encoders) { - if (displays.size() > 0) { - // TODO: Consider implementing support for multiple displays - auto display = displays[0]; - if (encoder->startLvgl(display->getLvglDisplay())) { + // Start encoders + TT_LOG_I(TAG, "Start encoders"); + auto encoders = hal::findDevices(hal::Device::Type::Encoder); + for (auto encoder : encoders) { + if (encoder->startLvgl(primary_display->getLvglDisplay())) { TT_LOG_I(TAG, "Started %s", encoder->getName().c_str()); } else { TT_LOG_E(TAG, "Start failed for %s", encoder->getName().c_str());