From 9312fe780a13245fa3e15cdbc9d890c94421cffa Mon Sep 17 00:00:00 2001 From: Quency-D Date: Thu, 26 Feb 2026 17:47:03 +0800 Subject: [PATCH 1/2] add heltec v4.3 --- variants/heltec_v4/HeltecV4Board.cpp | 16 +--- variants/heltec_v4/HeltecV4Board.h | 4 +- variants/heltec_v4/LoRaFEMControl.cpp | 104 ++++++++++++++++++++++++++ variants/heltec_v4/LoRaFEMControl.h | 28 +++++++ variants/heltec_v4/platformio.ini | 8 +- 5 files changed, 143 insertions(+), 17 deletions(-) create mode 100644 variants/heltec_v4/LoRaFEMControl.cpp create mode 100644 variants/heltec_v4/LoRaFEMControl.h diff --git a/variants/heltec_v4/HeltecV4Board.cpp b/variants/heltec_v4/HeltecV4Board.cpp index 92f934376..fcb5050dc 100644 --- a/variants/heltec_v4/HeltecV4Board.cpp +++ b/variants/heltec_v4/HeltecV4Board.cpp @@ -7,15 +7,7 @@ void HeltecV4Board::begin() { pinMode(PIN_ADC_CTRL, OUTPUT); digitalWrite(PIN_ADC_CTRL, LOW); // Initially inactive - pinMode(P_LORA_PA_POWER, OUTPUT); - digitalWrite(P_LORA_PA_POWER,HIGH); - - rtc_gpio_hold_dis((gpio_num_t)P_LORA_PA_EN); - pinMode(P_LORA_PA_EN, OUTPUT); - digitalWrite(P_LORA_PA_EN,HIGH); - pinMode(P_LORA_PA_TX_EN, OUTPUT); - digitalWrite(P_LORA_PA_TX_EN,LOW); - + loRaFEMControl.init(); periph_power.begin(); @@ -33,12 +25,12 @@ void HeltecV4Board::begin() { void HeltecV4Board::onBeforeTransmit(void) { digitalWrite(P_LORA_TX_LED, HIGH); // turn TX LED on - digitalWrite(P_LORA_PA_TX_EN,HIGH); + loRaFEMControl.setTxModeEnable(); } void HeltecV4Board::onAfterTransmit(void) { digitalWrite(P_LORA_TX_LED, LOW); // turn TX LED off - digitalWrite(P_LORA_PA_TX_EN,LOW); + loRaFEMControl.setRxModeEnable(); } void HeltecV4Board::enterDeepSleep(uint32_t secs, int pin_wake_btn) { @@ -50,7 +42,7 @@ void HeltecV4Board::begin() { rtc_gpio_hold_en((gpio_num_t)P_LORA_NSS); - rtc_gpio_hold_en((gpio_num_t)P_LORA_PA_EN); //It also needs to be enabled in receive mode + loRaFEMControl.setRxModeEnableWhenMCUSleep();//It also needs to be enabled in receive mode if (pin_wake_btn < 0) { esp_sleep_enable_ext1_wakeup( (1L << P_LORA_DIO_1), ESP_EXT1_WAKEUP_ANY_HIGH); // wake up on: recv LoRa packet diff --git a/variants/heltec_v4/HeltecV4Board.h b/variants/heltec_v4/HeltecV4Board.h index 745e8d8f3..4d5ee4615 100644 --- a/variants/heltec_v4/HeltecV4Board.h +++ b/variants/heltec_v4/HeltecV4Board.h @@ -4,12 +4,12 @@ #include #include #include - +#include "LoRaFEMControl.h" class HeltecV4Board : public ESP32Board { public: RefCountedDigitalPin periph_power; - + LoRaFEMControl loRaFEMControl; HeltecV4Board() : periph_power(PIN_VEXT_EN,PIN_VEXT_EN_ACTIVE) { } void begin(); diff --git a/variants/heltec_v4/LoRaFEMControl.cpp b/variants/heltec_v4/LoRaFEMControl.cpp new file mode 100644 index 000000000..c5953b778 --- /dev/null +++ b/variants/heltec_v4/LoRaFEMControl.cpp @@ -0,0 +1,104 @@ +#include "LoRaFEMControl.h" +#include +#include +#include + +void LoRaFEMControl::init(void) +{ + setLnaCanControl(false);// Default is uncontrollable + rtc_gpio_hold_dis((gpio_num_t)P_LORA_PA_POWER); + rtc_gpio_hold_dis((gpio_num_t)P_LORA_GC1109_PA_EN); + rtc_gpio_hold_dis((gpio_num_t)P_LORA_GC1109_PA_TX_EN); + rtc_gpio_hold_dis((gpio_num_t)P_LORA_KCT8103L_PA_CSD); + rtc_gpio_hold_dis((gpio_num_t)P_LORA_KCT8103L_PA_CTX); + + pinMode(P_LORA_PA_POWER,OUTPUT); + digitalWrite(P_LORA_PA_POWER,HIGH); + delay(1); + pinMode(P_LORA_KCT8103L_PA_CSD,INPUT); // detect which FEM is used + delay(1); + if(digitalRead(P_LORA_KCT8103L_PA_CSD)==HIGH) { + // FEM is KCT8103L + fem_type= KCT8103L_PA; + pinMode(P_LORA_KCT8103L_PA_CSD, OUTPUT); + digitalWrite(P_LORA_KCT8103L_PA_CSD, HIGH); + pinMode(P_LORA_KCT8103L_PA_CTX, OUTPUT); + digitalWrite(P_LORA_KCT8103L_PA_CTX, HIGH); + setLnaCanControl(true); + } else if(digitalRead(P_LORA_KCT8103L_PA_CSD)==LOW) { + // FEM is GC1109 + fem_type= GC1109_PA; + pinMode(P_LORA_GC1109_PA_EN, OUTPUT); + digitalWrite(P_LORA_GC1109_PA_EN, HIGH); + pinMode(P_LORA_GC1109_PA_TX_EN, OUTPUT); + digitalWrite(P_LORA_GC1109_PA_TX_EN, LOW); + } else { + fem_type= OTHER_FEM_TYPES; + } +} + +void LoRaFEMControl::setSleepModeEnable(void) +{ + if(fem_type==GC1109_PA) { + /* + * Do not switch the power on and off frequently. + * After turning off P_LORA_PA_EN, the power consumption has dropped to the uA level. + */ + digitalWrite(P_LORA_GC1109_PA_EN, LOW); + digitalWrite(P_LORA_GC1109_PA_TX_EN, LOW); + } else if(fem_type==KCT8103L_PA) { + // shutdown the PA + digitalWrite(P_LORA_KCT8103L_PA_CSD, LOW); + } +} + +void LoRaFEMControl::setTxModeEnable(void) +{ + if(fem_type==GC1109_PA) { + digitalWrite(P_LORA_GC1109_PA_EN, HIGH); // CSD=1: Chip enabled + digitalWrite(P_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) { + digitalWrite(P_LORA_KCT8103L_PA_CSD, HIGH); + digitalWrite(P_LORA_KCT8103L_PA_CTX, HIGH); + } +} + +void LoRaFEMControl::setRxModeEnable(void) +{ + if(fem_type==GC1109_PA) { + digitalWrite(P_LORA_GC1109_PA_EN, HIGH); // CSD=1: Chip enabled + digitalWrite(P_LORA_GC1109_PA_TX_EN, LOW); + } else if(fem_type==KCT8103L_PA) { + digitalWrite(P_LORA_KCT8103L_PA_CSD, HIGH); + if(lna_enabled) { + digitalWrite(P_LORA_KCT8103L_PA_CTX, LOW); + } else { + digitalWrite(P_LORA_KCT8103L_PA_CTX, HIGH); + } + } +} + +void LoRaFEMControl::setRxModeEnableWhenMCUSleep(void) +{ + digitalWrite(P_LORA_PA_POWER, HIGH); + rtc_gpio_hold_en((gpio_num_t)P_LORA_PA_POWER); + if(fem_type==GC1109_PA) { + digitalWrite(P_LORA_GC1109_PA_EN, HIGH); + rtc_gpio_hold_en((gpio_num_t)P_LORA_GC1109_PA_EN); + gpio_pulldown_en((gpio_num_t)P_LORA_GC1109_PA_TX_EN); + } else if(fem_type==KCT8103L_PA) { + digitalWrite(P_LORA_KCT8103L_PA_CSD, HIGH); + rtc_gpio_hold_en((gpio_num_t)P_LORA_KCT8103L_PA_CSD); + if(lna_enabled) { + digitalWrite(P_LORA_KCT8103L_PA_CTX, LOW); + } else { + digitalWrite(P_LORA_KCT8103L_PA_CTX, HIGH); + } + rtc_gpio_hold_en((gpio_num_t)P_LORA_KCT8103L_PA_CTX); + } +} + +void LoRaFEMControl::setLNAEnable(bool enabled) +{ + lna_enabled = enabled; +} diff --git a/variants/heltec_v4/LoRaFEMControl.h b/variants/heltec_v4/LoRaFEMControl.h new file mode 100644 index 000000000..349f0ffb8 --- /dev/null +++ b/variants/heltec_v4/LoRaFEMControl.h @@ -0,0 +1,28 @@ +#pragma once +#include + +typedef enum { + GC1109_PA, + KCT8103L_PA, + OTHER_FEM_TYPES +} LoRaFEMType; + +class LoRaFEMControl +{ + public: + LoRaFEMControl(){ } + virtual ~LoRaFEMControl(){ } + void init(void); + void setSleepModeEnable(void); + void setTxModeEnable(void); + void setRxModeEnable(void); + void setRxModeEnableWhenMCUSleep(void); + void setLNAEnable(bool enabled); + bool isLnaCanControl(void) { return lna_can_control; } + void setLnaCanControl(bool can_control) { lna_can_control = can_control; } + private: + LoRaFEMType fem_type; + bool lna_enabled=false; + bool lna_can_control=false; +}; + diff --git a/variants/heltec_v4/platformio.ini b/variants/heltec_v4/platformio.ini index c5011e0e9..3bec19f5a 100644 --- a/variants/heltec_v4/platformio.ini +++ b/variants/heltec_v4/platformio.ini @@ -17,9 +17,11 @@ build_flags = -D P_LORA_SCLK=9 -D P_LORA_MISO=11 -D P_LORA_MOSI=10 - -D P_LORA_PA_POWER=7 ; VFEM_Ctrl - Power on GC1109 - -D P_LORA_PA_EN=2 ; PA CSD - Enable GC1109 - -D P_LORA_PA_TX_EN=46 ; PA CPS - GC1109 TX PA full(High) / bypass(Low) + -D P_LORA_PA_POWER=7 ; // VFEM_Ctrl -LDO power enable + -D P_LORA_GC1109_PA_EN=2 ; // CSD - GC1109 chip enable (HIGH=on) + -D P_LORA_GC1109_PA_TX_EN=46 ;// CPS - GC1109 PA mode (HIGH=full PA, LOW=bypass) + -D P_LORA_KCT8103L_PA_CSD=2 + -D P_LORA_KCT8103L_PA_CTX=5 -D PIN_USER_BTN=0 -D PIN_VEXT_EN=36 -D PIN_VEXT_EN_ACTIVE=LOW From f0d37e552d05d4013f516a4a1f0767e0b283645a Mon Sep 17 00:00:00 2001 From: Quency-D Date: Fri, 27 Feb 2026 16:49:00 +0800 Subject: [PATCH 2/2] Added version identification. --- variants/heltec_v4/HeltecV4Board.cpp | 10 +++++----- variants/heltec_v4/LoRaFEMControl.h | 3 ++- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/variants/heltec_v4/HeltecV4Board.cpp b/variants/heltec_v4/HeltecV4Board.cpp index fcb5050dc..6cad79ab9 100644 --- a/variants/heltec_v4/HeltecV4Board.cpp +++ b/variants/heltec_v4/HeltecV4Board.cpp @@ -78,9 +78,9 @@ void HeltecV4Board::begin() { } const char* HeltecV4Board::getManufacturerName() const { - #ifdef HELTEC_LORA_V4_TFT - return "Heltec V4 TFT"; - #else - return "Heltec V4 OLED"; - #endif +#ifdef HELTEC_LORA_V4_TFT + return loRaFEMControl.getFEMType() == KCT8103L_PA ? "Heltec V4.3 TFT" : "Heltec V4 TFT"; +#else + return loRaFEMControl.getFEMType() == KCT8103L_PA ? "Heltec V4.3 OLED" : "Heltec V4 OLED"; +#endif } diff --git a/variants/heltec_v4/LoRaFEMControl.h b/variants/heltec_v4/LoRaFEMControl.h index 349f0ffb8..13225bd56 100644 --- a/variants/heltec_v4/LoRaFEMControl.h +++ b/variants/heltec_v4/LoRaFEMControl.h @@ -20,8 +20,9 @@ class LoRaFEMControl void setLNAEnable(bool enabled); bool isLnaCanControl(void) { return lna_can_control; } void setLnaCanControl(bool can_control) { lna_can_control = can_control; } + LoRaFEMType getFEMType(void) const { return fem_type; } private: - LoRaFEMType fem_type; + LoRaFEMType fem_type=OTHER_FEM_TYPES; bool lna_enabled=false; bool lna_can_control=false; };