diff --git a/src/CrossPointSettings.cpp b/src/CrossPointSettings.cpp index 1f8c3bd..8959072 100644 --- a/src/CrossPointSettings.cpp +++ b/src/CrossPointSettings.cpp @@ -12,7 +12,7 @@ CrossPointSettings CrossPointSettings::instance; namespace { constexpr uint8_t SETTINGS_FILE_VERSION = 1; -constexpr uint8_t SETTINGS_COUNT = 2; +constexpr uint8_t SETTINGS_COUNT = 3; constexpr char SETTINGS_FILE[] = "/sd/.crosspoint/settings.bin"; } // namespace @@ -25,6 +25,7 @@ bool CrossPointSettings::saveToFile() const { serialization::writePod(outputFile, SETTINGS_COUNT); serialization::writePod(outputFile, whiteSleepScreen); serialization::writePod(outputFile, extraParagraphSpacing); + serialization::writePod(outputFile, shortPwrBtn); outputFile.close(); Serial.printf("[%lu] [CPS] Settings saved to file\n", millis()); @@ -51,15 +52,15 @@ bool CrossPointSettings::loadFromFile() { serialization::readPod(inputFile, fileSettingsCount); // load settings that exist - switch (fileSettingsCount) { - case 1: - serialization::readPod(inputFile, whiteSleepScreen); - break; - case 2: - serialization::readPod(inputFile, whiteSleepScreen); - serialization::readPod(inputFile, extraParagraphSpacing); - break; - } + uint8_t settingsRead = 0; + do { + serialization::readPod(inputFile, whiteSleepScreen); + if (++settingsRead >= fileSettingsCount) break; + serialization::readPod(inputFile, extraParagraphSpacing); + if (++settingsRead >= fileSettingsCount) break; + serialization::readPod(inputFile, shortPwrBtn); + if (++settingsRead >= fileSettingsCount) break; + } while (false); inputFile.close(); Serial.printf("[%lu] [CPS] Settings loaded from file\n", millis()); diff --git a/src/CrossPointSettings.h b/src/CrossPointSettings.h index b152eb7..d6ad766 100644 --- a/src/CrossPointSettings.h +++ b/src/CrossPointSettings.h @@ -17,15 +17,18 @@ class CrossPointSettings { // Sleep screen settings uint8_t whiteSleepScreen = 0; - // Text rendering settings uint8_t extraParagraphSpacing = 1; + // Duration of the power button press + uint8_t shortPwrBtn = 0; ~CrossPointSettings() = default; // Get singleton instance static CrossPointSettings& getInstance() { return instance; } + uint16_t getPowerButtonDuration() const { return shortPwrBtn ? 10 : 500; } + bool saveToFile() const; bool loadFromFile(); }; diff --git a/src/activities/settings/SettingsActivity.cpp b/src/activities/settings/SettingsActivity.cpp index 3b287d6..154c9cc 100644 --- a/src/activities/settings/SettingsActivity.cpp +++ b/src/activities/settings/SettingsActivity.cpp @@ -9,7 +9,8 @@ const SettingInfo SettingsActivity::settingsList[settingsCount] = { {"White Sleep Screen", &CrossPointSettings::whiteSleepScreen}, - {"Extra Paragraph Spacing", &CrossPointSettings::extraParagraphSpacing}}; + {"Extra Paragraph Spacing", &CrossPointSettings::extraParagraphSpacing}, + {"Short Power Button Click", &CrossPointSettings::shortPwrBtn}}; void SettingsActivity::taskTrampoline(void* param) { auto* self = static_cast(param); diff --git a/src/activities/settings/SettingsActivity.h b/src/activities/settings/SettingsActivity.h index b7ace22..2464015 100644 --- a/src/activities/settings/SettingsActivity.h +++ b/src/activities/settings/SettingsActivity.h @@ -25,7 +25,7 @@ class SettingsActivity final : public Activity { const std::function onGoHome; // Static settings list - static constexpr int settingsCount = 2; // Number of settings + static constexpr int settingsCount = 3; // Number of settings static const SettingInfo settingsList[settingsCount]; static void taskTrampoline(void* param); diff --git a/src/main.cpp b/src/main.cpp index 53701f4..a518201 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -57,11 +57,6 @@ EpdFont ubuntu10Font(&ubuntu_10); EpdFont ubuntuBold10Font(&ubuntu_bold_10); EpdFontFamily ubuntuFontFamily(&ubuntu10Font, &ubuntuBold10Font); -// Power button timing -// Time required to confirm boot from sleep -constexpr unsigned long POWER_BUTTON_WAKEUP_MS = 500; -// Time required to enter sleep mode -constexpr unsigned long POWER_BUTTON_SLEEP_MS = 500; // Auto-sleep timeout (10 minutes of inactivity) constexpr unsigned long AUTO_SLEEP_TIMEOUT_MS = 10 * 60 * 1000; @@ -79,23 +74,24 @@ void enterNewActivity(Activity* activity) { // Verify long press on wake-up from deep sleep void verifyWakeupLongPress() { - // Give the user up to 1000ms to start holding the power button, and must hold for POWER_BUTTON_WAKEUP_MS + // 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; - Serial.printf("[%lu] [ ] Verifying power button press\n", millis()); inputManager.update(); + // Verify the user has actually pressed while (!inputManager.isPressed(InputManager::BTN_POWER) && millis() - start < 1000) { - delay(50); + delay(10); // only wait 10ms each iteration to not delay too much in case of short configured duration. inputManager.update(); } if (inputManager.isPressed(InputManager::BTN_POWER)) { do { - delay(50); + delay(10); inputManager.update(); - } while (inputManager.isPressed(InputManager::BTN_POWER) && inputManager.getHeldTime() < POWER_BUTTON_WAKEUP_MS); - abort = inputManager.getHeldTime() < POWER_BUTTON_WAKEUP_MS; + } while (inputManager.isPressed(InputManager::BTN_POWER) && + inputManager.getHeldTime() < SETTINGS.getPowerButtonDuration()); + abort = inputManager.getHeldTime() < SETTINGS.getPowerButtonDuration(); } else { abort = true; } @@ -121,7 +117,7 @@ void enterDeepSleep() { exitActivity(); enterNewActivity(new SleepActivity(renderer, inputManager)); - Serial.printf("[%lu] [ ] Power button released after a long press. Entering deep sleep.\n", millis()); + Serial.printf("[%lu] [ ] Entering deep sleep.\n", millis()); delay(1000); // Allow Serial buffer to empty and display to update // Enable Wakeup on LOW (button press) @@ -156,14 +152,25 @@ void setup() { Serial.printf("[%lu] [ ] Starting CrossPoint version " CROSSPOINT_VERSION "\n", millis()); inputManager.begin(); - verifyWakeupLongPress(); - // Initialize pins pinMode(BAT_GPIO0, INPUT); // Initialize SPI with custom pins SPI.begin(EPD_SCLK, SD_SPI_MISO, EPD_MOSI, EPD_CS); + // SD Card Initialization + if (!SD.begin(SD_SPI_CS, SPI, SPI_FQ)) { + Serial.printf("[%lu] [ ] SD card initialization failed\n", millis()); + exitActivity(); + enterNewActivity(new FullScreenMessageActivity(renderer, inputManager, "SD card error", BOLD)); + return; + } + + SETTINGS.loadFromFile(); + + // verify power button press duration after we've read settings. + verifyWakeupLongPress(); + // Initialize display einkDisplay.begin(); Serial.printf("[%lu] [ ] Display initialized\n", millis()); @@ -176,15 +183,6 @@ void setup() { exitActivity(); enterNewActivity(new BootActivity(renderer, inputManager)); - // SD Card Initialization - if (!SD.begin(SD_SPI_CS, SPI, SPI_FQ)) { - Serial.printf("[%lu] [ ] SD card initialization failed\n", millis()); - exitActivity(); - enterNewActivity(new FullScreenMessageActivity(renderer, inputManager, "SD card error", BOLD)); - return; - } - - SETTINGS.loadFromFile(); APP_STATE.loadFromFile(); if (APP_STATE.openEpubPath.empty()) { onGoHome(); @@ -221,7 +219,8 @@ void loop() { return; } - if (inputManager.wasReleased(InputManager::BTN_POWER) && inputManager.getHeldTime() > POWER_BUTTON_SLEEP_MS) { + if (inputManager.wasReleased(InputManager::BTN_POWER) && + inputManager.getHeldTime() > SETTINGS.getPowerButtonDuration()) { enterDeepSleep(); // This should never be hit as `enterDeepSleep` calls esp_deep_sleep_start return;