From ce6676d211f21b6710bab266e4fd2fc3252008da Mon Sep 17 00:00:00 2001 From: jpirnay Date: Wed, 18 Mar 2026 12:56:35 +0100 Subject: [PATCH 1/4] Add immediate response for usb cable plug in / removal --- lib/hal/HalGPIO.cpp | 9 ++++++++- lib/hal/HalGPIO.h | 6 ++++++ src/main.cpp | 5 +++++ 3 files changed, 19 insertions(+), 1 deletion(-) diff --git a/lib/hal/HalGPIO.cpp b/lib/hal/HalGPIO.cpp index 64a251de..ec0176a2 100644 --- a/lib/hal/HalGPIO.cpp +++ b/lib/hal/HalGPIO.cpp @@ -7,7 +7,14 @@ void HalGPIO::begin() { pinMode(UART0_RXD, INPUT); } -void HalGPIO::update() { inputMgr.update(); } +void HalGPIO::update() { + inputMgr.update(); + const bool connected = isUsbConnected(); + usbStateChanged = (connected != lastUsbConnected); + lastUsbConnected = connected; +} + +bool HalGPIO::wasUsbStateChanged() const { return usbStateChanged; } bool HalGPIO::isPressed(uint8_t buttonIndex) const { return inputMgr.isPressed(buttonIndex); } diff --git a/lib/hal/HalGPIO.h b/lib/hal/HalGPIO.h index 09e1fa52..a283ed60 100644 --- a/lib/hal/HalGPIO.h +++ b/lib/hal/HalGPIO.h @@ -23,6 +23,9 @@ class HalGPIO { InputManager inputMgr; #endif + bool lastUsbConnected = false; + bool usbStateChanged = false; + public: HalGPIO() = default; @@ -41,6 +44,9 @@ class HalGPIO { // Check if USB is connected bool isUsbConnected() const; + // Returns true once per edge (plug or unplug) since the last update() + bool wasUsbStateChanged() const; + enum class WakeupReason { PowerButton, AfterFlash, AfterUSBPower, Other }; WakeupReason getWakeupReason() const; diff --git a/src/main.cpp b/src/main.cpp index 7bd21f37..a9710f7c 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -347,6 +347,11 @@ void loop() { powerManager.setPowerSaving(false); // Restore normal CPU frequency on user activity } + // Refresh the battery icon immediately when USB is plugged or unplugged + if (gpio.wasUsbStateChanged()) { + activityManager.requestUpdate(); + } + static bool screenshotButtonsReleased = true; if (gpio.isPressed(HalGPIO::BTN_POWER) && gpio.isPressed(HalGPIO::BTN_DOWN)) { if (screenshotButtonsReleased) { From ec864a25e0e63ae47b0af375e497e11e9f0b23b0 Mon Sep 17 00:00:00 2001 From: jpirnay Date: Wed, 18 Mar 2026 13:04:02 +0100 Subject: [PATCH 2/4] Fix const --- src/components/themes/BaseTheme.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/themes/BaseTheme.cpp b/src/components/themes/BaseTheme.cpp index 765343c4..76bc6316 100644 --- a/src/components/themes/BaseTheme.cpp +++ b/src/components/themes/BaseTheme.cpp @@ -37,7 +37,7 @@ void drawBatteryIcon(const GfxRenderer& renderer, int x, int y, int battWidth, i const bool charging = gpio.isUsbConnected(); // The +1 is to round up, so that we always fill at least one pixel - constexpr int maxFillWidth = battWidth - 5; + const int maxFillWidth = battWidth - 5; int filledWidth = percentage * maxFillWidth / 100 + 1; if (filledWidth > maxFillWidth) { filledWidth = maxFillWidth; From 72b00e1829c5fc0b2d2c4d3775a99ec6854497d9 Mon Sep 17 00:00:00 2001 From: jpirnay Date: Wed, 18 Mar 2026 13:09:58 +0100 Subject: [PATCH 3/4] Review comments --- src/main.cpp | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index a9710f7c..75bf69c5 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -347,11 +347,6 @@ void loop() { powerManager.setPowerSaving(false); // Restore normal CPU frequency on user activity } - // Refresh the battery icon immediately when USB is plugged or unplugged - if (gpio.wasUsbStateChanged()) { - activityManager.requestUpdate(); - } - static bool screenshotButtonsReleased = true; if (gpio.isPressed(HalGPIO::BTN_POWER) && gpio.isPressed(HalGPIO::BTN_DOWN)) { if (screenshotButtonsReleased) { @@ -384,6 +379,12 @@ void loop() { return; } + // Refresh the battery icon when USB is plugged or unplugged. + // Placed after sleep guards so we never queue a render that won't be processed. + if (gpio.wasUsbStateChanged()) { + activityManager.requestUpdate(); + } + const unsigned long activityStartTime = millis(); activityManager.loop(); const unsigned long activityDuration = millis() - activityStartTime; From 3cc9538cca0e98781f92e29d8a07435582a9f2f4 Mon Sep 17 00:00:00 2001 From: jpirnay Date: Wed, 18 Mar 2026 13:13:56 +0100 Subject: [PATCH 4/4] Another review comment --- src/components/themes/BaseTheme.cpp | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/components/themes/BaseTheme.cpp b/src/components/themes/BaseTheme.cpp index 76bc6316..9c563eb1 100644 --- a/src/components/themes/BaseTheme.cpp +++ b/src/components/themes/BaseTheme.cpp @@ -5,6 +5,7 @@ #include #include +#include #include #include @@ -38,6 +39,10 @@ void drawBatteryIcon(const GfxRenderer& renderer, int x, int y, int battWidth, i // The +1 is to round up, so that we always fill at least one pixel const int maxFillWidth = battWidth - 5; + const int fillHeight = rectHeight - 4; + if (maxFillWidth <= 0 || fillHeight <= 0) { + return; + } int filledWidth = percentage * maxFillWidth / 100 + 1; if (filledWidth > maxFillWidth) { filledWidth = maxFillWidth; @@ -46,10 +51,10 @@ void drawBatteryIcon(const GfxRenderer& renderer, int x, int y, int battWidth, i // When charging, ensure minimum fill so lightning bolt is fully visible constexpr int minFillForBolt = 8; if (charging && filledWidth < minFillForBolt) { - filledWidth = minFillForBolt; + filledWidth = std::min(minFillForBolt, maxFillWidth); } - renderer.fillRect(x + 2, y + 2, filledWidth, rectHeight - 4); + renderer.fillRect(x + 2, y + 2, filledWidth, fillHeight); // Draw lightning bolt when charging (white/inverted on black fill for visibility) if (charging) {