From 8705be7b38a3d767bd13b2005d323221590062a3 Mon Sep 17 00:00:00 2001 From: Manuel <71137295+mverch67@users.noreply.github.com> Date: Fri, 6 Mar 2026 20:39:04 +0100 Subject: [PATCH] T-Display S3 Pro LR1121 --- boards/t-display-s3.json | 39 ++++++ platformio.ini | 2 +- src/graphics/TFTDisplay.cpp | 2 +- src/mesh/NodeDB.cpp | 2 +- .../esp32s3/tdisplay-s3pro/pins_arduino.h | 19 +++ .../esp32s3/tdisplay-s3pro/platformio.ini | 84 ++++++++++++ variants/esp32s3/tdisplay-s3pro/rfswitch.h | 11 ++ variants/esp32s3/tdisplay-s3pro/variant.cpp | 57 ++++++++ variants/esp32s3/tdisplay-s3pro/variant.h | 124 ++++++++++++++++++ 9 files changed, 337 insertions(+), 3 deletions(-) create mode 100644 boards/t-display-s3.json create mode 100644 variants/esp32s3/tdisplay-s3pro/pins_arduino.h create mode 100644 variants/esp32s3/tdisplay-s3pro/platformio.ini create mode 100644 variants/esp32s3/tdisplay-s3pro/rfswitch.h create mode 100644 variants/esp32s3/tdisplay-s3pro/variant.cpp create mode 100644 variants/esp32s3/tdisplay-s3pro/variant.h diff --git a/boards/t-display-s3.json b/boards/t-display-s3.json new file mode 100644 index 000000000..b8823b4bd --- /dev/null +++ b/boards/t-display-s3.json @@ -0,0 +1,39 @@ +{ + "build": { + "arduino": { + "ldscript": "esp32s3_out.ld", + "memory_type": "qio_opi" + }, + "core": "esp32", + "extra_flags": [ + "-DBOARD_HAS_PSRAM", + "-DARDUINO_USB_CDC_ON_BOOT=1", + "-DARDUINO_USB_MODE=0", + "-DARDUINO_RUNNING_CORE=1", + "-DARDUINO_EVENT_RUNNING_CORE=1" + ], + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "hwids": [["0x303A", "0x1001"]], + "mcu": "esp32s3", + "variant": "esp32s3" + }, + "connectivity": ["wifi", "bluetooth", "lora"], + "debug": { + "default_tool": "esp-builtin", + "onboard_tools": ["esp-builtin"], + "openocd_target": "esp32s3.cfg" + }, + "frameworks": ["arduino", "espidf"], + "name": "LilyGO T-Display S3 Pro LR1121 (16 MB FLASH, 8 MB PSRAM)", + "upload": { + "flash_size": "16MB", + "maximum_ram_size": 327680, + "maximum_size": 16777216, + "require_upload_port": true, + "speed": 921600 + }, + "url": "https://lilygo.cc/en-de/products/t-display-s3-pro-lr1121", + "vendor": "LilyGO" +} diff --git a/platformio.ini b/platformio.ini index c82cfd11c..99b061840 100644 --- a/platformio.ini +++ b/platformio.ini @@ -122,7 +122,7 @@ lib_deps = [device-ui_base] lib_deps = # renovate: datasource=git-refs depName=meshtastic/device-ui packageName=https://github.com/meshtastic/device-ui gitBranch=master - https://github.com/meshtastic/device-ui/archive/6c75195e9987b7a49563232234f2f868dd343cae.zip + https://github.com/meshtastic/device-ui/archive/2d306656cd67ec3dc3d86eb3ea062a30511f6c4c.zip ; Common libs for environmental measurements in telemetry module [environmental_base] diff --git a/src/graphics/TFTDisplay.cpp b/src/graphics/TFTDisplay.cpp index 1c2eb72d4..dfff66604 100644 --- a/src/graphics/TFTDisplay.cpp +++ b/src/graphics/TFTDisplay.cpp @@ -1496,7 +1496,7 @@ bool TFTDisplay::connect() attachInterrupt(digitalPinToInterrupt(SCREEN_TOUCH_INT), rak14014_tpIntHandle, FALLING); #elif defined(T_DECK) || defined(PICOMPUTER_S3) || defined(CHATTER_2) tft->setRotation(1); // T-Deck has the TFT in landscape -#elif defined(T_WATCH_S3) +#elif defined(T_WATCH_S3) || defined(T_DISPLAY_S3_PRO) tft->setRotation(2); // T-Watch S3 left-handed orientation #elif ARCH_PORTDUINO || defined(SENSECAP_INDICATOR) || defined(T_LORA_PAGER) tft->setRotation(0); // use config.yaml to set rotation diff --git a/src/mesh/NodeDB.cpp b/src/mesh/NodeDB.cpp index 529f50003..9c05dbfad 100644 --- a/src/mesh/NodeDB.cpp +++ b/src/mesh/NodeDB.cpp @@ -681,7 +681,7 @@ void NodeDB::installDefaultConfig(bool preserveKey = false) strncpy(config.network.ntp_server, "meshtastic.pool.ntp.org", 32); #if (defined(T_DECK) || defined(T_WATCH_S3) || defined(UNPHONE) || defined(PICOMPUTER_S3) || defined(SENSECAP_INDICATOR) || \ - defined(ELECROW_PANEL) || defined(HELTEC_V4_TFT)) && \ + defined(ELECROW_PANEL) || defined(HELTEC_V4_TFT) || defined(T_DISPLAY_S3_PRO)) && \ HAS_TFT // switch BT off by default; use TFT programming mode or hotkey to enable config.bluetooth.enabled = false; diff --git a/variants/esp32s3/tdisplay-s3pro/pins_arduino.h b/variants/esp32s3/tdisplay-s3pro/pins_arduino.h new file mode 100644 index 000000000..a764e2afb --- /dev/null +++ b/variants/esp32s3/tdisplay-s3pro/pins_arduino.h @@ -0,0 +1,19 @@ +#ifndef Pins_Arduino_h +#define Pins_Arduino_h + +#include + +#define USB_VID 0x303a +#define USB_PID 0x1001 + +// used for keyboard, battery gauge, charger and haptic driver +static const uint8_t SDA = 5; +static const uint8_t SCL = 6; + +// Default SPI will be mapped to Radio +static const uint8_t SS = 7; +static const uint8_t MOSI = 17; +static const uint8_t MISO = 8; +static const uint8_t SCK = 18; + +#endif /* Pins_Arduino_h */ diff --git a/variants/esp32s3/tdisplay-s3pro/platformio.ini b/variants/esp32s3/tdisplay-s3pro/platformio.ini new file mode 100644 index 000000000..c55221b87 --- /dev/null +++ b/variants/esp32s3/tdisplay-s3pro/platformio.ini @@ -0,0 +1,84 @@ +; LilyGo T-Display S3 Pro LR1121 +[env:tdisplay-s3-pro] +custom_meshtastic_hw_model = 103 +custom_meshtastic_hw_model_slug = T_DISPLAY_S3_PRO +custom_meshtastic_architecture = esp32-s3 +custom_meshtastic_actively_supported = true +custom_meshtastic_support_level = 1 +custom_meshtastic_display_name = LILYGO T-Display S3 Pro +custom_meshtastic_images = lilygo-tdisplay-s3-pro.svg +custom_meshtastic_tags = LilyGo +custom_meshtastic_requires_dfu = true +custom_meshtastic_partition_scheme = 16MB + +extends = esp32s3_base +board = t-display-s3 +board_check = true +board_build.partitions = default_16MB.csv +upload_protocol = esptool + +build_src_filter = + ${esp32s3_base.build_src_filter} + +<../variants/esp32s3/tdisplay-s3pro> + +build_flags = ${esp32s3_base.build_flags} + -I variants/esp32s3/tdisplay-s3pro + -D T_DISPLAY_S3_PRO + -D BOARD_HAS_PSRAM +; -D USE_ST7796 + -D HAS_SDCARD + +lib_deps = ${esp32s3_base.lib_deps} + # renovate: datasource=custom.pio depName=LovyanGFX packageName=lovyan03/library/LovyanGFX + lovyan03/LovyanGFX@1.2.19 + # renovate: datasource=custom.pio depName=ESP8266Audio packageName=earlephilhower/library/ESP8266Audio + earlephilhower/ESP8266Audio@1.9.9 + # renovate: datasource=custom.pio depName=ESP8266SAM packageName=earlephilhower/library/ESP8266SAM + earlephilhower/ESP8266SAM@1.1.0 + # renovate: datasource=custom.pio depName=Adafruit DRV2605 packageName=adafruit/library/Adafruit DRV2605 Library + lewisxhe/PCF8563_Library@1.0.1 + # renovate: datasource=custom.pio depName=SensorLib packageName=lewisxhe/library/SensorLib + lewisxhe/SensorLib@0.3.4 + +[env:tdisplay-s3-pro-tft] +board_level = extra +extends = env:tdisplay-s3-pro +build_flags = + ${env:tdisplay-s3-pro.build_flags} + -D CONFIG_DISABLE_HAL_LOCKS=1 + -D INPUTDRIVER_ENCODER_TYPE=2 + -D INPUTDRIVER_ENCODER_LEFT=12 + -D INPUTDRIVER_ENCODER_RIGHT=16 + -D INPUTDRIVER_ENCODER_BTN=0 + -D HAS_SCREEN=1 + -D HAS_TFT=1 + -D USE_I2S_BUZZER + -D RAM_SIZE=5120 + -D LV_LVGL_H_INCLUDE_SIMPLE + -D LV_CONF_INCLUDE_SIMPLE + -D LV_COMP_CONF_INCLUDE_SIMPLE + -D LV_USE_SYSMON=0 + -D LV_USE_PROFILER=0 + -D LV_USE_PERF_MONITOR=0 + -D LV_USE_MEM_MONITOR=0 + -D LV_USE_LOG=0 + -D USE_LOG_DEBUG + -D LOG_DEBUG_INC=\"DebugConfiguration.h\" + -D RADIOLIB_SPI_PARANOID=0 + -D LGFX_SCREEN_WIDTH=222 + -D LGFX_SCREEN_HEIGHT=480 + -D LGFX_BUFSIZE=617460 + -D DISPLAY_SIZE=480x222 ; landscape mode + -D DISPLAY_SET_RESOLUTION + -D LGFX_DRIVER=LGFX_TDISPLAY_S3PRO + -D GFX_DRIVER_INC=\"graphics/LGFX/LGFX_TDISPLAY_S3PRO.h\" +; -D LVGL_DRIVER=LVGL_TDISPLAY_S3PRO +; -D LV_USE_ST7796=1 + -D VIEW_480x222 + -D CUSTOM_TOUCH_DRIVER + -D USE_PACKET_API + -D MAP_FULL_REDRAW + +lib_deps = + ${env:tdisplay-s3-pro.lib_deps} + ${device-ui_base.lib_deps} diff --git a/variants/esp32s3/tdisplay-s3pro/rfswitch.h b/variants/esp32s3/tdisplay-s3pro/rfswitch.h new file mode 100644 index 000000000..589f24767 --- /dev/null +++ b/variants/esp32s3/tdisplay-s3pro/rfswitch.h @@ -0,0 +1,11 @@ +#include "RadioLib.h" + +static const uint32_t rfswitch_dio_pins[] = {RADIOLIB_LR11X0_DIO5, RADIOLIB_LR11X0_DIO6, RADIOLIB_NC, RADIOLIB_NC, RADIOLIB_NC}; + +static const Module::RfSwitchMode_t rfswitch_table[] = { + // mode DIO5 DIO6 + {LR11x0::MODE_STBY, {LOW, LOW}}, {LR11x0::MODE_RX, {HIGH, LOW}}, + {LR11x0::MODE_TX, {LOW, HIGH}}, {LR11x0::MODE_TX_HP, {LOW, HIGH}}, + {LR11x0::MODE_TX_HF, {LOW, LOW}}, {LR11x0::MODE_GNSS, {LOW, LOW}}, + {LR11x0::MODE_WIFI, {LOW, LOW}}, END_OF_MODE_TABLE, +}; diff --git a/variants/esp32s3/tdisplay-s3pro/variant.cpp b/variants/esp32s3/tdisplay-s3pro/variant.cpp new file mode 100644 index 000000000..19be76923 --- /dev/null +++ b/variants/esp32s3/tdisplay-s3pro/variant.cpp @@ -0,0 +1,57 @@ +#include "variant.h" +#include "Arduino.h" +#include "configuration.h" + +void earlyInitVariant() +{ + pinMode(LORA_CS, OUTPUT); + digitalWrite(LORA_CS, HIGH); + pinMode(SDCARD_CS, OUTPUT); + digitalWrite(SDCARD_CS, HIGH); + pinMode(TFT_CS, OUTPUT); + digitalWrite(TFT_CS, HIGH); + pinMode(MAX98357A_EN, OUTPUT); + digitalWrite(MAX98357A_EN, HIGH); +} + +#ifdef HAS_CST226SE // only for BUI + +#include "TouchDrvCSTXXX.hpp" +#include "input/TouchScreenImpl1.h" +#include + +TouchDrvCSTXXX tsPanel; +static constexpr uint8_t PossibleAddresses[2] = {CST328_ADDR, CST226SE_ADDR_ALT}; +uint8_t i2cAddress = 0; + +bool readTouch(int16_t *x, int16_t *y) +{ + int16_t x_array[1], y_array[1]; + uint8_t touched = tsPanel.getPoint(x_array, y_array, 1); + if (touched > 0) { + *y = x_array[0]; + *x = (TFT_WIDTH - y_array[0]); + // Check bounds + if (*x < 0 || *x >= TFT_WIDTH || *y < 0 || *y >= TFT_HEIGHT) { + return false; + } + return true; // Valid touch detected + } + return false; // No valid touch data +} + +void lateInitVariant() +{ + tsPanel.setTouchDrvModel(TouchDrv_CST226); + for (uint8_t addr : PossibleAddresses) { + if (tsPanel.begin(Wire, addr, I2C_SDA, I2C_SCL)) { + i2cAddress = addr; + LOG_DEBUG("CST226SE init OK at address 0x%02X", addr); + touchScreenImpl1 = new TouchScreenImpl1(TFT_WIDTH, TFT_HEIGHT, readTouch); + touchScreenImpl1->init(); + return; + } + } + LOG_ERROR("CST226SE init failed at all known addresses"); +} +#endif diff --git a/variants/esp32s3/tdisplay-s3pro/variant.h b/variants/esp32s3/tdisplay-s3pro/variant.h new file mode 100644 index 000000000..442a508d1 --- /dev/null +++ b/variants/esp32s3/tdisplay-s3pro/variant.h @@ -0,0 +1,124 @@ +// ST7796 TFT LCD +#define TFT_CS 39 +#define ST7796_CS TFT_CS +#define ST7796_RS 9 // DC +#define ST7796_SDA MOSI // MOSI +#define ST7796_SCK SCK +#define ST7796_RESET -1 +#define ST7796_MISO MISO +#define ST7796_BUSY -1 +#define ST7796_BL 48 +#define ST7796_SPI_HOST SPI2_HOST +#define TFT_BL 48 +#define SPI_FREQUENCY 75000000 +#define SPI_READ_FREQUENCY 16000000 +#define TFT_HEIGHT 480 +#define TFT_WIDTH 222 +#define TFT_OFFSET_X 49 +#define TFT_OFFSET_Y 0 +#define TFT_OFFSET_ROTATION 3 +#define SCREEN_ROTATE +#define SCREEN_TRANSITION_FRAMERATE 5 +#define BRIGHTNESS_DEFAULT 130 // Medium Low Brightness +#define USE_TFTDISPLAY 1 + +#define I2C_SDA SDA +#define I2C_SCL SCL + +// #define I2C_SDA1 +// #define I2C_SCL1 + +#define USE_POWERSAVE +#define SLEEP_TIME 120 + +#define PIN_POWER_EN 42 + +// GNNS +#define GPS_DEFAULT_NOT_PRESENT 1 + +// PCF85063 RTC Module +#define PCF85063_RTC 0x51 + +// SY6970 battery charger +#define SY6970_Address 0x6A +#define SY6970_INT 21 + +// MAX98357A PCM amplifier +#define HAS_I2S +#define DAC_I2S_BCK 4 +#define DAC_I2S_WS 15 +#define DAC_I2S_DOUT 11 +#define DAC_I2S_MCLK 13 // not used +#define MAX98357A_EN 41 + +// ICM20948 motion tracker +#define ICM20948_ADDRESS 0x28 +#define ICM20948_INT 21 + +// MP34DT05TRF MEMS mic +#define MP34DT05TR_LRCLK 1 +#define MP34DT05TR_DATA 2 +#define MP34DT05TR_EN 3 + +#define BUTTON_PIN 16 +#define BUTTON_NEED_PULLUP +#define ALT_BUTTON_PIN 12 +#define ALT_BUTTON_ACTIVE_LOW true +#define ALT_BUTTON_ACTIVE_PULLUP true +#define PIN_BUTTON3 0 + +// vibration motor +#define PIN_VIBRATION 45 + +// SPI interface SD card slot +#define SPI_MOSI MOSI +#define SPI_SCK SCK +#define SPI_MISO MISO +#define SPI_CS 14 +#define SDCARD_CS SPI_CS +#define SD_SPI_FREQUENCY 75000000U + +// LoRa +// #define USE_SX1262 +// #define USE_SX1268 +// #define USE_SX1280 +#define USE_LR1121 + +#define LORA_SCK 18 +#define LORA_MISO 8 +#define LORA_MOSI 17 +#define LORA_CS 7 +#define LORA_RESET 10 + +#define LORA_DIO0 -1 // a No connect on the SX1262 module +#define LORA_DIO1 40 // SX1262 IRQ +#define LORA_DIO2 46 // SX1262 BUSY +#define LORA_DIO3 // Not connected on PCB, but internally on the TTGO SX1262, if DIO3 is high the TXCO is enabled + +#if defined(USE_SX1262) || defined(USE_SX1268) +#define SX126X_CS LORA_CS +#define SX126X_DIO1 LORA_DIO1 +#define SX126X_BUSY LORA_DIO2 +#define SX126X_RESET LORA_RESET +#define SX126X_DIO2_AS_RF_SWITCH +#define SX126X_DIO3_TCXO_VOLTAGE 3.0 +#endif + +#ifdef USE_SX1280 +#define SX128X_CS LORA_CS +#define SX128X_DIO1 LORA_DIO1 +#define SX128X_BUSY LORA_DIO2 +#define SX128X_RESET LORA_RESET +#endif + +#ifdef USE_LR1121 +#define LR1121_IRQ_PIN LORA_DIO1 +#define LR1121_NRESET_PIN LORA_RESET +#define LR1121_BUSY_PIN LORA_DIO2 +#define LR1121_SPI_NSS_PIN LORA_CS +#define LR1121_SPI_SCK_PIN LORA_SCK +#define LR1121_SPI_MOSI_PIN LORA_MOSI +#define LR1121_SPI_MISO_PIN LORA_MISO +#define LR11X0_DIO3_TCXO_VOLTAGE 3.0 +#define LR11X0_DIO_AS_RF_SWITCH +#endif