From 063f5056f23b7a3999016f6b60028bd724c3837b Mon Sep 17 00:00:00 2001 From: Kevin Le Date: Mon, 2 Feb 2026 11:21:00 +0700 Subject: [PATCH 1/8] Fixed RefCountedDigitalPin.h to release claim correctly. Ensure no negative claims number. --- src/helpers/RefCountedDigitalPin.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/helpers/RefCountedDigitalPin.h b/src/helpers/RefCountedDigitalPin.h index 753f6c30e9..4cf53cda4e 100644 --- a/src/helpers/RefCountedDigitalPin.h +++ b/src/helpers/RefCountedDigitalPin.h @@ -20,10 +20,12 @@ class RefCountedDigitalPin { digitalWrite(_pin, _active); } } + void release() { - _claims--; if (_claims == 0) { digitalWrite(_pin, !_active); + } else { + _claims--; } } }; From 39fb2902ec5653971a62fb308b9d2e56e77f7480 Mon Sep 17 00:00:00 2001 From: Kevin Le Date: Thu, 5 Feb 2026 22:42:02 +0700 Subject: [PATCH 2/8] Avoid negative _claims --- src/helpers/RefCountedDigitalPin.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/helpers/RefCountedDigitalPin.h b/src/helpers/RefCountedDigitalPin.h index 4cf53cda4e..f30c4c58be 100644 --- a/src/helpers/RefCountedDigitalPin.h +++ b/src/helpers/RefCountedDigitalPin.h @@ -22,10 +22,11 @@ class RefCountedDigitalPin { } void release() { + if (_claims == 0) return; // avoid negative _claims + + _claims--; if (_claims == 0) { digitalWrite(_pin, !_active); - } else { - _claims--; } } }; From f6603fe7a5edf8b8197e45b7e909c6e781507511 Mon Sep 17 00:00:00 2001 From: Kevin Le Date: Thu, 5 Feb 2026 23:26:08 +0700 Subject: [PATCH 3/8] Set back PIN_VEXT_EN_ACTIVE=HIGH --- variants/heltec_v4/platformio.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/variants/heltec_v4/platformio.ini b/variants/heltec_v4/platformio.ini index c5011e0e9b..fdddcd5d0c 100644 --- a/variants/heltec_v4/platformio.ini +++ b/variants/heltec_v4/platformio.ini @@ -22,7 +22,7 @@ build_flags = -D P_LORA_PA_TX_EN=46 ; PA CPS - GC1109 TX PA full(High) / bypass(Low) -D PIN_USER_BTN=0 -D PIN_VEXT_EN=36 - -D PIN_VEXT_EN_ACTIVE=LOW + -D PIN_VEXT_EN_ACTIVE=HIGH -D LORA_TX_POWER=10 ;If it is configured as 10 here, the final output will be 22 dbm. -D MAX_LORA_TX_POWER=22 ; Max SX1262 output -D SX126X_REGISTER_PATCH=1 ; Patch register 0x8B5 for improved RX From 44b80d00c202a9783773086ef93f64bc0ce85457 Mon Sep 17 00:00:00 2001 From: Kevin Le Date: Thu, 5 Feb 2026 23:27:10 +0700 Subject: [PATCH 4/8] Disabled periph_power for Heltec v4's display --- variants/heltec_v4/target.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/variants/heltec_v4/target.cpp b/variants/heltec_v4/target.cpp index f971cc6085..54fc05e891 100644 --- a/variants/heltec_v4/target.cpp +++ b/variants/heltec_v4/target.cpp @@ -24,7 +24,7 @@ AutoDiscoverRTCClock rtc_clock(fallback_clock); #endif #ifdef DISPLAY_CLASS - DISPLAY_CLASS display(&(board.periph_power)); + DISPLAY_CLASS display(NULL); MomentaryButton user_btn(PIN_USER_BTN, 1000, true); #endif From 13d0dff9182bf7931b9b6c87b67d7e5120301099 Mon Sep 17 00:00:00 2001 From: Kevin Le Date: Wed, 18 Feb 2026 22:29:33 +0700 Subject: [PATCH 5/8] Reverted to use GPIO 17, 18 as I2C for Heltec v4 repeater --- variants/heltec_v4/platformio.ini | 2 -- 1 file changed, 2 deletions(-) diff --git a/variants/heltec_v4/platformio.ini b/variants/heltec_v4/platformio.ini index fdddcd5d0c..71ffc2e6a9 100644 --- a/variants/heltec_v4/platformio.ini +++ b/variants/heltec_v4/platformio.ini @@ -54,8 +54,6 @@ build_flags = -D PIN_BOARD_SDA=17 -D PIN_BOARD_SCL=18 -D PIN_OLED_RESET=21 - -D ENV_PIN_SDA=4 - -D ENV_PIN_SCL=3 build_src_filter= ${Heltec_lora32_v4.build_src_filter} lib_deps = ${Heltec_lora32_v4.lib_deps} From 8ad17d1022242ac066021778e5ca4b79c839225f Mon Sep 17 00:00:00 2001 From: enricolorenzoni59 Date: Sat, 28 Feb 2026 09:07:30 +0000 Subject: [PATCH 6/8] `gps sync` reply: fill buffer with text --- src/helpers/CommonCLI.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/helpers/CommonCLI.cpp b/src/helpers/CommonCLI.cpp index f2f961b93a..e20bbb1c02 100644 --- a/src/helpers/CommonCLI.cpp +++ b/src/helpers/CommonCLI.cpp @@ -717,6 +717,9 @@ void CommonCLI::handleCommand(uint32_t sender_timestamp, const char* command, ch LocationProvider * l = _sensors->getLocationProvider(); if (l != NULL) { l->syncTime(); + strcpy(reply, "ok"); + } else { + strcpy(reply, "gps provider not found"); } } else if (memcmp(command, "gps setloc", 10) == 0) { _prefs->node_lat = _sensors->node_lat; From 329e40819720981b2c208831ab38ac907a849970 Mon Sep 17 00:00:00 2001 From: Wessel Nieboer Date: Fri, 6 Feb 2026 01:57:27 +0100 Subject: [PATCH 7/8] Hold GC1109 PA_POWER during deep sleep for LNA RX wake The GC1109 FEM needs its VFEM_Ctrl pin held HIGH during deep sleep to keep the LNA active, enabling proper RX sensitivity for wake-on-packet. Without this, the LNA is unpowered during sleep and RX wake sensitivity is degraded by ~17dB. Release RTC holds in begin() after configuring GPIO registers (not before) to ensure glitch-free pin transitions on wake. Trade-off: ~6.5mA additional sleep current for significantly improved wake-on-packet range. --- variants/heltec_tracker_v2/HeltecTrackerV2Board.cpp | 11 +++++++++-- variants/heltec_tracker_v2/platformio.ini | 10 +++++----- variants/heltec_v4/HeltecV4Board.cpp | 11 +++++++++-- 3 files changed, 23 insertions(+), 9 deletions(-) diff --git a/variants/heltec_tracker_v2/HeltecTrackerV2Board.cpp b/variants/heltec_tracker_v2/HeltecTrackerV2Board.cpp index 4975d5cdeb..1b694c11d4 100644 --- a/variants/heltec_tracker_v2/HeltecTrackerV2Board.cpp +++ b/variants/heltec_tracker_v2/HeltecTrackerV2Board.cpp @@ -6,12 +6,17 @@ void HeltecTrackerV2Board::begin() { pinMode(PIN_ADC_CTRL, OUTPUT); digitalWrite(PIN_ADC_CTRL, LOW); // Initially inactive + // Set up digital GPIO registers before releasing RTC hold. The hold latches + // the pad state including function select, so register writes accumulate + // without affecting the pad. On hold release, all changes apply atomically + // (IO MUX switches to digital GPIO with output already HIGH — no glitch). pinMode(P_LORA_PA_POWER, OUTPUT); digitalWrite(P_LORA_PA_POWER,HIGH); + rtc_gpio_hold_dis((gpio_num_t)P_LORA_PA_POWER); - rtc_gpio_hold_dis((gpio_num_t)P_LORA_PA_EN); pinMode(P_LORA_PA_EN, OUTPUT); digitalWrite(P_LORA_PA_EN,HIGH); + rtc_gpio_hold_dis((gpio_num_t)P_LORA_PA_EN); pinMode(P_LORA_PA_TX_EN, OUTPUT); digitalWrite(P_LORA_PA_TX_EN,LOW); @@ -48,7 +53,9 @@ void HeltecTrackerV2Board::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 + // Hold GC1109 FEM pins during sleep to keep LNA active for RX wake + rtc_gpio_hold_en((gpio_num_t)P_LORA_PA_POWER); + rtc_gpio_hold_en((gpio_num_t)P_LORA_PA_EN); 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_tracker_v2/platformio.ini b/variants/heltec_tracker_v2/platformio.ini index 25d16f2f66..af41b4f56a 100644 --- a/variants/heltec_tracker_v2/platformio.ini +++ b/variants/heltec_tracker_v2/platformio.ini @@ -17,11 +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 ;power en - -D P_LORA_PA_EN=4 - -D P_LORA_PA_TX_EN=46 ;enable tx - -D LORA_TX_POWER=10 ;If it is configured as 10 here, the final output will be 22 dbm. - -D MAX_LORA_TX_POWER=22 ;Max SX1262 output + -D P_LORA_PA_POWER=7 ; VFEM_Ctrl - GC1109 LDO power enable + -D P_LORA_PA_EN=4 ; CSD - GC1109 chip enable (HIGH=on) + -D P_LORA_PA_TX_EN=46 ; CPS - GC1109 PA mode (HIGH=full PA, LOW=bypass) + -D LORA_TX_POWER=10 ; 10dBm + ~11dB GC1109 gain = ~21dBm output + -D MAX_LORA_TX_POWER=22 ; Max SX1262 output -> ~28dBm at antenna -D SX126X_DIO2_AS_RF_SWITCH=true -D SX126X_DIO3_TCXO_VOLTAGE=1.8 -D SX126X_CURRENT_LIMIT=140 diff --git a/variants/heltec_v4/HeltecV4Board.cpp b/variants/heltec_v4/HeltecV4Board.cpp index 92f9343767..626f25773e 100644 --- a/variants/heltec_v4/HeltecV4Board.cpp +++ b/variants/heltec_v4/HeltecV4Board.cpp @@ -7,12 +7,17 @@ void HeltecV4Board::begin() { pinMode(PIN_ADC_CTRL, OUTPUT); digitalWrite(PIN_ADC_CTRL, LOW); // Initially inactive + // Set up digital GPIO registers before releasing RTC hold. The hold latches + // the pad state including function select, so register writes accumulate + // without affecting the pad. On hold release, all changes apply atomically + // (IO MUX switches to digital GPIO with output already HIGH — no glitch). pinMode(P_LORA_PA_POWER, OUTPUT); digitalWrite(P_LORA_PA_POWER,HIGH); + rtc_gpio_hold_dis((gpio_num_t)P_LORA_PA_POWER); - rtc_gpio_hold_dis((gpio_num_t)P_LORA_PA_EN); pinMode(P_LORA_PA_EN, OUTPUT); digitalWrite(P_LORA_PA_EN,HIGH); + rtc_gpio_hold_dis((gpio_num_t)P_LORA_PA_EN); pinMode(P_LORA_PA_TX_EN, OUTPUT); digitalWrite(P_LORA_PA_TX_EN,LOW); @@ -50,7 +55,9 @@ 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 + // Hold GC1109 FEM pins during sleep to keep LNA active for RX wake + rtc_gpio_hold_en((gpio_num_t)P_LORA_PA_POWER); + rtc_gpio_hold_en((gpio_num_t)P_LORA_PA_EN); 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 From 2bb6f636a4ae18da2f793501effe9265cd9654cd Mon Sep 17 00:00:00 2001 From: Wessel Nieboer Date: Sun, 8 Feb 2026 16:36:13 +0100 Subject: [PATCH 8/8] Add 1ms delay after powering PA (cold-boot) --- variants/heltec_tracker_v2/HeltecTrackerV2Board.cpp | 7 +++++-- variants/heltec_v4/HeltecV4Board.cpp | 6 ++++-- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/variants/heltec_tracker_v2/HeltecTrackerV2Board.cpp b/variants/heltec_tracker_v2/HeltecTrackerV2Board.cpp index 1b694c11d4..bd7f680ea2 100644 --- a/variants/heltec_tracker_v2/HeltecTrackerV2Board.cpp +++ b/variants/heltec_tracker_v2/HeltecTrackerV2Board.cpp @@ -20,9 +20,12 @@ void HeltecTrackerV2Board::begin() { pinMode(P_LORA_PA_TX_EN, OUTPUT); digitalWrite(P_LORA_PA_TX_EN,LOW); - periph_power.begin(); - esp_reset_reason_t reason = esp_reset_reason(); + if (reason != ESP_RST_DEEPSLEEP) { + delay(1); // GC1109 startup time after cold power-on + } + + periph_power.begin(); if (reason == ESP_RST_DEEPSLEEP) { long wakeup_source = esp_sleep_get_ext1_wakeup_status(); if (wakeup_source & (1 << P_LORA_DIO_1)) { // received a LoRa packet (while in deep sleep) diff --git a/variants/heltec_v4/HeltecV4Board.cpp b/variants/heltec_v4/HeltecV4Board.cpp index 626f25773e..8186f2d4b2 100644 --- a/variants/heltec_v4/HeltecV4Board.cpp +++ b/variants/heltec_v4/HeltecV4Board.cpp @@ -21,10 +21,12 @@ void HeltecV4Board::begin() { pinMode(P_LORA_PA_TX_EN, OUTPUT); digitalWrite(P_LORA_PA_TX_EN,LOW); + esp_reset_reason_t reason = esp_reset_reason(); + if (reason != ESP_RST_DEEPSLEEP) { + delay(1); // GC1109 startup time after cold power-on + } periph_power.begin(); - - esp_reset_reason_t reason = esp_reset_reason(); if (reason == ESP_RST_DEEPSLEEP) { long wakeup_source = esp_sleep_get_ext1_wakeup_status(); if (wakeup_source & (1 << P_LORA_DIO_1)) { // received a LoRa packet (while in deep sleep)