HAL: add PWR long-press + release edges to power_hal

Adds power_hal_pwr_long_pressed() and power_hal_pwr_released() to the HAL
contract so shared code can implement a hold-to-pair gesture board-agnostically.

- 216: enable the AXP2101 PKEY LONG + POSITIVE IRQs; bump press-off to 8s so a
  ~3-6s pair hold doesn't trip the hardware shutdown.
- 1.8": synthesize the same long/release edges in software from the polled
  XCA9554 EXIO4 level (short-press now fires on release-if-short).
- template: stub the two new functions (no gesture) for new ports.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
Hermann Björgvin Haraldsson
2026-06-02 14:01:57 +00:00
co-authored by Claude Opus 4.7
parent 7df64eecec
commit 98a513a403
5 changed files with 120 additions and 45 deletions
@@ -4,7 +4,10 @@
#include <Wire.h>
#include <XPowersLib.h>
// PWR button comes from AXP2101 PKEY short-press IRQ.
// PWR button comes from AXP2101 PKEY IRQs:
// SHORT — quick tap (cycle splash animations)
// LONG — ~1.5s mark, starts the hold-to-pair countdown
// POSITIVE — release edge, completes/cancels the gesture
#define BATTERY_POLL_MS 2000
#define CHARGING_POLL_MS 500
@@ -12,13 +15,15 @@
static XPowersPMU pmu;
static int cached_pct = -1;
static bool cached_charging = false;
static bool cached_vbus = false;
static bool pwr_pressed_flag = false;
static uint32_t last_battery_ms = 0;
static uint32_t last_charging_ms = 0;
static uint32_t last_pwr_ms = 0;
static int cached_pct = -1;
static bool cached_charging = false;
static bool cached_vbus = false;
static bool pwr_pressed_flag = false;
static bool pwr_long_flag = false;
static bool pwr_released_flag = false;
static uint32_t last_battery_ms = 0;
static uint32_t last_charging_ms = 0;
static uint32_t last_pwr_ms = 0;
void power_hal_init(void) {
if (!pmu.begin(Wire, AXP2101_ADDR, IIC_SDA, IIC_SCL)) {
@@ -32,7 +37,14 @@ void power_hal_init(void) {
pmu.disableIRQ(XPOWERS_AXP2101_ALL_IRQ);
pmu.clearIrqStatus();
pmu.enableIRQ(XPOWERS_AXP2101_PKEY_SHORT_IRQ);
pmu.enableIRQ(XPOWERS_AXP2101_PKEY_SHORT_IRQ
| XPOWERS_AXP2101_PKEY_LONG_IRQ
| XPOWERS_AXP2101_PKEY_POSITIVE_IRQ);
// Default press-off (force-shutdown) is 6s, only 2s after the pair gesture
// arms at ~3s and disarms at ~6s. Bump to 8s so a slightly-too-long hold
// doesn't shut the device down mid-gesture.
pmu.setPowerKeyPressOffTime(XPOWERS_POWEROFF_8S);
cached_charging = pmu.isCharging();
cached_vbus = pmu.isVbusIn();
@@ -54,9 +66,9 @@ void power_hal_tick(void) {
if (now - last_pwr_ms >= PWR_POLL_MS) {
last_pwr_ms = now;
pmu.getIrqStatus();
if (pmu.isPekeyShortPressIrq()) {
pwr_pressed_flag = true;
}
if (pmu.isPekeyShortPressIrq()) pwr_pressed_flag = true;
if (pmu.isPekeyLongPressIrq()) pwr_long_flag = true;
if (pmu.isPekeyPositiveIrq()) pwr_released_flag = true;
pmu.clearIrqStatus();
}
}
@@ -66,9 +78,16 @@ bool power_hal_is_charging(void) { return cached_charging; }
bool power_hal_is_vbus_in(void) { return cached_vbus; }
bool power_hal_pwr_pressed(void) {
if (pwr_pressed_flag) {
pwr_pressed_flag = false;
return true;
}
if (pwr_pressed_flag) { pwr_pressed_flag = false; return true; }
return false;
}
bool power_hal_pwr_long_pressed(void) {
if (pwr_long_flag) { pwr_long_flag = false; return true; }
return false;
}
bool power_hal_pwr_released(void) {
if (pwr_released_flag) { pwr_released_flag = false; return true; }
return false;
}