2026-02-22 05:50:08 +00:00
# Architecture Overview
CrossPoint is firmware for the Xteink X4 (unaffiliated with Xteink), built with PlatformIO targeting the ESP32-C3 microcontroller.
At a high level, it is firmware that uses an activity-driven application architecture loop with persistent settings/state, SD-card-first caching, and a rendering pipeline optimized for e-ink constraints.
## System at a glance
```mermaid
graph TD
2026-06-27 14:22:58 -04:00
A[Hardware: ESP32-C3 + SD + E-ink + Buttons] --> B[freeink-sdk]
2026-06-07 21:47:44 +02:00
B --> C[lib/hal wrappers]
C --> D[src/main.cpp runtime loop]
D --> E[Activities layer]
D --> F[State and settings]
E --> G[Reader flows]
E --> H[Home/Library/Settings flows]
E --> I[Network/Web server flows]
G --> J[lib/Epub parsing + layout + hyphenation]
J --> K[SD cache in .crosspoint]
E --> L[GfxRenderer]
L --> M[E-ink display buffer]
2026-02-22 05:50:08 +00:00
```
## Runtime lifecycle
Primary entry point is `src/main.cpp` .
```mermaid
flowchart TD
A[Boot] --> B[Init GPIO and optional serial]
B --> C[Init SD storage]
C --> D[Load settings and app state]
D --> E[Init display and fonts]
E --> F{Resume reader?}
F -->|No| G[Enter Home activity]
F -->|Yes| H[Enter Reader activity]
G --> I[Main loop]
H --> I
I --> J[Poll input and run current activity]
J --> K{Sleep condition met?}
K -->|No| I
K -->|Yes| L[Persist state and enter deep sleep]
```
In each loop iteration, the firmware updates input, runs the active activity, handles auto-sleep/power behavior, and applies a short delay policy to balance responsiveness and power.
## Activity model
Activities are screen-level controllers deriving from `src/activities/Activity.h` .
Some flows use `src/activities/ActivityWithSubactivity.h` to host nested activities.
- `onEnter()` and `onExit()` manage setup/teardown
- `loop()` handles per-frame behavior
- `skipLoopDelay()` and `preventAutoSleep()` are used by long-running flows (for example web server mode)
Top-level activity groups:
- `src/activities/home/` : home and library navigation
- `src/activities/reader/` : EPUB/XTC/TXT reading flows
- `src/activities/settings/` : settings menus and configuration
2026-06-07 21:47:44 +02:00
- `src/activities/network/` : Wi-Fi selection, AP/STA mode, file transfer server
2026-02-22 05:50:08 +00:00
- `src/activities/boot_sleep/` : boot and sleep transitions
## Reader and content pipeline
Reader orchestration starts in `src/activities/reader/ReaderActivity.h` and dispatches to format-specific readers.
EPUB processing is implemented in `lib/Epub/` .
```mermaid
flowchart LR
A[Select book] --> B[ReaderActivity]
B --> C{Format}
C -->|EPUB| D[lib/Epub/Epub]
C -->|XTC| E[lib/Xtc reader]
C -->|TXT| F[lib/Txt reader]
2026-06-07 21:47:44 +02:00
D --> G[Parse OPF/TOC and collect CSS refs]
G --> H[Build/load book.bin and css_rules.cache]
H --> I[Layout pages/sections]
I --> J[Write section cache]
J --> K[Render current page via GfxRenderer]
2026-02-22 05:50:08 +00:00
```
Why caching matters:
- RAM is limited on ESP32-C3, so expensive parsed/layout data is persisted to SD
- repeat opens/page navigation can reuse cached data instead of full reparsing
## Reader internals call graph
This diagram zooms into the EPUB path to show the main control and data flow from activity entry to on-screen draw.
```mermaid
flowchart TD
A[ReaderActivity onEnter] --> B{File type}
B -->|EPUB| C[Create Epub object]
B -->|XTC/TXT| Z[Use format-specific reader]
C --> D[Epub load]
D --> E[Locate container and OPF]
E --> F[Build or load BookMetadataCache]
F --> G[Load TOC and spine]
2026-06-07 21:47:44 +02:00
G --> H[Load CSS cache or parse manifest/base-dir CSS]
2026-02-22 05:50:08 +00:00
H --> I[EpubReaderActivity]
I --> J{Section cache exists for current settings?}
J -->|Yes| K[Read section bin from SD cache]
J -->|No| L[Parse chapter HTML and layout text]
L --> M[Apply typography settings and hyphenation]
M --> N[Write section cache bin]
K --> O[Build page model]
N --> O
O --> P[GfxRenderer draw calls]
P --> Q[HAL display framebuffer update]
Q --> R[E-ink refresh policy]
S[SETTINGS singleton] -. influences .-> J
S -. influences .-> M
T[APP_STATE singleton] -. persists .-> U[Reading progress and resume context]
U -. used by .-> I
```
Notes:
2026-06-07 21:47:44 +02:00
- CSS files are collected from the OPF manifest and, when needed, discovered by
streaming ZIP paths under the OPF content base directory; the firmware avoids
preloading the full ZIP central directory for large books.
- "section cache exists" depends on cache-busting parameters such as font,
viewport size, paragraph alignment, hyphenation, embedded CSS, image rendering,
and Focus Reading settings
2026-02-22 05:50:08 +00:00
- rendering favors reusing precomputed layout data to keep page turns responsive on constrained hardware
- progress/session state is persisted so the reader can reopen at the last position after reboot/sleep
## State and persistence
Two singletons are central:
- `src/CrossPointSettings.h` (`SETTINGS` ): user preferences and behavior flags
- `src/CrossPointState.h` (`APP_STATE` ): runtime/session state such as current book and sleep context
Typical persisted areas on SD:
```text
/.crosspoint/
epub_<hash>/
book.bin
2026-06-07 21:47:44 +02:00
css_rules.cache
2026-02-22 05:50:08 +00:00
progress.bin
cover.bmp
sections/*.bin
2026-06-07 21:47:44 +02:00
img_* cache files
settings.json
state.json
2026-02-22 05:50:08 +00:00
```
2026-08-01 21:37:07 +01:00
`sections/*.bin` contains rendered pages plus anchor, paragraph, list-item, and
page-start visible-text-offset lookup tables. The offset table makes reading
positions content-based: KOReader XPaths resolve to an exact chapter offset,
and the current layout derives the corresponding page. For binary cache
formats, see `docs/file-formats.md` .
2026-02-22 05:50:08 +00:00
## Networking architecture
Network file transfer is controlled by `src/activities/network/CrossPointWebServerActivity.h` and served by `src/network/CrossPointWebServer.h` .
Modes:
2026-06-07 21:47:44 +02:00
- STA: join existing Wi-Fi network
2026-02-22 05:50:08 +00:00
- AP: create hotspot
2026-06-07 21:47:44 +02:00
- Calibre Wireless: STA flow specialized for Calibre plugin uploads
2026-02-22 05:50:08 +00:00
Server behavior:
- HTTP server on port 80
- WebSocket upload server on port 81
2026-06-07 21:47:44 +02:00
- WebDAV handler on the HTTP server
- UDP discovery listener for upload clients
2026-02-22 05:50:08 +00:00
- file operations backed by SD storage
2026-06-07 21:47:44 +02:00
- browser APIs for file management, settings, fonts, OPDS servers, and saved Wi-Fi networks
2026-02-22 05:50:08 +00:00
- activity requests faster loop responsiveness while server is running
Endpoint reference: `docs/webserver-endpoints.md` .
## Build-time generated assets
Some sources are generated and should not be edited manually.
- `scripts/build_html.py` generates `src/network/html/*.generated.h` from HTML files
2026-06-07 21:47:44 +02:00
- `scripts/gen_i18n.py` generates `lib/I18n/I18nKeys.h` , `I18nStrings.h` , and `I18nStrings.cpp`
2026-02-22 05:50:08 +00:00
- `scripts/generate_hyphenation_trie.py` generates hyphenation headers under `lib/Epub/Epub/hyphenation/generated/`
When editing related source assets, regenerate via normal build steps/scripts.
## Key directories
- `src/` : app orchestration, settings/state, and activity implementations
- `src/network/` : web server and OTA/update networking
- `src/components/` : theming and shared UI components
2026-06-27 14:22:58 -04:00
- `lib/hal/` : hardware abstraction wrappers around freeink-sdk
2026-02-22 05:50:08 +00:00
- `lib/Epub/` : EPUB parser, layout, CSS handling, and hyphenation
- `lib/` : supporting libraries (fonts, text, filesystem helpers, etc.)
2026-06-27 14:22:58 -04:00
- `freeink-sdk/` : hardware SDK submodule (display, input, storage, battery). Docs: https://freeink.org/docs
2026-02-22 05:50:08 +00:00
- `docs/` : user and technical documentation
## Embedded constraints that shape design
- constrained RAM drives SD-first caching and careful allocations
- e-ink refresh cost drives render/update batching choices
- main loop responsiveness matters for input, power handling, and watchdog safety
- background/network flows must cooperate with sleep and loop timing logic
## Scope guardrails
Before implementing larger ideas, check:
- [SCOPE.md ](../../SCOPE.md )
- [GOVERNANCE.md ](../../GOVERNANCE.md )