Skip to content

Hold GC1109 PA_POWER during deep sleep for LNA RX wake#1600

Open
weebl2000 wants to merge 2 commits intomeshcore-dev:devfrom
weebl2000:heltec_deep_sleep_lna
Open

Hold GC1109 PA_POWER during deep sleep for LNA RX wake#1600
weebl2000 wants to merge 2 commits intomeshcore-dev:devfrom
weebl2000:heltec_deep_sleep_lna

Conversation

@weebl2000
Copy link
Contributor

@weebl2000 weebl2000 commented Feb 6, 2026

Summary

  • Hold the GC1109 VFEM_Ctrl (PA_POWER) pin HIGH during deep sleep so the FEM's LNA remains active for wake-on-packet RX
  • Release the RTC hold on wake so normal GPIO operation resumes
  • Add 1ms delay after GC1109 power-on during cold boot to allow the FEM to stabilize before use (skipped on deep sleep wake since the FEM was already powered)
  • Applies to both Heltec V4 and Heltec Tracker V2

Without this, the GC1109 LNA could be unpowered during sleep, degrading RX wake sensitivity by ~17dB.

Trade-off: ~1.2mA additional deep sleep current (measured: 11.1mA → 12.3mA) for significantly improved wake-on-packet range.

Test plan

  • Flash Heltec V4, verify wake-on-packet works at expected range
  • Verify TX still works correctly after wake
  • Measure deep sleep current (~1.2mA additional with LNA active, confirmed by @towerviewcams)

Supersedes #1249

@beachmiles
Copy link

beachmiles commented Feb 6, 2026

Nice, hope this fix will get merged soon for cases when powersave is enabled. Awesome.
Any chance I could get a build of this for repeaters and companions for the v4? Thanks.

@Socalix
Copy link

Socalix commented Feb 6, 2026

@weebl2000 Thank you for replacing the original PR with this one. It is much simpler and straightforward code, and easy to see what exactly it's doing.
Just need to move the hold_dis() before write() calls.

@beachmiles
Copy link

beachmiles commented Feb 6, 2026

I finally got the meshcore build env working.
Built the heltec v4 repeater and v4 companion bluetooth version from the dev branch with pr1398 and added this pr1600 along with socalix's recommendation to move that rtc disconnect to line 9.
Edit. Looks like socalixs recommendation was incorrect so I need to rebuild again. The zip attached were what I flashed and the companion only results below are with the mod that socalix recommended so hopefully someone can rebuild or I can do it on Monday
I flashed these to my v4 repeater and companion and both appear to to be working.

Dont know how to enable powersaving mode on the companion but I'm drawing ~0.74 watts (.143 amps at 5.15V) with the screen off where on the 1.11 ver I was previously running just under .6 watts in idle mode. Maybe this is because the LNA is now staying powered on while the esp32 is in idle or light sleep?

Edit. If I disconnect from bluetooth and reconnect the watttage drops back down under .6 watts for a like ~30 seconds but then jumps back up to .74 watts and never comes back down.

Edit. This build doesn't have good powersaving for repeaters and higher power usage for companions. My build from the dev branch must have brought something bad in. But the RX fix seems to be working at least!
heltec_v4_repeater_and_companion_1.12_w_pr1398_and_pr1600_RX_fixes_rev2.zip

The dev put a repeater .bin with his fixes here which has the good power savings.
#1600 (comment)

@weebl2000 weebl2000 force-pushed the heltec_deep_sleep_lna branch from 624b40e to 08880bf Compare February 6, 2026 09:03
@weebl2000
Copy link
Contributor Author

@Socalix I think the current order is correct.

The key distinction here is between the GPIO peripheral registers and the pad hold logic.

digitalWrite() updates the GPIO output registers unconditionally — even while the pad is held. The hold only freezes the pad, not the register state. When rtc_gpio_hold_dis() is called, the pad immediately reflects whatever level is already programmed in the GPIO registers.

This is why the ESP-IDF docs for gpio_hold_dis() state:

“If you don't want the level changes, the gpio should be configured to a known state before this function is called.”

