Skip to content

Commit 671bb19

Browse files
committed
Update Heltec V4 code to support V4.3 with KCT8103L FEM
- runtime auto-detection of v4.3 board (KCT8103L FEM) vs V4.0-V4.2 (GC1109) via GPIO2 pull level - different TX/RX path using PGIO5 for KCT8103L, GPIO46 CPS for GC1109 - hold both FEMs active for RX - report Heltec V4.3 in manufacturer name
1 parent d42588c commit 671bb19

File tree

3 files changed

+54
-23
lines changed

3 files changed

+54
-23
lines changed

variants/heltec_v4/HeltecV4Board.cpp

Lines changed: 51 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -3,49 +3,71 @@
33
void HeltecV4Board::begin() {
44
ESP32Board::begin();
55

6-
76
pinMode(PIN_ADC_CTRL, OUTPUT);
8-
digitalWrite(PIN_ADC_CTRL, LOW); // Initially inactive
7+
digitalWrite(PIN_ADC_CTRL, LOW);
98

10-
// Set up digital GPIO registers before releasing RTC hold. The hold latches
11-
// the pad state including function select, so register writes accumulate
12-
// without affecting the pad. On hold release, all changes apply atomically
13-
// (IO MUX switches to digital GPIO with output already HIGH — no glitch).
9+
// Power on FEM LDO — set registers before releasing RTC hold for
10+
// atomic transition (no glitch on deep sleep wake).
1411
pinMode(P_LORA_PA_POWER, OUTPUT);
15-
digitalWrite(P_LORA_PA_POWER,HIGH);
12+
digitalWrite(P_LORA_PA_POWER, HIGH);
1613
rtc_gpio_hold_dis((gpio_num_t)P_LORA_PA_POWER);
1714

18-
pinMode(P_LORA_PA_EN, OUTPUT);
19-
digitalWrite(P_LORA_PA_EN,HIGH);
20-
rtc_gpio_hold_dis((gpio_num_t)P_LORA_PA_EN);
21-
pinMode(P_LORA_PA_TX_EN, OUTPUT);
22-
digitalWrite(P_LORA_PA_TX_EN,LOW);
23-
2415
esp_reset_reason_t reason = esp_reset_reason();
2516
if (reason != ESP_RST_DEEPSLEEP) {
26-
delay(1); // GC1109 startup time after cold power-on
17+
delay(1); // FEM startup time after cold power-on
18+
}
19+
20+
// Auto-detect FEM type via GPIO2 default pull level.
21+
// GC1109 CSD: internal pull-down → reads LOW
22+
// KCT8103L CSD: internal pull-up → reads HIGH
23+
rtc_gpio_hold_dis((gpio_num_t)P_LORA_PA_EN);
24+
pinMode(P_LORA_PA_EN, INPUT);
25+
delay(1);
26+
is_kct8103l_ = (digitalRead(P_LORA_PA_EN) == HIGH);
27+
28+
// CSD/enable: HIGH for both FEM types
29+
pinMode(P_LORA_PA_EN, OUTPUT);
30+
digitalWrite(P_LORA_PA_EN, HIGH);
31+
32+
if (is_kct8103l_) {
33+
// V4.3 — KCT8103L: CTX on GPIO5 controls TX/RX path
34+
rtc_gpio_hold_dis((gpio_num_t)P_LORA_PA_CTX);
35+
pinMode(P_LORA_PA_CTX, OUTPUT);
36+
digitalWrite(P_LORA_PA_CTX, LOW); // RX mode (LNA enabled)
37+
} else {
38+
// V4.2 — GC1109: CPS on GPIO46 controls PA mode
39+
pinMode(P_LORA_PA_TX_EN, OUTPUT);
40+
digitalWrite(P_LORA_PA_TX_EN, LOW); // RX bypass mode
2741
}
2842

2943
periph_power.begin();
44+
3045
if (reason == ESP_RST_DEEPSLEEP) {
3146
long wakeup_source = esp_sleep_get_ext1_wakeup_status();
32-
if (wakeup_source & (1 << P_LORA_DIO_1)) { // received a LoRa packet (while in deep sleep)
47+
if (wakeup_source & (1 << P_LORA_DIO_1)) {
3348
startup_reason = BD_STARTUP_RX_PACKET;
3449
}
35-
3650
rtc_gpio_hold_dis((gpio_num_t)P_LORA_NSS);
3751
rtc_gpio_deinit((gpio_num_t)P_LORA_DIO_1);
3852
}
3953
}
4054

4155
void HeltecV4Board::onBeforeTransmit(void) {
42-
digitalWrite(P_LORA_TX_LED, HIGH); // turn TX LED on
43-
digitalWrite(P_LORA_PA_TX_EN,HIGH);
56+
digitalWrite(P_LORA_TX_LED, HIGH);
57+
if (is_kct8103l_) {
58+
digitalWrite(P_LORA_PA_CTX, HIGH); // CTX: TX path
59+
} else {
60+
digitalWrite(P_LORA_PA_TX_EN, HIGH); // CPS: full PA
61+
}
4462
}
4563

4664
void HeltecV4Board::onAfterTransmit(void) {
47-
digitalWrite(P_LORA_TX_LED, LOW); // turn TX LED off
48-
digitalWrite(P_LORA_PA_TX_EN,LOW);
65+
digitalWrite(P_LORA_TX_LED, LOW);
66+
if (is_kct8103l_) {
67+
digitalWrite(P_LORA_PA_CTX, LOW); // CTX: RX path (LNA on)
68+
} else {
69+
digitalWrite(P_LORA_PA_TX_EN, LOW); // CPS: bypass
70+
}
4971
}
5072

5173
void HeltecV4Board::enterDeepSleep(uint32_t secs, int pin_wake_btn) {
@@ -57,10 +79,16 @@ void HeltecV4Board::begin() {
5779

5880
rtc_gpio_hold_en((gpio_num_t)P_LORA_NSS);
5981

60-
// Hold GC1109 FEM pins during sleep to keep LNA active for RX wake
82+
// Hold FEM pins during sleep to keep LNA active for RX wake
6183
rtc_gpio_hold_en((gpio_num_t)P_LORA_PA_POWER);
6284
rtc_gpio_hold_en((gpio_num_t)P_LORA_PA_EN);
6385

86+
if (is_kct8103l_) {
87+
// Hold CTX LOW during deep sleep for RX wake (LNA enabled)
88+
digitalWrite(P_LORA_PA_CTX, LOW);
89+
rtc_gpio_hold_en((gpio_num_t)P_LORA_PA_CTX);
90+
}
91+
6492
if (pin_wake_btn < 0) {
6593
esp_sleep_enable_ext1_wakeup( (1L << P_LORA_DIO_1), ESP_EXT1_WAKEUP_ANY_HIGH); // wake up on: recv LoRa packet
6694
} else {
@@ -96,8 +124,8 @@ void HeltecV4Board::begin() {
96124

97125
const char* HeltecV4Board::getManufacturerName() const {
98126
#ifdef HELTEC_LORA_V4_TFT
99-
return "Heltec V4 TFT";
127+
return is_kct8103l_ ? "Heltec V4.3 TFT" : "Heltec V4 TFT";
100128
#else
101-
return "Heltec V4 OLED";
129+
return is_kct8103l_ ? "Heltec V4.3 OLED" : "Heltec V4 OLED";
102130
#endif
103131
}

variants/heltec_v4/HeltecV4Board.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,4 +20,6 @@ class HeltecV4Board : public ESP32Board {
2020
uint16_t getBattMilliVolts() override;
2121
const char* getManufacturerName() const override ;
2222

23+
private:
24+
bool is_kct8103l_ = false; // true = V4.3 (KCT8103L), false = V4.2 (GC1109)
2325
};

variants/heltec_v4/platformio.ini

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ build_flags =
2020
-D P_LORA_PA_POWER=7 ; VFEM_Ctrl - Power on GC1109
2121
-D P_LORA_PA_EN=2 ; PA CSD - Enable GC1109
2222
-D P_LORA_PA_TX_EN=46 ; PA CPS - GC1109 TX PA full(High) / bypass(Low)
23+
-D P_LORA_PA_CTX=5 ; KCT8103L CTX pin (V4.3 only, auto-detected)
2324
-D PIN_USER_BTN=0
2425
-D PIN_VEXT_EN=36
2526
-D PIN_VEXT_EN_ACTIVE=HIGH

0 commit comments

Comments
 (0)