Skip to content

Commit 0de623e

Browse files
uxjuliabrianhusterUri-TauberPaulDelestracitsthisjustin
committed
Release v1.5.0
* feat(epub): native <ruby> support for Chinese, Japanese (crosspoint-reader#2665) * fix: avoid Arduino HEX macro collision * fix: free SD font caches before epub relayout * chore: update freeink-sdk * chore: Migrate Settings/State onto PersistableStore Co-authored-by: Uri Tauber <uritaube@gmail.com> * feat: unified Text Settings screen with live preview (crosspoint-reader#2605) Co-authored-by: Uri Tauber <uritaube@gmail.com> (cherry picked from commit 4e41bf6) * fix: Move sunlight fading fix setting to different group (crosspoint-reader#2689) Relocate STR_SUNLIGHT_FADING_FIX from the touch reader controls group to the front button orientation group in the settings filter logic. Sunlight fix was accidentally being hidden on non-touch where it should have been hidden on touch instead. Closes crosspoint-reader#2030 * feat: cjk UI font fallback (crosspoint-reader#2521) * Optimize font cache by persisting data across scopes Keep loaded font data (intervals/glyphs/bitmaps/kern) across PrewarmScopes instead of clearing it. This allows idle prewarm of page N+1 to serve the actual page turn with zero SD reads when the mini cache already covers all requested codepoints. Add miniMetadataOnly flag to track bitmap availability and miniHysteresisPending to limit underuse hysteresis evaluation to once per rebuild. Remove freeStyleMiniKern call that was forcing reallocation every page. * fix: Warp around in Percent Selection (crosspoint-reader#2677) ## Summary Address request crosspoint-reader#2659 --- ### AI Usage While CrossPoint doesn't have restrictions on AI tools in contributing, please be transparent about their usage as it helps set the right context for reviewers. Did you use AI tools to help write this code? _**< NO >**_ * fix: avoid X3 Quick Resume flashes (crosspoint-reader#2698) * feat(epub): native <ruby> support for Chinese, Japanese (crosspoint-reader#2665) Co-authored-by: Julia Nguyen <julia@uxj.io> * Add capacitive home key support to HalGPIO Co-authored-by: Julia Nguyen <julia@uxj.io> * Make frontlight panel a dismissible overlay Co-authored-by: Julia Nguyen <julia@uxj.io> * Reduce horizontal padding in settings tab bar Tighten horizontal insets from 4 to 2 pixels to prevent wide labels like "Controls" from truncating to ellipsis at large UI scales. The four equal slots share the tab band, so reducing the pill width allows more room for label text while maintaining vertical padding for proper pill height. * Add X4 Pro power button double-click frontlight toggle Co-authored-by: Julia Nguyen <julia@uxj.io> * Add long-press gesture support for touch interactions Co-authored-by: Julia Nguyen <julia@uxj.io> * test: add X4 Pro simulator environment * fix(i18n): add missing strings in PT-PT translation (crosspoint-reader#2701) * feat: simulate X4 Pro home key * feat: move frontlight reader tabs to bottom * fix: extend reader tabs to touch edge * chore: small Italian translation fixes (crosspoint-reader#2703) * feat: allow full-screen reader vertical swipes * fix: add touch controls for nearby transfer offers * feat: Add UC8279 panel controller detection for X3 devices (crosspoint-reader#2707) (cherry picked from commit 1d98ce1) * fix: ignore ambiguous EPUB guide text so books open at the right location (crosspoint-reader#2716) * fix: Lower TLS minimum free memory threshold to 35KB for kosync (crosspoint-reader#2719) * feat: point-size font selection (crosspoint-reader#2720) * fix: return text settings focus to active tab commit 447758c622131da551380606b6b6e17af1f782b0 Author: Julia Nguyen <julia@uxj.io> Date: Sat Jul 25 18:51:36 2026 -0400 fix: stop text settings back from closing parent menu commit 3fca47bca913b3465d53d2c0af5b7f67cf56847f Author: Julia Nguyen <julia@uxj.io> Date: Sat Jul 25 18:51:27 2026 -0400 fix: hide reader home icon on non-touch devices * fix: preserve short button presses in low-power mode * fix: preserve custom font ligatures (crosspoint-reader#2673) * docs: update dictionary docs * docs: Add StarDict sources list * fix: show receiving screen before accepting nearby transfer * chore: changelog cleanup * fix: add on-screen buttons in nearby file transfer for touch devices * fix: allow full-screen reader page swipes * chore: changelog cleanup * Revert "feat: unified Text Settings screen with live preview (crosspoint-reader#2605)". This feature doesn't map cleanly to Crossink's expanded text features as-is and needs more design thought before merge. This reverts commit 48248f2. * test: repair malformed section-break EPUB fixture (crosspoint-reader#2728) * chore: Update czech.yaml (crosspoint-reader#2726) * fix: translate BMP viewer error messages (crosspoint-reader#2730) * fix: fixing german translation inconsistencies (crosspoint-reader#2702) * feat: Add packages to nix dev shell required for clang-format-fix and… (crosspoint-reader#2695) * fix: add touch controls for filename conflicts during nearby file transfer * docs: add nearby file transfer docs * fix: ignore ambiguous EPUB guide text so books open at the right location (crosspoint-reader#2716) (cherry picked from commit dde7e03) * fix: name dictionary lookup failures (low-memory vs decompress vs read) instead of 'Not found' (crosspoint-reader#2706) * fix: bind settings labels to enum values (crosspoint-reader#2644) * docs: explain EPUB indexing methods * fix: map reading stats hints to assigned buttons (fixes issue 411) * docs: document EPUB word spacing * fix: TextSettingsActivity default to selected font (crosspoint-reader#2739) * fix: align Lyra header battery indicator * fix: allow switching dictionary after misses * fix: convert icons to lucide * feat: UI and touch enhancements * chore: update freeink sdk to allow virtual list scrolling * feat: add footnotes header and defer dictionary check until touch lookup gesture * docs: Add instructions to fix a bricked Xteink (crosspoint-reader#2622) (crosspoint-reader#2682) * fix: dictionary and UI updates for touch devices * fix: treat <br> in CJK flowing text as a paragraph separator (crosspoint-reader#2710) * perf: drop all-empty ruby vectors from TextBlock (crosspoint-reader#2772) * chore: remove redundant wolfSSL TLS defines (crosspoint-reader#2727) ## Summary * **What is the goal of this PR?** * Remove the macro-redefinition warning storm from the normal ESP32-C3 build without changing enabled TLS features. * **What changes are included?** * Stop repeating four TLS feature macros already enabled by Arduino-wolfSSL's `user_settings.h` when `WOLFSSL_TLS13` is set. * Document which configuration layer owns those features. ## Scope Check - [x] I have read SCOPE.md and ROADMAP.md. - [x] This PR is **not** a new built-in theme. - [x] This PR is **not** a new external network connector. - [x] This PR is **not** an interactive app, writing tool, browser, media, or PDF feature. - [x] No issue or pending PR removes these redundant definitions. - [x] This PR does not touch `freeink-sdk/`, `lib/hal/`, bootloader, OTA, or recovery code. ## Additional Context `HAVE_TLS_EXTENSIONS`, `HAVE_SUPPORTED_CURVES`, `HAVE_HKDF`, and `WC_RSA_PSS` remain enabled by the installed Arduino-wolfSSL configuration. This removes duplicate command-line definitions; it does not disable those features. Validation: - Full ESP32-C3 `default` rebuild passed. - Reported size: 52,028 bytes RAM and 5,505,149 bytes flash. - The wolfSSL macro-redefinition warnings are gone. - The only remaining warning in that build was an unrelated deprecated `NetworkClient::flush()` call inside the vendored WebSockets library. - `git diff --check`. Memory/flash impact: no intentional change. The effective preprocessor feature set is unchanged. --- ### AI Usage Did you use AI tools to help write this code? **YES** AI tools were used to trace the duplicate definitions to the library configuration and compare the full build output before and after cleanup. ## Emulator disclosure The ESP32-C3 firmware was compiled locally and the warning output was checked on Intel macOS. Runtime smoke testing used the desktop emulator; this PR was not flashed to a physical X3 or X4. * chore: update freeink sdk * fix: Gyro not powering down on x3 and newer x4 battery latch issues (crosspoint-reader#2774) Removes X3ProbeResult struct and associated I2C device detection functions (probeBQ27220Signature, probeDS3231Signature, probeQMI8658Signature) along with helper function readI2CReg8 in favor of an SDK driven device detect API * fix: connect strikethrough line across words * perf: skip ruby scratch allocations on ruby-less lines (crosspoint-reader#2735) * fix: derive file-transfer WebSocket port from HTTP (crosspoint-reader#2729) ## Summary * **What is the goal of this PR?** * Preserve the firmware's adjacent HTTP/WebSocket port contract when the web UI is served from a mapped host port in the desktop simulator. * **What changes are included?** * Use the current page's HTTP port, defaulting to 80 on-device. * Connect WebSocket uploads to the next port instead of always using host port 81. ## Scope Check - [x] I have read SCOPE.md and ROADMAP.md. - [x] This PR is **not** a new built-in theme. - [x] This PR is **not** a new external network connector. - [x] This PR is **not** an interactive app, writing tool, browser, media, or PDF feature. - [x] The current file-transfer page does not handle simulator port mapping and no pending PR fixes it. - [x] This PR does not touch `freeink-sdk/`, `lib/hal/`, bootloader, OTA, or recovery code. ## Additional Context On hardware the page is served from port 80 and WebSocket remains port 81, so device behavior is unchanged. In the simulator, a page served from 8080 now uses 8081; a configured 18080 listener uses 18081. Validation: - Built the real CrossPoint file-transfer server in the simulator. - Loaded the page through `http://127.0.0.1:18080/`. - Verified a WebSocket upgrade on port 18081 returns HTTP 101. - Exercised WebSocket upload progress and the HTTP fallback path. - `git diff --check`. Memory impact: no firmware heap allocation is added. The change is JavaScript inside the existing compressed web asset. --- ### AI Usage Did you use AI tools to help write this code? **YES** AI tools were used to reproduce the browser/simulator port mismatch and verify the HTTP and WebSocket listeners together. ## Emulator disclosure The mapped-port HTTP/WebSocket behavior was reproduced and validated with the desktop emulator on Intel macOS. The on-device port-80/81 behavior was established from the unchanged firmware contract; no physical device was used for runtime validation. * build: simulate web server * fix: Lower TLS minimum free memory threshold to 35KB for kosync (crosspoint-reader#2719) (cherry picked from commit 1cf265a) * fix: preserve custom font ligatures (crosspoint-reader#2673) (cherry picked from commit 9ec7767) * docs: Add StarDict sources list (cherry picked from commit 9cff12b) * test: repair malformed section-break EPUB fixture (crosspoint-reader#2728) (cherry picked from commit b25e57d) * feat: Add packages to nix dev shell required for clang-format-fix and… (crosspoint-reader#2695) (cherry picked from commit ef3d980) * fix: name dictionary lookup failures (low-memory vs decompress vs read) instead of 'Not found' (crosspoint-reader#2706) (cherry picked from commit 087c3da) * fix: preserve paragraph spacing after EPUB br tags Co-Authored-By: Julia Nguyen <julia@uxj.io> * perf: drop all-empty ruby vectors from TextBlock (crosspoint-reader#2772) (cherry picked from commit 52ff942) * chore: remove redundant wolfSSL TLS defines (crosspoint-reader#2727) ## Summary * **What is the goal of this PR?** * Remove the macro-redefinition warning storm from the normal ESP32-C3 build without changing enabled TLS features. * **What changes are included?** * Stop repeating four TLS feature macros already enabled by Arduino-wolfSSL's `user_settings.h` when `WOLFSSL_TLS13` is set. * Document which configuration layer owns those features. ## Scope Check - [x] I have read SCOPE.md and ROADMAP.md. - [x] This PR is **not** a new built-in theme. - [x] This PR is **not** a new external network connector. - [x] This PR is **not** an interactive app, writing tool, browser, media, or PDF feature. - [x] No issue or pending PR removes these redundant definitions. - [x] This PR does not touch `freeink-sdk/`, `lib/hal/`, bootloader, OTA, or recovery code. ## Additional Context `HAVE_TLS_EXTENSIONS`, `HAVE_SUPPORTED_CURVES`, `HAVE_HKDF`, and `WC_RSA_PSS` remain enabled by the installed Arduino-wolfSSL configuration. This removes duplicate command-line definitions; it does not disable those features. Validation: - Full ESP32-C3 `default` rebuild passed. - Reported size: 52,028 bytes RAM and 5,505,149 bytes flash. - The wolfSSL macro-redefinition warnings are gone. - The only remaining warning in that build was an unrelated deprecated `NetworkClient::flush()` call inside the vendored WebSockets library. - `git diff --check`. Memory/flash impact: no intentional change. The effective preprocessor feature set is unchanged. --- ### AI Usage Did you use AI tools to help write this code? **YES** AI tools were used to trace the duplicate definitions to the library configuration and compare the full build output before and after cleanup. ## Emulator disclosure The ESP32-C3 firmware was compiled locally and the warning output was checked on Intel macOS. Runtime smoke testing used the desktop emulator; this PR was not flashed to a physical X3 or X4. (cherry picked from commit 5965dc6) * fix: Gyro not powering down on x3 and newer x4 battery latch issues (crosspoint-reader#2774) Removes X3ProbeResult struct and associated I2C device detection functions (probeBQ27220Signature, probeDS3231Signature, probeQMI8658Signature) along with helper function readI2CReg8 in favor of an SDK driven device detect API (cherry picked from commit 5713432) * fix: restore spaces between CJK words (crosspoint-reader#2768) * fix: clean image page after sync return (crosspoint-reader#2747) * feat: Access text settings from epub reader (crosspoint-reader#2788) * docs: replace contributing guides with development docs * fix: Restrict CrossPoint position extension to official server (crosspoint-reader#2790) * fix: updates to UI/UX of dictionary, clippings, and bookmarks * fix: derive file-transfer WebSocket port from HTTP (crosspoint-reader#2729) ## Summary * **What is the goal of this PR?** * Preserve the firmware's adjacent HTTP/WebSocket port contract when the web UI is served from a mapped host port in the desktop simulator. * **What changes are included?** * Use the current page's HTTP port, defaulting to 80 on-device. * Connect WebSocket uploads to the next port instead of always using host port 81. ## Scope Check - [x] I have read SCOPE.md and ROADMAP.md. - [x] This PR is **not** a new built-in theme. - [x] This PR is **not** a new external network connector. - [x] This PR is **not** an interactive app, writing tool, browser, media, or PDF feature. - [x] The current file-transfer page does not handle simulator port mapping and no pending PR fixes it. - [x] This PR does not touch `freeink-sdk/`, `lib/hal/`, bootloader, OTA, or recovery code. ## Additional Context On hardware the page is served from port 80 and WebSocket remains port 81, so device behavior is unchanged. In the simulator, a page served from 8080 now uses 8081; a configured 18080 listener uses 18081. Validation: - Built the real CrossPoint file-transfer server in the simulator. - Loaded the page through `http://127.0.0.1:18080/`. - Verified a WebSocket upgrade on port 18081 returns HTTP 101. - Exercised WebSocket upload progress and the HTTP fallback path. - `git diff --check`. Memory impact: no firmware heap allocation is added. The change is JavaScript inside the existing compressed web asset. --- ### AI Usage Did you use AI tools to help write this code? **YES** AI tools were used to reproduce the browser/simulator port mismatch and verify the HTTP and WebSocket listeners together. ## Emulator disclosure The mapped-port HTTP/WebSocket behavior was reproduced and validated with the desktop emulator on Intel macOS. The on-device port-80/81 behavior was established from the unchanged firmware contract; no physical device was used for runtime validation. * fix: restore spaces between CJK words (crosspoint-reader#2768) (cherry picked from commit 9163149) * fix: clean image page after sync return (crosspoint-reader#2747) (cherry picked from commit dadc8ec) * fix: Restrict CrossPoint position extension to official server (crosspoint-reader#2790) (cherry picked from commit 2ceeecc) * fix: keep reader settings clear of landscape button hints * fix: order languages by native name instead of language code (crosspoint-reader#2803) * fix: improve File Transfer menu * docs: update device guidance * fix: prevent CSS rule OOM reboot (issue 423) * fix: add epub section splitting toggle * fix: Save text settings immediately on each change (crosspoint-reader#2806) * fix: Properly power down SD power rails on x3 (crosspoint-reader#2808) Fixes a regression in the sticky device support that lumped GPIO13 into a device check that never powered down the SD rails on this device. * fix: orient dictionary navigation buttons (crosspoint-reader#2749) * chore: update freeink sdk * make OptionPopup orientation-aware * fix: avoid duplicate OTA update actions (crosspoint-reader#2807) * fix: port touch UI compatibility updates * fix: Replace vector with deque for text token storage (crosspoint-reader#2814) * fix: dictionary lookup OOM on .dict.dz definitions (crosspoint-reader#2791) * perf: open dictionary index files once per lookup (crosspoint-reader#2733) * perf: check dictionary sidecar freshness once per open needsIndex() opens .idx and .qidx and re-reads the sidecar header on every call, and DictionaryWordSelectActivity called it once per tapped word rather than once per dictionary open. A lookup therefore cost 4 SD opens and 2 std::string path temporaries, not the 2 and 0 the previous change set out to achieve. Ask needsIndex() once, inside the same guarded block that opens the dictionary, and feed the build result back so a successful build stops re-triggering while a failed one still retries on the next word. Reimplement needsIndex() on openSession() so the "is the sidecar usable?" rule lives in one place rather than two that have to be kept in step. This is behaviour-preserving for everything buildIndex() can produce: it always writes at least one sample (entry 0) and removes the file on failure, so sampleCount == 0 means absent, stale or corrupt, all of which rebuild. The one divergence is an improvement -- a corrupt sidecar with a valid magic previously reported fresh and then full-scanned every lookup forever, and now rebuilds once. Also make the open()-time length bound a compile-time constant instead of two runtime strlen() calls, and correct the buildPath() comment, which claimed a lookup allocates nothing at all -- cleanWord(), stemVariants() and the matched headword all still do. * fix: show more of truncated file names * fix: refresh dashboard progress after reading * fix: various UI fixes Squashed commit of the following: commit 50e5029228cbd4ff1a337c369f432a3996fc8979 Author: Julia Nguyen <julia@uxj.io> Date: Fri Jul 31 08:46:39 2026 -0400 fix: restore auto turn after reader restart commit ef1d90e001b055a8afde952d3e2e2cf4db954af9 Author: Julia Nguyen <julia@uxj.io> Date: Fri Jul 31 08:44:31 2026 -0400 fix: add touch back button to file transfer commit 68f2adaae8a0fc1a0a023b9e8b19a4bbc2754704 Author: Julia Nguyen <julia@uxj.io> Date: Fri Jul 31 08:41:12 2026 -0400 fix: correct landscape dictionary button hints * fix: refresh UI scale fonts immediately * fix: order languages by native name instead of language code (crosspoint-reader#2803) (cherry picked from commit 3eeb6ac) * make OptionPopup orientation-aware (cherry picked from commit b215ed8) * fix: avoid duplicate OTA update actions (crosspoint-reader#2807) (cherry picked from commit 74065f1) * fix: Replace vector with deque for text token storage (crosspoint-reader#2814) (cherry picked from commit d0b70b3) * chore: update freeink sdk * fix: restore option popup navigation build * perf: prewarm next-page SD font glyphs Adapted from crosspoint-reader commit 4d19d38. Co-authored-by: Justin Mitchell <justin@jmitch.com> * perf: reuse dictionary files across lookup probes Adapted from crosspoint-reader commits bf253b1 and 5933da8. Co-authored-by: William Floyd <william.floyd@modopayments.com> Co-authored-by: Uri Tauber <uritaube@gmail.com> * perf: batch web file list responses Adapted from crosspoint-reader commit 302c077. Co-authored-by: Justin Mitchell <justin@jmitch.com> * perf: share one static bidi scratch buffer to save ~1.5 KB RAM (crosspoint-reader#2554) * chore: update freeink sdk * fix: apply book style setting before EPUB load * fix: preserve clipping highlights across font changes (issue 426) * chore: prepare v1.5.0 release * fix: fall back to plain text for malformed dictionary HTML * fix: keep clipping markers visible in dark mode (issue 431) * fix: avoid file list callback allocation (issue 432) * fix: restore dictionary left and right button hints * fix: improvements to epup opening pipeline Squashed commit of the following: commit 0a4cfbabdee5bc8caf4d1b9f43350fe2f36b12a0 Author: Julia Nguyen <julia@uxj.io> Date: Fri Jul 31 14:31:44 2026 -0400 docs: document EPUB loading hardening commit a0f7b1084aac240234b1156ba58592e4d7066485 Author: Julia Nguyen <julia@uxj.io> Date: Fri Jul 31 14:18:05 2026 -0400 fix: make sleep EPUB allocation fallible commit 726d84cfc6d26a4e887f19eae7876a1d87b35369 Author: Julia Nguyen <julia@uxj.io> Date: Fri Jul 31 14:16:25 2026 -0400 fix: report EPUB open failures commit 00d7bc248718e0c5870c9e4522692b9106cbabee Author: Julia Nguyen <julia@uxj.io> Date: Fri Jul 31 14:11:21 2026 -0400 perf: defer optional EPUB location metadata commit 05bca368ce716655478d0b8d9e161e234c0a4694 Author: Julia Nguyen <julia@uxj.io> Date: Fri Jul 31 14:09:09 2026 -0400 fix: make EPUB location allocation fallible commit 422612ae49592ac89db80d59d0e553fabf41f1a5 Author: Julia Nguyen <julia@uxj.io> Date: Fri Jul 31 14:06:58 2026 -0400 fix: align sleep EPUB load memory timing commit 7aefaaf75c05b7d3949276558066289c38bb7201 Author: Julia Nguyen <julia@uxj.io> Date: Fri Jul 31 14:06:50 2026 -0400 refactor: snapshot EPUB settings before load commit 398c98d11cae492a182d8bfbc32e7f6b9e43a2c2 Author: Julia Nguyen <julia@uxj.io> Date: Fri Jul 31 14:05:13 2026 -0400 fix: retry sleep page partial EPUB builds commit fc59765b079887229411dc1b85cb9057277bfdd6 Author: Julia Nguyen <julia@uxj.io> Date: Fri Jul 31 14:03:46 2026 -0400 refactor: centralize EPUB section fallbacks commit e9bb58cdbe236c2b2c50b0b1d0c16a761b6c0c6e Author: Julia Nguyen <julia@uxj.io> Date: Fri Jul 31 14:02:08 2026 -0400 fix: classify EPUB setup allocation failures commit 805767f9277b90d5037649242f15eb6f06f9c0a2 Author: Julia Nguyen <julia@uxj.io> Date: Fri Jul 31 14:01:28 2026 -0400 perf: inspect EPUB CSS cache without hydration commit afcaf1faec4ec7288dd9155c538777669b8c587b Author: Julia Nguyen <julia@uxj.io> Date: Fri Jul 31 13:58:07 2026 -0400 fix: skip unused EPUB stylesheet discovery * fix: match SD card font generation to built-in fonts and add dictionary font generation script * fix: match SD card font generation to built-in fonts and add dictionary font generation script * fix: preserve dictionary screenshot context (issue 437) * fix: guarantee screenshot confirmation border (issue 437) * build: update version labels * fix: avoid crashing during a clock sync (issue 436) * fix: make EPUB sync positions content-based (crosspoint-reader#2805) * fix: CJK dictionary selection and lookups not working correcctly * build: honor local PlatformIO version override * Make bookmarks survive re-pagination Ties bookmarks to the actual text on the page rather than to a page number. Page numbers shift whenever the book gets re-laid-out — changing font size, margins, line spacing, or rotating the screen — which could previously land you on the wrong spot. This is a followup of crosspoint-reader#2805, making bookmarks use the same mechanism. Several minor improvments ride along. * fix: hide unsupported web settings * fix: open reading stats date editor * perf: various performance improvements, a few borrowed from Sichroteph/YACP Squashed commit of the following: commit 2d4ec2c6826b61395eb16ebafa15585e59bc5d6c Author: Julia Nguyen <julia@uxj.io> Date: Sat Aug 1 22:28:06 2026 -0400 fix: avoid duplicate uncached EPUB image display commit 946ccf003d90c71c308c26adb912ce79049e3193 Author: Julia Nguyen <julia@uxj.io> Date: Sat Aug 1 13:55:40 2026 -0400 fix: persist progress after EPUB relayout Track the pagination value alongside the debounced EPUB position and force one save after a live relayout has rendered. This keeps ordinary page turns batched while ensuring font and layout changes cannot leave stale pagination on disk. commit f0271820e7a2fc3a11b349c186065678f61649bd Author: Julia Nguyen <julia@uxj.io> Date: Fri Jul 31 14:34:12 2026 -0400 perf: avoid repeated next-chapter probes Adapt the one-page/direct-jump trigger and successful-prefetch marker from Sichroteph/YACP commit 3f3c5fc42e794c021edb9832856ef98c2d2065b9 under the MIT license. Preserve CrossInk full-section-only behavior, fallible Section allocation, heap gates, render-mode fallbacks, and SdFat file-lifetime rules. Co-authored-by: Totofaki <Christophe.Jeannette@gmail.com> commit 828dfb1ba0c737d204ea88761f945daafa4a8f87 Author: Julia Nguyen <julia@uxj.io> Date: Fri Jul 31 14:32:26 2026 -0400 perf: reuse EPUB grayscale strip buffer Adapt the reusable grayscale-strip lifecycle from Sichroteph/YACP commit 3f3c5fc42e794c021edb9832856ef98c2d2065b9 under the MIT license. The port keeps CrossInk async plane rendering and releases the 8 KB fallback before section builds, prefetch, and teardown. Co-authored-by: Totofaki <Christophe.Jeannette@gmail.com> commit a5fa25e6c1aedfabbbabc309d2d6847b643ea9a2 Author: Julia Nguyen <julia@uxj.io> Date: Fri Jul 31 14:25:30 2026 -0400 perf: debounce reader progress writes Adapt the allocation-free save policy and reader integrations from Sichroteph/YACP commit 3f3c5fc42e794c021edb9832856ef98c2d2065b9 under the MIT license. CrossInk-specific handling keeps explicit saves immediate, preserves EPUB estimated page counts, and flushes pending progress before reader teardown. Co-authored-by: Totofaki <Christophe.Jeannette@gmail.com> commit 6be71d0c3703ce0e5e207ec756373e42ec1f6f17 Author: Julia Nguyen <julia@uxj.io> Date: Fri Jul 31 14:17:40 2026 -0400 perf: defer SD font discovery Adapt the lazy-discovery concept from Sichroteph/YACP commit 3f3c5fc42e794c021edb9832856ef98c2d2065b9 while preserving CrossInk saved-font loading and CJK UI fallbacks. Co-authored-by: Totofaki <Christophe.Jeannette@gmail.com> * fix: prevent dictionary suggestion lookup freezes * fix: landscape button labels in dictionary * fix: clear reader menu headings from landscape hints * fix: avoid web task watchdog timeout (issue 432) * fix: prevent bionic letter overlap (issue 442) * fix: load EPUB locations before reader handoff x-locations.json loading was being deferred, which could block user input. It has been moved back to the epub load lifecycle, before entering the reader. * fix: make EPUB sync positions content-based ported from crosspoint PR crosspoint-reader#2805 Co-authored-by: Thiago Kenji Okada <thiagokokada@gmail.com> * fix: avoid duplicate EPUB image display * fix: limit EPUB image clean refresh to sync return * docs: update docs for touch devices * fix: restore book cover placeholder icon * fix: preserve X3 power-button wake (issue 445) * fix: allow clipping selection past arbitrary chapter-end limit (issue 449) * fix: localize Russian dashboard stats (issue 450) * fix: stream table rendering to reduce maxAlloc required * fix: preserve button clicks after clearing recent book cache button clicks after clearing a book cache from recent books would get swallowed, making the first click get ignored. * fix: stabilize EPUB indexing and prioritize reader input * Add NVS-backed wake verification before SD mount Verify power button wake reason early in boot, before mounting SD card. Mirror the 'short press = sleep' setting to NVS so wake verification can run without waiting for SD-based settings. This reduces boot time for accidental wakes and ensures consistent hold-duration requirements regardless of SD mount delays. * chore: update freeink sdk includes draft changes for new x3 display drivers and possible fix for sleep screen ghosting * feat: custom dictionary font and size along with dictionary performance optimizations * refactor: remove stale web watchdog resets * fix: improve dark clipping highlight contrast (issue 431) * fix: avoid XTCH settings memory errors (issue 457) * chore: update freeink sdk * fix: restore precise cached EPUB sync positions * docs: add dictionary folder structure example * fix: keep saved clipping text legible in dark mode * chore: use GitHub Actions token for releases * fix: hide dictionary font options without dictionaries and update dictionary docs * feat: add global dictionary font setting * ci: update github token * fix: clear inactive dictionary button hints * fix: avod manage fonts screen from crashing * fix: honor side-button layout in dictionary suggestions * fix: load Wi-Fi credentials on first access (issue 421) * perf: avoid copying reader settings at construction * fix: cache EPUB books without covers (issue 465) * fix: distinguish missing EPUB covers (issue 465) * fix: preserve EPUB page on reopen (issue 466) * fix: improve custom dictionary font persistence * fix: reflow dictionary font after switching dictionaries * fix: improve x4 screen refreshes after using wifi (issue 470 and 462) * fix: preserve wake button release before sleep (issue 453) * fix: consume wake power release (issue 453) * fix: bold book titles in recent books list and bookmarks/clippings * fix: cleanly redraw home after a silent restart after wifi usage * fix: align Lyra settings tab underline * chore: update freeink sdk * fix: guard dictionary lookup against low heap * fix: retain dictionary lookup cache path * chore: update bug report template * fix: dictionary font falling back to reader font * fix: speed up random sleep image selection (issue 473) * fix: lend framebuffer during next chapter indexing (issue 475) * fix: allow cancellation of silent full section pre-indexing * fix: render EPUB overlay images above text * fix: chained dictionary lookups showing missing glyph diamond * fix: silent restart into Manage Fonts with a fresh heap * fix: unify theme battery icons (fixes #471) * chore: update freeink sdk * Add USB host detection and battery poll on charge Implement SOF-based USB host detection for ESP32-S3 boards without VBUS pin (X4 Pro) by monitoring USB-Serial-JTAG frame counter. Add periodic battery percentage polling every 60 seconds when USB is connected to trigger display updates as battery charges. (cherry picked from commit 3c4377e) * fix: size translated-label buffers for UTF-8 Adapted for CrossInk from upstream commit cc96e3c (crosspoint-reader#2850). * fix: recognize watchdog-triggered resets as panics Adapted for CrossInk from upstream commit 53232ee (crosspoint-reader#2830). * fix(epub): prevent ruby overflow in justified CJK text Adapted for CrossInk from upstream commit 046827f (crosspoint-reader#2781), preserving the arena-backed layout path and sparse ruby cache format. * fix: make Wi-Fi credential storage thread-safe Adapted for CrossInk from upstream commit c507e54 (crosspoint-reader#2834). CrossInk already validates obfuscated payloads, so this retains that format while adding synchronized snapshots, thread-safe key initialization, and bounded decoding. * fix: reject firmware for a different chip family Adapted for CrossInk from upstream commit e00f595 (crosspoint-reader#2880). The OTA path buffers the complete chip-ID header before its first flash write. * fix: serialize KOReader network time sync (issue 480) * fix: load end-of-book suggestions before moving * chore: update freeink sdk * fix: wrap long UI error messages * fix: resolve dictionary word selection cppcheck warnings * fix: use selected image for sleep cover * fix: release reader font cache before overlay PNG * chore: clang-format * fix: switch book menu tabs on held navigation (issue 483) * chore: remove Sticky side button diagnostics * fix: include silent restart helper in reader options * fix: build v1.5 default and sticky releases * chore: prepare for release * ci: update build scripts * docs: update docs for release * docs: add link to inky --------- Co-authored-by: Phạm Bình An <111893501+brianhuster@users.noreply.github.com> Co-authored-by: Uri Tauber <uritaube@gmail.com> Co-authored-by: Paul Delestrac <40175004+PaulDelestrac@users.noreply.github.com> Co-authored-by: Justin Mitchell <justin@jmitch.com> Co-authored-by: Tsz Ho Sze <szetszho@users.noreply.github.com> Co-authored-by: Totofaki <Christophe.Jeannette@gmail.com> Co-authored-by: CookieCaptainD <65847023+CookieCaptainD@users.noreply.github.com> Co-authored-by: Matteo Scopel <matteo@scopel.email> Co-authored-by: Thiago Kenji Okada <thiagokokada@gmail.com> Co-authored-by: Leopoldo Pla Sempere <leopoldo.pla@treelogic.com> Co-authored-by: Ing. Jan Kaláb <jan+github@kalabovi.org> Co-authored-by: Bastian <391732+dasrecht@users.noreply.github.com> Co-authored-by: Emily Marriott <emilylynmarriott@proton.me> Co-authored-by: William Floyd <william.floyd@modopayments.com> Co-authored-by: Paul Portocarrero <46283992+paulporto@users.noreply.github.com> Co-authored-by: Eduard <ed.fruty@gmail.com> Co-authored-by: Bob Vincent <pillarsdotnet@gmail.com> Co-authored-by: winst0niuss <chumachenko.vadym@gmail.com> Co-authored-by: Jesse Vincent <jesse@fsck.com>
1 parent 54ba245 commit 0de623e

505 files changed

Lines changed: 75931 additions & 19472 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.claude/CONTEXT.md

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,15 @@
22

33
Keep this file focused on repo-specific gotchas that are worth reusing in future sessions.
44

5+
## FreeInk SDK
6+
7+
Refer to https://freeink.org/llms.txt for guidance.
8+
59
## Simulator
610

7-
- Simulator patches belong in the adjacent `crosspoint-simulator` repo.
11+
- Simulator patches belong in the adjacent `crossink-simulator` repo.
812
- The valid local simulator env in this repo is `simulator`, and `pio run -e simulator` currently builds cleanly.
9-
- The simulator `PNGdec` stub in `crosspoint-simulator/src/PNGdec.h` needs to mirror the real API shape used by app code, including `hasAlpha()` and `getTransparentColor()`, even though decode still fails intentionally.
13+
- The simulator `PNGdec` stub in `crossink-simulator/src/PNGdec.h` needs to mirror the real API shape used by app code, including `hasAlpha()` and `getTransparentColor()`, even though decode still fails intentionally.
1014
- Known simulator limits:
1115
- No image rendering: `platformio.ini` ignores `hal`, `PNGdec`, and `JPEGDEC`, so image decoders are intentionally absent.
1216
- JPEGDEC stub always fails; `JPEGDEC fallback: open failed (err=-1)` is expected in simulator.
@@ -23,6 +27,19 @@ Keep this file focused on repo-specific gotchas that are worth reusing in future
2327
- Kindle EPUBs may contain paired high-res and old-Kindle fallback images. `ChapterHtmlSlimParser` should skip `<img>` nodes with `data-AmznRemoved-M8` to avoid duplicate stacked images.
2428
- After image/layout pipeline changes that affect cached EPUB output, clear the affected `.crosspoint/epub_<hash>/` cache if behavior looks stale.
2529

30+
## UI Consistency
31+
32+
- Use FreeInkUI SDK components and input routing for list-style screens where possible. Row rendering, touch targets,
33+
hit testing, and pagination should share the same FreeInkUI list configuration instead of custom touch scaling.
34+
35+
## Heap Baselines (X4 hardware, SD card font)
36+
37+
- A normal resume-into-partial reading session runs at ~85-90KB free / ~49KB maxAlloc by
38+
the first watermark crossing (Epub metadata + x-locations + resident glyph caches).
39+
Do not read mid-range heap numbers as session degradation without checking the scenario.
40+
- SD-font section builds cost ~38-50KB at cold start; the 4-style advance-table prewarm
41+
(~30KB incl. 16KB contiguous scratch) dominates and is skipped below 80KB free.
42+
2643
## Misc Repo Gotchas
2744

2845
- POSIX TZ signs are inverted from ISO 8601 in `TimeStore::applyTimezone()`: `"UTC-1"` means UTC+1.

.github/ISSUE_TEMPLATE/bug_report.yml

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,10 @@ body:
1414
label: Device
1515
description: Which device is this affecting?
1616
options:
17+
- "--- Select ---"
1718
- X4
1819
- X3
19-
- Both
20+
- Seeed Sticky
2021
validations:
2122
required: true
2223

@@ -35,6 +36,7 @@ body:
3536
label: EPUB Optimization
3637
description: Is your EPUB optimized?
3738
options:
39+
- "--- Select ---"
3840
- No / Not Applicable
3941
- Yes, using the built-in web transfer EPUB optimizer
4042
- Yes, using a different EPUB optimizer
@@ -48,6 +50,7 @@ body:
4850
label: Cache State
4951
description: Have you attempted to clear any cached data?
5052
options:
53+
- "--- Select ---"
5154
- No / Not Applicable
5255
- Yes, book cache (Reader menu > Delete Book Cache)
5356
- Yes, reading cache (Settings > System > Clear Reading Cache)
@@ -61,7 +64,7 @@ body:
6164
attributes:
6265
label: Describe the Bug
6366
description: A clear and concise description of what the bug is.
64-
placeholder:
67+
placeholder: |
6568
validations:
6669
required: true
6770

@@ -85,6 +88,19 @@ body:
8588
validations:
8689
required: true
8790

91+
- type: dropdown
92+
id: epub-attachment
93+
attributes:
94+
label: File Provided
95+
description: If your issue is related to a specific file (EPUB, XTC, etc.), please make sure to attach the exact file in this ticket or email it to julia@uxj.io and reference your issue number. **_EPUBs and XTC files need to be zipped to be attached._**
96+
options:
97+
- "--- Select ---"
98+
- Not Applicable
99+
- I've attached it
100+
- I've emailed it
101+
validations:
102+
required: true
103+
88104
- type: textarea
89105
id: logs
90106
attributes:

.github/PULL_REQUEST_TEMPLATE.md

Lines changed: 0 additions & 5 deletions
This file was deleted.

.github/workflows/ci.yml

Lines changed: 33 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -65,36 +65,58 @@ jobs:
6565
run: pio check --fail-on-defect low --fail-on-defect medium --fail-on-defect high
6666

6767
build:
68-
# Never run untrusted fork PR code on the self-hosted runner.
69-
if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository
70-
runs-on: [self-hosted, linux, crossink-build]
68+
runs-on: ubuntu-latest
69+
strategy:
70+
fail-fast: false
71+
matrix:
72+
environment: [default, sticky]
7173
steps:
7274
- uses: actions/checkout@v6
7375
with:
7476
submodules: recursive
7577

76-
- name: Verify PlatformIO Core
77-
run: pio --version
78+
- uses: actions/setup-python@v6
79+
with:
80+
python-version: "3.14"
81+
82+
- name: Install uv
83+
uses: astral-sh/setup-uv@v7
84+
with:
85+
version: "latest"
86+
enable-cache: true
87+
88+
- name: Cache PlatformIO packages
89+
uses: actions/cache@v4
90+
with:
91+
path: ~/.platformio
92+
key: ${{ runner.os }}-platformio-${{ matrix.environment }}-${{ hashFiles('platformio.ini', 'platformio.local.example.ini') }}
93+
restore-keys: |
94+
${{ runner.os }}-platformio-${{ matrix.environment }}-
95+
${{ runner.os }}-platformio-
96+
97+
- name: Install PlatformIO Core
98+
run: uv pip install --system -U https://github.com/pioarduino/platformio-core/archive/refs/tags/v6.1.19.zip
7899

79-
- name: Build CrossInk tiny
100+
- name: Build ${{ matrix.environment }} firmware
80101
run: |
81102
set -euo pipefail
82-
pio run -e tiny | tee pio.log
103+
pio run -e ${{ matrix.environment }} | tee pio-${{ matrix.environment }}.log
83104
84105
- name: Extract firmware stats
85106
run: |
86107
set -euo pipefail
87108
{
88-
echo "## Firmware build stats"
89-
grep -E "RAM:\s|Flash:\s" pio.log | while read -r line; do echo "- ${line}"; done
109+
echo "## ${{ matrix.environment }} firmware build stats"
110+
grep -E "RAM:\s|Flash:\s" pio-${{ matrix.environment }}.log | while read -r line; do echo "- ${line}"; done
90111
} >> "$GITHUB_STEP_SUMMARY"
91112
92113
- name: Upload firmware artifacts
114+
if: matrix.environment == 'default'
93115
uses: actions/upload-artifact@v7
94116
with:
95-
name: firmware-tiny
117+
name: firmware-x3-x4
96118
path: |
97-
.pio/build/tiny/firmware-tiny.bin
119+
.pio/build/default/firmware-x3-x4.bin
98120
if-no-files-found: error
99121

100122
# This job is used as the PR required actions check, allows for changes to other steps in the future without breaking

.github/workflows/pages.yml

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ on:
55
branches: [main]
66
paths:
77
- "docs/**"
8+
- "site/**"
89
- ".github/workflows/pages.yml"
910
workflow_dispatch:
1011

@@ -28,14 +29,21 @@ jobs:
2829

2930
- uses: actions/configure-pages@v6
3031

31-
- uses: actions/jekyll-build-pages@v1
32+
- uses: actions/setup-node@v5
3233
with:
33-
source: ./docs
34-
destination: ./_site
34+
node-version: 22
35+
cache: npm
36+
cache-dependency-path: site/package-lock.json
37+
38+
- run: npm ci
39+
working-directory: site
40+
41+
- run: npm run build
42+
working-directory: site
3543

3644
- uses: actions/upload-pages-artifact@v4
3745
with:
38-
path: ./_site
46+
path: ./site/dist
3947

4048
- name: Deploy to GitHub Pages
4149
id: deployment

.github/workflows/release.yml

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -57,20 +57,20 @@ jobs:
5757
fi
5858
VERSION="${VERSION#v}"
5959
echo "RELEASE_VERSION=$VERSION" >> "$GITHUB_ENV"
60-
sed -i "s/crossink_version = .*/crossink_version = $VERSION/" platformio.ini
60+
sed -i "/^\[crossink\]$/,/^\[/s/^version = .*/version = $VERSION/" platformio.ini
6161
6262
- name: Build CrossInk
6363
env:
64-
CROSSPOINT_RELEASE_VERSION: ${{ env.RELEASE_VERSION }}
65-
run: pio run -e tiny -e xlarge
64+
CROSSINK_RELEASE_VERSION: ${{ env.RELEASE_VERSION }}
65+
run: pio run -j1 -e default -e sticky
6666

6767
- name: Generate release catalog
6868
run: |
6969
python3 scripts/generate_release_catalog.py \
7070
--version "${{ env.RELEASE_VERSION }}" \
7171
--repo "${{ github.repository }}" \
72-
--firmware ".pio/build/tiny/firmware-tiny-v${{ env.RELEASE_VERSION }}.bin" \
73-
--firmware ".pio/build/xlarge/firmware-xlarge-v${{ env.RELEASE_VERSION }}.bin" \
72+
--firmware ".pio/build/default/firmware-x3-x4-v${{ env.RELEASE_VERSION }}.bin" \
73+
--firmware ".pio/build/sticky/firmware-sticky-v${{ env.RELEASE_VERSION }}.bin" \
7474
--output ".pio/build/catalog"
7575
7676
- name: Publish catalog to GitHub Pages source
@@ -113,5 +113,5 @@ jobs:
113113
target_commitish: ${{ github.sha }}
114114
draft: true
115115
files: |
116-
.pio/build/tiny/firmware-tiny-v${{ env.RELEASE_VERSION }}.bin
117-
.pio/build/xlarge/firmware-xlarge-v${{ env.RELEASE_VERSION }}.bin
116+
.pio/build/default/firmware-x3-x4-v${{ env.RELEASE_VERSION }}.bin
117+
.pio/build/sticky/firmware-sticky-v${{ env.RELEASE_VERSION }}.bin

.github/workflows/release_candidate.yml

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -77,18 +77,18 @@ jobs:
7777
escaped_version=$(printf '%s\n' "$VERSION" | sed 's/[&|]/\\&/g')
7878
sed -i "s|^crossink_version = .*|crossink_version = ${escaped_version}|" platformio.ini
7979
80-
- name: Build CrossPoint
80+
- name: Build CrossInk
8181
shell: bash
8282
env:
83-
CROSSPOINT_RC_ARTIFACTS: "1"
84-
CROSSPOINT_RC_BRANCH: ${{ env.RC_BRANCH_RAW }}
85-
CROSSPOINT_RC_HASH: ${{ env.RC_HASH_SHORT }}
83+
CROSSINK_RELEASE_VERSION: "1"
84+
CROSSINK_RC_BRANCH: ${{ env.RC_BRANCH_RAW }}
85+
CROSSINK_RC_HASH: ${{ env.RC_HASH_SHORT }}
8686
run: |
8787
build_args=()
8888
for env_name in $RC_ENVS; do
8989
build_args+=(-e "$env_name")
9090
done
91-
pio run "${build_args[@]}"
91+
pio run -j1 "${build_args[@]}"
9292
9393
- name: Create GitHub RC Prerelease
9494
uses: softprops/action-gh-release@v3
@@ -102,5 +102,5 @@ jobs:
102102
draft: true
103103
prerelease: true
104104
files: |
105-
.pio/build/tiny/firmware-tiny-${{ env.RC_BRANCH_SAFE }}-${{ env.RC_HASH_SHORT }}-RC.bin
106-
.pio/build/xlarge/firmware-xlarge-${{ env.RC_BRANCH_SAFE }}-${{ env.RC_HASH_SHORT }}-RC.bin
105+
.pio/build/default/firmware-x3-x4-${{ env.RC_BRANCH_SAFE }}-${{ env.RC_HASH_SHORT }}-RC.bin
106+
.pio/build/sticky/firmware-sticky-${{ env.RC_BRANCH_SAFE }}-${{ env.RC_HASH_SHORT }}-RC.bin

.gitignore

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,12 @@ build
1616
/.venv
1717
*.local*
1818
fs_/
19+
/site/node_modules/
20+
/site/dist/
21+
/site/.astro/
22+
/site/public/images/
23+
/site/public/catalog
24+
/site/public/CNAME
1925

2026
# scratchpad used as release notes for next crossink version
2127
release.md
@@ -35,4 +41,11 @@ lib/EpdFont/scripts/output/
3541
/site/public/catalog
3642
/site/public/CNAME
3743

38-
dist-publish/
44+
dist-publish/
45+
46+
# Generated by pioarduino when custom_sdkconfig rebuilds the framework.
47+
/managed_components/
48+
/.dummy/
49+
/CMakeLists.txt
50+
/dependencies.lock
51+
/sdkconfig.*

AGENTS.md

Lines changed: 19 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,14 @@
33
This is the canonical repo instruction file.
44
`CLAUDE.md` should point here so Codex and Claude read the same guidance.
55

6-
Project: Open-source e-reader firmware for Xteink X4 (ESP32-C3).
6+
Project: Open-source e-reader firmware for ESP32-C3 and ESP32-S3 devices.
77

88
## Core Rules
99

1010
- Role: Senior Embedded Systems Engineer for ESP-IDF / Arduino-ESP32 work.
11-
- The ESP32-C3 has no PSRAM and about 380 KB usable RAM. Stability beats features.
11+
- Support both constrained ESP32-C3 devices and PSRAM-equipped ESP32-S3 devices. Keep shared code safe for the C3 unless it is explicitly capability-gated; stability beats features.
1212
- Cite file paths and line numbers before proposing non-trivial changes.
13-
- Do not assume ESP-IDF or SDK API availability. Verify in `open-x4-sdk/` or the live code.
13+
- Do not assume ESP-IDF or SDK API availability. Verify in `freeink-sdk/` or the live code.
1414
- Do not claim performance or memory wins without explaining the mechanism, such as reduced heap churn, flash vs DRAM placement, or smaller stack use.
1515
- Justify new heap allocations or explain why stack/static storage is not suitable.
1616
- Explain fixes in plain language where possible, ideally in terms a Node / React developer would follow.
@@ -20,7 +20,6 @@ Project: Open-source e-reader firmware for Xteink X4 (ESP32-C3).
2020

2121
- Read `.claude/CONTEXT.md` at session start for durable repo-specific gotchas.
2222
- Keep `.claude/CONTEXT.md` short. Add only reusable findings, not turn-by-turn history.
23-
- If asked to summarize a session, create `.claude/CONTEXT-YYYY-MM-DD.md` with the relevant findings for that session.
2423

2524
## Repo Skills
2625

@@ -37,10 +36,11 @@ Project: Open-source e-reader firmware for Xteink X4 (ESP32-C3).
3736

3837
## Hardware Constraints
3938

40-
- MCU: ESP32-C3, single-core RISC-V at 160 MHz.
41-
- Display: 800x480 e-ink.
42-
- Single framebuffer only: `800 * 480 / 8 = 48000` bytes.
43-
- Storage is SD via SdFat. On real hardware, only one reader can hold a file open at a time.
39+
- ESP32-C3 targets (Xteink X3/X4): single-core RISC-V at 160 MHz, no PSRAM, and about 380 KB usable internal RAM.
40+
- ESP32-S3R8 targets (Seeed reTerminal Sticky/Xteink X4 Pro): dual-core Xtensa at up to 240 MHz with 8 MB PSRAM. PSRAM is slower than internal DRAM and is not suitable for every DMA, ISR, or latency-sensitive buffer.
41+
- Current displays use an 800x480 1-bit e-ink framebuffer: `800 * 480 / 8 = 48000` bytes. Use runtime renderer dimensions because orientation and future device profiles may differ.
42+
- Use one framebuffer only. C3 targets keep it in internal RAM; current S3 targets place it in PSRAM via `FREEINK_FB_PSRAM`.
43+
- Storage is exposed through SdFat, but the transport is device-specific (SPI SD on X3/X4/Sticky and SDMMC on X4 Pro). On real hardware, only one reader can hold a file open at a time.
4444

4545
## Resource Rules
4646

@@ -55,6 +55,7 @@ Project: Open-source e-reader firmware for Xteink X4 (ESP32-C3).
5555
9. `new` is not nothrow on ESP32. With exceptions disabled, bare `new` calls `abort()` on allocation failure instead of returning `nullptr`. Use `new (std::nothrow)` or `makeUniqueNoThrow<T>()` from `lib/Memory/Memory.h` for fallible allocations.
5656
10. Prefer `makeUniqueNoThrow<T>()` / `makeUniqueNoThrow<T[]>()` for owned heap allocations so cleanup is automatic on early returns.
5757
11. Use raw `malloc` or `new (std::nothrow)` only when a C or SDK API takes ownership; add a short comment explaining that ownership transfer.
58+
12. Treat PSRAM as a device capability, not a universal assumption. Keep shared paths within C3 limits or gate S3-only allocations behind the relevant board/capability macro, and handle PSRAM allocation failure.
5859

5960
## HAL And Platform Rules
6061

@@ -106,13 +107,15 @@ Project: Open-source e-reader firmware for Xteink X4 (ESP32-C3).
106107
- Host environment may be macOS, Linux, WSL, or Windows Git Bash. Check `uname -s` before recommending platform-specific shell commands.
107108
- Logging uses `LOG_INF`, `LOG_DBG`, and `LOG_ERR`.
108109
- The simulator env in this repo is `simulator`.
109-
- For simulator work, build from this firmware repo unless the change belongs in `crosspoint-simulator` itself.
110+
- For simulator work, build from this firmware repo unless the change belongs in `crossink-simulator` itself.
110111
- Common validation commands:
111112
- `pio run -e simulator` for simulator-facing UI/reader work.
112-
- `pio run -e default` for firmware compile validation.
113+
- `pio run -e default` for the ESP32-C3 X3/X4 firmware.
114+
- `pio run -e sticky` for the ESP32-S3 Sticky firmware.
115+
- `pio run -e x4-pro` for the ESP32-S3 X4 Pro firmware.
113116
- `pio check -e default --fail-on-defect low --fail-on-defect medium --fail-on-defect high` for static analysis.
114117
- `find src lib include test -name "*.cpp" -o -name "*.h" | xargs clang-format -i` for formatting touched C++ files.
115-
- For crash debugging, check serial logs, heap with `ESP.getFreeHeap()`, task stack high-water marks, and whether cache files need clearing.
118+
- For crash debugging, check serial logs, internal heap with `ESP.getFreeHeap()` and `ESP.getMaxAllocHeap()`, task stack high-water marks, and whether cache files need clearing. On S3 targets, also inspect PSRAM free space and largest allocatable block; abundant PSRAM does not prove that internal-RAM or DMA-capable allocations can succeed.
116119
- Hardware verification should mention the concrete device path to test, expected UI/log behavior, and any cache reset needed.
117120

118121
## Generated Files
@@ -131,7 +134,10 @@ Project: Open-source e-reader firmware for Xteink X4 (ESP32-C3).
131134
## Git Workflow
132135

133136
- Check `git status --short` before edits and before reporting results. Preserve unrelated user changes.
134-
- Do not commit unless the user explicitly asks.
137+
- When resolving merge, rebase, or cherry-pick conflicts, inspect the relevant commit messages for upstream PR references such as `#2608`. Open the PR in its source repository and read its description and changed files before resolving the conflict so the intended behavior is understood.
138+
- Do not resolve conflicts by automatically keeping CrossInk's current implementation or by discarding the upstream change wholesale. Preserve or adapt the upstream intent unless it is already fully implemented, would introduce a regression, or would substantially and unjustifiably change CrossInk's UX or behavior. When rejecting an upstream change, state the concrete reason.
139+
- If a referenced PR cannot be accessed, inspect the source commit diff and nearby history, then report that the PR intent could not be verified instead of guessing.
140+
- Do not commit unless the user explicitly asks or committing is part of the skill utilized.
135141
- Before staging, ensure ignored/generated/local files such as `.pio/`, `*.generated.h`, `compile_commands.json`, and `platformio.local.ini` are not included.
136142
- Branch names should use repo-style prefixes such as `feat/`, `fix/`, `docs/`, `refactor/`, `test/`, or `chore/`.
137143
- Suggested commit messages should follow `<type>: <short summary>`, using types like `feat`, `fix`, `docs`, `refactor`, `test`, `chore`, or `perf`.
@@ -150,6 +156,7 @@ When new features are added or issues are fixed, make sure to add an entry to `C
150156
- The release date of each version is displayed.
151157

152158
### Types of Changelog Changes
159+
153160
- Added - for new features.
154161
- Changed - for changes in existing functionality.
155162
- Deprecated - for soon-to-be removed features.

0 commit comments

Comments
 (0)