Skip to content

Repository files navigation

CrossPoint Reader — M5Stack PaperS3 port

This is a fork of CrossPoint Reader 1.5.0, ported to the official M5Stack PaperS3 development kit (shop.m5stack.com). That board is an ESP32-S3R8 with a 4.7" 960×540 16-gray e-paper panel, GT911 touch and a BM8563 RTC. Build with pio run -e m5papers3.

The hardware support lives in a freeink-sdk fork (new FREEINK_DEVICE_M5PAPERS3 board profile), referenced by this repo's freeink-sdk submodule. No physical unit was available when this port was first written, so every pin was sourced from the official, MIT-licensed m5stack/M5Unified/m5stack/M5GFX vendor libraries. It has since been bench-tested on a real M5PaperS3, with general operation reported working as of this update (testing is ongoing). Before you flash your own device, read freeink-sdk/docs/m5papers3-support.md for the full CONFIRMED/PENDING breakdown. In short:

  • CONFIRMED (direct from vendor source, and now bench-verified on a real M5PaperS3): display bus pins + rotation, touch I²C/INT pins and raw range, SD SPI pins, RTC address/bus, buzzer pin, battery ADC pin + divider, charge-status pin, and the (unusual) 5×-pulse power-off sequence.
  • Working on real hardware: display renders correctly filling the panel, and touch navigation (swipe-up-from-bottom opens the menu, general navigation) functions.
  • PENDING hardware validation: precise touch corner-tap accuracy (works in practice so far, not yet pixel-verified), physical navigation buttons (none found, so they are currently modeled as touch-only), and the IMU chip/address.

This is not the same hardware as the freeink-sdk's existing papermono board (different touch chip, RTC, and power topology). See the doc above for the comparison if you're not sure which one matches your device.

Dual-boot: sharing the device with MicroBASIC

The dev unit this port is developed on carries two unrelated firmwares at once, so more than one project can use the same physical board without reflashing the layout every time:

app0 / ota_0  0x20000   6656K   CrossPoint (this repo)
app1 / ota_1  0x6A0000  6656K   MicroBASIC or MicroWriter
                                (github.com/fperuzzo72/MicroWriter-BASIC-PaperS3)

The bootloader picks between them from otadata, so switching writes 32 bytes and never touches an app image. On this build the Home menu lists the sibling after Settings; selecting it reboots straight into it. MicroBASIC has the same switch on its own status bar, so both directions work from the device. scripts/m5papers3-boot-slot.sh 0|1 does it from the host.

Gated behind CROSSPOINT_DUAL_BOOT, set only in [env:m5papers3]. Every other target links stubs, detects nothing, and shows no extra menu entries. A slot counts as a sibling only if it holds a different project, so a spare A/B copy of this same firmware is never offered.

Flashing this board is not the same as flashing an X3/X4. The web installer and upstream's "Install firmware" section below do not apply: this device uses its own partition table (partitions_m5papers3.csv, not partitions.csv), and you write the app alone into its slot rather than a merged image. pio run -t upload is wrong here too, since it also writes the bootloader, the partition table, and a boot_app0.bin that resets the boot selection to slot 0.

For the same reason, CrossPoint's own SD/OTA self-update refuses to run while a sibling occupies the other slot: its target is "the next OTA partition", which here is MicroBASIC. Update over USB instead.

docs/m5papers3-dual-boot.md has all of it: the layout, the one-time migration, the day-to-day flashing recipe, and recovery.


CrossPoint Reader

Fund contributors

CrossPoint is open-source e-reader firmware - community-built, fully hackable, free forever. It's maintained by a growing community of developers and readers who believe your device should do what you want - not what a manufacturer decided for you.

Now running on: ESP32C3-based Xteink X4 and X3.

CrossPoint Reader running on Xteink device

If you're planning to buy an Xteink device, consider purchasing an X3/X4 Developer Edition through https://crosspointreader.com. CrossPoint receives a small share of each sale, helping fund development costs.

