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:
co-authored by
Claude Opus 4.7
parent
7df64eecec
commit
98a513a403
@@ -20,3 +20,7 @@ int power_hal_battery_pct(void) { return -1; }
|
||||
bool power_hal_is_charging(void) { return false; }
|
||||
bool power_hal_is_vbus_in(void) { return false; }
|
||||
bool power_hal_pwr_pressed(void) { return false; }
|
||||
// Hold-to-pair gesture signals. Mirror the 216 (PMU PKEY long/positive IRQs)
|
||||
// or the 1.8" (software hold-timing off a polled GPIO) port. Stub = no gesture.
|
||||
bool power_hal_pwr_long_pressed(void) { return false; }
|
||||
bool power_hal_pwr_released(void) { return false; }
|
||||
|
||||
@@ -7,10 +7,18 @@
|
||||
|
||||
// PWR button comes from XCA9554 EXIO4 (active HIGH). The PMU still
|
||||
// provides battery monitoring; we just don't subscribe to its PKEY IRQ.
|
||||
//
|
||||
// The AXP2101 PKEY IRQs (short/long/release) aren't available here, so we
|
||||
// synthesize the same three edges in software from the polled EXIO4 level:
|
||||
// short — fired on release if the hold was shorter than PWR_LONG_MS
|
||||
// long — fired once when a hold crosses PWR_LONG_MS
|
||||
// release — fired on every falling edge
|
||||
// This keeps the hold-to-pair gesture logic in main.cpp board-agnostic.
|
||||
|
||||
#define BATTERY_POLL_MS 2000
|
||||
#define CHARGING_POLL_MS 500
|
||||
#define PWR_POLL_MS 50
|
||||
#define PWR_LONG_MS 1500 // hold threshold, mirrors the AXP LONG IRQ
|
||||
|
||||
static XPowersPMU pmu;
|
||||
|
||||
@@ -18,7 +26,11 @@ 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 bool last_pwr_state = false; // edge detector for EXIO4
|
||||
static uint32_t pwr_press_started_ms = 0;
|
||||
static bool pwr_long_fired = false; // long already fired for this hold
|
||||
static uint32_t last_battery_ms = 0;
|
||||
static uint32_t last_charging_ms = 0;
|
||||
static uint32_t last_pwr_ms = 0;
|
||||
@@ -54,8 +66,17 @@ void power_hal_tick(void) {
|
||||
if (now - last_pwr_ms >= PWR_POLL_MS) {
|
||||
last_pwr_ms = now;
|
||||
bool pwr_now = io_expander_get(IOX_PIN_PWR_BTN);
|
||||
if (pwr_now && !last_pwr_state) {
|
||||
pwr_pressed_flag = true;
|
||||
if (pwr_now && !last_pwr_state) { // rising edge — hold begins
|
||||
pwr_press_started_ms = now;
|
||||
pwr_long_fired = false;
|
||||
} else if (pwr_now && last_pwr_state) { // held
|
||||
if (!pwr_long_fired && (now - pwr_press_started_ms >= PWR_LONG_MS)) {
|
||||
pwr_long_flag = true;
|
||||
pwr_long_fired = true;
|
||||
}
|
||||
} else if (!pwr_now && last_pwr_state) { // falling edge — release
|
||||
pwr_released_flag = true;
|
||||
if (!pwr_long_fired) pwr_pressed_flag = true; // short press
|
||||
}
|
||||
last_pwr_state = pwr_now;
|
||||
}
|
||||
@@ -66,9 +87,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;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
@@ -16,6 +19,8 @@ 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;
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -20,6 +20,8 @@ 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;
|
||||
@@ -36,7 +38,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 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();
|
||||
@@ -58,9 +67,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();
|
||||
}
|
||||
}
|
||||
@@ -70,9 +79,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;
|
||||
}
|
||||
|
||||
@@ -17,3 +17,11 @@ bool power_hal_is_vbus_in(void); // USB cable present (true even without a bat
|
||||
|
||||
// Edge-triggered: returns true once per PWR short-press, then clears.
|
||||
bool power_hal_pwr_pressed(void);
|
||||
|
||||
// Edge-triggered: true once when a PWR hold crosses the long-press threshold
|
||||
// (~1.5s), then clears. Starts the hold-to-pair gesture.
|
||||
bool power_hal_pwr_long_pressed(void);
|
||||
|
||||
// Edge-triggered: true once on the PWR release edge, then clears. Completes
|
||||
// or cancels the hold-to-pair gesture.
|
||||
bool power_hal_pwr_released(void);
|
||||
|
||||
Reference in New Issue
Block a user