Skip to content

Commit 2c324ed

Browse files
Wesselthebentern
authored andcommitted
🔧 Fix LNA/PA power control for Heltec v4, wireless tracker v2 (meshtastic#9029)
* Fix LNA/PA power control for Heltec v4, wireless tracker v2 * Stop using pin 46 as RF switch, just let DIO2 switch handle the RF path --------- Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
1 parent 6e9ea4d commit 2c324ed

3 files changed

Lines changed: 66 additions & 14 deletions

File tree

src/mesh/SX126xInterface.cpp

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -53,13 +53,21 @@ template <typename T> bool SX126xInterface<T>::init()
5353
#endif
5454

5555
#if defined(USE_GC1109_PA)
56+
// GC1109 FEM chip initialization
57+
// See variant.h for full pin mapping and control logic documentation
58+
59+
// VFEM_Ctrl (LORA_PA_POWER): Power enable for GC1109 LDO (always on)
5660
pinMode(LORA_PA_POWER, OUTPUT);
5761
digitalWrite(LORA_PA_POWER, HIGH);
5862

63+
// CSD (LORA_PA_EN): Chip enable - must be HIGH to enable GC1109 for both RX and TX
5964
pinMode(LORA_PA_EN, OUTPUT);
60-
digitalWrite(LORA_PA_EN, LOW);
65+
digitalWrite(LORA_PA_EN, HIGH);
66+
67+
// CPS (LORA_PA_TX_EN): PA mode select - HIGH enables full PA during TX, LOW for RX (don't care)
68+
// Note: TX/RX path switching (CTX) is handled by DIO2 via SX126X_DIO2_AS_RF_SWITCH
6169
pinMode(LORA_PA_TX_EN, OUTPUT);
62-
digitalWrite(LORA_PA_TX_EN, LOW);
70+
digitalWrite(LORA_PA_TX_EN, LOW); // Start in RX-ready state
6371
#endif
6472

6573
#ifdef RF95_FAN_EN
@@ -377,13 +385,13 @@ template <typename T> bool SX126xInterface<T>::sleep()
377385
return true;
378386
}
379387

380-
/** Some boards require GPIO control of tx vs rx paths */
388+
/** Control PA mode for GC1109 FEM - CPS pin selects full PA (txon=true) or bypass mode (txon=false) */
381389
template <typename T> void SX126xInterface<T>::setTransmitEnable(bool txon)
382390
{
383391
#if defined(USE_GC1109_PA)
384-
digitalWrite(LORA_PA_POWER, HIGH);
385-
digitalWrite(LORA_PA_EN, HIGH);
386-
digitalWrite(LORA_PA_TX_EN, txon ? 1 : 0);
392+
digitalWrite(LORA_PA_POWER, HIGH); // Ensure LDO is on
393+
digitalWrite(LORA_PA_EN, HIGH); // CSD=1: Chip enabled
394+
digitalWrite(LORA_PA_TX_EN, txon ? 1 : 0); // CPS: 1=full PA, 0=bypass (for RX, CPS is don't care)
387395
#endif
388396
}
389397

variants/esp32s3/heltec_v4/variant.h

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -29,10 +29,32 @@
2929
#define SX126X_DIO2_AS_RF_SWITCH
3030
#define SX126X_DIO3_TCXO_VOLTAGE 1.8
3131

