From 381944894551628d24dca573d96ca71089db4c0a Mon Sep 17 00:00:00 2001 From: Will Morrow Date: Fri, 9 Jan 2026 08:34:53 -0500 Subject: [PATCH 1/4] Ensure new custom sleep image every time When picking a random sleep image from a set of custom images, compare the randomly chosen index against a cached value in settings. If the value matches, use the next image (rolling over if it's the last image). Cache the chosen image index to settings in either case. --- src/CrossPointSettings.cpp | 5 ++++- src/CrossPointSettings.h | 2 ++ src/activities/boot_sleep/SleepActivity.cpp | 6 +++++- 3 files changed, 11 insertions(+), 2 deletions(-) diff --git a/src/CrossPointSettings.cpp b/src/CrossPointSettings.cpp index cd8b56f7..4898fdde 100644 --- a/src/CrossPointSettings.cpp +++ b/src/CrossPointSettings.cpp @@ -14,7 +14,7 @@ CrossPointSettings CrossPointSettings::instance; namespace { constexpr uint8_t SETTINGS_FILE_VERSION = 1; // Increment this when adding new persisted settings fields -constexpr uint8_t SETTINGS_COUNT = 17; +constexpr uint8_t SETTINGS_COUNT = 18; constexpr char SETTINGS_FILE[] = "/.crosspoint/settings.bin"; } // namespace @@ -46,6 +46,7 @@ bool CrossPointSettings::saveToFile() const { serialization::writePod(outputFile, sleepScreenCoverMode); serialization::writeString(outputFile, std::string(opdsServerUrl)); serialization::writePod(outputFile, textAntiAliasing); + serialization::writePod(outputFile, lastUsedSleep); outputFile.close(); Serial.printf("[%lu] [CPS] Settings saved to file\n", millis()); @@ -110,6 +111,8 @@ bool CrossPointSettings::loadFromFile() { } serialization::readPod(inputFile, textAntiAliasing); if (++settingsRead >= fileSettingsCount) break; + serialization::readPod(inputFile, lastUsedSleep); + if (++settingsRead >= fileSettingsCount) break; } while (false); inputFile.close(); diff --git a/src/CrossPointSettings.h b/src/CrossPointSettings.h index 3a2a3503..3b72aa6b 100644 --- a/src/CrossPointSettings.h +++ b/src/CrossPointSettings.h @@ -82,6 +82,8 @@ class CrossPointSettings { uint8_t screenMargin = 5; // OPDS browser settings char opdsServerUrl[128] = ""; + // Last used sleep screen index (for custom screens) + uint8_t lastUsedSleep = 0; ~CrossPointSettings() = default; diff --git a/src/activities/boot_sleep/SleepActivity.cpp b/src/activities/boot_sleep/SleepActivity.cpp index 43e8e60b..1d1c27a8 100644 --- a/src/activities/boot_sleep/SleepActivity.cpp +++ b/src/activities/boot_sleep/SleepActivity.cpp @@ -81,7 +81,11 @@ void SleepActivity::renderCustomSleepScreen() const { if (numFiles > 0) { // Generate a random number between 1 and numFiles const auto randomFileIndex = random(numFiles); - const auto filename = "/sleep/" + files[randomFileIndex]; + // If we re-generated the same index as the last sleep screen, use the next one (modulo the number of files we have) + const auto realFileIndex = randomFileIndex == SETTINGS.lastUsedSleep? randomFileIndex+1 % numFiles : randomFileIndex; + SETTINGS.lastUsedSleep = realFileIndex; + SETTINGS.saveToFile(); + const auto filename = "/sleep/" + files[realFileIndex]; FsFile file; if (SdMan.openFileForRead("SLP", filename, file)) { Serial.printf("[%lu] [SLP] Randomly loading: /sleep/%s\n", millis(), files[randomFileIndex].c_str()); From fedfb80258ac08867a0c52303eb4ed6d9b8f071b Mon Sep 17 00:00:00 2001 From: Will Morrow Date: Fri, 9 Jan 2026 19:55:30 -0500 Subject: [PATCH 2/4] Fix style problem --- src/activities/boot_sleep/SleepActivity.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/activities/boot_sleep/SleepActivity.cpp b/src/activities/boot_sleep/SleepActivity.cpp index 1d1c27a8..7df9fcb2 100644 --- a/src/activities/boot_sleep/SleepActivity.cpp +++ b/src/activities/boot_sleep/SleepActivity.cpp @@ -81,8 +81,10 @@ void SleepActivity::renderCustomSleepScreen() const { if (numFiles > 0) { // Generate a random number between 1 and numFiles const auto randomFileIndex = random(numFiles); - // If we re-generated the same index as the last sleep screen, use the next one (modulo the number of files we have) - const auto realFileIndex = randomFileIndex == SETTINGS.lastUsedSleep? randomFileIndex+1 % numFiles : randomFileIndex; + // If we re-generated the same index as the last sleep screen, + // use the next one (modulo the number of files we have) + const auto realFileIndex = + randomFileIndex == SETTINGS.lastUsedSleep ? randomFileIndex + 1 % numFiles : randomFileIndex; SETTINGS.lastUsedSleep = realFileIndex; SETTINGS.saveToFile(); const auto filename = "/sleep/" + files[realFileIndex]; From 396365c709d7f18a1ed44b9d9bea0f4cdeda6bf0 Mon Sep 17 00:00:00 2001 From: Will Morrow Date: Mon, 12 Jan 2026 17:56:47 -0500 Subject: [PATCH 3/4] Revert changes --- src/CrossPointSettings.cpp | 5 +---- src/CrossPointSettings.h | 2 -- src/activities/boot_sleep/SleepActivity.cpp | 8 +------- 3 files changed, 2 insertions(+), 13 deletions(-) diff --git a/src/CrossPointSettings.cpp b/src/CrossPointSettings.cpp index 4898fdde..cd8b56f7 100644 --- a/src/CrossPointSettings.cpp +++ b/src/CrossPointSettings.cpp @@ -14,7 +14,7 @@ CrossPointSettings CrossPointSettings::instance; namespace { constexpr uint8_t SETTINGS_FILE_VERSION = 1; // Increment this when adding new persisted settings fields -constexpr uint8_t SETTINGS_COUNT = 18; +constexpr uint8_t SETTINGS_COUNT = 17; constexpr char SETTINGS_FILE[] = "/.crosspoint/settings.bin"; } // namespace @@ -46,7 +46,6 @@ bool CrossPointSettings::saveToFile() const { serialization::writePod(outputFile, sleepScreenCoverMode); serialization::writeString(outputFile, std::string(opdsServerUrl)); serialization::writePod(outputFile, textAntiAliasing); - serialization::writePod(outputFile, lastUsedSleep); outputFile.close(); Serial.printf("[%lu] [CPS] Settings saved to file\n", millis()); @@ -111,8 +110,6 @@ bool CrossPointSettings::loadFromFile() { } serialization::readPod(inputFile, textAntiAliasing); if (++settingsRead >= fileSettingsCount) break; - serialization::readPod(inputFile, lastUsedSleep); - if (++settingsRead >= fileSettingsCount) break; } while (false); inputFile.close(); diff --git a/src/CrossPointSettings.h b/src/CrossPointSettings.h index 3b72aa6b..3a2a3503 100644 --- a/src/CrossPointSettings.h +++ b/src/CrossPointSettings.h @@ -82,8 +82,6 @@ class CrossPointSettings { uint8_t screenMargin = 5; // OPDS browser settings char opdsServerUrl[128] = ""; - // Last used sleep screen index (for custom screens) - uint8_t lastUsedSleep = 0; ~CrossPointSettings() = default; diff --git a/src/activities/boot_sleep/SleepActivity.cpp b/src/activities/boot_sleep/SleepActivity.cpp index 7df9fcb2..43e8e60b 100644 --- a/src/activities/boot_sleep/SleepActivity.cpp +++ b/src/activities/boot_sleep/SleepActivity.cpp @@ -81,13 +81,7 @@ void SleepActivity::renderCustomSleepScreen() const { if (numFiles > 0) { // Generate a random number between 1 and numFiles const auto randomFileIndex = random(numFiles); - // If we re-generated the same index as the last sleep screen, - // use the next one (modulo the number of files we have) - const auto realFileIndex = - randomFileIndex == SETTINGS.lastUsedSleep ? randomFileIndex + 1 % numFiles : randomFileIndex; - SETTINGS.lastUsedSleep = realFileIndex; - SETTINGS.saveToFile(); - const auto filename = "/sleep/" + files[realFileIndex]; + const auto filename = "/sleep/" + files[randomFileIndex]; FsFile file; if (SdMan.openFileForRead("SLP", filename, file)) { Serial.printf("[%lu] [SLP] Randomly loading: /sleep/%s\n", millis(), files[randomFileIndex].c_str()); From 0725e815007f7b9d9468a26da27fe3f3f47b46e7 Mon Sep 17 00:00:00 2001 From: Will Morrow Date: Mon, 12 Jan 2026 19:39:23 -0500 Subject: [PATCH 4/4] Refactor to use CrossPointState --- src/CrossPointState.cpp | 10 ++++++++-- src/CrossPointState.h | 1 + src/activities/boot_sleep/SleepActivity.cpp | 8 +++++++- src/main.cpp | 1 + 4 files changed, 17 insertions(+), 3 deletions(-) diff --git a/src/CrossPointState.cpp b/src/CrossPointState.cpp index 31cb2acb..91aa2536 100644 --- a/src/CrossPointState.cpp +++ b/src/CrossPointState.cpp @@ -5,7 +5,7 @@ #include namespace { -constexpr uint8_t STATE_FILE_VERSION = 1; +constexpr uint8_t STATE_FILE_VERSION = 2; constexpr char STATE_FILE[] = "/.crosspoint/state.bin"; } // namespace @@ -19,6 +19,7 @@ bool CrossPointState::saveToFile() const { serialization::writePod(outputFile, STATE_FILE_VERSION); serialization::writeString(outputFile, openEpubPath); + serialization::writePod(outputFile, lastSleepImage); outputFile.close(); return true; } @@ -31,13 +32,18 @@ bool CrossPointState::loadFromFile() { uint8_t version; serialization::readPod(inputFile, version); - if (version != STATE_FILE_VERSION) { + if (version > STATE_FILE_VERSION) { Serial.printf("[%lu] [CPS] Deserialization failed: Unknown version %u\n", millis(), version); inputFile.close(); return false; } serialization::readString(inputFile, openEpubPath); + if (version >= 2) { + serialization::readPod(inputFile, lastSleepImage); + } else { + lastSleepImage = 0; + } inputFile.close(); return true; diff --git a/src/CrossPointState.h b/src/CrossPointState.h index f060a0c6..87ce4e96 100644 --- a/src/CrossPointState.h +++ b/src/CrossPointState.h @@ -8,6 +8,7 @@ class CrossPointState { public: std::string openEpubPath; + uint8_t lastSleepImage; ~CrossPointState() = default; // Get singleton instance diff --git a/src/activities/boot_sleep/SleepActivity.cpp b/src/activities/boot_sleep/SleepActivity.cpp index 43e8e60b..a0306855 100644 --- a/src/activities/boot_sleep/SleepActivity.cpp +++ b/src/activities/boot_sleep/SleepActivity.cpp @@ -80,7 +80,13 @@ void SleepActivity::renderCustomSleepScreen() const { const auto numFiles = files.size(); if (numFiles > 0) { // Generate a random number between 1 and numFiles - const auto randomFileIndex = random(numFiles); + auto randomFileIndex = random(numFiles); + // If we picked the same image as last time, reroll + while (numFiles > 1 && randomFileIndex == APP_STATE.lastSleepImage) { + randomFileIndex = random(numFiles); + } + APP_STATE.lastSleepImage = randomFileIndex; + APP_STATE.saveToFile(); const auto filename = "/sleep/" + files[randomFileIndex]; FsFile file; if (SdMan.openFileForRead("SLP", filename, file)) { diff --git a/src/main.cpp b/src/main.cpp index 5261df3d..34e7376b 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -303,6 +303,7 @@ void setup() { // Clear app state to avoid getting into a boot loop if the epub doesn't load const auto path = APP_STATE.openEpubPath; APP_STATE.openEpubPath = ""; + APP_STATE.lastSleepImage = 0; APP_STATE.saveToFile(); onGoToReader(path); }