That instruction only makes sense if register writes are expected to occur while the pad is held.

With the current order:

Configure GPIO output HIGH (register updated, pad still held HIGH)

Release hold → pad transitions from held-HIGH to register-HIGH (no glitch)

Reversing the order would cause the pad to briefly revert to its default state on hold release, which would momentarily remove power from the GC1109 FEM.

So the existing order is intentional and avoids a power glitch during wake from deep sleep.

image https://docs.espressif.com/projects/esp-idf/en/stable/esp32s3/api-reference/peripherals/gpio.html

@alexsporn
Copy link

@weebl2000 adding this as a comment to the code might be valuable so it does not get changed in the future because "it looks wrong"

@weebl2000 weebl2000 force-pushed the heltec_deep_sleep_lna branch from 08880bf to eb1aa2f Compare February 6, 2026 10:13
@weebl2000
Copy link
Contributor Author

@weebl2000 adding this as a comment to the code might be valuable so it does not get changed in the future because "it looks wrong"

done

@weebl2000
Copy link
Contributor Author

weebl2000 commented Feb 6, 2026

Edit. If I disconnect from bluetooth and reconnect the watttage drops back down under .6 watts for a like ~30 seconds but then jumps back up to .74 watts and never comes back down.
heltec_v4_repeater_and_companion_1.12_w_pr1398_and_pr1600_RX_fixes_rev2.zip

I haven't tried it myself yet with the companion. It might be difficult to test if you're receiving messages all the time btw.

Unless you have a faraday cage. 😋

@Socalix
Copy link

Socalix commented Feb 7, 2026

@Socalix I think the current order is correct.
The key distinction here is between the GPIO peripheral registers and the pad hold logic.
digitalWrite() updates the GPIO output registers unconditionally — even while the pad is held. The hold only freezes the pad, not the register state. When rtc_gpio_hold_dis() is called, the pad immediately reflects whatever level is already programmed in the GPIO registers.

@weebl2000 This is interesting. Before commenting above, I checked the same documentation specifically for rtc_gpio_hold_dis() that's used in the code and there is no mention of switching to default state. It just says:
Disabling hold function will allow the pad receive the values of input enable, output enable, output value, function, drive strength from RTC_IO peripheral.

I don't know why there's difference between gpio_hold_dis() and rtc_gpio_hold_dis() documentation and what is the correct answer. Maybe we need Heltec to provide info specifically for the v4 implementation, or do some more digging and hardware testing?

rtc_gpio_hold_dis

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.
@weebl2000 weebl2000 force-pushed the heltec_deep_sleep_lna branch from eb1aa2f to d7ff722 Compare February 7, 2026 14:04
@weebl2000
Copy link
Contributor Author

I've updated the code comments to clarify a bit more.

@towerviewcams
Copy link

@beachmiles I have tested your 1398 / 1600 rxfix.rev2 repeater firm file and V4 draws 37mA. I loaded stock firm 1.12 and then yours. I also tried the no display firm that brings down to 11mA and then yours and it jumps to 37mA again.

@ignisf
Copy link

ignisf commented Feb 7, 2026

@weebl2000 can we please get steps how to test this? Reading through the comments I think people are talking about different things and possibly testing incorrectly.

@weebl2000
Copy link
Contributor Author

weebl2000 commented Feb 8, 2026

@weebl2000 can we please get steps how to test this? Reading through the comments I think people are talking about different things and possibly testing incorrectly.

Realistically, you can test by running a repeater with power saving enabled. Then, when it goes to sleep you should measure voltage across the GC1109 pins and see that it's still being powered.

The GC1109 is behind the screen so you would have to remove your heltec v4's screen.

But the real fix is in keeping it alive during sleep/wake cycles.

You can also "test" by checking RSSI during receive that happen when the v4 is sleeping.

weebl2000 added a commit to weebl2000/meshtastic-firmware that referenced this pull request Feb 8, 2026
Use rtc_gpio_hold_en to latch PA_POWER (LDO) and PA_EN (CSD) HIGH
during deep sleep so the GC1109 LNA remains powered for wake-on-packet
RX. Previously these pins used weak pull-ups which could lose state.

