feat: add ScreenSleepController and ScreenSleepObserver for display sleep management#293
Conversation
|
Here is what it looks like in practice. IMG_9818.mov |
|
The AI-generated code appears completely unwieldy and unmaintainable. It should be moved to a separate class for hiding the screen and not unnecessarily bloat the DisplayDriver interface. |
|
I did consider that, but at the same time it would still have to integrate into display driver in a way that replaces or overloads it. |
|
I have been thinking about how to hook a better wake/sleep mechanism that allows me to also sync and fade the keyboard backlight but did not arrive at any design that doesn't involve hacking at the display driver and input driver invasively. |
You could use an instance of a new ScreenSaver class instantiated in DisplayDriver and allow access to that instance, e.g.
where |
|
Sure. Let me hand-refactor it. |
…leep management Extracts the display sleep/wake state machine from LGFXDriver::task_handler into a dedicated ScreenSleepController class, and adds a ScreenSleepObserver hook for peripheral backlight synchronisation (e.g. keyboard LED). Key design points: - Sinusoidal backlight fade (cos ease-out to sleep, sin ease-in to wake) replaces the previous linear step-per-tick approach. - Animation frames use setHardwareBrightness() so they never corrupt the wakeBrightness mirror; only the user-facing setBrightness() updates it. - A fresh dim clears wakeStartTime so a stale post-powersave wake animation cannot cause a brightness snap when activity later interrupts the dim. - The no-backlight activity-wake condition is guarded by !sleepRequested, matching the backlight path, so a manual sleep() request does not immediately re-wake on no-backlight devices. - Static requestWake/requestSleep/isScreenSleeping forwarders on DisplayDriver allow any driver context (e.g. I2C keyboard) to signal the controller without a direct pointer to LGFXDriver. - New virtual methods on DisplayDriver (panelSleep, panelWake, powerSaveOn, powerSaveOff, hasBacklight, getTouchIntPin, setHardwareBrightness) follow the established no-op default pattern so non-LGFX drivers are unaffected. - ScreenSleepObserver is an optional singleton; all call-sites null-guard so devices that don't need peripheral sync can leave it unregistered. docs/class-diagram.png needs updating (ScreenSleepController, ScreenSleepObserver). Signed-off-by: Andrew Yong <me@ndoo.sg>
00139bc to
503185c
Compare
Done, but screensaver -> ScreenSleepController instead as it feels more descriptive (since screensaver makes it sound like it's to reduce burn in rather than turn off the screen) Updated the PR text too. ScreenSleepObserver will be used for keyboard backlight sync, other lighting sync in future. |
Extracts the display sleep/wake state machine from
LGFXDriver::task_handlerinto a dedicated
ScreenSleepControllerclass, and adds aScreenSleepObserverhook for peripheral backlight synchronisation (e.g. keyboard LED).
Key design points
setHardwareBrightness()so they never corrupt thewakeBrightnessmirror; only the user-facingsetBrightness()updates it.wakeStartTimeso a stale post-powersave wake animation cannot cause a brightness snap when activity later interrupts the dim.!sleepRequested, matching the backlight path, so a manualsleep()request does not immediately re-wake on no-backlight devices.requestWake/requestSleep/isScreenSleepingforwarders onDisplayDriverallow any driver context (e.g. I2C keyboard) to signal the controller without a direct pointer toLGFXDriver.DisplayDriver(panelSleep,panelWake,powerSaveOn,powerSaveOff,hasBacklight,getTouchIntPin,setHardwareBrightness) follow the established no-op default pattern so non-LGFX drivers are unaffected.ScreenSleepObserveris an optional singleton; all call-sites null-guard so devices that don't need peripheral sync can leave it unregistered.Changes
ScreenSleepController(new, 2 files): owns the full sleep/wake state machine. Fade is 10 s for idle timeout, 1 s for user-initiated sleep or screen lock. Mid-fade activity reverses the animation smoothly from the current brightness level via a backdated sinusoid phase (asinf).InputDriver::instance()call-sites are null-guarded throughout.ScreenSleepObserver(new, 2 files): narrow optional singleton interface for peripherals that need to mirror the display fade (e.g. a keyboard backlight). All call-sites null-guard so it is safe to leave unregistered.DisplayDriver: new virtual methods and staticrequestWake/requestSleep/isScreenSleepingforwarders as described above.LGFXDriver:task_handlerreduced to_sleepController.tick().setBrightnessupdates the wake-brightness mirror;setHardwareBrightnessdrives hardware only.docs/class-diagram.pngneeds updating to reflectScreenSleepControllerandScreenSleepObserver.Test plan
t-deck-tft): display dims sinusoidally on idle timeout and on screen lock; wakes smoothly on touch/encoder input; no crash with no registeredInputDriversingletonScreenSleepObserver(unmerged downstream work)