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.h"
|
||||||
#include "idle_cfg.h"
|
#include "idle_cfg.h"
|
||||||
#include "display_cfg.h" // declares `extern Arduino_CO5300 *gfx;`
|
#include "display_cfg.h" // declares `extern Arduino_CO5300 *gfx;`
|
||||||
|
#include "power.h"
|
||||||
|
|
||||||
enum IdleState {
|
enum IdleState {
|
||||||
STATE_AWAKE,
|
STATE_AWAKE,
|
||||||
@@ -69,6 +70,16 @@ bool idle_is_asleep(void) {
|
|||||||
void idle_tick(void) {
|
void idle_tick(void) {
|
||||||
uint32_t now = millis();
|
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) {
|
switch (state) {
|
||||||
case STATE_AWAKE:
|
case STATE_AWAKE:
|
||||||
if (now - last_activity_ms >= IDLE_TIMEOUT_MS) {
|
if (now - last_activity_ms >= IDLE_TIMEOUT_MS) {
|
||||||
|
|||||||
@@ -9,3 +9,15 @@
|
|||||||
#define IDLE_FADE_STEP_MS 20 // tick interval per fade step
|
#define IDLE_FADE_STEP_MS 20 // tick interval per fade step
|
||||||
|
|
||||||
#define DISPLAY_DEFAULT_BRIGHTNESS 200 // active-screen brightness
|
#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
|
||||||
|
|||||||
+29
-4
@@ -55,10 +55,35 @@ static void touch_read() {
|
|||||||
touch_pressed = false;
|
touch_pressed = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Touch never counts as user activity and is fully swallowed while the
|
// Touch policy is driven by IDLE_WAKE_ON_TOUCH:
|
||||||
// panel is dark — avoids accidental wakes and prevents LVGL from secretly
|
// true → a press edge while asleep wakes the device and the first
|
||||||
// toggling splash<->usage behind a black screen.
|
// touch is swallowed (mirrors the button wake-consumption); a
|
||||||
if (idle_is_asleep()) touch_pressed = false;
|
// 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) ----
|
// ---- LVGL draw buffers (PSRAM-backed, partial render) ----
|
||||||
|
|||||||
@@ -8,6 +8,7 @@
|
|||||||
|
|
||||||
static int cached_pct = -1;
|
static int cached_pct = -1;
|
||||||
static bool cached_charging = false;
|
static bool cached_charging = false;
|
||||||
|
static bool cached_vbus = false;
|
||||||
static bool pwr_pressed_flag = false;
|
static bool pwr_pressed_flag = false;
|
||||||
static uint32_t last_battery_ms = 0;
|
static uint32_t last_battery_ms = 0;
|
||||||
static uint32_t last_charging_ms = 0;
|
static uint32_t last_charging_ms = 0;
|
||||||
@@ -30,6 +31,7 @@ void power_init(void) {
|
|||||||
pmu.enableIRQ(XPOWERS_AXP2101_PKEY_SHORT_IRQ);
|
pmu.enableIRQ(XPOWERS_AXP2101_PKEY_SHORT_IRQ);
|
||||||
|
|
||||||
cached_charging = pmu.isCharging();
|
cached_charging = pmu.isCharging();
|
||||||
|
cached_vbus = pmu.isVbusIn();
|
||||||
cached_pct = pmu.getBatteryPercent();
|
cached_pct = pmu.getBatteryPercent();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -39,6 +41,7 @@ void power_tick(void) {
|
|||||||
if (now - last_charging_ms >= CHARGING_POLL_MS) {
|
if (now - last_charging_ms >= CHARGING_POLL_MS) {
|
||||||
last_charging_ms = now;
|
last_charging_ms = now;
|
||||||
cached_charging = pmu.isCharging();
|
cached_charging = pmu.isCharging();
|
||||||
|
cached_vbus = pmu.isVbusIn();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (now - last_battery_ms >= BATTERY_POLL_MS) {
|
if (now - last_battery_ms >= BATTERY_POLL_MS) {
|
||||||
@@ -65,6 +68,10 @@ bool power_is_charging(void) {
|
|||||||
return cached_charging;
|
return cached_charging;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool power_is_vbus_in(void) {
|
||||||
|
return cached_vbus;
|
||||||
|
}
|
||||||
|
|
||||||
bool power_pwr_pressed(void) {
|
bool power_pwr_pressed(void) {
|
||||||
if (pwr_pressed_flag) {
|
if (pwr_pressed_flag) {
|
||||||
pwr_pressed_flag = false;
|
pwr_pressed_flag = false;
|
||||||
|
|||||||
@@ -4,4 +4,5 @@ void power_init(void);
|
|||||||
void power_tick(void);
|
void power_tick(void);
|
||||||
int power_battery_pct(void); // 0-100, or -1 if no battery
|
int power_battery_pct(void); // 0-100, or -1 if no battery
|
||||||
bool power_is_charging(void);
|
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
|
bool power_pwr_pressed(void); // true once per AXP2101 PWR button short-press
|
||||||
|
|||||||
Reference in New Issue
Block a user