diff --git a/lib/hal/HalGPIO.cpp b/lib/hal/HalGPIO.cpp index 41026ad0..88104fb9 100644 --- a/lib/hal/HalGPIO.cpp +++ b/lib/hal/HalGPIO.cpp @@ -231,6 +231,8 @@ unsigned long HalGPIO::getHeldTime() const { return inputMgr.getHeldTime(); } unsigned long HalGPIO::getPowerButtonHeldTime() const { return inputMgr.getPowerButtonHeldTime(); } +bool HalGPIO::wasTouchTap(float& nx, float& ny) const { return inputMgr.wasTouchTap(nx, ny); } + void HalGPIO::startDeepSleep() { // Ensure that the power button has been released to avoid immediately turning back on if you're holding it while (inputMgr.isPressed(BTN_POWER)) { diff --git a/lib/hal/HalGPIO.h b/lib/hal/HalGPIO.h index 94e9bcd7..c9c3d373 100644 --- a/lib/hal/HalGPIO.h +++ b/lib/hal/HalGPIO.h @@ -72,6 +72,11 @@ class HalGPIO { unsigned long getHeldTime() const; unsigned long getPowerButtonHeldTime() const; + // Touch: one-shot tap with the release position normalized 0..1 in the panel's + // native orientation. Returns false on non-touch devices. (Reusable gesture + // primitive; see MappedInputManager for the top-left = Back mapping.) + bool wasTouchTap(float& nx, float& ny) const; + // Setup wake up GPIO and enter deep sleep void startDeepSleep(); diff --git a/lib/hal/HalPowerManager.h b/lib/hal/HalPowerManager.h index bf78623c..0387a49d 100644 --- a/lib/hal/HalPowerManager.h +++ b/lib/hal/HalPowerManager.h @@ -28,7 +28,16 @@ class HalPowerManager { SemaphoreHandle_t modeMutex = nullptr; // Protect access to currentLockMode public: - static constexpr int LOW_POWER_FREQ = 10; // MHz + // On PSRAM boards (classic ESP32 / M5Paper) the APB clock follows the CPU below + // 80 MHz, and APB clocks both the SD SPI bus and the 80 MHz PSRAM (which holds + // the framebuffer). Dropping to 10 MHz breaks SD writes and PSRAM, so floor the + // low-power CPU at 80 MHz (APB stays pinned at 80 for CPU 80/160/240, so power + // still drops from the 240 MHz default while SD/PSRAM stay stable). +#if defined(BOARD_HAS_PSRAM) + static constexpr int LOW_POWER_FREQ = 80; // MHz (APB-safe floor for PSRAM/SD) +#else + static constexpr int LOW_POWER_FREQ = 10; // MHz +#endif static constexpr unsigned long IDLE_POWER_SAVING_MS = 3000; // ms static constexpr unsigned long BATTERY_POLL_MS = 1500; // ms diff --git a/src/MappedInputManager.cpp b/src/MappedInputManager.cpp index 81bc5d87..68757f2d 100644 --- a/src/MappedInputManager.cpp +++ b/src/MappedInputManager.cpp @@ -54,9 +54,29 @@ bool MappedInputManager::mapButton(const Button button, bool (HalGPIO::*fn)(uint return false; } -bool MappedInputManager::wasPressed(const Button button) const { return mapButton(button, &HalGPIO::wasPressed); } +// Top-left corner of the panel (panel-native, normalized). Generous so it's easy +// to hit; v1 is not yet orientation-mapped (see wasBackGesture NOTE in header). +static constexpr float BACK_GESTURE_FRAC_X = 0.22f; +static constexpr float BACK_GESTURE_FRAC_Y = 0.12f; -bool MappedInputManager::wasReleased(const Button button) const { return mapButton(button, &HalGPIO::wasReleased); } +bool MappedInputManager::wasBackGesture() const { + float nx = 0.0f, ny = 0.0f; + if (!gpio.wasTouchTap(nx, ny)) return false; + return nx <= BACK_GESTURE_FRAC_X && ny <= BACK_GESTURE_FRAC_Y; +} + +bool MappedInputManager::wasPressed(const Button button) const { + // A top-left tap fires on the release frame; expose it on Back's press edge too + // so menus that act on wasPressed(Back) also respond. Deliberately NOT folded + // into isPressed, so a quick tap never satisfies the readers' long-press-home. + if (button == Button::Back && wasBackGesture()) return true; + return mapButton(button, &HalGPIO::wasPressed); +} + +bool MappedInputManager::wasReleased(const Button button) const { + if (button == Button::Back && wasBackGesture()) return true; + return mapButton(button, &HalGPIO::wasReleased); +} bool MappedInputManager::isPressed(const Button button) const { return mapButton(button, &HalGPIO::isPressed); } diff --git a/src/MappedInputManager.h b/src/MappedInputManager.h index 67f094cc..fef4bf50 100644 --- a/src/MappedInputManager.h +++ b/src/MappedInputManager.h @@ -19,6 +19,11 @@ class MappedInputManager { bool wasPressed(Button button) const; bool wasReleased(Button button) const; bool isPressed(Button button) const; + // Reusable touch "back" gesture: a tap released in the top-left corner. Folded + // into Back's press/release edges, so every screen gets it with no per-activity + // code and no coordinates passed. False on non-touch devices. + // NOTE: v1 uses panel-native coordinates (not yet orientation-mapped). + bool wasBackGesture() const; bool wasAnyPressed() const; bool wasAnyReleased() const; unsigned long getHeldTime() const;