What can CrossPoint do?

  • Reader engine: EPUB 2/3 rendering with embedded-style option, image handling, hyphenation, kerning, chapter navigation, footnotes, bookmarks, dictionary lookups (StarDict), go-to-percent, auto page turn, orientation control, focus reading, KOReader progress sync and more.

  • Various formats: native handling for .epub, .xtc/.xtch, .txt, and .bmp.

  • Screenshots.

  • Custom fonts: install your favorite fonts on the SD card.

  • Tilt page turn (X3 only).

  • Library workflow: folder browser, hidden-file toggle, long-press delete, recent books, SD-cache management.

  • Wireless workflows:

    • File transfer web UI
    • EPUB Optimizer
    • Web settings UI/API (edit many device settings from browser)
    • WebSocket fast uploads
    • WebDAV handler
    • AP mode (hotspot) and STA mode (join existing Wi-Fi), both with QR helpers
    • Calibre wireless connect flow
    • OPDS browser with saved servers (up to 8), search, pagination, and direct download
    • OTA update checks and installs from GitHub releases
  • Customization: multiple themes (Classic, Lyra, Lyra Extended, RoundedRaff), sleep screen modes, front/side button remapping, status bar controls, power-button behavior, refresh cadence, and more.

  • Localization: 24 UI languages and counting. RTL support.

Coming soon:

  • More themes.

  • Much more! stay tuned.


USB-locked devices (Xteink Unlocker)

Some Xteink units purchased from third-party stores (e.g. AliExpress) ship with USB flashing locked from the factory. If your device is locked, you will need to use the Xteink Unlocker tool available at https://crosspointreader.com/#unlock-tool before you can flash CrossPoint.

You do not need this tool if you bought your device directly from xteink.com. Those units are not locked.

Not sure if your device is locked? Power it on, connect the USB-C cable, and try flashing via the web flasher first (see Install firmware below). If the browser's serial device picker does not show your device, try a different USB port or browser before assuming the device is locked. Only reach for the unlocker if the device still doesn't appear.

⚠️ WARNING: READ THIS BEFORE USING THE UNLOCKER ⚠️

The only officially supported firmwares in the unlock tool are CrossPoint and CrossInk.

Flashing any other firmware on a USB-locked device may permanently brick the device or leave it permanently stuck on that firmware with no recovery path. Once USB flashing is re-locked, your only way back is via OTA, and if the firmware you flashed doesn't support OTA, there is no way out.

Install firmware

Web installer (recommended)

  1. Connect your device to your computer via USB-C and wake/unlock the device
  2. Go to https://crosspointreader.com/#flash-tools, select device (X3 or X4), and choose an official CrossPoint release.

Web installer (specific version)

  1. Connect your device to your computer via USB-C and wake/unlock the device
  2. Download a firmware.bin from Releases, local build, or continuous integration artifact.
  3. Go to https://crosspointreader.com/#flash-tools, select device (X3 or X4), click "Custom .bin" and upload a firmware.bin.

Revert to Official Firmware

To revert to the official firmware, you can also flash the latest official firmware using https://crosspointreader.com/#flash-tools.

Command line

  1. Install esptool:
pip install esptool
  1. Download firmware.bin from the releases page.
  2. Connect your device via USB-C.
  3. Find the device port. On Linux, run dmesg after connecting. On macOS:
log stream --predicate 'subsystem == "com.apple.iokit"' --info
  1. Flash:
esptool.py --chip esp32c3 --port /dev/ttyACM0 --baud 921600 write_flash 0x10000 /path/to/firmware.bin

Adjust /dev/ttyACM0 to match your system.

Manual

See Development quick start below.


Custom SD-card fonts

Convert your own TTF/OTF files into .cpfont files that load from the SD card. No firmware reflash is needed.

  1. Go to https://crosspointreader.com/fonts and open the "SD-card font builder" form.
  2. Upload up to four styles (regular, bold, italic, bold-italic), set the family name, point sizes, and Unicode range.
  3. Download the generated .cpfont files.
  4. Copy them to your SD card under /fonts/YourFont/ (or /.fonts/YourFont/ to hide the folder).
  5. Select the font on the device from the font settings.

Conversion runs the firmware repo's lib/EpdFont/scripts/fontconvert_sdcard.py script unmodified, so output matches a local host build.


Documentation


Development quick start

Prerequisites

  • pioarduino or VS Code + pioarduino plugin
  • Python 3.8+
  • clang-format 21
  • USB-C cable supporting data transfer

Setup

