Skip to content

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

Open
weebl2000 wants to merge 1 commit 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 1 commit 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
  • 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: ~6.5mA additional deep sleep current 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 (~6.5mA expected with LNA active)

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.
heltec_v4_repeater_and_companion_1.12_w_pr1398_and_pr1600_RX_fixes_rev2.zip

@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.

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