Skip to content

Commit 4316f1a

Browse files
committed
feat(board): add LilyGo T-Beam Supreme support with AXP2101 and SH1106
Upgrades the existing TTGO_TBEAM_SX1262 board entry with full hardware support for the LilyGo T-Beam Supreme S3, a newer revision of the same board line. The original entry had basic pin mappings but lacked PMU support, display driver, and auto-detection. Board entry changes: - TCXO voltage 1.6V to 1.8V (Meshtastic/community standard) - LED pin uses SUPREME_LED define, GNSS pins mapped - Renamed to "433 Mhz LilyGo T-Beam Supreme SX1262" - Board index bounds check on boot prevents crash if enum changes New hardware support: - AXP2101 PMU on Wire1 (GPIO 42/41): battery voltage/percentage, VBUS, per-rail power control (ALDO1 sensors, ALDO3 radio, ALDO4 GNSS), sensor deep sleep, unused rails disabled - SH1106 OLED auto-detection with 5-minute display timeout - Auto-detection via AXP2101 probe on Wire1 in boardDetection() - DIO2 RF switch enable for SX1262/SX1268 - Battery voltage via Power API replacing raw analogRead(36) median-sort Includes board JSON, PlatformIO env, and setup documentation. 433 MHz SX1262 variant only.
1 parent fa58833 commit 4316f1a

File tree

14 files changed

+455
-130
lines changed

14 files changed

+455
-130
lines changed

boards/lilygo-t-beam-supreme.json

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
{
2+
"build": {
3+
"arduino":{
4+
"ldscript": "esp32s3_out.ld",
5+
"partitions": "default.csv",
6+
"memory_type": "qio_qspi"
7+
},
8+
"core": "esp32",
9+
"extra_flags": [
10+
"-DARDUINO_USB_MODE=1",
11+
"-DARDUINO_USB_CDC_ON_BOOT=1",
12+
"-DARDUINO_RUNNING_CORE=1",
13+
"-DARDUINO_EVENT_RUNNING_CORE=1"
14+
],
15+
"f_cpu": "240000000L",
16+
"f_flash": "80000000L",
17+
"flash_mode": "qio",
18+
"hwids": [
19+
[
20+
"0x303A",
21+
"0x1001"
22+
]
23+
],
24+
"mcu": "esp32s3",
25+
"variant": "esp32s3"
26+
},
27+
"connectivity": [
28+
"wifi"
29+
],
30+
"debug": {
31+
"default_tool": "esp-builtin",
32+
"onboard_tools": [
33+
"esp-builtin"
34+
],
35+
"openocd_target": "esp32s3.cfg"
36+
},
37+
"frameworks": [
38+
"arduino",
39+
"espidf"
40+
],
41+
"name": "LilyGo T-Beam supreme (8MB Flash 8MB PSRAM)",
42+
"upload": {
43+
"flash_size": "8MB",
44+
"maximum_ram_size": 327680,
45+
"maximum_size": 8388608,
46+
"require_upload_port": true,
47+
"speed": 460800
48+
},
49+
"url": "https://www.lilygo.cc/products/t-beamsupreme-m",
50+
"vendor": "LilyGo"
51+
}

doc/LilyGo_T-Beam_Supreme.md

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
# LilyGo T-Beam Supreme (S3) Setup for TinyGS
2+
3+
The LilyGo T-Beam Supreme is an ESP32-S3 based board with an SX1262 LoRa radio, AXP2101 PMU, and an integrated GPS (Ublox M10 or L76K).
4+
5+
## Pin Mapping (Verified)
6+
7+
| Function | Pin (GPIO) |
8+
| :--- | :--- |
9+
| **LoRa CS (NSS)** | 10 |
10+
| **LoRa DIO1** | 1 |
11+
| **LoRa BUSY** | 4 |
12+
| **LoRa RESET** | 5 |
13+
| **LoRa SCK** | 12 |
14+
| **LoRa MISO** | 13 |
15+
| **LoRa MOSI** | 11 |
16+
| **I2C SDA** | 17 |
17+
| **I2C SCL** | 18 |
18+
| **GPS TX** | 8 |
19+
| **GPS RX** | 9 |
20+
| **GPS Wakeup** | 7 |
21+
| **PMU SDA** | 42 (Wire1) |
22+
| **PMU SCL** | 41 (Wire1) |
23+
| **User Button** | 0 |
24+
| **Green LED** | 3 |
25+
26+
## Features
27+
28+
### 1. Power Management (AXP2101)
29+
- Full support for AXP2101 PMU via Wire1.
30+
- Correct battery voltage reading (1mV/bit).
31+
- Accurate fuel gauge percentage.
32+
- Automatic power control for Radio and GPS.
33+
34+
### 2. Display (SH1106)
35+
- SH1106 OLED driver (vs SSD1306 on other boards).
36+
- Auto-off after 5 minutes of inactivity to save power.
37+
- Wakes on button press or serial input.
38+
39+
### 3. Power Saving
40+
- **Shared Rail (ALDO1)**: Powers the OLED and onboard sensors (QMC5883L Compass, BME280). This rail remains active even when the display is off.
41+
- **Radio Rail (ALDO3)**: Powers the SX1262 LoRa module.
42+
- **GPS Rail (ALDO4)**: Powers the GNSS module independently.
43+
- **Unused Rails**: Unused PMU rails (ALDO2, BLDO1/2, DLDO1/2) are explicitly disabled to minimize quiescent current.
44+
45+
## Configuration
46+
47+
1. Connect to the TinyGS Access Point.
48+
2. Navigate to `http://192.168.4.1/config`.
49+
3. Select **433 Mhz LilyGo T-Beam Supreme SX1262** as the board type.
50+
4. Save and Restart.
51+
52+
## Troubleshooting
53+
54+
- **No Packets**: Ensure you are using a 433MHz or 868/915MHz antenna matching your board variant. The SX1262 pins are identical for all frequency variants.
55+
- **Battery 0.00V**: Ensure the board is selected as "Supreme" to enable the AXP2101 driver.