git clone --recursive https://github.com/crosspoint-reader/crosspoint-reader
cd crosspoint-reader

# if cloned without --recursive:
git submodule update --init --recursive

Nix/NixOS

Nix/NixOS users can enter the development shell with either nix develop (flakes) or nix-shell:

nix develop -f nix
# or
nix-shell nix

To flash a connected ESP32-C3 device, enable PlatformIO's udev rules in your NixOS configuration:

services.udev.packages = with pkgs; [ platformio-core.udev ];

After rebuilding the system configuration, reconnect the device or reload udev rules.

Build / flash / monitor

pio run --target upload

Contributor pre-PR checks

./bin/clang-format-fix
pio check -e default
pio run -e default

Debugging

After flashing the new features, it’s recommended to capture detailed logs from the serial port.

First, make sure all required Python packages are installed:

python3 -m pip install pyserial colorama matplotlib

After that run the script:

# For Linux
# This was tested on Debian and should work on most Linux systems.
python3 scripts/debugging_monitor.py

# For macOS
python3 scripts/debugging_monitor.py /dev/cu.usbmodem2101

Minor adjustments may be required for Windows.


Internals

CrossPoint Reader is pretty aggressive about caching data down to the SD card to minimise RAM usage. The ESP32-C3 only has ~380KB of usable RAM, so we have to be careful. A lot of the decisions made in the design of the firmware were based on this constraint.

Data caching

The first time chapters of a book are loaded, they are cached to the SD card. Subsequent loads are served from the cache. This cache directory exists at .crosspoint on the SD card. The structure is as follows:

.crosspoint/
├── epub_<hash>/         # one directory per book, named by content hash
│   ├── progress.bin     # reading position (chapter, page, etc.)
│   ├── cover.bmp        # generated cover image
│   ├── book.bin         # metadata: title, author, spine, TOC
│   ├── css_rules.cache  # parsed CSS rule cache
│   ├── img_*            # rendered image cache files
│   └── sections/        # per-chapter layout cache
│       ├── 0.bin
│       ├── 1.bin
│       └── ...
├── settings.json        # device settings
├── state.json           # resume/runtime state
└── recent.json          # recent books list

Removing /.crosspoint clears all cached metadata and forces a full regeneration on next open. Book deletes, overwrites, and moves done through the firmware or web UI clear or re-key matching caches; manual SD-card edits may leave stale cache directories behind.

For more details on the internal file structures, see the file formats document.


Contributing

Contributions are welcome. If you're new to the codebase, start with the contributing docs. For things to work on, check the ideas discussion board — leave a comment before starting so we don't duplicate effort.

Everyone here is a volunteer, so please be respectful and patient. For governance and community expectations, see GOVERNANCE.md.


Community forks

One of the best things about open source is that anyone can take the code in a different direction. If you need something outside CrossPoint's scope, check out the community forks:

  • CrossInk — Typography and reading tracking: Bionic Reading (bolds word stems to create fixation points), guide dots between words, improved paragraph indents, and replaces the default fonts with ChareInk/Lexend/Bitter.

  • papyrix-reader — Adds FB2 and MD format support. Actively maintained with Arabic script support. Custom themes via SD card.

  • crosspet — A Vietnamese fork that adds a Tamagotchi-style virtual chicken that grows based on your reading milestones (pages read, streaks, care). Also: Flashcards, Weather, Pomodoro timer, and mini-games. (Unmaintained)

  • crosspoint-reader-cjk — Purpose-built for Chinese, Japanese, and Korean reading.

  • inx — Completely reimagines the user interface with tabbed navigation.

  • PlusPoint — custom JS apps support. (Unmaintained)

  • crosspoint-reader-papers3 — Crosspoint port for M5Stack Paper S3.

  • t5s3-reader — Crosspoint port for LilyGo T5 ePaper S3 / T5S3 4.7-inch e-paper device.

Note: Many of these features will make their way into CrossPoint over time. We maintain a slower pace to ensure rock-solid stability and squash bugs before they reach your device.

Want to build your own device? Be sure to check out the de-link project.


CrossPoint Reader is not affiliated with Xteink or any device manufacturer.

Huge shoutout to diy-esp32-epub-reader, which inspired this project.

About

Crosspoint 1.5.0 port for the official M5Stack PaperS3

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages