From 3d524be96527247c5fe2cb743f045e131dbaf384 Mon Sep 17 00:00:00 2001 From: Quency-D <55523105+Quency-D@users.noreply.github.com> Date: Fri, 6 Mar 2026 20:15:42 +0800 Subject: [PATCH] Update Heltec Tracker v2 to version KCT8103L. (#9822) * Update Heltec Tracker v2 to version KCT8103L. * Fixed the issue of inaccurate comments. --------- Co-authored-by: Ben Meadors --- src/configuration.h | 6 +++ src/mesh/LoRaFEMInterface.cpp | 45 ++++++++++++++++--- variants/esp32s3/heltec_v4/variant.h | 4 +- .../heltec_wireless_tracker_v2/pins_arduino.h | 4 +- .../heltec_wireless_tracker_v2/variant.h | 35 ++++++--------- 5 files changed, 64 insertions(+), 30 deletions(-) diff --git a/src/configuration.h b/src/configuration.h index 451bdfb3b..a5f2cd9a9 100644 --- a/src/configuration.h +++ b/src/configuration.h @@ -149,6 +149,12 @@ along with this program. If not, see . #define TX_GAIN_LORA 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 10, 10, 9, 9, 8, 7 #endif +#ifdef USE_KCT8103L_PA +// Power Amps are often non-linear, so we can use an array of values for the power curve +#define NUM_PA_POINTS 22 +#define TX_GAIN_LORA 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 13, 13, 13, 12, 12, 11, 10, 9, 8, 7 +#endif + #ifdef RAK13302 #define NUM_PA_POINTS 22 #define TX_GAIN_LORA 7, 8, 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 8 diff --git a/src/mesh/LoRaFEMInterface.cpp b/src/mesh/LoRaFEMInterface.cpp index a1b56320e..bad795c3a 100644 --- a/src/mesh/LoRaFEMInterface.cpp +++ b/src/mesh/LoRaFEMInterface.cpp @@ -41,18 +41,33 @@ void LoRaFEMInterface::init(void) } #elif defined(USE_GC1109_PA) fem_type = GC1109_PA; + pinMode(LORA_PA_POWER, OUTPUT); + digitalWrite(LORA_PA_POWER, HIGH); #if defined(ARCH_ESP32) rtc_gpio_hold_dis((gpio_num_t)LORA_PA_POWER); rtc_gpio_hold_dis((gpio_num_t)LORA_GC1109_PA_EN); rtc_gpio_hold_dis((gpio_num_t)LORA_GC1109_PA_TX_EN); #endif - pinMode(LORA_PA_POWER, OUTPUT); - digitalWrite(LORA_PA_POWER, HIGH); delay(1); pinMode(LORA_GC1109_PA_EN, OUTPUT); digitalWrite(LORA_GC1109_PA_EN, HIGH); pinMode(LORA_GC1109_PA_TX_EN, OUTPUT); digitalWrite(LORA_GC1109_PA_TX_EN, LOW); +#elif defined(USE_KCT8103L_PA) + fem_type = KCT8103L_PA; + pinMode(LORA_PA_POWER, OUTPUT); + digitalWrite(LORA_PA_POWER, HIGH); +#if defined(ARCH_ESP32) + rtc_gpio_hold_dis((gpio_num_t)LORA_PA_POWER); + rtc_gpio_hold_dis((gpio_num_t)LORA_KCT8103L_PA_CSD); + rtc_gpio_hold_dis((gpio_num_t)LORA_KCT8103L_PA_CTX); +#endif + delay(1); + pinMode(LORA_KCT8103L_PA_CSD, OUTPUT); + digitalWrite(LORA_KCT8103L_PA_CSD, HIGH); + pinMode(LORA_KCT8103L_PA_CTX, OUTPUT); + digitalWrite(LORA_KCT8103L_PA_CTX, HIGH); + setLnaCanControl(true); #endif } @@ -73,6 +88,9 @@ void LoRaFEMInterface::setSleepModeEnable(void) #elif defined(USE_GC1109_PA) digitalWrite(LORA_GC1109_PA_EN, LOW); digitalWrite(LORA_GC1109_PA_TX_EN, LOW); +#elif defined(USE_KCT8103L_PA) + // shutdown the PA + digitalWrite(LORA_KCT8103L_PA_CSD, LOW); #endif } @@ -89,6 +107,9 @@ void LoRaFEMInterface::setTxModeEnable(void) #elif defined(USE_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) +#elif defined(USE_KCT8103L_PA) + digitalWrite(LORA_KCT8103L_PA_CSD, HIGH); + digitalWrite(LORA_KCT8103L_PA_CTX, HIGH); #endif } @@ -109,6 +130,13 @@ void LoRaFEMInterface::setRxModeEnable(void) #elif defined(USE_GC1109_PA) digitalWrite(LORA_GC1109_PA_EN, HIGH); // CSD=1: Chip enabled digitalWrite(LORA_GC1109_PA_TX_EN, LOW); +#elif defined(USE_KCT8103L_PA) + digitalWrite(LORA_KCT8103L_PA_CSD, HIGH); + if (lna_enabled) { + digitalWrite(LORA_KCT8103L_PA_CTX, LOW); + } else { + digitalWrite(LORA_KCT8103L_PA_CTX, HIGH); + } #endif } @@ -143,6 +171,15 @@ void LoRaFEMInterface::setRxModeEnableWhenMCUSleep(void) rtc_gpio_hold_en((gpio_num_t)LORA_GC1109_PA_EN); gpio_pulldown_en((gpio_num_t)LORA_GC1109_PA_TX_EN); #endif +#elif defined(USE_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); + } + rtc_gpio_hold_en((gpio_num_t)LORA_KCT8103L_PA_CTX); #endif } @@ -169,11 +206,9 @@ int8_t LoRaFEMInterface::powerConversion(int8_t loraOutputPower) } #else #ifdef ARCH_PORTDUINO - size_t num_pa_points = portduino_config.num_pa_points; const uint16_t *tx_gain = portduino_config.tx_gain_lora; - uint16_t tx_gain_num = num_pa_points; + uint16_t tx_gain_num = portduino_config.num_pa_points; #else - size_t num_pa_points = NUM_PA_POINTS; const uint16_t tx_gain[NUM_PA_POINTS] = {TX_GAIN_LORA}; uint16_t tx_gain_num = NUM_PA_POINTS; #endif diff --git a/variants/esp32s3/heltec_v4/variant.h b/variants/esp32s3/heltec_v4/variant.h index 8843f75c9..83443c5f3 100644 --- a/variants/esp32s3/heltec_v4/variant.h +++ b/variants/esp32s3/heltec_v4/variant.h @@ -65,12 +65,12 @@ // Pin mapping: // CPS (pin 5) -> SX1262 DIO2: TX/RX path select (automatic via SX126X_DIO2_AS_RF_SWITCH) // CSD (pin 4) -> GPIO2: Chip enable (HIGH=on, LOW=shutdown) -// CTX (pin 6) -> GPIO5: Switch between Receive LNA Mode and Receive Bypass Mode. (HIGH=bypass PA, LOW=LNA) +// CTX (pin 6) -> GPIO5: Switch between Receive LNA Mode and Receive Bypass Mode. (HIGH=RX bypass, LOW=RX LNA) // VCC0/VCC1 -> Vfem via U3 LDO, controlled by GPIO7 // KCT8103L FEM: TX/RX path switching is handled by DIO2 -> CPS pin (via SX126X_DIO2_AS_RF_SWITCH) #define LORA_KCT8103L_PA_CSD 2 // CSD - KCT8103L chip enable (HIGH=on) -#define LORA_KCT8103L_PA_CTX 5 // CTX - Switch between Receive LNA Mode and Receive Bypass Mode. (HIGH=bypass PA, LOW=LNA) +#define LORA_KCT8103L_PA_CTX 5 // CTX - Switch between Receive LNA Mode and Receive Bypass Mode. (HIGH=RX bypass, LOW=RX LNA) #if HAS_TFT #define USE_TFTDISPLAY 1 diff --git a/variants/esp32s3/heltec_wireless_tracker_v2/pins_arduino.h b/variants/esp32s3/heltec_wireless_tracker_v2/pins_arduino.h index 9fb825002..d30e2fcb7 100644 --- a/variants/esp32s3/heltec_wireless_tracker_v2/pins_arduino.h +++ b/variants/esp32s3/heltec_wireless_tracker_v2/pins_arduino.h @@ -13,8 +13,8 @@ static const uint8_t TX = 43; static const uint8_t RX = 44; -static const uint8_t SDA = 5; -static const uint8_t SCL = 6; +static const uint8_t SDA = 6; +static const uint8_t SCL = 17; static const uint8_t SS = 8; static const uint8_t MOSI = 10; diff --git a/variants/esp32s3/heltec_wireless_tracker_v2/variant.h b/variants/esp32s3/heltec_wireless_tracker_v2/variant.h index 7937039ba..7c797a503 100644 --- a/variants/esp32s3/heltec_wireless_tracker_v2/variant.h +++ b/variants/esp32s3/heltec_wireless_tracker_v2/variant.h @@ -73,29 +73,22 @@ #define SX126X_DIO2_AS_RF_SWITCH #define SX126X_DIO3_TCXO_VOLTAGE 1.8 -// ---- GC1109 RF FRONT END CONFIGURATION ---- -// The Heltec Wireless Tracker V2 uses a GC1109 FEM chip with integrated PA and LNA -// RF path: SX1262 -> GC1109 PA -> Pi attenuator -> Antenna -// Measured net TX gain (non-linear due to PA compression): -// +11dB at 0-15dBm input (e.g., 10dBm in -> 21dBm out) -// +10dB at 16-17dBm input -// +9dB at 18-19dBm input -// +7dB at 21dBm input (e.g., 21dBm in -> 28dBm out max) -// Control logic (from GC1109 datasheet): +// ---- KCT8103L RF FRONT END CONFIGURATION ---- +// The heltec_wireless_tracker_v2 uses a KCT8103L FEM chip with integrated PA and LNA +// RF path: SX1262 -> Pi attenuator -> KCT8103L PA -> Antenna +// Control logic (from KCT8103L datasheet): +// Transmit PA: CSD=1, CTX=1, CPS=1 +// Receive LNA: CSD=1, CTX=0, CPS=X (21dB gain, 1.9dB NF) +// Receive bypass: CSD=1, CTX=1, CPS=0 // Shutdown: CSD=0, CTX=X, CPS=X -// Receive LNA: CSD=1, CTX=0, CPS=X (17dB gain, 2dB NF) -// Transmit bypass: CSD=1, CTX=1, CPS=0 (~1dB loss, no PA) -// Transmit PA: CSD=1, CTX=1, CPS=1 (full PA enabled) // Pin mapping: -// CTX (pin 6) -> SX1262 DIO2: TX/RX path select (automatic via SX126X_DIO2_AS_RF_SWITCH) +// CPS (pin 5) -> SX1262 DIO2: TX/RX path select (automatic via SX126X_DIO2_AS_RF_SWITCH) // CSD (pin 4) -> GPIO4: Chip enable (HIGH=on, LOW=shutdown) -// CPS (pin 5) -> GPIO46: PA mode select (HIGH=full PA, LOW=bypass) +// CTX (pin 6) -> GPIO5: Switch between Receive LNA Mode and Receive Bypass Mode. (HIGH=RX bypass, LOW=RX LNA) // VCC0/VCC1 -> Vfem via U3 LDO, controlled by GPIO7 -#define USE_GC1109_PA -#define LORA_PA_POWER 7 // VFEM_Ctrl - GC1109 LDO power enable -#define LORA_GC1109_PA_EN 4 // CSD - GC1109 chip enable (HIGH=on) -#define LORA_GC1109_PA_TX_EN 46 // CPS - GC1109 PA mode (HIGH=full PA, LOW=bypass) +// KCT8103L FEM: TX/RX path switching is handled by DIO2 -> CPS pin (via SX126X_DIO2_AS_RF_SWITCH) -// GC1109 FEM: TX/RX path switching is handled by DIO2 -> CTX pin (via SX126X_DIO2_AS_RF_SWITCH) -// GPIO46 is CPS (PA mode), not TX control - setTransmitEnable() handles it in SX126xInterface.cpp -// Do NOT use SX126X_TXEN/RXEN as that would cause double-control of GPIO46 \ No newline at end of file +#define USE_KCT8103L_PA +#define LORA_PA_POWER 7 // VFEM_Ctrl - KCT8103L LDO power enable +#define LORA_KCT8103L_PA_CSD 4 // CSD - KCT8103L chip enable (HIGH=on) +#define LORA_KCT8103L_PA_CTX 5 // CTX - Switch between Receive LNA Mode and Receive Bypass Mode. (HIGH=RX bypass, LOW=RX LNA) \ No newline at end of file