On deep sleep wake, skip these pins in the blanket RTC hold release and
instead release them in SX126xInterface::init() after GPIO registers are
set HIGH first, avoiding a power glitch on the GC1109.

Trade-off: ~6.5mA additional deep sleep current for significantly
improved wake-on-packet RX sensitivity (~17dB).

Reference: meshcore-dev/MeshCore#1600
@towerviewcams
Copy link

towerviewcams commented Feb 8, 2026

@weebl2000 I'm measuring the GC1109 now. Pin 15 and 16 both have 3.7 volts. It looks like possibly that your file has the OLED screen still powered. This was found to be the case with 1.12 and then both there was a temporary "no display" firm file made by @Socalix to fix this. Then Kevin @IoTThinks made a more perm fix after that. was PR1570 and then looks like another opened with 1608 even though not much clarity there.

If I load the "no display" firmware, then I see 11mA....... Now, there is NO power on the GC1109 once sleep delay ends. pin 15 and 16 go to zero. When I do a telemetry check I see a SNR of -116 and then after that it goes up to -104 that shows in fact the LNA did NOT have power - so your correct. Power then stays on for the long delay and then once powersaving goes back into effect, GC1109 goes dark.

Lets test this and see if it truly draws 6 ish mA more on top of the 11mA. look forward to your next file.

@weebl2000
Copy link
Contributor Author

@weebl2000 I'm measuring the GC1109 now. Pin 15 and 16 both have 3.7 volts. It looks like possibly that your file has the OLED screen still powered. This was found to be the case with 1.12 and then both there was a temporary "no display" firm file made by @Socalix to fix this. Then Kevin @IoTThinks made a more perm fix after that. was PR1570 and then looks like another opened with 1608 even though not much clarity there.

If I load the "no display" firmware, then I see 11mA....... Now, there is NO power on the GC1109 once sleep delay ends. pin 15 and 16 go to zero. When I do a telemetry check I see a SNR of -116 and then after that it goes up to -104 that shows in fact the LNA did NOT have power - so your correct. Power then stays on for the long delay and then once powersaving goes back into effect, GC1109 goes dark.

Lets test this and see if it truly draws 6 ish mA more on top of the 11mA. look forward to your next file.

Try building this branch, it contains all my open PRs + dev: https://github.com/weebl2000/MeshCore/tree/dev_plus

@towerviewcams
Copy link

@weebl2000 there are a ton of files there. Not my strong suit. But if another test bin is created I will test.

@weebl2000
Copy link
Contributor Author

@weebl2000 there are a ton of files there. Not my strong suit. But if another test bin is created I will test.

https://x230.weebl.me/public/v4_dev_plus.bin - v4 repeater build with all fixes. Flash without erase.

@towerviewcams
Copy link

towerviewcams commented Feb 8, 2026

@weebl2000 Yes sir, we went from 11.1 mA to now 12.3mA and the GC1109 has power in sleep. I'm still testing but when I see the current drop from 47ma after the last signal is received, it holds, then after 20 seconds, sleeps and then drops back to 12.3 ish.......GC1109 power remains on

@beachmiles
Copy link

beachmiles commented Feb 8, 2026

@weebl2000 there are a ton of files there. Not my strong suit. But if another test bin is created I will test.

https://x230.weebl.me/public/v4_dev_plus.bin - v4 repeater build with all fixes. Flash without erase.

Could you please make a .bin for the companion Bluetooth as well for me to test? Not sure if companions ever deep sleep since there is no way to run the "powersaving on" command that I know of, but am curious to see if there is less power usage on your build.

Sounds like something else in the dev branch I built from with your fix maybe broke powersaving on the repeater version that towercams tested?
Thanks!

@weebl2000
Copy link
Contributor Author

Here's a build for Heltec v4 companion (BLE): https://x230.weebl.me/public/v4_companion_ble_dev_plus_25c7ec3d.bin

This includes the deep sleep LNA fix from this PR, plus BLE companion power saving (#1347) — power saving kicks in when you disable Bluetooth with the button.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants