From 4e8cb29eded99ab7c56485e68fb3d0f69003f238 Mon Sep 17 00:00:00 2001 From: Revers-BR Date: Sat, 21 Feb 2026 09:32:55 -0300 Subject: [PATCH 1/6] Add initial support for LilyGO T-HMI S3 with device configuration and driver implementations --- Devices/lilygo-thmi-s3/CMakeLists.txt | 7 +++ .../lilygo-thmi-s3/Source/Configuration.cpp | 24 +++++++++ Devices/lilygo-thmi-s3/Source/Init.cpp | 49 +++++++++++++++++++ .../lilygo-thmi-s3/Source/devices/Display.cpp | 45 +++++++++++++++++ .../lilygo-thmi-s3/Source/devices/Display.h | 34 +++++++++++++ .../lilygo-thmi-s3/Source/devices/Power.cpp | 12 +++++ Devices/lilygo-thmi-s3/Source/devices/Power.h | 10 ++++ .../lilygo-thmi-s3/Source/devices/SdCard.cpp | 22 +++++++++ .../lilygo-thmi-s3/Source/devices/SdCard.h | 14 ++++++ Devices/lilygo-thmi-s3/Source/module.cpp | 24 +++++++++ Devices/lilygo-thmi-s3/device.properties | 23 +++++++++ Devices/lilygo-thmi-s3/devicetree.yaml | 3 ++ Devices/lilygo-thmi-s3/lilygo,thmi-s3.dts | 16 ++++++ changes.diff | 0 14 files changed, 283 insertions(+) create mode 100644 Devices/lilygo-thmi-s3/CMakeLists.txt create mode 100644 Devices/lilygo-thmi-s3/Source/Configuration.cpp create mode 100644 Devices/lilygo-thmi-s3/Source/Init.cpp create mode 100644 Devices/lilygo-thmi-s3/Source/devices/Display.cpp create mode 100644 Devices/lilygo-thmi-s3/Source/devices/Display.h create mode 100644 Devices/lilygo-thmi-s3/Source/devices/Power.cpp create mode 100644 Devices/lilygo-thmi-s3/Source/devices/Power.h create mode 100644 Devices/lilygo-thmi-s3/Source/devices/SdCard.cpp create mode 100644 Devices/lilygo-thmi-s3/Source/devices/SdCard.h create mode 100644 Devices/lilygo-thmi-s3/Source/module.cpp create mode 100644 Devices/lilygo-thmi-s3/device.properties create mode 100644 Devices/lilygo-thmi-s3/devicetree.yaml create mode 100644 Devices/lilygo-thmi-s3/lilygo,thmi-s3.dts create mode 100644 changes.diff diff --git a/Devices/lilygo-thmi-s3/CMakeLists.txt b/Devices/lilygo-thmi-s3/CMakeLists.txt new file mode 100644 index 000000000..5f1b69dcf --- /dev/null +++ b/Devices/lilygo-thmi-s3/CMakeLists.txt @@ -0,0 +1,7 @@ +file(GLOB_RECURSE SOURCE_FILES Source/*.c*) + +idf_component_register( + SRCS ${SOURCE_FILES} + INCLUDE_DIRS "Source" + REQUIRES Tactility ButtonControl XPT2046SoftSPI PwmBacklight EstimatedPower ST7789-i8080 driver vfs fatfs +) diff --git a/Devices/lilygo-thmi-s3/Source/Configuration.cpp b/Devices/lilygo-thmi-s3/Source/Configuration.cpp new file mode 100644 index 000000000..e66e1c3e5 --- /dev/null +++ b/Devices/lilygo-thmi-s3/Source/Configuration.cpp @@ -0,0 +1,24 @@ +#include "devices/Power.h" +#include "devices/SdCard.h" +#include "devices/Display.h" + +#include +#include + +bool initBoot(); + +using namespace tt::hal; + +static std::vector> createDevices() { + return { + createPower(), + createSdCard(), + createDisplay(), + ButtonControl::createTwoButtonControl(0, 14), + }; +} + +extern const Configuration hardwareConfiguration = { + .initBoot = initBoot, + .createDevices = createDevices +}; diff --git a/Devices/lilygo-thmi-s3/Source/Init.cpp b/Devices/lilygo-thmi-s3/Source/Init.cpp new file mode 100644 index 000000000..d42a6ed7c --- /dev/null +++ b/Devices/lilygo-thmi-s3/Source/Init.cpp @@ -0,0 +1,49 @@ +#include "devices/Power.h" +#include "devices/Display.h" + +#include "PwmBacklight.h" +#include "Tactility/kernel/SystemEvents.h" +#include + +#define TAG "thmi-s3" + +static bool powerOn() { + gpio_config_t power_signal_config = { + .pin_bit_mask = (1ULL << TDISPLAY_S3_POWERON_GPIO) | (1ULL << TDISPLAY_S3_POWEREN_GPIO), + .mode = GPIO_MODE_OUTPUT, + .pull_up_en = GPIO_PULLUP_DISABLE, + .pull_down_en = GPIO_PULLDOWN_DISABLE, + .intr_type = GPIO_INTR_DISABLE, + }; + + if (gpio_config(&power_signal_config) != ESP_OK) { + return false; + } + + if (gpio_set_level(TDISPLAY_S3_POWERON_GPIO, 1) != ESP_OK) { + return false; + } + + if (gpio_set_level(TDISPLAY_S3_POWEREN_GPIO, 1) != ESP_OK) { + return false; + } + + return true; +} + +bool initBoot() { + ESP_LOGI(TAG, "Powering on the board..."); + if (!powerOn()) { + ESP_LOGE(TAG, "Failed to power on the board."); + return false; + } + + if (!driver::pwmbacklight::init(DISPLAY_BL, 30000)) { + ESP_LOGE(TAG, "Failed to initialize backlight."); + return false; + } + + driver::pwmbacklight::setBacklightDuty(100); + + return true; +} \ No newline at end of file diff --git a/Devices/lilygo-thmi-s3/Source/devices/Display.cpp b/Devices/lilygo-thmi-s3/Source/devices/Display.cpp new file mode 100644 index 000000000..73da119d4 --- /dev/null +++ b/Devices/lilygo-thmi-s3/Source/devices/Display.cpp @@ -0,0 +1,45 @@ +#include +#include + +#include "Display.h" +#include "PwmBacklight.h" +#include "St7789i8080Display.h" + +static bool touchSpiInitialized = false; + +static std::shared_ptr createTouch() { + auto config = std::make_unique( + TOUCH_MOSI_PIN, + TOUCH_MISO_PIN, + TOUCH_SCK_PIN, + TOUCH_CS_PIN, + DISPLAY_HORIZONTAL_RESOLUTION, + DISPLAY_VERTICAL_RESOLUTION + ); + + return std::make_shared(std::move(config)); +} + +std::shared_ptr createDisplay() { + // Create configuration + auto config = St7789i8080Display::Configuration( + DISPLAY_CS, // CS + DISPLAY_DC, // DC + DISPLAY_WR, // WR + DISPLAY_RD, // RD + { DISPLAY_I80_D0, DISPLAY_I80_D1, DISPLAY_I80_D2, DISPLAY_I80_D3, + DISPLAY_I80_D4, DISPLAY_I80_D5, DISPLAY_I80_D6, DISPLAY_I80_D7 }, // D0..D7 + DISPLAY_RST, // RST + DISPLAY_BL // BL + ); + + // Set resolution explicitly + config.horizontalResolution = DISPLAY_HORIZONTAL_RESOLUTION; + config.verticalResolution = DISPLAY_VERTICAL_RESOLUTION; + config.backlightDutyFunction = driver::pwmbacklight::setBacklightDuty; + config.touch = createTouch(); + config.invertColor = false; + + auto display = std::make_shared(config); + return display; +} diff --git a/Devices/lilygo-thmi-s3/Source/devices/Display.h b/Devices/lilygo-thmi-s3/Source/devices/Display.h new file mode 100644 index 000000000..2ea592bbf --- /dev/null +++ b/Devices/lilygo-thmi-s3/Source/devices/Display.h @@ -0,0 +1,34 @@ +#pragma once +#include +#include + +#include "driver/spi_common.h" + +class St7789i8080Display; + +constexpr auto DISPLAY_CS = GPIO_NUM_6; +constexpr auto DISPLAY_DC = GPIO_NUM_7; +constexpr auto DISPLAY_WR = GPIO_NUM_8; +constexpr auto DISPLAY_RD = GPIO_NUM_NC; +constexpr auto DISPLAY_RST = GPIO_NUM_NC; +constexpr auto DISPLAY_BL = GPIO_NUM_38; +constexpr auto DISPLAY_I80_D0 = GPIO_NUM_48; +constexpr auto DISPLAY_I80_D1 = GPIO_NUM_47; +constexpr auto DISPLAY_I80_D2 = GPIO_NUM_39; +constexpr auto DISPLAY_I80_D3 = GPIO_NUM_40; +constexpr auto DISPLAY_I80_D4 = GPIO_NUM_41; +constexpr auto DISPLAY_I80_D5 = GPIO_NUM_42; +constexpr auto DISPLAY_I80_D6 = GPIO_NUM_45; +constexpr auto DISPLAY_I80_D7 = GPIO_NUM_46; +constexpr auto DISPLAY_HORIZONTAL_RESOLUTION = 240; +constexpr auto DISPLAY_VERTICAL_RESOLUTION = 320; + +// Touch (XPT2046, resistive, shared SPI with display) +constexpr auto TOUCH_MISO_PIN = GPIO_NUM_4; +constexpr auto TOUCH_MOSI_PIN = GPIO_NUM_3; +constexpr auto TOUCH_SCK_PIN = GPIO_NUM_1; +constexpr auto TOUCH_CS_PIN = GPIO_NUM_2; +constexpr auto TOUCH_IRQ_PIN = GPIO_NUM_9; + +// Factory function for registration +std::shared_ptr createDisplay(); diff --git a/Devices/lilygo-thmi-s3/Source/devices/Power.cpp b/Devices/lilygo-thmi-s3/Source/devices/Power.cpp new file mode 100644 index 000000000..febacad19 --- /dev/null +++ b/Devices/lilygo-thmi-s3/Source/devices/Power.cpp @@ -0,0 +1,12 @@ +#include "Power.h" + +#include +#include + +std::shared_ptr createPower() { + ChargeFromAdcVoltage::Configuration configuration; + // 2.0 ratio, but +.11 added as display voltage sag compensation. + configuration.adcMultiplier = 2.11; + + return std::make_shared(configuration); +} \ No newline at end of file diff --git a/Devices/lilygo-thmi-s3/Source/devices/Power.h b/Devices/lilygo-thmi-s3/Source/devices/Power.h new file mode 100644 index 000000000..8fe275bab --- /dev/null +++ b/Devices/lilygo-thmi-s3/Source/devices/Power.h @@ -0,0 +1,10 @@ +#pragma once + +#include +#include +#include + +constexpr auto TDISPLAY_S3_POWEREN_GPIO = GPIO_NUM_10; +constexpr auto TDISPLAY_S3_POWERON_GPIO = GPIO_NUM_14; + +std::shared_ptr createPower(); diff --git a/Devices/lilygo-thmi-s3/Source/devices/SdCard.cpp b/Devices/lilygo-thmi-s3/Source/devices/SdCard.cpp new file mode 100644 index 000000000..09761bf38 --- /dev/null +++ b/Devices/lilygo-thmi-s3/Source/devices/SdCard.cpp @@ -0,0 +1,22 @@ +#include "SdCard.h" + +#include +#include + +using tt::hal::sdcard::SdmmcDevice; + +std::shared_ptr createSdCard() { + auto configuration = std::make_unique( + SD_DIO_SCLK, //CLK + SD_DIO_CMD, //CMD + SD_DIO_DATA0, //D0 + SD_DIO_NC, //D1 + SD_DIO_NC, //D2 + SD_DIO_NC, //D3 + SdCardDevice::MountBehaviour::AtBoot + ); + + return std::make_shared( + std::move(configuration) + ); +} diff --git a/Devices/lilygo-thmi-s3/Source/devices/SdCard.h b/Devices/lilygo-thmi-s3/Source/devices/SdCard.h new file mode 100644 index 000000000..390378e62 --- /dev/null +++ b/Devices/lilygo-thmi-s3/Source/devices/SdCard.h @@ -0,0 +1,14 @@ +#pragma once + +#include + +#include "Tactility/hal/sdcard/SdCardDevice.h" + +using tt::hal::sdcard::SdCardDevice; + +constexpr auto SD_DIO_CMD = GPIO_NUM_11; +constexpr auto SD_DIO_SCLK = GPIO_NUM_12; +constexpr auto SD_DIO_DATA0 = GPIO_NUM_13; +constexpr auto SD_DIO_NC = GPIO_NUM_NC; + +std::shared_ptr createSdCard(); \ No newline at end of file diff --git a/Devices/lilygo-thmi-s3/Source/module.cpp b/Devices/lilygo-thmi-s3/Source/module.cpp new file mode 100644 index 000000000..5952d11b1 --- /dev/null +++ b/Devices/lilygo-thmi-s3/Source/module.cpp @@ -0,0 +1,24 @@ +#include + +extern "C" { + +static error_t start() { + // Empty for now + return ERROR_NONE; +} + +static error_t stop() { + // Empty for now + return ERROR_NONE; +} + +/** @warning The variable name must be exactly "device_module" */ +struct Module device_module = { + .name = "lilygo-thmi-s3", + .start = start, + .stop = stop, + .symbols = nullptr, + .internal = nullptr +}; + +} diff --git a/Devices/lilygo-thmi-s3/device.properties b/Devices/lilygo-thmi-s3/device.properties new file mode 100644 index 000000000..9e70d045c --- /dev/null +++ b/Devices/lilygo-thmi-s3/device.properties @@ -0,0 +1,23 @@ +[general] +vendor=LilyGO +name=T-HMI S3 + +[apps] +launcherAppId=Launcher + +[hardware] +target=ESP32S3 +flashSize=16MB +spiRam=true +spiRamMode=OCT +spiRamSpeed=120M +tinyUsb=true +esptoolFlashFreq=120M + +[display] +size=2.8" +shape=rectangle +dpi=125 + +[lvgl] +colorDepth=16 diff --git a/Devices/lilygo-thmi-s3/devicetree.yaml b/Devices/lilygo-thmi-s3/devicetree.yaml new file mode 100644 index 000000000..0474b6950 --- /dev/null +++ b/Devices/lilygo-thmi-s3/devicetree.yaml @@ -0,0 +1,3 @@ +dependencies: + - Platforms/platform-esp32 +dts: lilygo,thmi-s3.dts diff --git a/Devices/lilygo-thmi-s3/lilygo,thmi-s3.dts b/Devices/lilygo-thmi-s3/lilygo,thmi-s3.dts new file mode 100644 index 000000000..8bc85203a --- /dev/null +++ b/Devices/lilygo-thmi-s3/lilygo,thmi-s3.dts @@ -0,0 +1,16 @@ +/dts-v1/; + +#include +#include +#include +#include + +/ { + compatible = "root"; + model = "LilyGO T-HMI S3"; + + gpio0 { + compatible = "espressif,esp32-gpio"; + gpio-count = <49>; + }; +}; diff --git a/changes.diff b/changes.diff new file mode 100644 index 000000000..e69de29bb From 83a9e75f9bbda4b203d9ffd031a98495c6793fbe Mon Sep 17 00:00:00 2001 From: Rivair Sabino dos Santos <65681783+Revers-BR@users.noreply.github.com> Date: Sat, 21 Feb 2026 10:03:48 -0300 Subject: [PATCH 2/6] Update Devices/lilygo-thmi-s3/Source/devices/Power.h Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> --- Devices/lilygo-thmi-s3/Source/devices/Power.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Devices/lilygo-thmi-s3/Source/devices/Power.h b/Devices/lilygo-thmi-s3/Source/devices/Power.h index 8fe275bab..f54de9355 100644 --- a/Devices/lilygo-thmi-s3/Source/devices/Power.h +++ b/Devices/lilygo-thmi-s3/Source/devices/Power.h @@ -4,7 +4,7 @@ #include #include -constexpr auto TDISPLAY_S3_POWEREN_GPIO = GPIO_NUM_10; -constexpr auto TDISPLAY_S3_POWERON_GPIO = GPIO_NUM_14; +constexpr auto THMI_S3_POWEREN_GPIO = GPIO_NUM_10; +constexpr auto THMI_S3_POWERON_GPIO = GPIO_NUM_14; std::shared_ptr createPower(); From fbc17faf81eb0f22fffacc66075a0d49eb5cf262 Mon Sep 17 00:00:00 2001 From: Revers-BR Date: Sat, 21 Feb 2026 10:19:23 -0300 Subject: [PATCH 3/6] Fix GPIO pin configuration for power control and update button control initialization --- Devices/lilygo-thmi-s3/Source/Configuration.cpp | 2 +- Devices/lilygo-thmi-s3/Source/Init.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Devices/lilygo-thmi-s3/Source/Configuration.cpp b/Devices/lilygo-thmi-s3/Source/Configuration.cpp index e66e1c3e5..36d4497b5 100644 --- a/Devices/lilygo-thmi-s3/Source/Configuration.cpp +++ b/Devices/lilygo-thmi-s3/Source/Configuration.cpp @@ -14,7 +14,7 @@ static std::vector> createDevices() { createPower(), createSdCard(), createDisplay(), - ButtonControl::createTwoButtonControl(0, 14), + ButtonControl::createTwoButtonControl(0), }; } diff --git a/Devices/lilygo-thmi-s3/Source/Init.cpp b/Devices/lilygo-thmi-s3/Source/Init.cpp index d42a6ed7c..8b4b5a990 100644 --- a/Devices/lilygo-thmi-s3/Source/Init.cpp +++ b/Devices/lilygo-thmi-s3/Source/Init.cpp @@ -9,7 +9,7 @@ static bool powerOn() { gpio_config_t power_signal_config = { - .pin_bit_mask = (1ULL << TDISPLAY_S3_POWERON_GPIO) | (1ULL << TDISPLAY_S3_POWEREN_GPIO), + .pin_bit_mask = (1ULL << THMI_S3_POWERON_GPIO) | (1ULL << THMI_S3_POWEREN_GPIO), .mode = GPIO_MODE_OUTPUT, .pull_up_en = GPIO_PULLUP_DISABLE, .pull_down_en = GPIO_PULLDOWN_DISABLE, From 35532be701ce45b187a804bd31145f1327c1c536 Mon Sep 17 00:00:00 2001 From: Revers-BR Date: Sat, 21 Feb 2026 10:21:04 -0300 Subject: [PATCH 4/6] Fix GPIO pin references for power control in initBoot function --- Devices/lilygo-thmi-s3/Source/Init.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Devices/lilygo-thmi-s3/Source/Init.cpp b/Devices/lilygo-thmi-s3/Source/Init.cpp index 8b4b5a990..7e251db5e 100644 --- a/Devices/lilygo-thmi-s3/Source/Init.cpp +++ b/Devices/lilygo-thmi-s3/Source/Init.cpp @@ -20,11 +20,11 @@ static bool powerOn() { return false; } - if (gpio_set_level(TDISPLAY_S3_POWERON_GPIO, 1) != ESP_OK) { + if (gpio_set_level(THMI_S3_POWERON_GPIO, 1) != ESP_OK) { return false; } - if (gpio_set_level(TDISPLAY_S3_POWEREN_GPIO, 1) != ESP_OK) { + if (gpio_set_level(THMI_S3_POWEREN_GPIO, 1) != ESP_OK) { return false; } From 2ffd7f17e0331550667729356dbe62c5784480eb Mon Sep 17 00:00:00 2001 From: Revers-BR Date: Sat, 21 Feb 2026 10:25:12 -0300 Subject: [PATCH 5/6] Replace two-button control with one-button control in device creation --- Devices/lilygo-thmi-s3/Source/Configuration.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Devices/lilygo-thmi-s3/Source/Configuration.cpp b/Devices/lilygo-thmi-s3/Source/Configuration.cpp index 36d4497b5..817da37e7 100644 --- a/Devices/lilygo-thmi-s3/Source/Configuration.cpp +++ b/Devices/lilygo-thmi-s3/Source/Configuration.cpp @@ -14,7 +14,7 @@ static std::vector> createDevices() { createPower(), createSdCard(), createDisplay(), - ButtonControl::createTwoButtonControl(0), + ButtonControl::createOneButtonControl(0) }; } From 87276feb7009a7c88a056dbe0cb98d5592c98a7a Mon Sep 17 00:00:00 2001 From: Revers-BR Date: Sat, 21 Feb 2026 10:43:52 -0300 Subject: [PATCH 6/6] Refactor SD card configuration to include bus width and remove unnecessary backlight setting --- Devices/lilygo-thmi-s3/Source/Init.cpp | 2 -- Devices/lilygo-thmi-s3/Source/devices/SdCard.cpp | 3 ++- Devices/lilygo-thmi-s3/Source/devices/SdCard.h | 1 + 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Devices/lilygo-thmi-s3/Source/Init.cpp b/Devices/lilygo-thmi-s3/Source/Init.cpp index 7e251db5e..f64d64c37 100644 --- a/Devices/lilygo-thmi-s3/Source/Init.cpp +++ b/Devices/lilygo-thmi-s3/Source/Init.cpp @@ -43,7 +43,5 @@ bool initBoot() { return false; } - driver::pwmbacklight::setBacklightDuty(100); - return true; } \ No newline at end of file diff --git a/Devices/lilygo-thmi-s3/Source/devices/SdCard.cpp b/Devices/lilygo-thmi-s3/Source/devices/SdCard.cpp index 09761bf38..03137e90b 100644 --- a/Devices/lilygo-thmi-s3/Source/devices/SdCard.cpp +++ b/Devices/lilygo-thmi-s3/Source/devices/SdCard.cpp @@ -13,7 +13,8 @@ std::shared_ptr createSdCard() { SD_DIO_NC, //D1 SD_DIO_NC, //D2 SD_DIO_NC, //D3 - SdCardDevice::MountBehaviour::AtBoot + SdCardDevice::MountBehaviour::AtBoot, + SD_DIO_BUS_WIDTH ); return std::make_shared( diff --git a/Devices/lilygo-thmi-s3/Source/devices/SdCard.h b/Devices/lilygo-thmi-s3/Source/devices/SdCard.h index 390378e62..ab4ec439f 100644 --- a/Devices/lilygo-thmi-s3/Source/devices/SdCard.h +++ b/Devices/lilygo-thmi-s3/Source/devices/SdCard.h @@ -10,5 +10,6 @@ constexpr auto SD_DIO_CMD = GPIO_NUM_11; constexpr auto SD_DIO_SCLK = GPIO_NUM_12; constexpr auto SD_DIO_DATA0 = GPIO_NUM_13; constexpr auto SD_DIO_NC = GPIO_NUM_NC; +constexpr auto SD_DIO_BUS_WIDTH = 1; std::shared_ptr createSdCard(); \ No newline at end of file