diff --git a/firmware/src/idle.cpp b/firmware/src/idle.cpp index c8d9192..ad7349f 100644 --- a/firmware/src/idle.cpp +++ b/firmware/src/idle.cpp @@ -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) { diff --git a/firmware/src/idle_cfg.h b/firmware/src/idle_cfg.h index 33ce2ec..2586704 100644 --- a/firmware/src/idle_cfg.h +++ b/firmware/src/idle_cfg.h @@ -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 diff --git a/firmware/src/main.cpp b/firmware/src/main.cpp index 91b2b1e..4ba85af 100644 --- a/firmware/src/main.cpp +++ b/firmware/src/main.cpp @@ -55,10 +55,35 @@ 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. - if (idle_is_asleep()) touch_pressed = false; + // 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) ---- diff --git a/firmware/src/power.cpp b/firmware/src/power.cpp index 23d711d..d131dea 100644 --- a/firmware/src/power.cpp +++ b/firmware/src/power.cpp @@ -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; diff --git a/firmware/src/power.h b/firmware/src/power.h index 81736b4..5008c6c 100644 --- a/firmware/src/power.h +++ b/firmware/src/power.h @@ -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