Merge pull request #32 from drkhsh/feat/power-management

Power: manual screen-off + pocket-carry input gating
This commit is contained in:
dude.eth authored and GitHub committed 2026-04-25 21:17:13 -06:00
commit bb11a38e2e
5 files changed
+42 -8

No files matched your search

+13
View File
@@ -48,11 +48,22 @@ uint8_t Power::percentToPWM(uint8_t pct) const {
void Power::activity() {
_lastActivity = millis();
if (_state == SCREEN_OFF) {
_justWokeFromOff = true;
}
if (_state != ACTIVE) {
setState(ACTIVE);
}
}
void Power::forceScreenOff() {
if (_justWokeFromOff) {
_justWokeFromOff = false;
return;
}
setState(SCREEN_OFF);
}
void Power::weakActivity() {
_lastActivity = millis();
// Trackball wakes from DIM but not from SCREEN_OFF
@@ -96,6 +107,8 @@ void Power::loop() {
case SCREEN_OFF:
break;
}
_justWokeFromOff = false;
}
void Power::setState(State newState) {
+4
View File
@@ -15,6 +15,9 @@ public:
void activity();
// Weak activity = trackball — wakes from DIM only, not SCREEN_OFF
void weakActivity();
// Manual screen-off; no-op if activity() just woke from SCREEN_OFF this tick
// so a single keypress can't both wake and re-sleep.
void forceScreenOff();
// Battery
float batteryVoltage() const;
@@ -57,4 +60,5 @@ private:
static constexpr uint8_t DIM_PWM = 40; // ~15% PWM when dimmed
bool _kbAutoOn = false;
bool _kbAutoOff = false;
bool _justWokeFromOff = false;
};
+16 -6
View File
@@ -31,8 +31,11 @@ void InputManager::update() {
_activity = true; // Movement is weak — only wakes from dim
}
// Generate nav events from trackball movement (click handled below via GPIO)
if (!_hasKey) {
// Generate nav events from trackball movement (click handled below via GPIO).
// Skip entirely when screen is off so a backpacked device doesn't accumulate
// phantom up/down/left/right keypresses or wake from movement.
bool screenOn = !_powerMgr || _powerMgr->isScreenOn();
if (!_hasKey && screenOn) {
unsigned long now = millis();
// Accumulate deltas, clamp to ±20
@@ -85,11 +88,16 @@ void InputManager::update() {
_clickPending = true;
_longPressFired = false;
_clickStartMs = millis();
// Capture screen state BEFORE activity wakes it, so long-press
// doesn't blank a freshly-woken screen (wake-then-blank ping-pong)
_clickFromScreenOn = _powerMgr ? _powerMgr->isScreenOn() : true;
_activity = true;
_strongActivity = true; // Click wakes from screen off
} else if (!_longPressFired && millis() - _clickStartMs >= LONG_PRESS_MS) {
// Long press threshold reached
_longPress = true;
// Long press threshold reached — only emit if click started screen-on
if (_clickFromScreenOn) {
_longPress = true;
}
_longPressFired = true;
_hasKey = false; // Suppress any concurrent events
_activity = true;
@@ -117,8 +125,10 @@ void InputManager::update() {
}
}
// Touch activity check — throttled to ~50Hz
if (_touch) {
// Touch activity check — throttled to ~50Hz.
// Suppressed while screen is off (pocket-carry safety: prevents
// accidental wakes from pressure on the touch panel).
if (_touch && (!_powerMgr || _powerMgr->isScreenOn())) {
unsigned long now = millis();
if (now - _lastTouchPoll >= TOUCH_POLL_MS) {
_lastTouchPoll = now;
+4
View File
@@ -3,10 +3,12 @@
#include "hal/Keyboard.h"
#include "hal/Trackball.h"
#include "hal/TouchInput.h"
#include "hal/Power.h"
class InputManager {
public:
void begin(Keyboard* kb, Trackball* tb, TouchInput* touch);
void setPowerMgr(Power* pm) { _powerMgr = pm; }
void update();
// Keyboard events
@@ -26,6 +28,7 @@ private:
Keyboard* _kb = nullptr;
Trackball* _tb = nullptr;
TouchInput* _touch = nullptr;
Power* _powerMgr = nullptr;
bool _hasKey = false;
KeyEvent _keyEvent;
@@ -34,6 +37,7 @@ private:
bool _longPress = false;
bool _clickPending = false;
bool _longPressFired = false;
bool _clickFromScreenOn = true; // Captured at click DOWN to gate long-press
unsigned long _clickStartMs = 0;
unsigned long _lastClickDownMs = 0;
static constexpr unsigned long LONG_PRESS_MS = 1200;
+5 -2
View File
@@ -456,6 +456,7 @@ void setup() {
// Step 10: Input manager
inputManager.begin(&keyboard, &trackball, &touch);
inputManager.setPowerMgr(&powerMgr);
// Step 10.5: LVGL input drivers
LvInput::init(&keyboard, &trackball, &touch);
@@ -956,9 +957,11 @@ void loop() {
powerMgr.weakActivity(); // Trackball: wake from dim only
}
// 2. Long-press dispatch
// 2. Long-press dispatch — screen blanking is the default if no screen consumes it
if (inputManager.hadLongPress()) {
ui.handleLongPress();
if (!ui.handleLongPress()) {
powerMgr.forceScreenOff();
}
}
// 3. Key event dispatch