Compare commits

...

2 Commits

Author SHA1 Message Date
Clive Blackledge cd2466692f fix: FEM Sleep/Wake Fix - Enable PA after sleep (#10617)
CI / setup (all) (push) Waiting to run
CI / setup (check) (push) Waiting to run
CI / version (push) Waiting to run
CI / check (push) Blocked by required conditions
CI / build (push) Blocked by required conditions
CI / build-debian-src (push) Waiting to run
CI / MacOS (15) (push) Waiting to run
CI / MacOS (26) (push) Waiting to run
CI / package-pio-deps-native-tft (push) Waiting to run
CI / test-native (push) Waiting to run
CI / docker (alpine, native, linux/amd64) (push) Waiting to run
CI / docker (alpine, native, linux/arm64) (push) Waiting to run
CI / docker (alpine, native-tft, linux/amd64) (push) Waiting to run
CI / docker (debian, native, linux/amd64) (push) Waiting to run
CI / docker (debian, native, linux/arm/v7) (push) Waiting to run
CI / docker (debian, native, linux/arm64) (push) Waiting to run
CI / docker (debian, native-tft, linux/amd64) (push) Waiting to run
CI / gather-artifacts (esp32) (push) Blocked by required conditions
CI / gather-artifacts (esp32c3) (push) Blocked by required conditions
CI / gather-artifacts (esp32c6) (push) Blocked by required conditions
CI / gather-artifacts (esp32s3) (push) Blocked by required conditions
CI / gather-artifacts (nrf52840) (push) Blocked by required conditions
CI / gather-artifacts (rp2040) (push) Blocked by required conditions
CI / gather-artifacts (rp2350) (push) Blocked by required conditions
CI / gather-artifacts (stm32) (push) Blocked by required conditions
CI / firmware-size-report (push) Blocked by required conditions
CI / release-artifacts (push) Blocked by required conditions
CI / release-firmware (esp32) (push) Blocked by required conditions
CI / release-firmware (esp32c3) (push) Blocked by required conditions
CI / release-firmware (esp32c6) (push) Blocked by required conditions
CI / release-firmware (esp32s3) (push) Blocked by required conditions
CI / release-firmware (nrf52840) (push) Blocked by required conditions
CI / release-firmware (rp2040) (push) Blocked by required conditions
CI / release-firmware (rp2350) (push) Blocked by required conditions
CI / release-firmware (stm32) (push) Blocked by required conditions
CI / publish-firmware (push) Blocked by required conditions
* fix: release Heltec v4 FEM sleep holds

* fix: increase FEM power settle delay

* Fix heltec_V4 documentation

Fixing the heltec_v4 documentation for enabling the PA after sleep.

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>

* Add comment for the next guy about why 5ms was chosen.

---------

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2026-06-04 20:40:05 -05:00
Austin 4b424f0234 Add support for T-Beam Supreme 144mhz variant (#10624)
Adds support for T-Beam-Supreme 144mhz version
https://github.com/Xinyuan-LilyGO/LilyGo-LoRa-Series/blob/master/docs/en/t_beam_supreme/t_beam_supreme_144_hw.md

Tested / working.
2026-06-04 16:03:39 -05:00
2 changed files with 89 additions and 16 deletions
+81 -16
View File
@@ -2,11 +2,58 @@
#include "LoRaFEMInterface.h"
#if defined(ARCH_ESP32)
#include <driver/gpio.h>
#include <driver/rtc_io.h>
#include <esp_sleep.h>
#endif
LoRaFEMInterface loraFEMInterface;
static void enableFEMPower()
{
bool wasOff = digitalRead(LORA_PA_POWER) != HIGH;
digitalWrite(LORA_PA_POWER, HIGH);
if (wasOff) {
delay(5); // This is an arbitrary 5ms for FEM rail power-up.
}
}
#if defined(ARCH_ESP32)
static void releasePinHold(int pin)
{
if (pin < 0) {
return;
}
gpio_num_t gpio = (gpio_num_t)pin;
#if SOC_RTCIO_HOLD_SUPPORTED
if (rtc_gpio_is_valid_gpio(gpio)) {
rtc_gpio_hold_dis(gpio);
return;
}
#endif
if (GPIO_IS_VALID_OUTPUT_GPIO(gpio)) {
gpio_hold_dis(gpio);
}
}
static void releaseSleepHolds()
{
releasePinHold(LORA_PA_POWER);
#ifdef HELTEC_V4
releasePinHold(LORA_KCT8103L_PA_CSD);
releasePinHold(LORA_KCT8103L_PA_CTX);
#elif defined(USE_GC1109_PA)
releasePinHold(LORA_GC1109_PA_EN);
releasePinHold(LORA_GC1109_PA_TX_EN);
#elif defined(USE_KCT8103L_PA)
releasePinHold(LORA_KCT8103L_PA_CSD);
releasePinHold(LORA_KCT8103L_PA_CTX);
#endif
}
#endif
void LoRaFEMInterface::init(void)
{
setLnaCanControl(false); // Default is uncontrollable
@@ -21,6 +68,7 @@ void LoRaFEMInterface::init(void)
if (digitalRead(LORA_KCT8103L_PA_CSD) == HIGH) {
// FEM is KCT8103L
fem_type = KCT8103L_PA;
LOG_INFO("Detected KCT8103L LoRa FEM");
rtc_gpio_hold_dis((gpio_num_t)LORA_KCT8103L_PA_CTX);
pinMode(LORA_KCT8103L_PA_CSD, OUTPUT);
digitalWrite(LORA_KCT8103L_PA_CSD, HIGH);
@@ -30,6 +78,7 @@ void LoRaFEMInterface::init(void)
} else if (digitalRead(LORA_KCT8103L_PA_CSD) == LOW) {
// FEM is GC1109
fem_type = GC1109_PA;
LOG_INFO("Detected GC1109 LoRa FEM");
// LORA_GC1109_PA_EN and LORA_KCT8103L_PA_CSD are the same pin and do not need to be repeatedly turned off and held.
// rtc_gpio_hold_dis((gpio_num_t)LORA_GC1109_PA_EN);
pinMode(LORA_GC1109_PA_EN, OUTPUT);
@@ -41,6 +90,7 @@ void LoRaFEMInterface::init(void)
}
#elif defined(USE_GC1109_PA)
fem_type = GC1109_PA;
LOG_INFO("Using GC1109 LoRa FEM");
pinMode(LORA_PA_POWER, OUTPUT);
digitalWrite(LORA_PA_POWER, HIGH);
#if defined(ARCH_ESP32)
@@ -55,6 +105,7 @@ void LoRaFEMInterface::init(void)
digitalWrite(LORA_GC1109_PA_TX_EN, LOW);
#elif defined(USE_KCT8103L_PA)
fem_type = KCT8103L_PA;
LOG_INFO("Using KCT8103L LoRa FEM");
pinMode(LORA_PA_POWER, OUTPUT);
digitalWrite(LORA_PA_POWER, HIGH);
#if defined(ARCH_ESP32)
@@ -73,6 +124,10 @@ void LoRaFEMInterface::init(void)
void LoRaFEMInterface::setSleepModeEnable(void)
{
#if defined(ARCH_ESP32)
releaseSleepHolds();
#endif
#ifdef HELTEC_V4
if (fem_type == GC1109_PA) {
/*
@@ -84,6 +139,7 @@ void LoRaFEMInterface::setSleepModeEnable(void)
} else if (fem_type == KCT8103L_PA) {
// shutdown the PA
digitalWrite(LORA_KCT8103L_PA_CSD, LOW);
digitalWrite(LORA_PA_POWER, LOW);
}
#elif defined(USE_GC1109_PA)
digitalWrite(LORA_GC1109_PA_EN, LOW);
@@ -91,16 +147,22 @@ void LoRaFEMInterface::setSleepModeEnable(void)
#elif defined(USE_KCT8103L_PA)
// shutdown the PA
digitalWrite(LORA_KCT8103L_PA_CSD, LOW);
digitalWrite(LORA_PA_POWER, LOW);
#endif
}
void LoRaFEMInterface::setTxModeEnable(void)
{
#if defined(ARCH_ESP32)
releaseSleepHolds();
#endif
#ifdef HELTEC_V4
if (fem_type == GC1109_PA) {
digitalWrite(LORA_GC1109_PA_EN, HIGH); // CSD=1: Chip enabled
digitalWrite(LORA_GC1109_PA_TX_EN, HIGH); // CPS: 1=full PA, 0=bypass (for RX, CPS is don't care)
} else if (fem_type == KCT8103L_PA) {
enableFEMPower();
digitalWrite(LORA_KCT8103L_PA_CSD, HIGH);
digitalWrite(LORA_KCT8103L_PA_CTX, HIGH);
}
@@ -108,6 +170,7 @@ void LoRaFEMInterface::setTxModeEnable(void)
digitalWrite(LORA_GC1109_PA_EN, HIGH); // CSD=1: Chip enabled
digitalWrite(LORA_GC1109_PA_TX_EN, HIGH); // CPS: 1=full PA, 0=bypass (for RX, CPS is don't care)
#elif defined(USE_KCT8103L_PA)
enableFEMPower();
digitalWrite(LORA_KCT8103L_PA_CSD, HIGH);
digitalWrite(LORA_KCT8103L_PA_CTX, HIGH);
#endif
@@ -115,11 +178,16 @@ void LoRaFEMInterface::setTxModeEnable(void)
void LoRaFEMInterface::setRxModeEnable(void)
{
#if defined(ARCH_ESP32)
releaseSleepHolds();
#endif
#ifdef HELTEC_V4
if (fem_type == GC1109_PA) {
digitalWrite(LORA_GC1109_PA_EN, HIGH); // CSD=1: Chip enabled
digitalWrite(LORA_GC1109_PA_TX_EN, LOW);
} else if (fem_type == KCT8103L_PA) {
enableFEMPower();
digitalWrite(LORA_KCT8103L_PA_CSD, HIGH);
if (lna_enabled) {
digitalWrite(LORA_KCT8103L_PA_CTX, LOW);
@@ -131,6 +199,7 @@ void LoRaFEMInterface::setRxModeEnable(void)
digitalWrite(LORA_GC1109_PA_EN, HIGH); // CSD=1: Chip enabled
digitalWrite(LORA_GC1109_PA_TX_EN, LOW);
#elif defined(USE_KCT8103L_PA)
enableFEMPower();
digitalWrite(LORA_KCT8103L_PA_CSD, HIGH);
if (lna_enabled) {
digitalWrite(LORA_KCT8103L_PA_CTX, LOW);
@@ -142,12 +211,14 @@ void LoRaFEMInterface::setRxModeEnable(void)
void LoRaFEMInterface::setRxModeEnableWhenMCUSleep(void)
{
#if defined(ARCH_ESP32)
releaseSleepHolds();
#endif
#ifdef HELTEC_V4
// Keep GC1109 FEM powered during deep sleep so LNA remains active for RX wake.
// Set PA_POWER and PA_EN HIGH (overrides SX126xInterface::sleep() shutdown),
// then latch with RTC hold so the state survives deep sleep.
digitalWrite(LORA_PA_POWER, HIGH);
// Keep FEM rail powered during deep sleep so LoRa RX wake can work (GC1109 keeps LNA active; KCT8103L uses RX bypass).
// Set PA_POWER HIGH (overrides SX126xInterface::sleep() shutdown), then latch with RTC hold so the state survives deep sleep.
enableFEMPower();
rtc_gpio_hold_en((gpio_num_t)LORA_PA_POWER);
if (fem_type == GC1109_PA) {
digitalWrite(LORA_GC1109_PA_EN, HIGH);
@@ -156,15 +227,11 @@ void LoRaFEMInterface::setRxModeEnableWhenMCUSleep(void)
} else if (fem_type == KCT8103L_PA) {
digitalWrite(LORA_KCT8103L_PA_CSD, HIGH);
rtc_gpio_hold_en((gpio_num_t)LORA_KCT8103L_PA_CSD);
if (lna_enabled) {
digitalWrite(LORA_KCT8103L_PA_CTX, LOW);
} else {
digitalWrite(LORA_KCT8103L_PA_CTX, HIGH);
}
digitalWrite(LORA_KCT8103L_PA_CTX, HIGH); // RX bypass while MCU sleeps
rtc_gpio_hold_en((gpio_num_t)LORA_KCT8103L_PA_CTX);
}
#elif defined(USE_GC1109_PA)
digitalWrite(LORA_PA_POWER, HIGH);
enableFEMPower();
digitalWrite(LORA_GC1109_PA_EN, HIGH);
#if defined(ARCH_ESP32)
rtc_gpio_hold_en((gpio_num_t)LORA_PA_POWER);
@@ -172,13 +239,11 @@ void LoRaFEMInterface::setRxModeEnableWhenMCUSleep(void)
gpio_pulldown_en((gpio_num_t)LORA_GC1109_PA_TX_EN);
#endif
#elif defined(USE_KCT8103L_PA)
enableFEMPower();
digitalWrite(LORA_KCT8103L_PA_CSD, HIGH);
if (lna_enabled) {
digitalWrite(LORA_KCT8103L_PA_CTX, LOW);
} else {
digitalWrite(LORA_KCT8103L_PA_CTX, HIGH);
}
digitalWrite(LORA_KCT8103L_PA_CTX, HIGH); // RX bypass while MCU sleeps
#if defined(ARCH_ESP32)
rtc_gpio_hold_en((gpio_num_t)LORA_PA_POWER);
rtc_gpio_hold_en((gpio_num_t)LORA_KCT8103L_PA_CSD);
rtc_gpio_hold_en((gpio_num_t)LORA_KCT8103L_PA_CTX);
#endif
@@ -227,4 +292,4 @@ int8_t LoRaFEMInterface::powerConversion(int8_t loraOutputPower)
return loraOutputPower;
}
#endif
#endif
+8
View File
@@ -14,6 +14,7 @@
#define USE_SX1262
#define USE_SX1268
#define USE_LR1121
#define USE_RF95
#define LORA_DIO0 -1 // a No connect on the SX1262 module
#define LORA_RESET 5
@@ -21,6 +22,13 @@
#define LORA_DIO2 4 // SX1262 BUSY
#define LORA_DIO3 // Not connected on PCB, but internally on the TTGO SX1262, if DIO3 is high the TXCO is enabled
// 144mhz variant uses 'RF95' (SX1278)
#ifdef USE_RF95
#define RF95_IRQ 2
#define RF95_RESET LORA_RESET
#define RF95_DIO1 LORA_DIO1
#endif
#ifdef USE_SX1262
#define SX126X_CS 10 // FIXME - we really should define LORA_CS instead
#define SX126X_DIO1 LORA_DIO1