32-
#define USE_GC1109_PA // We have a GC1109 power amplifier+attenuator
33-
#define LORA_PA_POWER 7 // power en
34-
#define LORA_PA_EN 2
35-
#define LORA_PA_TX_EN 46 // enable tx
32+
// ---- GC1109 RF FRONT END CONFIGURATION ----
33+
// The Heltec V4 uses a GC1109 FEM chip with integrated PA and LNA
34+
// RF path: SX1262 -> GC1109 PA -> Pi attenuator -> Antenna
35+
// Measured net TX gain (non-linear due to PA compression):
36+
// +11dB at 0-15dBm input (e.g., 10dBm in -> 21dBm out)
37+
// +10dB at 16-17dBm input
38+
// +9dB at 18-19dBm input
39+
// +7dB at 21dBm input (e.g., 21dBm in -> 28dBm out max)
40+
// Control logic (from GC1109 datasheet):
41+
// Shutdown: CSD=0, CTX=X, CPS=X
42+
// Receive LNA: CSD=1, CTX=0, CPS=X (17dB gain, 2dB NF)
43+
// Transmit bypass: CSD=1, CTX=1, CPS=0 (~1dB loss, no PA)
44+
// Transmit PA: CSD=1, CTX=1, CPS=1 (full PA enabled)
45+
// Pin mapping:
46+
// CTX (pin 6) -> SX1262 DIO2: TX/RX path select (automatic via SX126X_DIO2_AS_RF_SWITCH)
47+
// CSD (pin 4) -> GPIO2: Chip enable (HIGH=on, LOW=shutdown)
48+
// CPS (pin 5) -> GPIO46: PA mode select (HIGH=full PA, LOW=bypass)
49+
// VCC0/VCC1 -> Vfem via U3 LDO, controlled by GPIO7
50+
#define USE_GC1109_PA
51+
#define LORA_PA_POWER 7 // VFEM_Ctrl - GC1109 LDO power enable
52+
#define LORA_PA_EN 2 // CSD - GC1109 chip enable (HIGH=on)
53+
#define LORA_PA_TX_EN 46 // CPS - GC1109 PA mode (HIGH=full PA, LOW=bypass)
54+
55+
// GC1109 FEM: TX/RX path switching is handled by DIO2 -> CTX pin (via SX126X_DIO2_AS_RF_SWITCH)
56+
// GPIO46 is CPS (PA mode), not TX control - setTransmitEnable() handles it in SX126xInterface.cpp
57+
// Do NOT use SX126X_TXEN/RXEN as that would cause double-control of GPIO46
3658

3759
#if HAS_TFT
3860
#define USE_TFTDISPLAY 1

variants/esp32s3/heltec_wireless_tracker_v2/variant.h

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,29 @@
7373
#define SX126X_DIO2_AS_RF_SWITCH
7474
#define SX126X_DIO3_TCXO_VOLTAGE 1.8
7575

76-
#define USE_GC1109_PA // We have a GC1109 power amplifier+attenuator
77-
#define LORA_PA_POWER 7 // power en
78-
#define LORA_PA_EN 4
79-
#define LORA_PA_TX_EN 46 // enable tx
76+
// ---- GC1109 RF FRONT END CONFIGURATION ----
77+
// The Heltec Wireless Tracker V2 uses a GC1109 FEM chip with integrated PA and LNA
78+
// RF path: SX1262 -> GC1109 PA -> Pi attenuator -> Antenna
79+
// Measured net TX gain (non-linear due to PA compression):
80+
// +11dB at 0-15dBm input (e.g., 10dBm in -> 21dBm out)
81+
// +10dB at 16-17dBm input
82+
// +9dB at 18-19dBm input
83+
// +7dB at 21dBm input (e.g., 21dBm in -> 28dBm out max)
84+
// Control logic (from GC1109 datasheet):
85+
// Shutdown: CSD=0, CTX=X, CPS=X
86+
// Receive LNA: CSD=1, CTX=0, CPS=X (17dB gain, 2dB NF)
87+
// Transmit bypass: CSD=1, CTX=1, CPS=0 (~1dB loss, no PA)
88+
// Transmit PA: CSD=1, CTX=1, CPS=1 (full PA enabled)
89+
// Pin mapping:
90+
// CTX (pin 6) -> SX1262 DIO2: TX/RX path select (automatic via SX126X_DIO2_AS_RF_SWITCH)
91+
// CSD (pin 4) -> GPIO4: Chip enable (HIGH=on, LOW=shutdown)
92+
// CPS (pin 5) -> GPIO46: PA mode select (HIGH=full PA, LOW=bypass)
93+
// VCC0/VCC1 -> Vfem via U3 LDO, controlled by GPIO7
94+
#define USE_GC1109_PA
95+
#define LORA_PA_POWER 7 // VFEM_Ctrl - GC1109 LDO power enable
96+
#define LORA_PA_EN 4 // CSD - GC1109 chip enable (HIGH=on)
97+
#define LORA_PA_TX_EN 46 // CPS - GC1109 PA mode (HIGH=full PA, LOW=bypass)
98+
99+
// GC1109 FEM: TX/RX path switching is handled by DIO2 -> CTX pin (via SX126X_DIO2_AS_RF_SWITCH)
100+
// GPIO46 is CPS (PA mode), not TX control - setTransmitEnable() handles it in SX126xInterface.cpp
101+
// Do NOT use SX126X_TXEN/RXEN as that would cause double-control of GPIO46

0 commit comments

Comments
 (0)