Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
63 changes: 57 additions & 6 deletions src/helpers/esp32/TBeamBoard.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
#if defined(TBEAM_SUPREME_SX1262) || defined(TBEAM_SX1262) || defined(TBEAM_SX1276)
#if defined(TBEAM_SUPREME_SX1262) || defined(TBEAM_1W_SX1262) || defined(TBEAM_SX1262) || defined(TBEAM_SX1276)

#include <Arduino.h>
#include "TBeamBoard.h"
Expand Down Expand Up @@ -125,11 +125,19 @@ void TBeamBoard::printPMU()

bool TBeamBoard::power_init()
{
#if defined(TBEAM_SUPREME_SX1262)
Wire1.begin(PIN_BOARD_SDA1, PIN_BOARD_SCL1);
delay(10);
#endif

delay(20); // Give I2C bus time to stabilize before PMU access

if (!PMU) {
#ifdef TBEAM_SUPREME_SX1262
PMU = new XPowersAXP2101(PMU_WIRE_PORT, PIN_BOARD_SDA1, PIN_BOARD_SCL1, I2C_PMU_ADD);
#if defined(TBEAM_SUPREME_SX1262)
PMU = new XPowersAXP2101(Wire1, PIN_BOARD_SDA1, PIN_BOARD_SCL1, I2C_PMU_ADD);
#else
PMU = new XPowersAXP2101(PMU_WIRE_PORT, PIN_BOARD_SDA, PIN_BOARD_SCL, I2C_PMU_ADD);
MESH_DEBUG_PRINTLN("[PMU] Trying AXP2101...");
PMU = new XPowersAXP2101(Wire, PIN_BOARD_SDA, PIN_BOARD_SCL, I2C_PMU_ADD);
#endif
if (!PMU->init()) {
MESH_DEBUG_PRINTLN("Warning: Failed to find AXP2101 power management");
Expand All @@ -140,7 +148,12 @@ bool TBeamBoard::power_init()
}
}
if (!PMU) {
PMU = new XPowersAXP192(PMU_WIRE_PORT, PIN_BOARD_SDA, PIN_BOARD_SCL, I2C_PMU_ADD);
#if defined(TBEAM_SUPREME_SX1262)
PMU = new XPowersAXP192(Wire1, PIN_BOARD_SDA1, PIN_BOARD_SCL1, I2C_PMU_ADD);
#else
MESH_DEBUG_PRINTLN("[PMU] Trying AXP192...");
PMU = new XPowersAXP192(Wire, PIN_BOARD_SDA, PIN_BOARD_SCL, I2C_PMU_ADD);
#endif
if (!PMU->init()) {
MESH_DEBUG_PRINTLN("Warning: Failed to find AXP192 power management");
delete PMU;
Expand All @@ -151,16 +164,31 @@ bool TBeamBoard::power_init()
}

if (!PMU) {
// XPowersLib calls Wire.end() when PMU object is deleted
// Need to re-initialize Wire for other I2C devices
#if !defined(TBEAM_SUPREME_SX1262)
Wire.begin(PIN_BOARD_SDA, PIN_BOARD_SCL);
#endif

#if defined(TBEAM_1W_SX1262) && defined(PIN_GPS_EN)
MESH_DEBUG_PRINTLN("PMU not found - using GPIO fallback for GPS power");
pinMode(PIN_GPS_EN, OUTPUT);
digitalWrite(PIN_GPS_EN, HIGH);
delay(100);
#endif

return false;
}

deviceOnline |= POWERMANAGE_ONLINE;

PMU->setChargingLedMode(XPOWERS_CHG_LED_CTRL_CHG);

// Set up PMU interrupts
// Set up PMU interrupts (T-Beam 1W has no PMU IRQ pin)
#ifndef TBEAM_1W_SX1262
pinMode(PIN_PMU_IRQ, INPUT_PULLUP);
attachInterrupt(PIN_PMU_IRQ, setPmuFlag, FALLING);
#endif

if (PMU->getChipModel() == XPOWERS_AXP192) {

Expand Down Expand Up @@ -234,6 +262,29 @@ bool TBeamBoard::power_init()
PMU->disablePowerOutput(XPOWERS_DLDO1);
PMU->disablePowerOutput(XPOWERS_DLDO2);
PMU->disablePowerOutput(XPOWERS_VBACKUP);
#elif defined(TBEAM_1W_SX1262)
// T-Beam 1W configuration
// Note: T-Beam 1W uses 7.4V battery and external LDO for radio
PMU->disablePowerOutput(XPOWERS_DCDC2);
PMU->disablePowerOutput(XPOWERS_DCDC3);
PMU->disablePowerOutput(XPOWERS_DCDC4);
PMU->disablePowerOutput(XPOWERS_DCDC5);
PMU->disablePowerOutput(XPOWERS_ALDO2);
PMU->disablePowerOutput(XPOWERS_ALDO4);
PMU->disablePowerOutput(XPOWERS_BLDO1);
PMU->disablePowerOutput(XPOWERS_BLDO2);
PMU->disablePowerOutput(XPOWERS_DLDO1);
PMU->disablePowerOutput(XPOWERS_DLDO2);

PMU->setPowerChannelVoltage(XPOWERS_ALDO1, 3300); // OLED and peripheral power
PMU->enablePowerOutput(XPOWERS_ALDO1);
delay(50);

PMU->setPowerChannelVoltage(XPOWERS_ALDO3, 3300); // GPS power
PMU->enablePowerOutput(XPOWERS_ALDO3);

PMU->setPowerChannelVoltage(XPOWERS_VBACKUP, 3300); // GPS RTC backup
PMU->enablePowerOutput(XPOWERS_VBACKUP);
#else
//Turn off unused power rails
PMU->disablePowerOutput(XPOWERS_DCDC2);
Expand Down
91 changes: 89 additions & 2 deletions src/helpers/esp32/TBeamBoard.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#pragma once

#if defined(TBEAM_SUPREME_SX1262) || defined(TBEAM_SX1262) || defined(TBEAM_SX1276)
#if defined(TBEAM_SUPREME_SX1262) || defined(TBEAM_1W_SX1262) || defined(TBEAM_SX1262) || defined(TBEAM_SX1276)

// Define pin mappings BEFORE including ESP32Board.h so sleep() can use P_LORA_DIO_1
#ifdef TBEAM_SUPREME_SX1262
Expand Down Expand Up @@ -45,6 +45,41 @@
#define RTC_WIRE_PORT Wire1
#endif

#ifdef TBEAM_1W_SX1262
// LoRa radio module pins for TBeam 1W with SX1262 and 1W PA
#define P_LORA_DIO_0 -1 //NC
#define P_LORA_DIO_1 1 //SX1262 IRQ pin
#define P_LORA_NSS 15 //SX1262 SS pin
#define P_LORA_RESET 3 //SX1262 Reset pin
#define P_LORA_BUSY 38 //SX1262 Busy pin
#define P_LORA_SCLK 13 //SX1262 SCLK pin
#define P_LORA_MISO 12 //SX1262 MISO pin
#define P_LORA_MOSI 11 //SX1262 MOSI pin
#define P_LORA_LDO_EN 40 //Radio LDO enable
#define P_LORA_CTRL 21 //LNA power control
#define P_LORA_TX_LED 18 //TX LED

// T-Beam 1W uses single I2C bus on GPIO 8/9 for ALL peripherals
#define PIN_BOARD_SDA 8 //SDA for PMU, OLED, and peripherals
#define PIN_BOARD_SCL 9 //SCL for PMU, OLED, and peripherals

#define PIN_PMU_IRQ -1 //No PMU IRQ on T-Beam 1W

#define PIN_GPS_RX 5
#define PIN_GPS_TX 6
#define PIN_GPS_EN 16
#define PIN_GPS_PPS 7

#define PIN_FAN_CTRL 41 //Cooling fan control

//I2C addresses (single I2C bus)
#define I2C_OLED_ADD 0x3C //SH1106 OLED I2C address
#define I2C_PMU_ADD 0x34 //AXP2101 I2C address

#define PMU_WIRE_PORT Wire
#define RTC_WIRE_PORT Wire
#endif

#ifdef TBEAM_SX1262
#define P_LORA_BUSY 32
#endif
Expand Down Expand Up @@ -88,6 +123,12 @@
#include "helpers/ESP32Board.h"
#include <driver/rtc_io.h>

// Forward declarations for fan control (defined in target.cpp)
#ifdef TBEAM_1W_SX1262
extern void activate_fan();
extern void update_fan_control();
#endif

class TBeamBoard : public ESP32Board {
XPowersLibInterface *PMU = NULL;
//PhysicalLayer * pl;
Expand Down Expand Up @@ -125,6 +166,9 @@ bool power_init();
#ifndef TBEAM_SUPREME_SX1262
void onBeforeTransmit() override{
digitalWrite(P_LORA_TX_LED, LOW); // turn TX LED on - invert pin for SX1276
#if defined(TBEAM_1W_SX1262) && defined(P_FAN_CTRL)
activate_fan(); // Activate cooling fan for 1W PA
#endif
}
void onAfterTransmit() override{
digitalWrite(P_LORA_TX_LED, HIGH); // turn TX LED off - invert pin for SX1276
Expand Down Expand Up @@ -155,7 +199,50 @@ bool power_init();
}

uint16_t getBattMilliVolts(){
return PMU->getBattVoltage();
if (PMU) {
return PMU->getBattVoltage();
}

#ifdef TBEAM_1W_SX1262
// Fallback: ADC-based battery voltage reading for T-Beam 1W
// GPIO 4 (ADC1_CH3) - per Meshtastic firmware variant
const int BATTERY_ADC_PIN = 4;
const float ADC_REFERENCE_VOLTAGE = 3300.0; // mV
const float ADC_MULTIPLIER = 2.9333; // Per Meshtastic T-Beam 1W variant
const int BATTERY_SENSE_SAMPLES = 30;
static bool adc_initialized = false;

if (!adc_initialized) {
pinMode(BATTERY_ADC_PIN, INPUT);
analogReadResolution(12);
analogSetAttenuation(ADC_11db);
adc_initialized = true;
}

uint32_t adc_sum = 0;
for (int i = 0; i < BATTERY_SENSE_SAMPLES; i++) {
adc_sum += analogRead(BATTERY_ADC_PIN);
delayMicroseconds(100);
}
uint16_t adc_raw = adc_sum / BATTERY_SENSE_SAMPLES;

float battery_voltage_f = (adc_raw / 4095.0) * ADC_REFERENCE_VOLTAGE * ADC_MULTIPLIER;
uint16_t battery_voltage = (uint16_t)battery_voltage_f;

static unsigned long last_debug = 0;
if (millis() - last_debug > 10000) {
Serial.printf("[BATTERY ADC] raw=%d, voltage=%.2fV (%.0fmV)\n", adc_raw, battery_voltage_f / 1000.0, battery_voltage_f);
last_debug = millis();
}

if (battery_voltage < 5500 || battery_voltage > 9000) {
return 7400; // Out of range, return nominal
}

return battery_voltage;
#else
return 0;
#endif
}

const char* getManufacturerName() const{
Expand Down
39 changes: 39 additions & 0 deletions t-beam-1w.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
{
"build": {
"arduino": {
"ldscript": "esp32s3_out.ld",
"memory_type": "qio_opi"
},
"core": "esp32",
"extra_flags": [
"-DBOARD_HAS_PSRAM",
"-DLILYGO_TBEAM_1W",
"-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",
"psram_type": "opi",
"hwids": [["0x303A", "0x1001"]],
"mcu": "esp32s3",
"variant": "t-beam-1w"
},
"connectivity": ["wifi", "bluetooth", "lora"],
"debug": {
"openocd_target": "esp32s3.cfg"
},
"frameworks": ["arduino"],
"name": "LilyGo TBeam-1W",
"upload": {
"flash_size": "16MB",
"maximum_ram_size": 327680,
"maximum_size": 16777216,
"require_upload_port": true,
"speed": 921600
},
"url": "http://www.lilygo.cn/",
"vendor": "LilyGo"
}
Loading