Readable in full sun
Reflective panel, no backlight. The brighter the day, the better it looks. Visor down, glance, done.
Heavy development · nothing here is finished
TrailInk turns a pocket e-ink reader into an offline map display for motorcycles and trails. No backlight to wash out, no battery gone by lunch. One still picture: where you are, where the route goes, what is around you.
Built on CrossPoint Reader. Map data © OpenStreetMap contributors.
01 — why e-ink
The screen washes out in direct sun. It cooks in a handlebar mount. The battery does not last a day of riding. E-ink has the opposite properties — and one hard cost you have to design around.
Reflective panel, no backlight. The brighter the day, the better it looks. Visor down, glance, done.
Holding an image costs nothing. Power goes only into changing the picture, so the X4 runs for tens of hours.
A full refresh takes about 1.7 s; four grey levels cost an extra waveform pass, and lose their grey to the next one. That rules out a moving map.
Position, route, surroundings — redrawn rarely, readable at a glance at speed. No rerouting, no voice, no traffic. The route is planned before you leave.
02 — the screen
Everything in the first row came off the panel over USB. Send a coordinate; the device draws the roads around it from tiles on its SD card. The second row is the renderer running on a laptop against the same tiles — that is how styling gets tuned without reflashing.
Honest caveat: the device renderer follows most of the style spec now — road widths, casings, buildings, forest, built-up and water areas all draw on the panel. Place labels, the route line and junction dots exist in the spec and in the laptop preview, not yet on the glass.
03 — how it is built
Fetches an area from OpenStreetMap, projects and clips it, routes along real
roads, and writes binary .tib tiles at three zoom levels. A browser
tuning tool renders a pixel-exact 480×800 preview, so the styling gets judged
as e-ink instead of as a pretty vector map.
A fork of CrossPoint Reader. Map screen, BLE position receiver, tiles off the SD card, zoom and marker height on the physical buttons, ride / hike / cycle filter, and a command console over USB serial and BLE. The e-reader stack comes out; maps go in.
Sends the phone's GPS fix to the device over BLE every few seconds and records every fix and packet for replay. One window, no settings screen, foreground service — it keeps sending with the phone locked in a bag. A GPS liveness gate throws away network fixes that would jump you across town.
04 — status
Formats, the render spec and the BLE protocol all still change without notice. Do not depend on any of it yet.
.tib tiles, three zoom levelsworks05 — development log
Buildings, forest and built-up areas now draw on the panel, filled with a dither pattern rather than hatch lines — at map scale a house is a handful of pixels, and lines across it read as dirt. Roads take a width per class, and the panel confirmed both.
Which of the two a village gets is decided when the tiles are built: individual buildings up close, one built-up area from 6 m/px out. The device never reads what it would not draw, and that shows in the numbers — a viewport reset takes 2506 ms reading 484 KB at 3 m/px, and 1088 ms reading 198 KB at 6 m/px.
All four grey levels render and are distinguishable by eye. A full grey frame measures ~2.1 s, and it has to be the last thing that touches the panel: a refresh issued in the same breath breaks the picture. A repeated nudge lightens the same pixel and adds grain, so grey cannot be topped up in place.
Judged side by side on the glass, the existing 2×2 dither simply read better for area fills — and it survives any refresh, because it is ordinary black and white. So fills stay dithered and four-level grey stays out of the map. The support layer and its test screen remain, behind a build flag, for the next panel question.
The device's own renderer now compiles as a host binary and runs against the style being edited, so the webapp preview shows real device output. Two seconds per edit instead of a build-and-flash cycle.
Forest and built-up land arrive in the tile format as aggregated areas. Buildings are drawn up close and replaced by a built-up tone further out — a build-time split, picked per level of detail rather than per style.
Network fixes were confirming implausible jumps. The app now ignores a network fix when satellite fixes are still alive. Validated on three real bike rides: 10–15 % of fixes filtered.
Grey went on the table after the driver was read properly — four levels, one extra waveform pass each. A pile of code comments still said 1-bit; they were lying.
The full dated log lives in the repo, alongside one topic document per hardware finding — how the panel actually behaves, why the obvious approach fails. Read it on GitHub →
06 — the hardware
A pocket e-ink reader, bought off the shelf. Not a dev board, not Android, no ADB — an ESP32-C3 with a display driver and physical buttons. Everything TrailInk does has to fit in that.
07 — get in touch
I ride, and I wanted a display that survives a sunny day on a handlebar. If you are doing something similar on Xteink hardware, or you want to try it, or you just want to tell me the map style is wrong — write to me.