A fork of https://github.com/crosspoint-reader/crosspoint-reader
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

docs: Add lightweight contributor onboarding documentation (#894)

### Summary

This PR introduces a lightweight contributor onboarding docs section
under `docs/contributing/` and improves local formatting ergonomics for
first-time contributors.

The goal is to make CrossPoint easier to contribute to for software
developers who are new to embedded systems (like me), while keeping
onboarding modular and aligned with existing project docs.

### What changed

- Added contributor docs hub: `docs/contributing/README.md`
- Added focused onboarding pages:
- `docs/contributing/getting-started.md`
- `docs/contributing/architecture.md`
- `docs/contributing/development-workflow.md`
- `docs/contributing/testing-debugging.md`
- Linked contributor docs from `README.md` for discoverability
- Expanded architecture documentation with Mermaid diagrams
- Improved `bin/clang-format-fix`:
- prefers `clang-format-21` when available
- validates formatter version and fails fast with a clear message if too
old
- handles missing positional arg safely
- Updated docs to explain common `clang-format` setup/version issues and
install paths (including fallback steps when `clang-format-21` is
unavailable in default apt sources)

### Why

- There was no dedicated contributor onboarding path; first-time
contributors had to infer workflow from multiple files.
- New contributors (especially from non-embedded backgrounds) need a
clear mental model of architecture, runtime flow, and debugging process.
- Local formatting setup caused avoidable friction due to clang-format
version mismatch (`.clang-format` expects newer keys used in CI).
- The updates make contribution setup more predictable, reduce
onboarding confusion, and align local checks with CI expectations.

### Additional context

- No firmware behavior/runtime logic was changed; this PR focuses on
contributor experience and tooling clarity.

---

### AI Usage

> Did you use AI tools to help write this code?

Yes, I used AI tools to assist with generating the documentation. I then
manually reviewed, tested, and refined the code to ensure it works
correctly. please feel free to point out any discrepancies or areas for
improvement.

authored by

Bilal and committed by
GitHub
f62529ad 88537769

+407 -8
+1
.gitignore
··· 10 10 **/__pycache__/ 11 11 /compile_commands.json 12 12 /.cache 13 + /.venv
+2
README.md
··· 154 154 155 155 Contributions are very welcome! 156 156 157 + If you are new to the codebase, start with the [contributing docs](./docs/contributing/README.md). 158 + 157 159 If you're looking for a way to help out, take a look at the [ideas discussion board](https://github.com/crosspoint-reader/crosspoint-reader/discussions/categories/ideas). 158 160 If there's something there you'd like to work on, leave a comment so that we can avoid duplicated effort. 159 161
+23 -8
bin/clang-format-fix
··· 1 1 #!/usr/bin/env bash 2 2 3 - # Check if clang-format is availible 4 - command -v clang-format >/dev/null 2>&1 || { 5 - printf "'clang-format' not found in current environment\n" 6 - printf "install 'clang', 'clang-tools', or 'clang-format' depending on your distro/os and tooling requirements\n" 7 - exit 1 8 - } 3 + # Check if clang-format is available and pick the preferred binary. 4 + if command -v clang-format-21 >/dev/null 2>&1; then 5 + CLANG_FORMAT_BIN="clang-format-21" 6 + elif command -v clang-format >/dev/null 2>&1; then 7 + CLANG_FORMAT_BIN="clang-format" 8 + else 9 + printf "'clang-format' not found in current environment\n" 10 + printf "Install clang-format-21 (recommended), clang, clang-tools, or clang-format depending on your distro/os and tooling requirements\n" 11 + exit 1 12 + fi 13 + 14 + set -euo pipefail 9 15 10 16 GIT_LS_FILES_FLAGS="" 11 - if [[ "$1" == "-g" ]]; then 17 + if [[ "${1:-}" == "-g" ]]; then 12 18 GIT_LS_FILES_FLAGS="--modified" 13 19 fi 14 20 21 + CLANG_FORMAT_VERSION_RAW="$(${CLANG_FORMAT_BIN} --version)" 22 + CLANG_FORMAT_MAJOR="$(printf '%s\n' "${CLANG_FORMAT_VERSION_RAW}" | grep -oE '[0-9]+' | head -n1)" 23 + 24 + if [[ -z "${CLANG_FORMAT_MAJOR}" || "${CLANG_FORMAT_MAJOR}" -lt 21 ]]; then 25 + echo "Error: ${CLANG_FORMAT_BIN} is too old: ${CLANG_FORMAT_VERSION_RAW}" 26 + echo "This repository's .clang-format requires clang-format 21 or newer." 27 + echo "Install clang-format-21 and rerun ./bin/clang-format-fix" 28 + exit 1 29 + fi 15 30 16 31 # --- Main Logic --- 17 32 ··· 27 42 | grep -v -E '^lib/EpdFont/builtinFonts/' \ 28 43 | grep -v -E '^lib/Epub/Epub/hyphenation/generated/' \ 29 44 | grep -v -E '^lib/uzlib/' \ 30 - | xargs -r clang-format -style=file -i 45 + | xargs -r "${CLANG_FORMAT_BIN}" -style=file -i
+11
docs/contributing/README.md
··· 1 + # Contributing Docs 2 + 3 + This section is a lightweight contributor guide for CrossPoint Reader. 4 + It is written for software developers who may be new to embedded development. 5 + 6 + - [Getting Started](./getting-started.md) 7 + - [Architecture Overview](./architecture.md) 8 + - [Development Workflow](./development-workflow.md) 9 + - [Testing and Debugging](./testing-debugging.md) 10 + 11 + If you are new, start with [Getting Started](./getting-started.md).
+199
docs/contributing/architecture.md
··· 1 + # Architecture Overview 2 + 3 + CrossPoint is firmware for the Xteink X4 (unaffiliated with Xteink), built with PlatformIO targeting the ESP32-C3 microcontroller. 4 + 5 + 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. 6 + 7 + ## System at a glance 8 + 9 + ```mermaid 10 + graph TD 11 + A[Hardware: ESP32-C3 + SD + E-ink + Buttons] --> B[open-x4-sdk HAL] 12 + B --> C[src/main.cpp runtime loop] 13 + C --> D[Activities layer] 14 + C --> E[State and settings] 15 + D --> F[Reader flows] 16 + D --> G[Home/Library/Settings flows] 17 + D --> H[Network/Web server flows] 18 + F --> I[lib/Epub parsing + layout + hyphenation] 19 + I --> J[SD cache in .crosspoint] 20 + D --> K[GfxRenderer] 21 + K --> L[E-ink display buffer] 22 + ``` 23 + 24 + ## Runtime lifecycle 25 + 26 + Primary entry point is `src/main.cpp`. 27 + 28 + ```mermaid 29 + flowchart TD 30 + A[Boot] --> B[Init GPIO and optional serial] 31 + B --> C[Init SD storage] 32 + C --> D[Load settings and app state] 33 + D --> E[Init display and fonts] 34 + E --> F{Resume reader?} 35 + F -->|No| G[Enter Home activity] 36 + F -->|Yes| H[Enter Reader activity] 37 + G --> I[Main loop] 38 + H --> I 39 + I --> J[Poll input and run current activity] 40 + J --> K{Sleep condition met?} 41 + K -->|No| I 42 + K -->|Yes| L[Persist state and enter deep sleep] 43 + ``` 44 + 45 + 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. 46 + 47 + ## Activity model 48 + 49 + Activities are screen-level controllers deriving from `src/activities/Activity.h`. 50 + Some flows use `src/activities/ActivityWithSubactivity.h` to host nested activities. 51 + 52 + - `onEnter()` and `onExit()` manage setup/teardown 53 + - `loop()` handles per-frame behavior 54 + - `skipLoopDelay()` and `preventAutoSleep()` are used by long-running flows (for example web server mode) 55 + 56 + Top-level activity groups: 57 + 58 + - `src/activities/home/`: home and library navigation 59 + - `src/activities/reader/`: EPUB/XTC/TXT reading flows 60 + - `src/activities/settings/`: settings menus and configuration 61 + - `src/activities/network/`: WiFi selection, AP/STA mode, file transfer server 62 + - `src/activities/boot_sleep/`: boot and sleep transitions 63 + 64 + ## Reader and content pipeline 65 + 66 + Reader orchestration starts in `src/activities/reader/ReaderActivity.h` and dispatches to format-specific readers. 67 + EPUB processing is implemented in `lib/Epub/`. 68 + 69 + ```mermaid 70 + flowchart LR 71 + A[Select book] --> B[ReaderActivity] 72 + B --> C{Format} 73 + C -->|EPUB| D[lib/Epub/Epub] 74 + C -->|XTC| E[lib/Xtc reader] 75 + C -->|TXT| F[lib/Txt reader] 76 + D --> G[Parse OPF/TOC/CSS] 77 + G --> H[Layout pages/sections] 78 + H --> I[Write section and metadata caches] 79 + I --> J[Render current page via GfxRenderer] 80 + ``` 81 + 82 + Why caching matters: 83 + 84 + - RAM is limited on ESP32-C3, so expensive parsed/layout data is persisted to SD 85 + - repeat opens/page navigation can reuse cached data instead of full reparsing 86 + 87 + ## Reader internals call graph 88 + 89 + This diagram zooms into the EPUB path to show the main control and data flow from activity entry to on-screen draw. 90 + 91 + ```mermaid 92 + flowchart TD 93 + A[ReaderActivity onEnter] --> B{File type} 94 + B -->|EPUB| C[Create Epub object] 95 + B -->|XTC/TXT| Z[Use format-specific reader] 96 + 97 + C --> D[Epub load] 98 + D --> E[Locate container and OPF] 99 + E --> F[Build or load BookMetadataCache] 100 + F --> G[Load TOC and spine] 101 + G --> H[Load or parse CSS rules] 102 + 103 + H --> I[EpubReaderActivity] 104 + I --> J{Section cache exists for current settings?} 105 + J -->|Yes| K[Read section bin from SD cache] 106 + J -->|No| L[Parse chapter HTML and layout text] 107 + L --> M[Apply typography settings and hyphenation] 108 + M --> N[Write section cache bin] 109 + 110 + K --> O[Build page model] 111 + N --> O 112 + O --> P[GfxRenderer draw calls] 113 + P --> Q[HAL display framebuffer update] 114 + Q --> R[E-ink refresh policy] 115 + 116 + S[SETTINGS singleton] -. influences .-> J 117 + S -. influences .-> M 118 + T[APP_STATE singleton] -. persists .-> U[Reading progress and resume context] 119 + U -. used by .-> I 120 + ``` 121 + 122 + Notes: 123 + 124 + - "section cache exists" depends on cache-busting parameters such as font and layout-related settings 125 + - rendering favors reusing precomputed layout data to keep page turns responsive on constrained hardware 126 + - progress/session state is persisted so the reader can reopen at the last position after reboot/sleep 127 + 128 + ## State and persistence 129 + 130 + Two singletons are central: 131 + 132 + - `src/CrossPointSettings.h` (`SETTINGS`): user preferences and behavior flags 133 + - `src/CrossPointState.h` (`APP_STATE`): runtime/session state such as current book and sleep context 134 + 135 + Typical persisted areas on SD: 136 + 137 + ```text 138 + /.crosspoint/ 139 + epub_<hash>/ 140 + book.bin 141 + progress.bin 142 + cover.bmp 143 + sections/*.bin 144 + settings.bin 145 + state.bin 146 + ``` 147 + 148 + For binary cache formats, see `docs/file-formats.md`. 149 + 150 + ## Networking architecture 151 + 152 + Network file transfer is controlled by `src/activities/network/CrossPointWebServerActivity.h` and served by `src/network/CrossPointWebServer.h`. 153 + 154 + Modes: 155 + 156 + - STA: join existing WiFi network 157 + - AP: create hotspot 158 + 159 + Server behavior: 160 + 161 + - HTTP server on port 80 162 + - WebSocket upload server on port 81 163 + - file operations backed by SD storage 164 + - activity requests faster loop responsiveness while server is running 165 + 166 + Endpoint reference: `docs/webserver-endpoints.md`. 167 + 168 + ## Build-time generated assets 169 + 170 + Some sources are generated and should not be edited manually. 171 + 172 + - `scripts/build_html.py` generates `src/network/html/*.generated.h` from HTML files 173 + - `scripts/generate_hyphenation_trie.py` generates hyphenation headers under `lib/Epub/Epub/hyphenation/generated/` 174 + 175 + When editing related source assets, regenerate via normal build steps/scripts. 176 + 177 + ## Key directories 178 + 179 + - `src/`: app orchestration, settings/state, and activity implementations 180 + - `src/network/`: web server and OTA/update networking 181 + - `src/components/`: theming and shared UI components 182 + - `lib/Epub/`: EPUB parser, layout, CSS handling, and hyphenation 183 + - `lib/`: supporting libraries (fonts, text, filesystem helpers, etc.) 184 + - `open-x4-sdk/`: hardware SDK submodule (display, input, storage, battery) 185 + - `docs/`: user and technical documentation 186 + 187 + ## Embedded constraints that shape design 188 + 189 + - constrained RAM drives SD-first caching and careful allocations 190 + - e-ink refresh cost drives render/update batching choices 191 + - main loop responsiveness matters for input, power handling, and watchdog safety 192 + - background/network flows must cooperate with sleep and loop timing logic 193 + 194 + ## Scope guardrails 195 + 196 + Before implementing larger ideas, check: 197 + 198 + - [SCOPE.md](../../SCOPE.md) 199 + - [GOVERNANCE.md](../../GOVERNANCE.md)
+43
docs/contributing/development-workflow.md
··· 1 + # Development Workflow 2 + 3 + This page defines the expected local workflow before opening a pull request. 4 + 5 + ## 1) Fork and create a focused branch 6 + 7 + - Fork the repository to your own GitHub account 8 + - Clone your fork locally and add the upstream repository if needed 9 + 10 + - Branch from `master` 11 + - Keep each PR focused on one fix or feature area 12 + 13 + ## 2) Implement with scope in mind 14 + 15 + - Confirm your idea is in project scope: [SCOPE.md](../../SCOPE.md) 16 + - Prefer incremental changes over broad refactors 17 + 18 + ## 3) Run local checks 19 + 20 + ```sh 21 + ./bin/clang-format-fix 22 + pio check --fail-on-defect low --fail-on-defect medium --fail-on-defect high 23 + pio run 24 + ``` 25 + 26 + CI enforces formatting, static analysis, and build checks. 27 + Use clang-format 21+ locally to match CI. 28 + If `clang-format` is missing or too old locally, see [Getting Started](./getting-started.md). 29 + 30 + ## 4) Open the PR 31 + 32 + - Use a semantic title (example: `fix: avoid crash when opening malformed epub`) 33 + - Fill out `.github/PULL_REQUEST_TEMPLATE.md` 34 + - Describe the problem, approach, and any tradeoffs 35 + - Include reproduction and verification steps for bug fixes 36 + 37 + ## 5) Review etiquette 38 + 39 + - Be explicit and concise in responses 40 + - Keep discussions technical and respectful 41 + - Assume good intent and focus on code-level feedback 42 + 43 + For community expectations, see [GOVERNANCE.md](../../GOVERNANCE.md).
+80
docs/contributing/getting-started.md
··· 1 + # Getting Started 2 + 3 + This guide helps you build and run CrossPoint locally. 4 + 5 + ## Prerequisites 6 + 7 + - PlatformIO Core (`pio`) or VS Code + PlatformIO IDE 8 + - Python 3.8+ 9 + - `clang-format` 21+ in your `PATH` (CI uses clang-format 21) 10 + - USB-C cable 11 + - Xteink X4 device for hardware testing 12 + 13 + If `./bin/clang-format-fix` fails with either of these errors, install clang-format 21: 14 + 15 + - `clang-format: No such file or directory` 16 + - `.clang-format: error: unknown key 'AlignFunctionDeclarations'` 17 + 18 + Examples: 19 + 20 + ```sh 21 + # Debian/Ubuntu (try this first) 22 + sudo apt-get update && sudo apt-get install -y clang-format-21 23 + 24 + # If the package is unavailable, add LLVM apt repo and retry 25 + wget https://apt.llvm.org/llvm.sh 26 + chmod +x llvm.sh 27 + sudo ./llvm.sh 21 28 + sudo apt-get update 29 + sudo apt-get install -y clang-format-21 30 + 31 + # macOS (Homebrew) 32 + brew install clang-format 33 + ``` 34 + 35 + Then verify: 36 + 37 + ```sh 38 + clang-format-21 --version 39 + ``` 40 + 41 + The reported major version must be 21 or newer. 42 + 43 + ## Clone and initialize 44 + 45 + ```sh 46 + git clone --recursive https://github.com/crosspoint-reader/crosspoint-reader 47 + cd crosspoint-reader 48 + ``` 49 + 50 + If you already cloned without submodules: 51 + 52 + ```sh 53 + git submodule update --init --recursive 54 + ``` 55 + 56 + ## Build 57 + 58 + ```sh 59 + pio run 60 + ``` 61 + 62 + ## Flash 63 + 64 + ```sh 65 + pio run --target upload 66 + ``` 67 + 68 + ## First checks before opening a PR 69 + 70 + ```sh 71 + ./bin/clang-format-fix 72 + pio check --fail-on-defect low --fail-on-defect medium --fail-on-defect high 73 + pio run 74 + ``` 75 + 76 + ## What to read next 77 + 78 + - [Architecture Overview](./architecture.md) 79 + - [Development Workflow](./development-workflow.md) 80 + - [Testing and Debugging](./testing-debugging.md)
+48
docs/contributing/testing-debugging.md
··· 1 + # Testing and Debugging 2 + 3 + CrossPoint runs on real hardware, so debugging usually combines local build checks and on-device logs. 4 + 5 + ## Local checks 6 + 7 + Make sure `clang-format` 21+ is installed and available in `PATH` before running the formatting step. 8 + If needed, see [Getting Started](./getting-started.md). 9 + 10 + ```sh 11 + ./bin/clang-format-fix 12 + pio check --fail-on-defect low --fail-on-defect medium --fail-on-defect high 13 + pio run 14 + ``` 15 + 16 + ## Flash and monitor 17 + 18 + Flash firmware: 19 + 20 + ```sh 21 + pio run --target upload 22 + ``` 23 + 24 + Open serial monitor: 25 + 26 + ```sh 27 + pio device monitor 28 + ``` 29 + 30 + Optional enhanced monitor: 31 + 32 + ```sh 33 + python3 -m pip install pyserial colorama matplotlib 34 + python3 scripts/debugging_monitor.py 35 + ``` 36 + 37 + ## Useful bug report contents 38 + 39 + - Firmware version and build environment 40 + - Exact steps to reproduce 41 + - Expected vs actual behavior 42 + - Serial logs from boot through failure 43 + - Whether issue reproduces after clearing `.crosspoint/` cache on SD card 44 + 45 + ## Common troubleshooting references 46 + 47 + - [User Guide troubleshooting section](../../USER_GUIDE.md#7-troubleshooting-issues--escaping-bootloop) 48 + - [Webserver troubleshooting](../troubleshooting.md)