idle: add IDLE_SLEEP_WHEN_CHARGING and IDLE_WAKE_ON_TOUCH
Addresses review feedback on #24: - New config IDLE_SLEEP_WHEN_CHARGING (default false): while USB is plugged in we don't enter sleep and we wake immediately if power comes back. Covers both "I like watching Clawd animations on my plugged-in desk device" and "alternative hardware without a battery is always on USB, sleep would be odd." - New config IDLE_WAKE_ON_TOUCH (default true): a touch on the dark panel wakes the device. The first touch is swallowed (mirrors the button wake-consumption), so tapping a dark screen wakes without also toggling splash<->usage. Set false to keep the original pets/sleeves-safe behaviour where touch is fully ignored while asleep. power.{h,cpp} grow a power_is_vbus_in() helper backed by pmu.isVbusIn() — distinct from isCharging() so the no-battery case ("plugged in, nothing to charge") is detected correctly.
This commit is contained in:
@@ -2,6 +2,7 @@
|
||||
#include "idle.h"
|
||||
#include "idle_cfg.h"
|
||||
#include "display_cfg.h" // declares `extern Arduino_CO5300 *gfx;`
|
||||
#include "power.h"
|
||||
|
||||
enum IdleState {
|
||||
STATE_AWAKE,
|
||||
@@ -69,6 +70,16 @@ bool idle_is_asleep(void) {
|
||||
void idle_tick(void) {
|
||||
uint32_t now = millis();
|
||||
|
||||
// While on USB power (if configured), don't sleep — and wake from sleep
|
||||
// when power comes back. Treats USB-in as continuous activity.
|
||||
if (!IDLE_SLEEP_WHEN_CHARGING && power_is_vbus_in()) {
|
||||
last_activity_ms = now;
|
||||
if (state == STATE_ASLEEP || state == STATE_FADING_OUT) {
|
||||
begin_fade(DISPLAY_DEFAULT_BRIGHTNESS, now);
|
||||
state = STATE_FADING_IN;
|
||||
}
|
||||
}
|
||||
|
||||
switch (state) {
|
||||
case STATE_AWAKE:
|
||||
if (now - last_activity_ms >= IDLE_TIMEOUT_MS) {
|
||||
|
||||
@@ -9,3 +9,15 @@
|
||||
#define IDLE_FADE_STEP_MS 20 // tick interval per fade step
|
||||
|
||||
#define DISPLAY_DEFAULT_BRIGHTNESS 200 // active-screen brightness
|
||||
|
||||
// When false, the device never enters sleep while USB power is present (also
|
||||
// wakes from sleep when USB is plugged back in). Useful when sitting on a
|
||||
// desk plugged in — also covers battery-less hardware that's always on USB.
|
||||
// Set true to sleep regardless of power source.
|
||||
#define IDLE_SLEEP_WHEN_CHARGING false
|
||||
|
||||
// When true, a touch on the dark panel wakes the device (first touch is
|
||||
// consumed for wake only, second touch acts normally). When false, touch is
|
||||
// fully ignored during sleep — useful if cats/sleeves brushing the panel
|
||||
// overnight would be a problem.
|
||||
#define IDLE_WAKE_ON_TOUCH true
|
||||
|
||||
+28
-3
@@ -55,11 +55,36 @@ static void touch_read() {
|
||||
touch_pressed = false;
|
||||
}
|
||||
|
||||
// Touch never counts as user activity and is fully swallowed while the
|
||||
// panel is dark — avoids accidental wakes and prevents LVGL from secretly
|
||||
// toggling splash<->usage behind a black screen.
|
||||
// Touch policy is driven by IDLE_WAKE_ON_TOUCH:
|
||||
// true → a press edge while asleep wakes the device and the first
|
||||
// touch is swallowed (mirrors the button wake-consumption); a
|
||||
// press while awake counts as activity.
|
||||
// false → touch never counts as activity and is fully swallowed while
|
||||
// the panel is dark, so pets/sleeves can't wake it overnight
|
||||
// and LVGL can't quietly toggle splash<->usage on a black panel.
|
||||
if (IDLE_WAKE_ON_TOUCH) {
|
||||
static bool touch_was = false;
|
||||
static bool touch_wake_swallowed = false;
|
||||
bool touch_now = touch_pressed;
|
||||
if (touch_now && !touch_was) {
|
||||
if (idle_consume_wake_press()) {
|
||||
touch_wake_swallowed = true;
|
||||
touch_pressed = false; // hide this press from LVGL
|
||||
}
|
||||
} else if (!touch_now && touch_was) {
|
||||
if (touch_wake_swallowed) {
|
||||
touch_wake_swallowed = false;
|
||||
touch_pressed = false; // also hide the corresponding release
|
||||
}
|
||||
} else if (touch_now && touch_wake_swallowed) {
|
||||
// Held finger through wake — keep hiding until release.
|
||||
touch_pressed = false;
|
||||
}
|
||||
touch_was = touch_now;
|
||||
} else {
|
||||
if (idle_is_asleep()) touch_pressed = false;
|
||||
}
|
||||
}
|
||||
|
||||
// ---- LVGL draw buffers (PSRAM-backed, partial render) ----
|
||||
#define BUF_LINES 40
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
|
||||
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;
|
||||
@@ -30,6 +31,7 @@ void power_init(void) {
|
||||
pmu.enableIRQ(XPOWERS_AXP2101_PKEY_SHORT_IRQ);
|
||||
|
||||
cached_charging = pmu.isCharging();
|
||||
cached_vbus = pmu.isVbusIn();
|
||||
cached_pct = pmu.getBatteryPercent();
|
||||
}
|
||||
|
||||
@@ -39,6 +41,7 @@ void power_tick(void) {
|
||||
if (now - last_charging_ms >= CHARGING_POLL_MS) {
|
||||
last_charging_ms = now;
|
||||
cached_charging = pmu.isCharging();
|
||||
cached_vbus = pmu.isVbusIn();
|
||||
}
|
||||
|
||||
if (now - last_battery_ms >= BATTERY_POLL_MS) {
|
||||
@@ -65,6 +68,10 @@ bool power_is_charging(void) {
|
||||
return cached_charging;
|
||||
}
|
||||
|
||||
bool power_is_vbus_in(void) {
|
||||
return cached_vbus;
|
||||
}
|
||||
|
||||
bool power_pwr_pressed(void) {
|
||||
if (pwr_pressed_flag) {
|
||||
pwr_pressed_flag = false;
|
||||
|
||||
@@ -4,4 +4,5 @@ void power_init(void);
|
||||
void power_tick(void);
|
||||
int power_battery_pct(void); // 0-100, or -1 if no battery
|
||||
bool power_is_charging(void);
|
||||
bool power_is_vbus_in(void); // USB cable present (true even with no battery)
|
||||
bool power_pwr_pressed(void); // true once per AXP2101 PWR button short-press
|
||||
|
||||
Reference in New Issue
Block a user