From 633cc04f4115b0799961f376766f4751308442f8 Mon Sep 17 00:00:00 2001 From: jpirnay Date: Mon, 6 Apr 2026 09:56:27 +0200 Subject: [PATCH] Additional checks --- lib/hal/HalGPIO.cpp | 8 +++++++- lib/hal/HalPowerManager.cpp | 17 ++++++++++------- src/main.cpp | 24 +++++++++++++----------- 3 files changed, 30 insertions(+), 19 deletions(-) diff --git a/lib/hal/HalGPIO.cpp b/lib/hal/HalGPIO.cpp index f3755dba..2904c9a4 100644 --- a/lib/hal/HalGPIO.cpp +++ b/lib/hal/HalGPIO.cpp @@ -240,7 +240,13 @@ void HalGPIO::waitForStablePowerRelease() { delay(10); } LOG_DBG("GPIO", "Power button stable-released after %lu ms", millis() - waitStart); - // Re-sync the InputManager so its debounced state matches reality + // Flush the InputManager debounced state to match reality. + // A single update() is insufficient: if lastState was stale ("pressed"), the first + // call resets the debounce timer but cannot update currentState until a second call + // arrives after DEBOUNCE_DELAY (5 ms). Without this, isPressed() / getHeldTime() + // would carry stale values into the next loop() iteration. + inputMgr.update(); + delay(10); // > InputManager DEBOUNCE_DELAY (5 ms) inputMgr.update(); } diff --git a/lib/hal/HalPowerManager.cpp b/lib/hal/HalPowerManager.cpp index 61e8a202..180d3b79 100644 --- a/lib/hal/HalPowerManager.cpp +++ b/lib/hal/HalPowerManager.cpp @@ -61,9 +61,11 @@ void HalPowerManager::setPowerSaving(bool enabled) { } void HalPowerManager::startDeepSleep(HalGPIO& gpio, bool keepClockAlive) const { - LOG_DBG("PWR", "startDeepSleep: waiting for power button release (isPressed=%d, rawPin=%d, keepClock=%d)", - gpio.isPressed(HalGPIO::BTN_POWER), digitalRead(InputManager::POWER_BUTTON_PIN) == LOW, keepClockAlive); - gpio.waitForStablePowerRelease(); + LOG_DBG("PWR", "startDeepSleep: isPressed=%d, rawPin=%d, keepClock=%d", gpio.isPressed(HalGPIO::BTN_POWER), + digitalRead(InputManager::POWER_BUTTON_PIN) == LOW, keepClockAlive); + // Perform all hardware preparation immediately (while the button may still be held) + // so the user gets instant visual feedback (display already off). Only block for + // button release at the very end, right before entering sleep. // GPIO13 is connected to the battery latch MOSFET. // When keepClockAlive is false (default): GPIO13 goes LOW, the MCU is // completely powered off during sleep (including the LP timer / RTC memory). @@ -82,16 +84,17 @@ void HalPowerManager::startDeepSleep(HalGPIO& gpio, bool keepClockAlive) const { gpio_deep_sleep_hold_en(); gpio_hold_en(GPIO_SPIWP); pinMode(InputManager::POWER_BUTTON_PIN, INPUT_PULLUP); + + // Now wait for the power button to be fully released before arming the wakeup + // trigger and entering sleep — prevents immediate re-wake from a held button. + gpio.waitForStablePowerRelease(); + // Arm the wakeup trigger *after* the button is released // Note: when keepClockAlive is false, this is only useful for waking up on USB power. On battery, the MCU will be // completely powered off, so the power button is hard-wired to briefly provide power to the MCU, waking it up // regardless of the wakeup source configuration. // When keepClockAlive is true, this is the actual wakeup mechanism since the MCU stays powered. esp_deep_sleep_enable_gpio_wakeup(1ULL << InputManager::POWER_BUTTON_PIN, ESP_GPIO_WAKEUP_GPIO_LOW); - // Final check: is the raw pin still LOW (button still physically pressed)? - if (digitalRead(InputManager::POWER_BUTTON_PIN) == LOW) { - LOG_DBG("PWR", "startDeepSleep: WARNING raw pin still LOW after release wait — may wake immediately!"); - } LOG_DBG("PWR", "startDeepSleep: entering deep sleep now"); // Enter Deep Sleep esp_deep_sleep_start(); diff --git a/src/main.cpp b/src/main.cpp index b4ebdcd2..4bcbc763 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -334,14 +334,16 @@ void loop() { return; } - static bool powerHoldLogged = false; - if (gpio.isPressed(HalGPIO::BTN_POWER)) { - const unsigned long heldTime = gpio.getHeldTime(); - if (!powerHoldLogged) { - LOG_DBG("MAIN", "loop: power button pressed, heldTime=%lu ms, required=%u ms, rawPin=%d", heldTime, - SETTINGS.getPowerButtonDuration(), digitalRead(InputManager::POWER_BUTTON_PIN) == LOW); - powerHoldLogged = true; - } + // Track power button hold for sleep. We require a fresh press edge (wasPressed) + // before starting to measure hold time, so that a hold carried over from boot + // (wake-up press) is never misinterpreted as a "go to sleep" press. + static unsigned long powerHoldStart = 0; + if (gpio.wasPressed(HalGPIO::BTN_POWER)) { + powerHoldStart = millis(); + LOG_DBG("MAIN", "loop: power button press detected (fresh edge)"); + } + if (gpio.isPressed(HalGPIO::BTN_POWER) && powerHoldStart > 0) { + const unsigned long heldTime = millis() - powerHoldStart; if (heldTime > SETTINGS.getPowerButtonDuration()) { // If the screenshot combination is potentially being pressed, don't sleep if (gpio.isPressed(HalGPIO::BTN_DOWN)) { @@ -349,13 +351,13 @@ void loop() { } LOG_DBG("MAIN", "loop: power button held for %lu ms (> %u ms), entering deep sleep", heldTime, SETTINGS.getPowerButtonDuration()); - powerHoldLogged = false; enterDeepSleep(); // This should never be hit as `enterDeepSleep` calls esp_deep_sleep_start return; } - } else { - powerHoldLogged = false; + } + if (!gpio.isPressed(HalGPIO::BTN_POWER)) { + powerHoldStart = 0; } // Refresh the battery icon when USB is plugged or unplugged.