platformio.ini

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,3 +75,17 @@ build_flags =
7575
${env.build_flags}
7676
-DBOARD_HAS_PSRAM
7777
board_build.partitions = tinygs_4M_partition_table.csv
78+
79+
[env:lilygo-t-beam-supreme]
80+
platform = https://github.com/pioarduino/platform-espressif32/releases/download/stable/platform-espressif32.zip
81+
board = lilygo-t-beam-supreme
82+
board_build.mcu = esp32s3
83+
framework = arduino
84+
build_flags =
85+
${env.build_flags}
86+
-DARDUINO_USB_CDC_ON_BOOT=1
87+
-DBOARD_HAS_PSRAM
88+
board_build.partitions = tinygs_4M_partition_table.csv
89+
lib_deps =
90+
${env.lib_deps}
91+
mikalhart/TinyGPSPlus @ ^1.0.3

tinyGS/src/ConfigManager/ConfigManager.cpp

Lines changed: 59 additions & 34 deletions
Large diffs are not rendered by default.

tinyGS/src/ConfigManager/ConfigManager.h

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,14 @@ constexpr auto configVersion = "0.05"; //max 4 chars
6969
#define MQTT_DEFAULT_SERVER "mqtt.tinygs.com"
7070
#define MQTT_DEFAULT_PORT "8883"
7171

72+
// T-Beam Supreme specific pins (Wire1 for PMU, separate from OLED Wire bus)
73+
#define SUPREME_GNSS_RX 9
74+
#define SUPREME_GNSS_TX 8
75+
#define SUPREME_GNSS_WAKEUP 7
76+
#define SUPREME_PMU_SDA 42
77+
#define SUPREME_PMU_SCL 41
78+
#define SUPREME_LED 3
79+
7280
constexpr auto AP_TIMEOUT_MS = "300000";
7381

7482
enum boardNum
@@ -129,15 +137,18 @@ struct board_t
129137
float L_TCXO_V;
130138
uint8_t RX_EN;
131139
uint8_t TX_EN;
140+
uint8_t GNSS_RX;
141+
uint8_t GNSS_TX;
142+
uint8_t GNSS_WAKEUP;
132143
String BOARD;
133144

134145
board_t() = default;
135146
board_t(uint8_t oled_addr, uint8_t oled_sda, uint8_t oled_scl, uint8_t oled_rst, uint8_t prog_btn, uint8_t board_led,
136147
uint8_t l_radio, uint8_t l_nss, uint8_t l_di00, uint8_t l_di01, uint8_t l_bussy, uint8_t l_rst, uint8_t l_miso, uint8_t l_mosi, uint8_t l_sck,
137-
float l_tcxo_v, uint8_t rx_en, uint8_t tx_en, String board_name)
148+
float l_tcxo_v, uint8_t rx_en, uint8_t tx_en, uint8_t gnss_rx, uint8_t gnss_tx, uint8_t gnss_wakeup, String board_name)
138149
: OLED__address(oled_addr), OLED__SDA(oled_sda), OLED__SCL(oled_scl), OLED__RST(oled_rst), PROG__BUTTON(prog_btn), BOARD_LED(board_led),
139150
L_radio(l_radio), L_NSS(l_nss), L_DI00(l_di00), L_DI01(l_di01), L_BUSSY(l_bussy), L_RST(l_rst), L_MISO(l_miso), L_MOSI(l_mosi), L_SCK(l_sck),
140-
L_TCXO_V(l_tcxo_v), RX_EN(rx_en), TX_EN(tx_en), BOARD(board_name) {}
151+
L_TCXO_V(l_tcxo_v), RX_EN(rx_en), TX_EN(tx_en), GNSS_RX(gnss_rx), GNSS_TX(gnss_tx), GNSS_WAKEUP(gnss_wakeup), BOARD(board_name) {}
141152
};
142153

