From df9b0f594cf73171dc0799fe27421421790a57f1 Mon Sep 17 00:00:00 2001 From: Kemal Hadimli Date: Mon, 1 Jun 2026 11:35:38 +0100 Subject: [PATCH] companion_radio: wake display on USB connect Light up the screen when external (USB) power is newly connected, as if a key had been pressed. A new _was_ext_powered member tracks the previous power state so the wake only fires on the rising edge, and it is seeded from the current state in begin() so booting while already powered does not trigger a spurious wake. The wake only acts when the screen is currently off, so an already-lit display is left untouched (no timer extension, no injected input). By default the screen auto-offs normally afterwards; the existing KEEP_DISPLAY_ON_USB opt-in is what keeps it lit while powered, and the two compose cleanly. Applied consistently across the ui-new, ui-orig and ui-tiny variants. isExternalPowered() is only implemented on NRF52, so this is effectively NRF52-only and inert on other targets. Co-Authored-By: Claude Opus 4.8 --- examples/companion_radio/ui-new/UITask.cpp | 10 ++++++++++ examples/companion_radio/ui-new/UITask.h | 1 + examples/companion_radio/ui-orig/UITask.cpp | 13 +++++++++++++ examples/companion_radio/ui-orig/UITask.h | 1 + examples/companion_radio/ui-tiny/UITask.cpp | 10 ++++++++++ examples/companion_radio/ui-tiny/UITask.h | 1 + 6 files changed, 36 insertions(+) diff --git a/examples/companion_radio/ui-new/UITask.cpp b/examples/companion_radio/ui-new/UITask.cpp index ee12ca740d..cd3c7e3381 100644 --- a/examples/companion_radio/ui-new/UITask.cpp +++ b/examples/companion_radio/ui-new/UITask.cpp @@ -558,6 +558,7 @@ void UITask::begin(DisplayDriver* display, SensorManager* sensors, NodePrefs* no _display = display; _sensors = sensors; _auto_off = millis() + AUTO_OFF_MILLIS; + _was_ext_powered = board.isExternalPowered(); // don't fire wake-on-connect if booted while powered #if defined(PIN_USER_BTN) user_btn.begin(); @@ -775,6 +776,15 @@ void UITask::loop() { } #endif + // Wake the display when external (USB) power is newly connected, as if a key + // was pressed. Only acts when the screen is currently off, so an already-lit + // display is left untouched (it still auto-offs unless KEEP_DISPLAY_ON_USB). + bool ext_powered = board.isExternalPowered(); + if (ext_powered && !_was_ext_powered && _display != NULL && !_display->isOn()) { + c = checkDisplayOn(c); + } + _was_ext_powered = ext_powered; + if (c != 0 && curr) { curr->handleInput(c); _auto_off = millis() + AUTO_OFF_MILLIS; // extend auto-off timer diff --git a/examples/companion_radio/ui-new/UITask.h b/examples/companion_radio/ui-new/UITask.h index a77ad6e7ec..1193438749 100644 --- a/examples/companion_radio/ui-new/UITask.h +++ b/examples/companion_radio/ui-new/UITask.h @@ -38,6 +38,7 @@ class UITask : public AbstractUITask { int _msgcount; unsigned long ui_started_at, next_batt_chck; int next_backlight_btn_check = 0; + bool _was_ext_powered = false; // tracks USB/external power edge for wake-on-connect #ifdef PIN_STATUS_LED int led_state = 0; int next_led_change = 0; diff --git a/examples/companion_radio/ui-orig/UITask.cpp b/examples/companion_radio/ui-orig/UITask.cpp index 5529046775..dc2534aaab 100644 --- a/examples/companion_radio/ui-orig/UITask.cpp +++ b/examples/companion_radio/ui-orig/UITask.cpp @@ -37,6 +37,7 @@ void UITask::begin(DisplayDriver* display, SensorManager* sensors, NodePrefs* no _display = display; _sensors = sensors; _auto_off = millis() + AUTO_OFF_MILLIS; + _was_ext_powered = board.isExternalPowered(); // don't fire wake-on-connect if booted while powered clearMsgPreview(); _node_prefs = node_prefs; if (_display != NULL) { @@ -329,6 +330,18 @@ void UITask::loop() { if (buzzer.isPlaying()) buzzer.loop(); #endif + // Wake the display when external (USB) power is newly connected, as if a + // button was pressed. Only acts when the screen is currently off, so an + // already-lit display is left untouched (it still auto-offs unless + // KEEP_DISPLAY_ON_USB). + bool ext_powered = board.isExternalPowered(); + if (ext_powered && !_was_ext_powered && _display != NULL && !_display->isOn()) { + _display->turnOn(); + _auto_off = millis() + AUTO_OFF_MILLIS; + _need_refresh = true; + } + _was_ext_powered = ext_powered; + if (_display != NULL && _display->isOn()) { static bool _firstBoot = true; if(_firstBoot && (millis() - ui_started_at) >= BOOT_SCREEN_MILLIS) { diff --git a/examples/companion_radio/ui-orig/UITask.h b/examples/companion_radio/ui-orig/UITask.h index 60cd0d042c..fd24939164 100644 --- a/examples/companion_radio/ui-orig/UITask.h +++ b/examples/companion_radio/ui-orig/UITask.h @@ -29,6 +29,7 @@ class UITask : public AbstractUITask { int _msgcount; bool _need_refresh = true; bool _displayWasOn = false; // Track display state before button press + bool _was_ext_powered = false; // tracks USB/external power edge for wake-on-connect unsigned long ui_started_at; // Button handlers diff --git a/examples/companion_radio/ui-tiny/UITask.cpp b/examples/companion_radio/ui-tiny/UITask.cpp index 45a07a02ef..0c3877b93e 100644 --- a/examples/companion_radio/ui-tiny/UITask.cpp +++ b/examples/companion_radio/ui-tiny/UITask.cpp @@ -428,6 +428,7 @@ void UITask::begin(DisplayDriver* display, SensorManager* sensors, NodePrefs* no _display = display; _sensors = sensors; _auto_off = millis() + AUTO_OFF_MILLIS; + _was_ext_powered = board.isExternalPowered(); // don't fire wake-on-connect if booted while powered _cached_batt_mv = getBattMilliVolts(); #if defined(PIN_USER_BTN) @@ -653,6 +654,15 @@ void UITask::loop() { } #endif + // Wake the display when external (USB) power is newly connected, as if a key + // was pressed. Only acts when the screen is currently off, so an already-lit + // display is left untouched (it still auto-offs unless KEEP_DISPLAY_ON_USB). + bool ext_powered = board.isExternalPowered(); + if (ext_powered && !_was_ext_powered && _display != NULL && !_display->isOn()) { + c = checkDisplayOn(c); + } + _was_ext_powered = ext_powered; + if (c != 0 && curr) { curr->handleInput(c); _auto_off = millis() + AUTO_OFF_MILLIS; // extend auto-off timer diff --git a/examples/companion_radio/ui-tiny/UITask.h b/examples/companion_radio/ui-tiny/UITask.h index 344e48b98f..882c79a4fb 100644 --- a/examples/companion_radio/ui-tiny/UITask.h +++ b/examples/companion_radio/ui-tiny/UITask.h @@ -42,6 +42,7 @@ class UITask : public AbstractUITask { int _msgcount; unsigned long ui_started_at, next_batt_chck; int next_backlight_btn_check = 0; + bool _was_ext_powered = false; // tracks USB/external power edge for wake-on-connect uint16_t _cached_batt_mv; #ifdef PIN_STATUS_LED int led_state = 0;