From 4575800e4069004cf8fb024517b2b33387bd2e5a Mon Sep 17 00:00:00 2001 From: Socalix <48040807+Socalix@users.noreply.github.com> Date: Wed, 14 Jan 2026 17:52:15 -0600 Subject: [PATCH 1/4] Turn on register 0x8B5 LSB for improved RX, turn off boosted gain --- src/helpers/radiolib/CustomSX1262.h | 8 ++++++++ variants/heltec_v4/platformio.ini | 11 ++++++----- 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/src/helpers/radiolib/CustomSX1262.h b/src/helpers/radiolib/CustomSX1262.h index bfaea7c7..be6812c6 100644 --- a/src/helpers/radiolib/CustomSX1262.h +++ b/src/helpers/radiolib/CustomSX1262.h @@ -76,6 +76,14 @@ class CustomSX1262 : public SX1262 { setRfSwitchPins(SX126X_RXEN, SX126X_TXEN); #endif + // for improved RX with Heltec v4 + #ifdef SX126X_REGISTER_PATCH + uint8_t r_data = 0; + readRegister(0x8B5, &r_data, 1); + r_data |= 0x01; + writeRegister(0x8B5, &r_data, 1); + #endif + return true; // success } diff --git a/variants/heltec_v4/platformio.ini b/variants/heltec_v4/platformio.ini index ecfd7889..9ab3e162 100644 --- a/variants/heltec_v4/platformio.ini +++ b/variants/heltec_v4/platformio.ini @@ -17,9 +17,9 @@ 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=2 - -D P_LORA_PA_TX_EN=46 ;enable tx + -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 PIN_BOARD_SDA=17 -D PIN_BOARD_SCL=18 -D PIN_USER_BTN=0 @@ -27,10 +27,11 @@ build_flags = -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_DIO2_AS_RF_SWITCH=true + -D SX126X_REGISTER_PATCH=1 ; Patch register 0x8B5 for improved RX + -D SX126X_DIO2_AS_RF_SWITCH=true ; GC1109 CTX is controlled by SX1262 DIO2 -D SX126X_DIO3_TCXO_VOLTAGE=1.8 -D SX126X_CURRENT_LIMIT=140 - -D SX126X_RX_BOOSTED_GAIN=1 +; -D SX126X_RX_BOOSTED_GAIN=1 ; Turned off for improved RX -D PIN_GPS_RX=38 -D PIN_GPS_TX=39 -D PIN_GPS_RESET=42 From 46e4cc06e39043c74cd4d164cc2aedb0f5bbeccf Mon Sep 17 00:00:00 2001 From: Socalix <48040807+Socalix@users.noreply.github.com> Date: Wed, 21 Jan 2026 21:12:54 -0600 Subject: [PATCH 2/4] Revert boosted gain flag to original --- 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 9ab3e162..258a9967 100644 --- a/variants/heltec_v4/platformio.ini +++ b/variants/heltec_v4/platformio.ini @@ -31,7 +31,7 @@ build_flags = -D SX126X_DIO2_AS_RF_SWITCH=true ; GC1109 CTX is controlled by SX1262 DIO2 -D SX126X_DIO3_TCXO_VOLTAGE=1.8 -D SX126X_CURRENT_LIMIT=140 -; -D SX126X_RX_BOOSTED_GAIN=1 ; Turned off for improved RX + -D SX126X_RX_BOOSTED_GAIN=1 ; In some cases, commenting this out will improve RX -D PIN_GPS_RX=38 -D PIN_GPS_TX=39 -D PIN_GPS_RESET=42 From c7eea3915d5d23e8cbe5271d3ae4ccc11f4bc68b Mon Sep 17 00:00:00 2001 From: taco Date: Fri, 30 Jan 2026 15:07:40 +1100 Subject: [PATCH 3/4] fix: remove esp_wifi.h from esp32board.h saves ~500 bytes of dram and allows Tbeam to compile again --- examples/companion_radio/main.cpp | 1 + src/helpers/ESP32Board.cpp | 1 + src/helpers/ESP32Board.h | 12 ++++++------ 3 files changed, 8 insertions(+), 6 deletions(-) diff --git a/examples/companion_radio/main.cpp b/examples/companion_radio/main.cpp index 7e636ace..eff9efca 100644 --- a/examples/companion_radio/main.cpp +++ b/examples/companion_radio/main.cpp @@ -194,6 +194,7 @@ void setup() { ); #ifdef WIFI_SSID + board.setInhibitSleep(true); // prevent sleep when WiFi is active WiFi.begin(WIFI_SSID, WIFI_PWD); serial_interface.begin(TCP_PORT); #elif defined(BLE_PIN_CODE) diff --git a/src/helpers/ESP32Board.cpp b/src/helpers/ESP32Board.cpp index 4dce467c..e0ca1d0e 100644 --- a/src/helpers/ESP32Board.cpp +++ b/src/helpers/ESP32Board.cpp @@ -11,6 +11,7 @@ #include bool ESP32Board::startOTAUpdate(const char* id, char reply[]) { + inhibit_sleep = true; // prevent sleep during OTA WiFi.softAP("MeshCore-OTA", NULL); sprintf(reply, "Started: http://%s/update", WiFi.softAPIP().toString().c_str()); diff --git a/src/helpers/ESP32Board.h b/src/helpers/ESP32Board.h index 01b4c980..bade3e89 100644 --- a/src/helpers/ESP32Board.h +++ b/src/helpers/ESP32Board.h @@ -8,12 +8,12 @@ #include #include #include -#include "esp_wifi.h" #include "driver/rtc_io.h" class ESP32Board : public mesh::MainBoard { protected: uint8_t startup_reason; + bool inhibit_sleep = false; public: void begin() { @@ -72,11 +72,7 @@ public: } void sleep(uint32_t secs) override { - // To check for WiFi status to see if there is active OTA - wifi_mode_t mode; - esp_err_t err = esp_wifi_get_mode(&mode); - - if (err != ESP_OK) { // WiFi is off ~ No active OTA, safe to go to sleep + if (!inhibit_sleep) { enterLightSleep(secs); // To wake up after "secs" seconds or when receiving a LoRa packet } } @@ -126,6 +122,10 @@ public: } bool startOTAUpdate(const char* id, char reply[]) override; + + void setInhibitSleep(bool inhibit) { + inhibit_sleep = inhibit; + } }; class ESP32RTCClock : public mesh::RTCClock { From a342ab8437e19ea792e51e46cd14c333c1c8b609 Mon Sep 17 00:00:00 2001 From: taco Date: Sun, 1 Feb 2026 14:46:55 +1100 Subject: [PATCH 4/4] nrf52: allow repeater to sleep when idle --- examples/simple_repeater/main.cpp | 9 ++++++--- src/helpers/NRF52Board.cpp | 26 ++++++++++++++++++++++++++ src/helpers/NRF52Board.h | 1 + 3 files changed, 33 insertions(+), 3 deletions(-) diff --git a/examples/simple_repeater/main.cpp b/examples/simple_repeater/main.cpp index d55d6118..eb4b5b09 100644 --- a/examples/simple_repeater/main.cpp +++ b/examples/simple_repeater/main.cpp @@ -127,14 +127,17 @@ void loop() { #endif rtc_clock.tick(); - if (the_mesh.getNodePrefs()->powersaving_enabled && // To check if power saving is enabled - the_mesh.millisHasNowPassed(lastActive + nextSleepinSecs * 1000)) { // To check if it is time to sleep - if (!the_mesh.hasPendingWork()) { // No pending work. Safe to sleep + if (the_mesh.getNodePrefs()->powersaving_enabled && !the_mesh.hasPendingWork()) { + #if defined(NRF52_PLATFORM) + board.sleep(1800); // nrf ignores seconds param, sleeps whenever possible + #else + if (the_mesh.millisHasNowPassed(lastActive + nextSleepinSecs * 1000)) { // To check if it is time to sleep board.sleep(1800); // To sleep. Wake up after 30 minutes or when receiving a LoRa packet lastActive = millis(); nextSleepinSecs = 5; // Default: To work for 5s and sleep again } else { nextSleepinSecs += 5; // When there is pending work, to work another 5s } + #endif } } diff --git a/src/helpers/NRF52Board.cpp b/src/helpers/NRF52Board.cpp index 6915c856..1db858f5 100644 --- a/src/helpers/NRF52Board.cpp +++ b/src/helpers/NRF52Board.cpp @@ -251,6 +251,32 @@ void NRF52BoardDCDC::begin() { } } +void NRF52Board::sleep(uint32_t secs) { + // Clear FPU interrupt flags to avoid insomnia + // see errata 87 for details https://docs.nordicsemi.com/bundle/errata_nRF52840_Rev3/page/ERR/nRF52840/Rev3/latest/anomaly_840_87.html + #if (__FPU_USED == 1) + __set_FPSCR(__get_FPSCR() & ~(0x0000009F)); + (void) __get_FPSCR(); + NVIC_ClearPendingIRQ(FPU_IRQn); + #endif + + // On nRF52, we use event-driven sleep instead of timed sleep + // The 'secs' parameter is ignored - we wake on any interrupt + uint8_t sd_enabled = 0; + sd_softdevice_is_enabled(&sd_enabled); + + if (sd_enabled) { + // first call processes pending softdevice events, second call sleeps. + sd_app_evt_wait(); + sd_app_evt_wait(); + } else { + // softdevice is disabled, use raw WFE + __SEV(); + __WFE(); + __WFE(); + } +} + // Temperature from NRF52 MCU float NRF52Board::getMCUTemperature() { NRF_TEMP->TASKS_START = 1; // Start temperature measurement diff --git a/src/helpers/NRF52Board.h b/src/helpers/NRF52Board.h index 1c70d8f0..0332af07 100644 --- a/src/helpers/NRF52Board.h +++ b/src/helpers/NRF52Board.h @@ -51,6 +51,7 @@ public: virtual float getMCUTemperature() override; virtual void reboot() override { NVIC_SystemReset(); } virtual bool startOTAUpdate(const char *id, char reply[]) override; + virtual void sleep(uint32_t secs) override; #ifdef NRF52_POWER_MANAGEMENT bool isExternalPowered() override;