diff --git a/src/CrossPointSettings.cpp b/src/CrossPointSettings.cpp index 232c7c57..7011136c 100644 --- a/src/CrossPointSettings.cpp +++ b/src/CrossPointSettings.cpp @@ -22,7 +22,7 @@ void readAndValidate(FsFile& file, uint8_t& member, const uint8_t maxValue) { namespace { constexpr uint8_t SETTINGS_FILE_VERSION = 1; // Increment this when adding new persisted settings fields -constexpr uint8_t SETTINGS_COUNT = 23; +constexpr uint8_t SETTINGS_COUNT = 24; constexpr char SETTINGS_FILE[] = "/.crosspoint/settings.bin"; } // namespace @@ -38,6 +38,7 @@ bool CrossPointSettings::saveToFile() const { serialization::writePod(outputFile, SETTINGS_FILE_VERSION); serialization::writePod(outputFile, SETTINGS_COUNT); serialization::writePod(outputFile, sleepScreen); + serialization::writePod(outputFile, showSleepScreen); serialization::writePod(outputFile, extraParagraphSpacing); serialization::writePod(outputFile, shortPwrBtn); serialization::writePod(outputFile, statusBar); @@ -148,6 +149,8 @@ bool CrossPointSettings::loadFromFile() { if (++settingsRead >= fileSettingsCount) break; readAndValidate(inputFile, sleepScreenCoverFilter, SLEEP_SCREEN_COVER_FILTER_COUNT); if (++settingsRead >= fileSettingsCount) break; + serialization::readPod(inputFile, showSleepScreen); + if (++settingsRead >= fileSettingsCount) break; // New fields added at end for backward compatibility } while (false); diff --git a/src/CrossPointSettings.h b/src/CrossPointSettings.h index c450d348..21fbe4ea 100644 --- a/src/CrossPointSettings.h +++ b/src/CrossPointSettings.h @@ -16,6 +16,7 @@ class CrossPointSettings { CrossPointSettings& operator=(const CrossPointSettings&) = delete; enum SLEEP_SCREEN_MODE { DARK = 0, LIGHT = 1, CUSTOM = 2, COVER = 3, BLANK = 4, SLEEP_SCREEN_MODE_COUNT }; + enum SHOW_SLEEP_SCREEN { ALWAYS = 0, EXCEPT_TIMEOUT = 1, NEVER = 2 }; enum SLEEP_SCREEN_COVER_MODE { FIT = 0, CROP = 1, SLEEP_SCREEN_COVER_MODE_COUNT }; enum SLEEP_SCREEN_COVER_FILTER { NO_FILTER = 0, @@ -99,6 +100,8 @@ class CrossPointSettings { // Sleep screen settings uint8_t sleepScreen = DARK; + // Show sleep screen settings + uint8_t showSleepScreen = ALWAYS; // Sleep screen cover mode settings uint8_t sleepScreenCoverMode = FIT; // Sleep screen cover filter diff --git a/src/activities/boot_sleep/SleepActivity.cpp b/src/activities/boot_sleep/SleepActivity.cpp index 7ffc5851..d3d6b854 100644 --- a/src/activities/boot_sleep/SleepActivity.cpp +++ b/src/activities/boot_sleep/SleepActivity.cpp @@ -11,12 +11,20 @@ #include "ScreenComponents.h" #include "fontIds.h" #include "images/CrossLarge.h" +#include "images/MoonIcon.h" #include "util/StringUtils.h" void SleepActivity::onEnter() { - Activity::onEnter(); + const bool SHOW_SLEEP_SCREEN = + SETTINGS.showSleepScreen == CrossPointSettings::SHOW_SLEEP_SCREEN::ALWAYS || + (!fromTimeout && SETTINGS.showSleepScreen == CrossPointSettings::SHOW_SLEEP_SCREEN::EXCEPT_TIMEOUT); - ScreenComponents::drawPopup(renderer, "Entering Sleep..."); + Activity::onEnter(); + if (SHOW_SLEEP_SCREEN) { + ScreenComponents::drawPopup(renderer, "Entering Sleep..."); + } else { + return renderLastScreenSleepScreen(); + } if (SETTINGS.sleepScreen == CrossPointSettings::SLEEP_SCREEN_MODE::BLANK) { return renderBlankSleepScreen(); @@ -266,6 +274,13 @@ void SleepActivity::renderCoverSleepScreen() const { renderDefaultSleepScreen(); } +void SleepActivity::renderLastScreenSleepScreen() const { + const auto pageHeight = renderer.getScreenHeight(); + + renderer.drawImage(MoonIcon, 0, pageHeight - 48, 48, 48); + renderer.displayBuffer(HalDisplay::HALF_REFRESH); +} + void SleepActivity::renderBlankSleepScreen() const { renderer.clearScreen(); renderer.displayBuffer(HalDisplay::HALF_REFRESH); diff --git a/src/activities/boot_sleep/SleepActivity.h b/src/activities/boot_sleep/SleepActivity.h index 87df8ba1..7d83f68c 100644 --- a/src/activities/boot_sleep/SleepActivity.h +++ b/src/activities/boot_sleep/SleepActivity.h @@ -5,8 +5,8 @@ class Bitmap; class SleepActivity final : public Activity { public: - explicit SleepActivity(GfxRenderer& renderer, MappedInputManager& mappedInput) - : Activity("Sleep", renderer, mappedInput) {} + explicit SleepActivity(GfxRenderer& renderer, MappedInputManager& mappedInput, bool fromTimeout) + : Activity("Sleep", renderer, mappedInput), fromTimeout(fromTimeout) {} void onEnter() override; private: @@ -14,5 +14,8 @@ class SleepActivity final : public Activity { void renderCustomSleepScreen() const; void renderCoverSleepScreen() const; void renderBitmapSleepScreen(const Bitmap& bitmap) const; + void renderLastScreenSleepScreen() const; void renderBlankSleepScreen() const; + + bool fromTimeout = false; }; diff --git a/src/activities/settings/SettingsActivity.cpp b/src/activities/settings/SettingsActivity.cpp index 7316db05..151b2b5a 100644 --- a/src/activities/settings/SettingsActivity.cpp +++ b/src/activities/settings/SettingsActivity.cpp @@ -11,10 +11,11 @@ const char* SettingsActivity::categoryNames[categoryCount] = {"Display", "Reader", "Controls", "System"}; namespace { -constexpr int displaySettingsCount = 6; +constexpr int displaySettingsCount = 7; const SettingInfo displaySettings[displaySettingsCount] = { // Should match with SLEEP_SCREEN_MODE SettingInfo::Enum("Sleep Screen", &CrossPointSettings::sleepScreen, {"Dark", "Light", "Custom", "Cover", "None"}), + SettingInfo::Enum("Show Sleep Screen", &CrossPointSettings::showSleepScreen, {"Always", "Except Timeout", "Never"}), SettingInfo::Enum("Sleep Screen Cover Mode", &CrossPointSettings::sleepScreenCoverMode, {"Fit", "Crop"}), SettingInfo::Enum("Sleep Screen Cover Filter", &CrossPointSettings::sleepScreenCoverFilter, {"None", "Contrast", "Inverted"}), diff --git a/src/images/MoonIcon.h b/src/images/MoonIcon.h new file mode 100644 index 00000000..34e617ba --- /dev/null +++ b/src/images/MoonIcon.h @@ -0,0 +1,24 @@ +#pragma once +#include + +// Image dimensions: 48x48 +#define MOONICON_WIDTH 48 +#define MOONICON_HEIGHT 48 + +static const uint8_t MoonIcon[] = { + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF7, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE7, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xE7, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x80, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xE7, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE7, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF7, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFB, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF9, 0xFF, 0xF7, 0xFF, 0xFF, 0xFF, 0xF9, 0xFF, 0xF0, 0xFF, 0xFF, + 0xFF, 0xC0, 0x1F, 0xF0, 0x3F, 0xFF, 0xFF, 0x00, 0x1F, 0xF8, 0x0F, 0xFF, 0xFF, 0xF0, 0x7F, 0xFC, 0x07, 0xFF, + 0xFF, 0xF9, 0xFF, 0xFC, 0x07, 0xFF, 0xFF, 0xF9, 0xFF, 0xFC, 0x03, 0xFF, 0xFF, 0xF9, 0xFF, 0xFE, 0x01, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFE, 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0x00, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFE, 0x00, 0xFF, 0xFF, 0xEF, 0xFF, 0xFC, 0x00, 0xFF, 0xFF, 0xEF, 0xFF, 0xFC, 0x00, 0xFF, + 0xFF, 0xC7, 0xFF, 0xF8, 0x00, 0xFF, 0xFF, 0xC3, 0xFF, 0xF8, 0x00, 0x7F, 0xFF, 0xC3, 0xFF, 0xF0, 0x00, 0x7F, + 0xFF, 0xC1, 0xFF, 0xC0, 0x00, 0x7F, 0xFF, 0xC0, 0x7F, 0x00, 0x00, 0x7F, 0xFF, 0xC0, 0x00, 0x00, 0x00, 0xFF, + 0xFF, 0xC0, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xE0, 0x00, 0x00, 0x01, 0xFF, 0xFF, 0xE0, 0x00, 0x00, 0x03, 0xFF, + 0xFF, 0xF0, 0x00, 0x00, 0x03, 0xFF, 0xFF, 0xF8, 0x00, 0x00, 0x07, 0xFF, 0xFF, 0xFC, 0x00, 0x00, 0x0F, 0xFF, + 0xFF, 0xFE, 0x00, 0x00, 0x1F, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x3F, 0xFF, 0xFF, 0xFF, 0xC0, 0x00, 0x7F, 0xFF, + 0xFF, 0xFF, 0xF0, 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; \ No newline at end of file diff --git a/src/main.cpp b/src/main.cpp index 89c4e13c..33420076 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -191,9 +191,9 @@ void waitForPowerRelease() { } // Enter deep sleep mode -void enterDeepSleep() { +void enterDeepSleep(bool fromTimeout) { exitActivity(); - enterNewActivity(new SleepActivity(renderer, mappedInputManager)); + enterNewActivity(new SleepActivity(renderer, mappedInputManager, fromTimeout)); display.deepSleep(); Serial.printf("[%lu] [ ] Power button press calibration value: %lu ms\n", millis(), t2 - t1); @@ -359,13 +359,13 @@ void loop() { const unsigned long sleepTimeoutMs = SETTINGS.getSleepTimeoutMs(); if (millis() - lastActivityTime >= sleepTimeoutMs) { Serial.printf("[%lu] [SLP] Auto-sleep triggered after %lu ms of inactivity\n", millis(), sleepTimeoutMs); - enterDeepSleep(); + enterDeepSleep(true); // This should never be hit as `enterDeepSleep` calls esp_deep_sleep_start return; } if (gpio.isPressed(HalGPIO::BTN_POWER) && gpio.getHeldTime() > SETTINGS.getPowerButtonDuration()) { - enterDeepSleep(); + enterDeepSleep(false); // This should never be hit as `enterDeepSleep` calls esp_deep_sleep_start return; }