Updates to X3-specific display and power button handling

Centralize display initialization and power button verification for X3 devices
This commit is contained in:
Justin Mitchell
2026-02-15 19:58:37 -05:00
parent 961a704aaa
commit cd4303a8fb
5 changed files with 89 additions and 99 deletions
+1 -1
View File
@@ -683,7 +683,7 @@ void EpubReaderActivity::renderContents(std::unique_ptr<Page> page, const int or
pagesUntilFullRefresh--;
}
const bool useGrayscaleAA = SETTINGS.textAntiAliasing && gpio.getDeviceType() != HalGPIO::DeviceType::X3;
const bool useGrayscaleAA = SETTINGS.textAntiAliasing && !gpio.deviceIsX3();
if (useGrayscaleAA) {
// Save BW buffer only when we actually run grayscale passes.
renderer.storeBwBuffer();
+3 -87
View File
@@ -30,7 +30,6 @@
#include "util/ButtonNavigator.h"
HalDisplay display;
HalGPIO gpio;
MappedInputManager mappedInputManager(gpio);
GfxRenderer renderer(display);
Activity* currentActivity;
@@ -124,10 +123,6 @@ EpdFont ui12RegularFont(&ubuntu_12_regular);
EpdFont ui12BoldFont(&ubuntu_12_bold);
EpdFontFamily ui12FontFamily(&ui12RegularFont, &ui12BoldFont);
// measurement of power button press duration calibration value
unsigned long t1 = 0;
unsigned long t2 = 0;
void exitActivity() {
if (currentActivity) {
currentActivity->onExit();
@@ -141,50 +136,6 @@ void enterNewActivity(Activity* activity) {
currentActivity->onEnter();
}
// Verify power button press duration on wake-up from deep sleep
// Pre-condition: isWakeupByPowerButton() == true
void verifyPowerButtonDuration() {
if (SETTINGS.shortPwrBtn == CrossPointSettings::SHORT_PWRBTN::SLEEP) {
// Fast path for short press
// Needed because inputManager.isPressed() may take up to ~500ms to return the correct state
return;
}
// Give the user up to 1000ms to start holding the power button, and must hold for SETTINGS.getPowerButtonDuration()
const auto start = millis();
bool abort = false;
// Subtract the current time, because inputManager only starts counting the HeldTime from the first update()
// This way, we remove the time we already took to reach here from the duration,
// assuming the button was held until now from millis()==0 (i.e. device start time).
const uint16_t calibration = start;
const uint16_t calibratedPressDuration =
(calibration < SETTINGS.getPowerButtonDuration()) ? SETTINGS.getPowerButtonDuration() - calibration : 1;
gpio.update();
// Needed because inputManager.isPressed() may take up to ~500ms to return the correct state
while (!gpio.isPressed(HalGPIO::BTN_POWER) && millis() - start < 1000) {
delay(10); // only wait 10ms each iteration to not delay too much in case of short configured duration.
gpio.update();
}
t2 = millis();
if (gpio.isPressed(HalGPIO::BTN_POWER)) {
do {
delay(10);
gpio.update();
} while (gpio.isPressed(HalGPIO::BTN_POWER) && gpio.getHeldTime() < calibratedPressDuration);
abort = gpio.getHeldTime() < calibratedPressDuration;
} else {
abort = true;
}
if (abort) {
// Button released too early. Returning to sleep.
// IMPORTANT: Re-arm the wakeup trigger before sleeping again
gpio.startDeepSleep();
}
}
void waitForPowerRelease() {
gpio.update();
while (gpio.isPressed(HalGPIO::BTN_POWER)) {
@@ -193,25 +144,6 @@ void waitForPowerRelease() {
}
}
bool verifyPowerButtonDurationX3() {
// Match X4 semantics: require only the *remaining* hold time after boot.
// This avoids extra wake-delay windows and sleep/retry loops.
const uint16_t requiredHoldMs = SETTINGS.getPowerButtonDuration();
const uint16_t calibration = millis();
const uint16_t calibratedPressDuration = (calibration < requiredHoldMs) ? (requiredHoldMs - calibration) : 1;
const uint8_t powerPin = InputManager::POWER_BUTTON_PIN;
// Wake is already caused by power button; require it to still be held now.
if (digitalRead(powerPin) != LOW) return false;
const unsigned long holdStart = millis();
while (millis() - holdStart < calibratedPressDuration) {
if (digitalRead(powerPin) != LOW) return false;
delay(5);
}
return true;
}
// Enter deep sleep mode
void enterDeepSleep() {
APP_STATE.lastSleepFromReader = currentActivity && currentActivity->isReaderActivity();
@@ -221,7 +153,6 @@ void enterDeepSleep() {
enterNewActivity(new SleepActivity(renderer, mappedInputManager));
display.deepSleep();
LOG_DBG("MAIN", "Power button press calibration value: %lu ms", t2 - t1);
LOG_DBG("MAIN", "Entering deep sleep");
gpio.startDeepSleep();
@@ -277,9 +208,6 @@ void onGoHome() {
}
void setupDisplayAndFonts() {
if (gpio.getDeviceType() == HalGPIO::DeviceType::X3) {
display.setDisplayDimensions(792, 528);
}
display.begin();
renderer.begin();
LOG_DBG("MAIN", "Display initialized");
@@ -305,8 +233,6 @@ void setupDisplayAndFonts() {
}
void setup() {
t1 = millis();
gpio.begin();
// Only start serial if USB connected
@@ -337,15 +263,9 @@ void setup() {
const auto wakeupReason = gpio.getWakeupReason();
switch (wakeupReason) {
case HalGPIO::WakeupReason::PowerButton:
if (gpio.getDeviceType() == HalGPIO::DeviceType::X3) {
LOG_DBG("MAIN", "Verifying power button press duration (X3)");
if (!verifyPowerButtonDurationX3()) {
gpio.startDeepSleep();
}
} else {
LOG_DBG("MAIN", "Verifying power button press duration");
verifyPowerButtonDuration();
}
LOG_DBG("MAIN", "Verifying power button press duration");
gpio.verifyPowerButtonWakeup(SETTINGS.getPowerButtonDuration(),
SETTINGS.shortPwrBtn == CrossPointSettings::SHORT_PWRBTN::SLEEP);
break;
case HalGPIO::WakeupReason::AfterUSBPower:
// If USB power caused a cold boot, go back to sleep
@@ -363,10 +283,6 @@ void setup() {
LOG_DBG("MAIN", "Starting CrossPoint version " CROSSPOINT_VERSION);
setupDisplayAndFonts();
if (wakeupReason == HalGPIO::WakeupReason::PowerButton || wakeupReason == HalGPIO::WakeupReason::AfterFlash ||
wakeupReason == HalGPIO::WakeupReason::Other) {
display.requestResync();
}
exitActivity();
enterNewActivity(new BootActivity(renderer, mappedInputManager));