Skip to content

companion_radio: Add optional KEEP_DISPLAY_ON_USB flag to keep display on while powered 🤖🤖#2643

Open
disq wants to merge 1 commit into
meshcore-dev:devfrom
disq:companion-display-keep-on-when-powered
Open

companion_radio: Add optional KEEP_DISPLAY_ON_USB flag to keep display on while powered 🤖🤖#2643
disq wants to merge 1 commit into
meshcore-dev:devfrom
disq:companion-display-keep-on-when-powered

Conversation

@disq
Copy link
Copy Markdown

@disq disq commented May 28, 2026

Summary

Optional build flag KEEP_DISPLAY_ON_USB that suppresses the companion radio's AUTO_OFF_MILLIS screen-blanking timer only while the board reports isExternalPowered() == true. Default is unchanged — the display still blanks after AUTO_OFF_MILLIS on every existing build. The flag is purely opt-in; LCD-based variants (e.g. heltec_t096) can add -D KEEP_DISPLAY_ON_USB to their env to gain always-on-while-powered behaviour. OLED-based variants stay on the safe default to avoid burn-in.

Why opt-in and not on by default

OLED panels burn in quickly with static content, so unconditionally keeping the screen on while USB-powered would degrade those displays. Thanks to the reviewer for raising this — defaulting to off and exposing it as a flag is the right shape. LCD targets where burn-in isn't a concern can opt in per-env without imposing the risk on every existing board.

Implementation

When KEEP_DISPLAY_ON_USB is defined, each companion UI flavour's loop() refreshes _auto_off every tick that board.isExternalPowered() is true:

#if AUTO_OFF_MILLIS > 0
#ifdef KEEP_DISPLAY_ON_USB
    if (board.isExternalPowered()) {
      _auto_off = millis() + AUTO_OFF_MILLIS;
    }
#endif
    if (millis() > _auto_off) {
      _display->turnOff();
    }
#endif

The refresh-while-powered pattern (rather than just guarding the turnOff() call) means the timer counts a fresh full AUTO_OFF_MILLIS window from the moment USB is unplugged — no instant blank on unplug, no surprise. When the flag is not defined, the block compiles out and the build is byte-identical to upstream.

Applied to all three companion_radio UI flavours: ui-new, ui-tiny, ui-orig.

Safety

  • MeshCore.h defines virtual bool isExternalPowered() { return false; } as the base-class default. Boards without an override are unaffected even if a downstream env adds -D KEEP_DISPLAY_ON_USB.
  • NRF52Board overrides isExternalPowered() only when NRF52_POWER_MANAGEMENT is defined (RAK3401, RAK4631, etc.).
  • Existing battery-only deployments and boards that don't (yet) report external-power state are completely unaffected.

Testing

Verified on RAK3401 + companion_radio_ble (no env change — flag undefined):

  • USB-powered, idle: OLED blanks after 15 s — upstream behaviour preserved.
  • Battery-only, idle: OLED blanks after 15 s — upstream behaviour preserved.

Same build with -D KEEP_DISPLAY_ON_USB added to the env:

  • USB-powered: OLED stays on indefinitely past AUTO_OFF_MILLIS.
  • Unplug USB: OLED stays on for a fresh 15 s window from the unplug moment, then blanks.
  • Battery-only (no USB ever attached): blanks at 15 s as before.

🤖 Generated with Claude Code

@disq disq changed the title companion_radio: keep OLED on while externally powered companion_radio: keep OLED on while externally powered 🤖🤖 May 28, 2026
@NickDunklee
Copy link
Copy Markdown

Not a diss to the intent of the PR, but FWIW, OLEDs suffer screen burn-in ridiculously quick. Freedom to choose one's destiny of course, but the default should probably be off but an option. Samsung tried to solve this by rotating pixels around the display on their OLED watches subtly, so burn-in would be more equal, but it's so complicated on finite display life. On the LCD nodes like the Heltec T096 though, bring it on!

…ered

AUTO_OFF_MILLIS is a power-save feature aimed at battery use. When the
board reports isExternalPowered() == true (USB or other DC source),
blanking the screen serves no purpose — there's nothing to conserve.

But OLEDs are vulnerable to burn-in with static content, so this
behaviour is gated behind a new build flag KEEP_DISPLAY_ON_USB. Default
is unchanged from upstream — the display blanks after AUTO_OFF_MILLIS
on USB or battery. Variants that ship with an LCD instead of an OLED
(e.g. heltec_t096) can opt in by adding -D KEEP_DISPLAY_ON_USB to
their env, gaining always-on-while-powered without exposing OLED users
to burn-in risk.

When the flag is enabled, the implementation refreshes _auto_off every
loop iteration while externally powered, so the timer naturally counts
a fresh AUTO_OFF_MILLIS window from the moment power is removed —
no instantaneous-blank-on-unplug.

Applied to all three companion_radio UI flavours (ui-new, ui-tiny,
ui-orig). Boards without an isExternalPowered() override use the
base-class default in MeshCore.h (returns false), so battery-powered
behaviour is unchanged everywhere.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@disq disq force-pushed the companion-display-keep-on-when-powered branch from 31cacac to bb781ff Compare May 29, 2026 10:25
@disq
Copy link
Copy Markdown
Author

disq commented May 29, 2026

@NickDunklee Good point :) Updated the PR: the keep-on-while-powered behaviour is now gated behind -D KEEP_DISPLAY_ON_USB, with the default reverting to upstream's blank-after-AUTO_OFF_MILLIS.

@disq disq changed the title companion_radio: keep OLED on while externally powered 🤖🤖 companion_radio: Add optional KEEP_DISPLAY_ON_USB flag to keep display on while powered 🤖🤖 May 29, 2026
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.

2 participants