#pragma once #include #include #include #include class CrossPointSettings { private: mutable std::mutex _mutex; // Private constructor for singleton CrossPointSettings() = default; // Static instance static CrossPointSettings instance; public: // Delete copy constructor and assignment CrossPointSettings(const CrossPointSettings&) = delete; CrossPointSettings& operator=(const CrossPointSettings&) = delete; // Access the settings mutex for protecting multi-field reads/writes from other cores. // Callers must not re-enter SETTINGS methods that lock _mutex while holding it. std::mutex& getMutex() const { return _mutex; } enum SLEEP_SCREEN_MODE { DARK = 0, LIGHT = 1, CUSTOM = 2, COVER = 3, COVER_CUSTOM = 4, BLANK = 5, QUICK_RESUME = 6, SLEEP_SCREEN_MODE_COUNT }; enum SLEEP_SCREEN_COVER_MODE { FIT = 0, CROP = 1, SLEEP_SCREEN_COVER_MODE_COUNT }; enum SLEEP_SCREEN_COVER_FILTER { NO_FILTER = 0, BLACK_AND_WHITE = 1, INVERTED_BLACK_AND_WHITE = 2, SLEEP_SCREEN_COVER_FILTER_COUNT }; // Status bar enum - legacy enum STATUS_BAR_MODE { NONE = 0, NO_PROGRESS = 1, FULL = 2, BOOK_PROGRESS_BAR = 3, ONLY_BOOK_PROGRESS_BAR = 4, CHAPTER_PROGRESS_BAR = 5, STATUS_BAR_MODE_COUNT }; enum STATUS_BAR_PROGRESS_BAR { BOOK_PROGRESS = 0, CHAPTER_PROGRESS = 1, HIDE_PROGRESS = 2, STATUS_BAR_PROGRESS_BAR_COUNT }; enum STATUS_BAR_PROGRESS_BAR_THICKNESS { PROGRESS_BAR_THIN = 0, PROGRESS_BAR_NORMAL = 1, PROGRESS_BAR_THICK = 2, STATUS_BAR_PROGRESS_BAR_THICKNESS_COUNT }; enum STATUS_BAR_TITLE { BOOK_TITLE = 0, CHAPTER_TITLE = 1, HIDE_TITLE = 2, STATUS_BAR_TITLE_COUNT }; enum XTC_STATUS_BAR_MODE { XTC_STATUS_BAR_HIDE = 0, XTC_STATUS_BAR_BOTTOM = 1, XTC_STATUS_BAR_TOP = 2, XTC_STATUS_BAR_MODE_COUNT }; enum STATUS_BAR_CLOCK_MODE { STATUS_BAR_CLOCK_HIDE = 0, STATUS_BAR_CLOCK_RIGHT = 1, STATUS_BAR_CLOCK_LEFT = 2 }; enum ORIENTATION { PORTRAIT = 0, // 480x800 logical coordinates (current default) LANDSCAPE_CW = 1, // 800x480 logical coordinates, rotated 180° (swap top/bottom) INVERTED = 2, // 480x800 logical coordinates, inverted LANDSCAPE_CCW = 3, // 800x480 logical coordinates, native panel orientation ORIENTATION_COUNT }; // Front button layout options (legacy) // Default: Back, Confirm, Left, Right // Swapped: Left, Right, Back, Confirm enum FRONT_BUTTON_LAYOUT { BACK_CONFIRM_LEFT_RIGHT = 0, LEFT_RIGHT_BACK_CONFIRM = 1, LEFT_BACK_CONFIRM_RIGHT = 2, BACK_CONFIRM_RIGHT_LEFT = 3, FRONT_BUTTON_LAYOUT_COUNT }; // Front button hardware identifiers (for remapping) enum FRONT_BUTTON_HARDWARE { FRONT_HW_BACK = 0, FRONT_HW_CONFIRM = 1, FRONT_HW_LEFT = 2, FRONT_HW_RIGHT = 3, FRONT_BUTTON_HARDWARE_COUNT }; // Side button layout options // Default: Up = Previous, Down = Next enum SIDE_BUTTON_LAYOUT { PREV_NEXT = 0, NEXT_PREV = 1, SIDE_BUTTONS_DISABLED = 2, SIDE_BUTTON_LAYOUT_COUNT }; // Font family options (built-in fonts only; SD card fonts use sdFontFamilyName) enum FONT_FAMILY { NOTOSERIF = 0, NOTOSANS = 1, FONT_FAMILY_COUNT }; static constexpr uint8_t LEGACY_OPENDYSLEXIC = 2; static constexpr uint8_t BUILTIN_FONT_COUNT = FONT_FAMILY_COUNT; // Font size options enum FONT_SIZE { SMALL = 0, MEDIUM = 1, LARGE = 2, EXTRA_LARGE = 3, FONT_SIZE_COUNT }; enum LINE_COMPRESSION { TIGHT = 0, NORMAL = 1, WIDE = 2, LINE_COMPRESSION_COUNT }; enum PARAGRAPH_ALIGNMENT { JUSTIFIED = 0, LEFT_ALIGN = 1, CENTER_ALIGN = 2, RIGHT_ALIGN = 3, BOOK_STYLE = 4, PARAGRAPH_ALIGNMENT_COUNT }; // Auto-sleep timeout options (in minutes) enum SLEEP_TIMEOUT { SLEEP_1_MIN = 0, SLEEP_5_MIN = 1, SLEEP_10_MIN = 2, SLEEP_15_MIN = 3, SLEEP_30_MIN = 4, SLEEP_TIMEOUT_COUNT }; // E-ink refresh frequency (pages between full refreshes) enum REFRESH_FREQUENCY { REFRESH_1 = 0, REFRESH_5 = 1, REFRESH_10 = 2, REFRESH_15 = 3, REFRESH_30 = 4, REFRESH_FREQUENCY_COUNT }; // Short power button press actions enum SHORT_PWRBTN { IGNORE = 0, SLEEP = 1, PAGE_TURN = 2, FORCE_REFRESH = 3, FOOTNOTES = 4, SHORT_PWRBTN_COUNT }; // Long-press Confirm action while reading an EPUB. The setting cycles through these values. // Persisted in settings.json by index: any new function (e.g. dictionary, bookmark) MUST use a // value >= 2 and be appended at the END of the enumValues array in SettingsList.h, otherwise the // stored indices shift and existing saves are silently misinterpreted. enum LONG_PRESS_MENU_FUNCTION { LP_MENU_KOSYNC = 0, LP_MENU_DISABLED = 1, LP_MENU_BOOKMARK = 2, LP_MENU_DICTIONARY = 3, LONG_PRESS_MENU_FUNCTION_COUNT }; // Hide battery percentage enum HIDE_BATTERY_PERCENTAGE { HIDE_NEVER = 0, HIDE_READER = 1, HIDE_ALWAYS = 2, HIDE_BATTERY_PERCENTAGE_COUNT }; // Page turn button long press behavior enum LONG_PRESS_BUTTON_BEHAVIOR { OFF = 0, CHAPTER_SKIP = 1, ORIENTATION_CHANGE = 2, LONG_PRESS_BUTTON_BEHAVIOR_COUNT }; // UI Theme enum UI_THEME { CLASSIC = 0, LYRA = 1, LYRA_3_COVERS = 2, ROUNDEDRAFF = 3 }; // Image rendering in EPUB reader enum IMAGE_RENDERING { IMAGES_DISPLAY = 0, IMAGES_PLACEHOLDER = 1, IMAGES_SUPPRESS = 2, IMAGE_RENDERING_COUNT }; enum TILT_PAGE_TURN { TILT_OFF = 0, TILT_NORMAL = 1, TILT_NVERTED = 2, TILT_PAGE_TURN_COUNT }; enum TOUCH_READER_CONTROLS { TOUCH_READER_OFF = 0, TOUCH_READER_ON = 1, TOUCH_READER_CONTROLS_COUNT }; enum QUICK_RESUME_SLEEP_SCREEN { QUICK_RESUME_NEVER = 0, QUICK_RESUME_AFTER_TIMEOUT = 1, QUICK_RESUME_SLEEP_SCREEN_COUNT }; // Sleep screen settings uint8_t sleepScreen = DARK; // Sleep screen cover mode settings uint8_t sleepScreenCoverMode = FIT; // Sleep screen cover filter uint8_t sleepScreenCoverFilter = NO_FILTER; // Status bar settings (statusBar retained for migration only) uint8_t statusBar = FULL; uint8_t statusBarChapterPageCount = 1; uint8_t statusBarBookProgressPercentage = 1; uint8_t statusBarProgressBar = HIDE_PROGRESS; uint8_t statusBarProgressBarThickness = PROGRESS_BAR_NORMAL; uint8_t statusBarTitle = CHAPTER_TITLE; uint8_t statusBarBattery = 1; uint8_t xtcStatusBarMode = XTC_STATUS_BAR_HIDE; // Clock display in status bar (X3 only, requires DS3231 RTC) uint8_t statusBarClock = STATUS_BAR_CLOCK_HIDE; // Clock UTC offset in quarter-hour steps, biased by 48 so it fits in uint8_t. // Value 48 = UTC+0, 0 = UTC-12:00, 104 = UTC+14:00. // Quarter-hour granularity supports oddball zones like Nepal (+5:45) and Chatham (+12:45). uint8_t clockUtcOffsetQ = 48; // Clock display format: 0 = 24-hour, 1 = 12-hour uint8_t clockFormat = 0; // Set once an NTP sync succeeds. Used to skip re-syncing on every WiFi connect. // Resetting to 0 (e.g. via the web UI) forces a re-sync on next WiFi connect. uint8_t clockHasBeenSynced = 0; // Text rendering settings uint8_t extraParagraphSpacing = 1; uint8_t textAntiAliasing = 1; // Short power button click behaviour uint8_t shortPwrBtn = IGNORE; // EPUB reading orientation settings // 0 = portrait (default), 1 = landscape clockwise, 2 = inverted, 3 = landscape counter-clockwise uint8_t orientation = PORTRAIT; // Button layouts (front layout retained for migration only) uint8_t frontButtonLayout = BACK_CONFIRM_LEFT_RIGHT; uint8_t sideButtonLayout = PREV_NEXT; uint8_t frontButtonFollowOrientation = 0; // Front button remap (logical -> hardware) // Used by MappedInputManager to translate logical buttons into physical front buttons. uint8_t frontButtonBack = FRONT_HW_BACK; uint8_t frontButtonConfirm = FRONT_HW_CONFIRM; uint8_t frontButtonLeft = FRONT_HW_LEFT; uint8_t frontButtonRight = FRONT_HW_RIGHT; // Reader font settings uint8_t fontFamily = NOTOSERIF; uint8_t fontSize = MEDIUM; uint8_t lineSpacing = NORMAL; uint8_t paragraphAlignment = JUSTIFIED; // Auto-sleep timeout setting (default 10 minutes). Legacy sleepTimeout enum values are migration-only. uint8_t sleepTimeoutMinutes = 10; // E-ink refresh frequency (default 15 pages) uint8_t refreshFrequency = REFRESH_15; uint8_t hyphenationEnabled = 0; // Reader screen margin settings uint8_t screenMargin = 5; // OPDS download destination folder ("" = SD root). Global; edited from the // OPDS server list. Persisted via a category-less SettingInfo::String in // SettingsList.h, so it stays out of the on-device Settings screen. char opdsDownloadFolder[64] = ""; // On-disk filename format for OPDS downloads (0=Author-Title default, 1=Title-Author, // 2=Title). See OpdsFilenameFormat. Persisted via a category-less SettingInfo::Enum, // edited from the OPDS server list; hidden from the on-device Settings screen. uint8_t opdsFilenameFormat = 0; // Hide battery percentage uint8_t hideBatteryPercentage = HIDE_NEVER; // Long-press page turn button behavior uint8_t longPressButtonBehavior = OFF; // Long-press Confirm function in EPUB reader (cycles through LONG_PRESS_MENU_FUNCTION values). // Defaults to Disabled so shortcut-based bookmark toggling remains opt-in. uint8_t longPressMenuFunction = LP_MENU_DISABLED; // UI Theme uint8_t uiTheme = LYRA; // Sunlight fading compensation uint8_t fadingFix = 0; // Power button return from footnotes (1 = enabled, 0 = disabled) uint8_t pwrBtnFootnoteBack = 1; // Use book's embedded CSS styles for EPUB rendering (1 = enabled, 0 = disabled) uint8_t embeddedStyle = 1; // Focus Reading - emphasizes the first part of words with bold uint8_t focusReadingEnabled = 0; // SD card font family name (empty = use built-in fontFamily) char sdFontFamilyName[32] = ""; // Dictionary folder name under /dictionaries (empty = no dictionary) char dictionaryName[32] = ""; // Show hidden files/directories (starting with '.') in the file browser (0 = hidden, 1 = show) uint8_t showHiddenFiles = 0; // Remove a book from the Recent Books list when its End-of-Book screen is reached (0 = off, 1 = on) uint8_t removeReadBooksFromRecents = 0; // Move epub to /Read/ folder on SD card when finished (0 = disabled, 1 = enabled) uint8_t moveFinishedToReadFolder = 0; // Short press Back goes to file browser instead of home (0 = disabled, 1 = enabled) uint8_t backShortToFileBrowser = 0; // Image rendering mode in EPUB reader uint8_t imageRendering = IMAGES_DISPLAY; // Tilt-based page turning (X3 only — requires QMI8658 IMU) uint8_t tiltPageTurn = TILT_OFF; // Touch screen reader zones/gestures on boards with a touch controller. uint8_t touchReaderControls = TOUCH_READER_ON; // Language setting (Language enum index, default 0 = EN) uint8_t language = 0; // Quick Resume: keep current content visible with moon icon instead of showing a static sleep screen. uint8_t quickResumeSleepScreen = QUICK_RESUME_NEVER; ~CrossPointSettings() = default; // Get singleton instance static CrossPointSettings& getInstance() { return instance; } static constexpr uint8_t MIN_SLEEP_TIMEOUT_MINUTES = 1; static constexpr uint8_t SLEEP_TIMEOUT_NEVER_MINUTES = 31; static constexpr uint8_t MAX_SLEEP_TIMEOUT_MINUTES = SLEEP_TIMEOUT_NEVER_MINUTES; // Callback to resolve SD card font IDs. Set by SdCardFontSystem::begin(). // Returns font ID or 0 if not found. using SdFontIdResolver = int (*)(void* ctx, const char* familyName, uint8_t fontSize); SdFontIdResolver sdFontIdResolver = nullptr; void* sdFontResolverCtx = nullptr; uint16_t getPowerButtonDuration() const { return (shortPwrBtn == CrossPointSettings::SHORT_PWRBTN::SLEEP) ? 10 : 400; } int getReaderFontId() const; // If count_only is true, returns the number of settings items that would be written. uint8_t writeSettings(HalFile& file, bool count_only = false) const; bool saveToFile() const; bool loadFromFile(); static void validateFrontButtonMapping(CrossPointSettings& settings); static uint8_t sleepTimeoutEnumToMinutes(uint8_t legacyValue); private: bool loadFromBinaryFile(); bool migrateLanguageBinaryFile(); public: float getReaderLineCompression() const; unsigned long getSleepTimeoutMs() const; int getRefreshFrequency() const; }; // Helper macro to access settings #define SETTINGS CrossPointSettings::getInstance()