mirror of
https://github.com/ratspeak/ratdeck.git
synced 2026-10-23 09:42:23 +00:00
Merge pull request #32 from drkhsh/feat/power-management
Power: manual screen-off + pocket-carry input gating
This commit is contained in:
5 files changed
+42
-8
No files matched your search
@@ -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) {
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
@@ -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;
|
||||
|
||||
@@ -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
@@ -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
|
||||
|
||||
Reference in new issue
Block a user