Compare commits

...

11 Commits

Author SHA1 Message Date
Jonathan Bennett de97840bca Better support for SY6970 2026-05-07 23:12:02 -05:00
Jonathan Bennett 5f1fc3d324 Add support for SY6970 fot tdisplay s3 pro 2026-05-05 19:05:40 -05:00
Manuel 3d6f8a3ace Merge branch 'develop' into t-display-s3-pro 2026-04-02 23:25:05 +02:00
Manuel 201baa892a Merge branch 'develop' into t-display-s3-pro 2026-03-24 21:22:46 +01:00
Manuel 29bfba10c7 Merge branch 'develop' into t-display-s3-pro 2026-03-15 14:12:56 +01:00
Manuel 32e9c828aa touch screen fix 2026-03-08 01:22:28 +01:00
Manuel b2cbe31f27 update hw-id 2026-03-07 17:11:17 +01:00
Manuel cdb97d0c3e Merge branch 'develop' into t-display-s3-pro 2026-03-07 17:04:14 +01:00
Manuel ac81a4f075 co-pilot fixes 2026-03-07 16:53:33 +01:00
Manuel c6db6c5a91 Merge branch 'develop' into t-display-s3-pro 2026-03-06 20:55:53 +01:00
Manuel 8705be7b38 T-Display S3 Pro LR1121 2026-03-06 20:39:04 +01:00
10 changed files with 363 additions and 10 deletions
+39
View File
@@ -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"
}
+2 -1
View File
@@ -126,7 +126,8 @@ 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/7b1485b86c8d55a40e5226749097767e8b87f396.zip
https://github.com/meshtastic/device-ui/archive/91d4f76d9fc523fb86ea31ebf48fd4bcdaea43c9.zip
; Common libs for environmental measurements in telemetry module
[environmental_base]
+26 -7
View File
@@ -1495,7 +1495,15 @@ bool Power::cw2015Init()
class LipoCharger : public HasBatteryLevel
{
private:
#if defined(XPOWERS_CHIP_SY6970)
#define PPM_ADDR SY6970_ADDR
#define CHARGE_TARGET_VOLTAGE 4352
#elif defined(XPOWERS_CHIP_BQ25896)
#define PPM_CLASS BQ27220
BQ27220 *bq = nullptr;
#define PPM_ADDR BQ25896_ADDR
#define CHARGE_TARGET_VOLTAGE 4288
#endif
public:
/**
@@ -1505,12 +1513,11 @@ class LipoCharger : public HasBatteryLevel
{
if (PPM == nullptr) {
PPM = new XPowersPPM;
bool result = PPM->init(Wire, I2C_SDA, I2C_SCL, BQ25896_ADDR);
bool result = PPM->init(Wire, I2C_SDA, I2C_SCL, PPM_ADDR);
if (result) {
LOG_INFO("PPM BQ25896 init succeeded");
LOG_INFO("PPM init succeeded");
// Set the minimum operating voltage. Below this voltage, the PPM will
// protect PPM->setSysPowerDownVoltage(3100);
// Set input current limit, default is 500mA
// PPM->setInputCurrentLimit(800);
@@ -1518,7 +1525,7 @@ class LipoCharger : public HasBatteryLevel
// PPM->disableCurrentLimitPin();
// Set the charging target voltage, Range:3840 ~ 4608mV ,step:16 mV
PPM->setChargeTargetVoltage(4288);
PPM->setChargeTargetVoltage(CHARGE_TARGET_VOLTAGE);
// Set the precharge current , Range: 64mA ~ 1024mA ,step:64mA
// PPM->setPrechargeCurr(64);
@@ -1542,8 +1549,9 @@ class LipoCharger : public HasBatteryLevel
return false;
}
}
#if HAS_BQ27220
if (bq == nullptr) {
bq = new BQ27220;
bq = new PPM_CLASS;
bq->setDefaultCapacity(BQ27220_DESIGN_CAPACITY);
bool result = bq->init();
@@ -1553,13 +1561,15 @@ class LipoCharger : public HasBatteryLevel
LOG_DEBUG("BQ27220 remaining capacity: %d", bq->getRemainingCapacity());
return true;
} else {
LOG_WARN("BQ27220 init failed");
LOG_WARN("PPM init failed");
delete bq;
bq = nullptr;
return false;
}
}
return false;
#endif
return true;
}
/**
@@ -1575,7 +1585,14 @@ class LipoCharger : public HasBatteryLevel
/**
* The raw voltage of the battery in millivolts, or NAN if unknown
*/
virtual uint16_t getBattVoltage() override { return bq->getVoltage(); }
virtual uint16_t getBattVoltage() override
{
#if HAS_BQ27220
return bq->getVoltage();
#else
return PPM->getBattVoltage();
#endif
}
/**
* return true if there is a battery installed in this unit
@@ -1593,6 +1610,7 @@ class LipoCharger : public HasBatteryLevel
virtual bool isCharging() override
{
bool isCharging = PPM->isCharging();
#if HAS_BQ27220
if (isCharging) {
LOG_DEBUG("BQ27220 time to full charge: %d min", bq->getTimeToFull());
} else {
@@ -1600,6 +1618,7 @@ class LipoCharger : public HasBatteryLevel
LOG_DEBUG("BQ27220 time to empty: %d min (%d mAh)", bq->getTimeToEmpty(), bq->getRemainingCapacity());
}
}
#endif
return isCharging;
}
};
+1 -1
View File
@@ -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) || defined(HELTEC_MESH_NODE_T096)
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
+1 -1
View File
@@ -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;
@@ -0,0 +1,19 @@
#ifndef Pins_Arduino_h
#define Pins_Arduino_h
#include <stdint.h>
#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 */
@@ -0,0 +1,81 @@
; LilyGo T-Display S3 Pro LR1121
[env:tdisplay-s3-pro]
custom_meshtastic_hw_model = 126
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 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=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}
@@ -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,
};
@@ -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 BaseUI
#include "TouchDrvCSTXXX.hpp"
#include "input/TouchScreenImpl1.h"
#include <Wire.h>
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
+126
View File
@@ -0,0 +1,126 @@
// 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
// GNSS
#define GPS_DEFAULT_NOT_PRESENT 1
// PCF85063 RTC Module
#define PCF85063_RTC 0x51
// SY6970 battery charger
#define SY6970_ADDR 0x6A
#define SY6970_INT 21
#define HAS_PPM 1
#define XPOWERS_CHIP_SY6970
// 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