/ README.md
README.md
  1  # SignalOS
  2  
  3  Open-source e-reader firmware for the Xteink X4. ESP32-C3. 380KB RAM. No telemetry. No accounts. Just reading.
  4  
  5  A [DWS Engineering](https://dws.rip) project.
  6  
  7  ![Home screen](./docs/images/device.jpg)
  8  
  9  ---
 10  
 11  ## Why SignalOS?
 12  
 13  The Xteink X4 is a fun, hackable device with solid hardware. But the stock firmware is closed-source and requires converting your EPUBs to XTC format for the best experience. No custom fonts. No WiFi transfers. No theming.
 14  
 15  **SignalOS changes the equation.**
 16  
 17  We started with the excellent [Papyrix Reader](https://github.com/bigbag/papyrix-reader) — open-source firmware that already brings EPUB support, WiFi transfers, and custom themes to the X4. Then we made it better for serious readers.
 18  
 19  **What we added:**
 20  
 21  - **In-reader menu** — TOC, bookmarks, and reading stats without leaving your book
 22  - **Library indexing** — Browse thousands of books with pagination
 23  - **File management** — Delete files and folders directly on the device
 24  - **Configurable action button** — Instant bookmark or TOC access
 25  - **Reading time tracking** — See how long you've spent with each book
 26  - **Quote-based sleep screen** — Literary quotes instead of blank screens
 27  - **UI consistency** — Coherent design across all screens
 28  - **Stability hardening** — Runs smoothly on 380KB RAM
 29  
 30  **The bottom line:** Native EPUB support, custom fonts, WiFi transfers, Calibre sync, and a refined interface that gets out of your way.
 31  
 32  It's your device. Read however you want.
 33  
 34  Not affiliated with Xteink.
 35  
 36  ---
 37  
 38  ## Documentation
 39  
 40  [User Guide](docs/user_guide.md) · [Customization](docs/customization.md) · [Fonts](docs/fonts.md) · [Architecture](docs/architecture.md) · [Device Specs](docs/device-specifications.md) · [File Formats](docs/file-formats.md) · [Images](docs/images.md) · [Webserver](docs/webserver.md) · [Calibre](docs/calibre.md) · [Changelog](CHANGELOG.md)
 41  
 42  ---
 43  
 44  ## Features
 45  
 46  ### What Makes SignalOS Different
 47  
 48  **Reading Experience**
 49  - In-reader menu with TOC, bookmarks, and reading stats
 50  - Configurable action button for instant bookmark or TOC
 51  - Library indexing with pagination and folder position memory
 52  - File and folder deletion from the device
 53  - Reading time tracking
 54  
 55  **Design**
 56  - Quote-based sleep screen with literary excerpts
 57  - Refreshed sleep screen visuals
 58  - Consistent UI across all views
 59  - Clear button bar indicators
 60  
 61  **Performance & Stability**
 62  - Reader hardening with cache reset on failure
 63  - Deadlock avoidance and mutex timeout protection
 64  - Parser safety with limits for fonts, themes, and EPUBs
 65  - Defensive memory management
 66  
 67  ### Core Capabilities
 68  
 69  **Formats**
 70  - EPUB 2/3 — Full CSS parsing, nav.xhtml + NCX fallback, inline images (JPEG/PNG/BMP up to 2048×3072)
 71  - XTC/XTCH — Native compressed format
 72  - Markdown & Plain Text — Clean rendering with ATX headers
 73  - Book Covers — JPG/PNG/BMP with dithering options
 74  
 75  **Typography**
 76  - Knuth-Plass line breaking (TeX-quality justified text)
 77  - CJK & Thai text layout with proper mark positioning
 78  - 3 font sizes, 4 alignments, 4 text layout presets
 79  - Streaming font system with LRU cache for memory-efficient custom fonts
 80  
 81  **Display**
 82  - Line spacing: compact, normal, relaxed, large
 83  - Pages per refresh: 1/5/10/15/30
 84  - 4 screen orientations
 85  - Sunlight fading fix (display power-down after refresh)
 86  
 87  **Customization**
 88  - Custom themes from `/config/themes/`
 89  - Custom fonts from `/config/fonts/` (`.epdfont` format)
 90  - Sleep screens: dark, light, custom image, or book cover
 91  - Button remapping (side or bottom page turn)
 92  - Power button page turn for one-handed reading
 93  
 94  **Connectivity**
 95  - WiFi file transfer via built-in web server
 96  - Calibre Wireless Device support
 97  
 98  **File System**
 99  - exFAT and FAT32 support
100  - UTF-8 filenames (Cyrillic, CJK, etc.)
101  - Nested folder browser
102  - Library indexing
103  
104  Example themes and fonts: [`docs/examples/`](docs/examples/)
105  
106  ---
107  
108  ## Installation
109  
110  ### Flasher (Recommended)
111  
112  [signalos-flasher](https://github.com/dws-signal/signalos-flasher) — Cross-platform CLI with auto-detection.
113  
114  ```bash
115  signalos-flasher flash firmware.bin
116  ```
117  
118  ### From Source
119  
120  See [Development](#development).
121  
122  ---
123  
124  ## Development
125  
126  ### Prerequisites
127  
128  - PlatformIO (`pio` CLI or VS Code extension)
129  - Node.js 18+ (build scripts)
130  - USB-C cable
131  - Xteink X4
132  
133  ### Nix (Recommended)
134  
135  All dependencies via `shell.nix`:
136  
137  ```bash
138  nix-shell
139  make build
140  ```
141  
142  <details>
143  <summary>First-time Nix setup</summary>
144  
145  ```bash
146  sh <(curl -L https://nixos.org/nix/install) --daemon
147  nix-channel --add https://nixos.org/channels/nixos-unstable nixpkgs
148  nix-channel --update
149  ```
150  
151  </details>
152  
153  ### Clone
154  
155  ```bash
156  git clone --recursive https://github.com/dws-signal/dws-signal
157  
158  # Already cloned without --recursive:
159  git submodule update --init --recursive
160  ```
161  
162  ### Build
163  
164  ```bash
165  make build            # Debug
166  make release          # Release
167  pio run               # PlatformIO directly
168  ```
169  
170  ### Flash
171  
172  Connect Xteink X4 via USB-C:
173  
174  ```bash
175  make flash
176  # or
177  pio run --target upload
178  ```
179  
180  Manual flash with esptool:
181  
182  ```bash
183  esptool.py --chip esp32c3 --port /dev/ttyACM0 --baud 460800 \
184    write_flash -z 0x0 firmware.bin
185  ```
186  
187  Port varies: `COM3` (Windows), `/dev/tty.usbmodem*` (macOS), `/dev/ttyACM0` (Linux).
188  
189  ### Build Scripts
190  
191  All in `scripts/`. Require Node.js 18+.
192  
193  ```bash
194  cd scripts && npm install
195  ```
196  
197  #### Fonts
198  
199  Convert TTF/OTF to `.epdfont`:
200  
201  ```bash
202  cd scripts
203  
204  # Basic
205  node convert-fonts.mjs my-font -r MyFont-Regular.ttf
206  
207  # Full family
208  node convert-fonts.mjs my-font -r Regular.ttf -b Bold.ttf -i Italic.ttf --all-sizes
209  
210  # Variable font weight
211  node convert-fonts.mjs roboto -r Roboto-Variable.ttf --var wght=400
212  
213  # CJK/Thai (streamed .bin format)
214  node convert-fonts.mjs noto-cjk -r NotoSansSC-Regular.ttf --bin --size 24
215  
216  # Preview
217  node convert-fonts.mjs my-font -r MyFont-Regular.ttf --preview
218  ```
219  
220  See [font docs](docs/fonts.md).
221  
222  #### Sleep Screens
223  
224  ```bash
225  make sleep-screen INPUT=photo.jpg OUTPUT=sleep.bmp
226  make sleep-screen INPUT=photo.jpg OUTPUT=sleep.bmp ARGS='--dither --bits 8'
227  ```
228  
229  Options: `--orientation portrait|landscape`, `--bits 2|4|8`, `--dither`, `--fit contain|cover|stretch`
230  
231  Copy output to `/sleep/` or `/sleep.bmp` on SD card.
232  
233  #### Logo
234  
235  128×128 monochrome, converted to C header:
236  
237  ```bash
238  cd scripts && node convert-logo.mjs logo.png ../src/images/SignalOSLogo.h
239  ```
240  
241  #### Calibre Simulators
242  
243  Test Calibre Wireless without hardware:
244  
245  ```bash
246  cd scripts
247  node device-simulator.mjs     # Simulate SignalOS device
248  node calibre-simulator.mjs    # Simulate Calibre desktop
249  ```
250  
251  ### Releases
252  
253  ```bash
254  make gh-release VERSION=0.1.1
255  make gh-release VERSION=0.1.1 NOTES="Release notes"
256  make changelog
257  ```
258  
259  ---
260  
261  ## Architecture
262  
263  380KB of RAM. Every byte matters.
264  
265  SignalOS is built for predictable performance on constrained hardware.
266  
267  ### Core Design
268  
269  - **State machine** — 10 pre-allocated states, no dynamic allocation after init
270  - **Dual-boot** — UI mode (full features) vs Reader mode (minimal RAM). Device restarts between modes to reclaim memory
271  - **Content providers** — Unified `ContentHandle` for EPUB, XTC, TXT, Markdown
272  - **Page cache** — Partial caching with background pre-rendering
273  
274  ### Memory Management
275  
276  The ESP32 WiFi stack allocates ~100KB and fragments heap irreversibly. After WiFi features, the device restarts to reclaim memory. This is by design.
277  
278  ### Performance
279  
280  | Optimization | Technique |
281  |-------------|-----------|
282  | EPUB spine/TOC lookup | FNV-1a hash maps, O(1) |
283  | Glyph cache | FNV-1a hash, O(1) |
284  | XTC rendering | Byte-level 1-bit processing |
285  | Image compression | CCITT Group5 for fast decompression |
286  | Word width cache | 512-entry cache |
287  | Image cache | Convert once, cache to SD |
288  | Font streaming | LRU cache for custom fonts |
289  
290  ### Cache
291  
292  Chapters are cached to SD on first load. Subsequent reads served from cache.
293  
294  ```
295  .signalos/
296  ├── epub_<hash>/
297  │   ├── progress.bin        # Reading progress
298  │   ├── cover.bmp           # Cover image
299  │   ├── book.bin            # Metadata
300  │   ├── sections/
301  │   │   └── 0.bin           # Chapter data
302  │   └── images/
303  │       └── <hash>.bmp      # Inline images
304  ├── txt_<hash>/
305  │   ├── progress.bin
306  │   ├── index.bin
307  │   └── cover.bmp
308  └── md_<hash>/
309      ├── progress.bin
310      ├── section.bin
311      └── cover.bmp
312  ```
313  
314  Clear via **Settings > Cleanup** or delete `.signalos/` manually.
315  
316  See [file formats](docs/file-formats.md).
317  
318  ---
319  
320  ## Related Tools
321  
322  - [epub-to-xtc-converter](https://github.com/bigbag/epub-to-xtc-converter) — Browser-based EPUB to XTC/XTCH converter
323  - [xteink-epub-optimizer](https://github.com/bigbag/xteink-epub-optimizer) — CLI to optimize EPUBs for 480×800 e-ink
324  
325  ---
326  
327  ## Contributing
328  
329  1. Fork
330  2. Branch (`feature/your-feature`)
331  3. PR
332  
333  ---
334  
335  ## Acknowledgments
336  
337  - **[Papyrix](https://github.com/bigbag/papyrix-reader)** — Pavel Liashkov. Direct upstream. Calibre Wireless, custom themes, Thai rendering, many UI improvements.
338  - **[CrossPoint Reader](https://github.com/daveallie/crosspoint-reader)** — Dave Allie. Original open-source X4 firmware.
339  - **[bb_epaper](https://github.com/bitbank2/bb_epaper)** — Larry Bank. Hardware insights, e-paper driver.
340  - **[MD4C](https://github.com/mity/md4c)** — Martin Mitas. Markdown parser.
341  - **[microreader](https://github.com/CidVonHighwind/microreader)** — CidVonHighwind. CSS parser.
342  
343  ---
344  
345  **[DWS Engineering LLC](https://dws.rip)** — It's your internet. Take it back.
346  
347  Not affiliated with Xteink.
348  
349  © 2026 DWS Engineering LLC