143154
const uint8_t UNUSED = -1;

tinyGS/src/ConfigManager/html.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ const char BOARD_NAMES[][BOARD_NAME_LENGTH] PROGMEM =
2929
#if CONFIG_IDF_TARGET_ESP32S3
3030
"433MHz HELTEC LORA32 V3",
3131
"Custom ESP32-S3 433MHz SX1278",
32-
"433 Mhz TTGO T-Beam Sup SX1262 V1.0",
32+
"433 Mhz LilyGo T-Beam Supreme SX1262",
3333
"2.4Ghz LILYGO SX1280",
3434
#elif CONFIG_IDF_TARGET_ESP32C3
3535
"433MHz HELTEC LORA32 HT-CT62 SX1262",
@@ -64,7 +64,7 @@ const char BOARD_NAMES[][BOARD_NAME_LENGTH] PROGMEM =
6464
constexpr auto BOARD_LENGTH = 3;
6565

6666
#if CONFIG_IDF_TARGET_ESP32S3
67-
const char BOARD_VALUES[][BOARD_LENGTH] PROGMEM = {"0", "1", "2","3" };
67+
const char BOARD_VALUES[][BOARD_LENGTH] PROGMEM = {"0", "1", "2", "3" };
6868
#elif CONFIG_IDF_TARGET_ESP32C3
6969
const char BOARD_VALUES[][BOARD_LENGTH] PROGMEM = {"0", "1" };
7070
#else

tinyGS/src/Display/Display.cpp

Lines changed: 35 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,13 @@
2323
#include "../Mqtt/MQTT_credentials.h"
2424
#include "../Logger/Logger.h"
2525

26-
SSD1306* display;
26+
OLEDDisplay* display;
2727
OLEDDisplayUi* ui = NULL;
2828

29+
#define DISPLAY_TIMEOUT 300000 // 5 minutes
30+
static unsigned long lastDisplayActivity = 0;
31+
static bool displayTimedOut = false;
32+
2933
void msOverlay(OLEDDisplay *display, OLEDDisplayUiState* state);
3034
void drawFrame1(OLEDDisplay *display, OLEDDisplayUiState* state, int16_t x, int16_t y);
3135
void drawFrame2(OLEDDisplay *display, OLEDDisplayUiState* state, int16_t x, int16_t y);
@@ -55,8 +59,18 @@ void displayInit()
5559
if (!ConfigManager::getInstance().getBoardConfig(board))
5660
return;
5761

58-
display = new SSD1306(board.OLED__address, board.OLED__SDA, board.OLED__SCL);
62+
uint8_t boardIdx = ConfigManager::getInstance().getBoard();
63+
#if CONFIG_IDF_TARGET_ESP32S3
64+
if (boardIdx == TTGO_TBEAM_SX1262) {
65+
Log::console(PSTR("Display: Initializing SH1106 for T-Beam Supreme"));
66+
display = new SH1106Wire(board.OLED__address, board.OLED__SDA, board.OLED__SCL);
67+
} else
68+
#endif
69+
{
70+
display = new SSD1306Wire(board.OLED__address, board.OLED__SDA, board.OLED__SCL);
71+
}
5972

73+
lastDisplayActivity = millis();
6074
ui = new OLEDDisplayUi(display);
6175
ui->setTargetFPS(60);
6276
ui->setActiveSymbol(activeSymbol);
@@ -355,6 +369,15 @@ void displayUpdate()
355369
// Get the current OLED brightness from configuration
356370
uint8_t oledBright = ConfigManager::getInstance().getOledBright();
357371

372+
// Check display timeout
373+
if (oledBright && !displayTimedOut && (millis() - lastDisplayActivity > DISPLAY_TIMEOUT)) {
374+
displayTimedOut = true;
375+
display->displayOff();
376+
return;
377+
}
378+
379+
if (displayTimedOut) return;
380+
358381
// Check if brightness has changed
359382
if (oldOledBright != oledBright) {
360383
if (oledBright) {
@@ -374,6 +397,16 @@ void displayUpdate()
374397
}
375398
}
376399

400+
void displayResetTimeout()
401+
{
402+
lastDisplayActivity = millis();
403+
if (displayTimedOut) {
404+
displayTimedOut = false;
405+
display->displayOn();
406+
oldOledBright = -1; // force brightness reapply
407+
}
408+
}
409+
377410
void displayTurnOff()
378411
{
379412
display->displayOff();

tinyGS/src/Display/Display.h

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/*
22
Display.h - Class responsible of controlling the display
3-
3+
44
Copyright (C) 2020 -2021 @G4lile0, @gmag12 and @dev_4m1g0
55
66
This program is free software: you can redistribute it and/or modify
@@ -17,8 +17,10 @@
1717
along with this program. If not, see <https://www.gnu.org/licenses/>.
1818
*/
1919

20-
#include "SSD1306.h" // https://github.com/ThingPulse/esp8266-oled-ssd1306
21-
#include "OLEDDisplayUi.h" // https://github.com/ThingPulse/esp8266-oled-ssd1306
20+
#include "OLEDDisplay.h" // https://github.com/ThingPulse/esp8266-oled-ssd1306
21+
#include "SSD1306Wire.h"
22+
#include "SH1106Wire.h"
23+
#include "OLEDDisplayUi.h"
2224
#include "../ConfigManager/ConfigManager.h"
2325
#include "../Status.h"
2426

@@ -30,7 +32,9 @@ void displayShowStaMode(bool ap);
3032
void displayUpdate();
3133
void displayTurnOff();
3234
void displayNextFrame();
35+
void displayResetTimeout();
3336

37+
extern OLEDDisplay* display;
3438
extern Status status;
3539

36-
40+

tinyGS/src/Mqtt/MQTT_Client.cpp

Lines changed: 3 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
#include "../Radio/Radio.h"
2727
#include "../OTA/OTA.h"
2828
#include "../Logger/Logger.h"
29+
#include "../Power/Power.h"
2930
#include <esp_ota_ops.h>
3031

3132

@@ -108,7 +109,7 @@ void MQTT_Client::loop()
108109
else
109110
{
110111
StaticJsonDocument<192> doc;
111-
doc["Vbat"] = voltage();
112+
doc["Vbat"] = Power::getInstance().getBatteryVoltage();
112113
doc["Mem"] = ESP.getFreeHeap();
113114
doc["MinMem"] = ESP.getMinFreeHeap(); // Mínimo histórico
114115
doc["MaxBlk"] = ESP.getMaxAllocHeap(); // Bloque más grande disponible
@@ -249,7 +250,7 @@ void MQTT_Client::sendWelcome()
249250
doc["board"] = configManager.getBoard();
250251
doc["mac"] = clientId;
251252
doc["seconds"] = millis()/1000;
252-
doc["Vbat"] = voltage();
253+
doc["Vbat"] = Power::getInstance().getBatteryVoltage();
253254
doc["chip"] = ESP.getChipModel();
254255
doc["slot"] = esp_ota_get_running_partition ()->label;
255256
doc["pSize"] = esp_ota_get_running_partition ()->size;
@@ -1173,34 +1174,4 @@ void MQTT_Client::begin()
11731174

11741175

11751176

1176-
int MQTT_Client::voltage() {
1177-
int medianVoltage;
1178-
int length = 21;
1179-
int voltages[22];
1180-
1181-
for (int i = 0; i < 21; i++)
1182-
{
1183-
voltages[i] = analogRead(36);
1184-
}
1185-
1186-
// BubbleSortAsc from https://www.luisllamas.es/arduino-bubble-sort/
1187-
int i, j, flag = 1;
1188-
int temp;
1189-
for (i = 1; (i <= length) && flag; i++)
1190-
{
1191-
flag = 0;
1192-
for (j = 0; j < (length - 1); j++)
1193-
{
1194-
if (voltages[j + 1] < voltages[j])
1195-
{
1196-
temp = voltages[j];
1197-
voltages[j] = voltages[j + 1];
1198-
voltages[j + 1] = temp;
1199-
flag = 1;
1200-
}
1201-
}
1202-
}
1203-
medianVoltage = voltages[10];
1204-
return medianVoltage;
1205-
}
12061177

tinyGS/src/Mqtt/MQTT_Client.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -112,8 +112,6 @@ class MQTT_Client : public PubSubClient {
112112
void processRxQueue();
113113
void sendRxFromQueue(const RxPacketMessage& msg); // Envía paquete desde la cola
114114

115-
int voltage();
116-
117115
//bool usingNewCert = true;
118116
SemaphoreHandle_t radioConfigMutex;
119117
QueueHandle_t rxQueue;

0 commit comments

Comments
 (0)