Get the case files by email
The case files for this reader are not in the repo; they come by email. Leave your address and I will send them, along with new firmware, a bigger-screen version, and the next open source build I publish.
The batch 01 kit is closed. If another batch opens, the email list above hears first. Everything you need to build one yourself is below, free.
Part 1: The hardware
You need four things: an ESP32-S3 dev board, an e-paper panel with its adapter board, a five-way button module, and a way to power it. Total cost lands between $35 and $60 depending on the panel you pick. The ESP32-S3 is the right microcontroller for this because it has WiFi built in, enough flash to store a few books, and a hardware SPI bus that drives the panel at full speed. Buy a board with 8 MB or 16 MB of flash if you can; the 4 MB boards work but leave little room for text. For the buttons, any five-way navigation module (up, down, left, right, center click) from the usual hobby suppliers will do, wired with one common leg to ground and five signal legs to free GPIO pins. Add a BME280 breakout if you want temperature and humidity on the status line; it is optional and costs a couple of dollars.
| Part | What to buy | Price | Notes |
|---|---|---|---|
| Microcontroller | ESP32-S3 dev board, 8 or 16 MB flash | $6 to $12 | Any generic S3 board with USB-C. Dual USB-C boards make flashing and monitoring easier. |
| Display | 5.76" E Ink Carta Display Module (GDEH0576T81) (use the promo code "stition3" at checkout), or the Waveshare 7.5" e-Paper (V2, 800x480, black and white) with its e-Paper driver HAT | $25 to $45 with adapter | Buy the panel and its adapter board as a kit. The ready-made firmware supports exactly these two panels. See the panel section below. |
| Buttons | Five-way navigation switch module | $1 | Five signals plus one common ground. |
| Capacitors | 470 uF electrolytic + 100 nF ceramic | under $1 | Across the adapter's VCC and GND. Not optional. |
| Power | USB only, 3x AA + Schottky diode, or a small lithium cell with charger board | $0 to $8 | Pick one. Details below. |
| Optional | BME280 breakout | $2 to $4 | Temperature and humidity on the status line. |
| Case | Two pieces of cardboard and tape, a 3D print, or a cheap CNC order | $0 to $15 | Cardboard is what you see in the photos. |
Choosing the e-ink panel
The ready-made firmware supports exactly two panels: the 5.76 inch Good Display GDEH0576T81 and the Waveshare 7.5 inch V2 (800x480). If you buy one of those, skip the filtering below. Ordering any other display is where people get lost, and it needs a code change (a new entry in the panel table in the repo), so here are the variables that matter. Go to waveshare.com (or good-display.com, whose panels Waveshare resells; use the promo code "stition3" at checkout) and filter on these:
- Size. 5.7 to 7.5 inches reads like a paperback. 4.2 inches is pocketable but cramped for a full page of text.
- Resolution. Aim for 800x480 or better. Below that, small text looks jagged and you lose a column of characters per line.
- Color. Plain black and white refreshes fastest. The three and four color panels take 10 to 20 seconds per page and are a poor fit for reading.
- Interface. You want SPI, which every hobby panel uses. Skip parallel panels; they need a dedicated controller board.
- Partial refresh. The one that decides whether page turns flash white for two seconds or update quietly in a few hundred milliseconds. Look for "partial refresh" or "fast refresh" on the product page.
The panel ships as bare glass with a flat ribbon cable, so you also need the matching adapter board (Waveshare calls it a driver HAT, Good Display calls it DESPI). Buy the panel and adapter together as a kit and confirm the adapter runs at 3.3 V. The panel in the photos is a Good Display GDEH0576T81, 5.76 inch, 920x680, black and white, on a DESPI-C02 adapter, and it supports fast partial refresh.
Using the 7.5 inch panel
The Waveshare 7.5 inch V2 uses the same pins as the DESPI adapter in the wiring table below, so the wiring does not change. On a driver HAT revision 2.3 or later there is also a PWR pin; tie it to 3.3 V. The firmware assumes the 5.76 inch panel, so a fresh install of the 7.5 inch build starts with a blank screen. To fix that, hold the center button while you press reset (or while you plug in the USB cable). The reader cycles through the supported panels and draws "Press center if you can read this" on each for about 8 seconds; let go of center, then press it when the text is readable and it saves that panel. After that, the menu item "Screen" switches between panels at any time. The 7.5 inch panel has larger, lower-resolution text, so fewer characters fit on a line, and books you already loaded are reformatted on the reader the first time you open them. Speed read works on the 5.76 inch panel only for now.
Power, with or without a battery
Power is flexible because e-paper holds its image with no power at all, and the position in the book gets saved to flash on every page turn. That means the simplest build has no battery: plug a USB cable in, read, unplug, and the last page stays on the glass. If you want it portable, three AA cells in series (4.5 V) fed through a Schottky diode into the board's 5 V pin works well; the diode drops about 0.3 V and stops the board's USB supply from pushing current back into the cells when you plug in to reflash. A small lithium cell (500 to 1000 mAh) with a $2 charger and protection board is the tidier option and gives weeks of use per charge.
Firmware: flash mine, no code needed
You do not have to write any software. The firmware running on the reader in the photos is open source at github.com/AllanBinder/ereader, and you can install it straight from this page. Wire your parts to the pins below, plug the board into a computer over USB, open this page in Chrome or Edge, and click Install. It takes about two minutes, and it comes with Alice's Adventures in Wonderland loaded so you can check that everything works before you add your own books.
| Adapter or part | ESP32-S3 pin | Notes |
|---|---|---|
| Panel adapter SDI | GPIO 17 | SPI data |
| Panel adapter SCK | GPIO 18 | SPI clock |
| Panel adapter CS | GPIO 8 | |
| Panel adapter D/C | GPIO 9 | |
| Panel adapter RES | GPIO 10 | |
| Panel adapter BUSY | GPIO 46 | |
| Panel adapter VCC, GND | 3V3, GND | 3.3 V, not 5 V. Set the adapter's RESE switch to 0.47. |
| Button up | GPIO 40 | Directions as you hold the reader in portrait. Each button connects its pin to ground; no resistors needed. |
| Button down | GPIO 41 | |
| Button left | GPIO 1 | |
| Button right | GPIO 2 | |
| Button center | GPIO 42 | |
| Button common | GND | |
| BME280 SDA, SCL | GPIO 12, 13 | Optional. The reader shows "n/a" without it. |
ereader-setup. Join it from your phone, pick your home network, type the password. Up to eight networks are remembered.ereader-games from your phone (password ereader1), or open http://ereader.local/ on your home WiFi. Upload any plain text book (Project Gutenberg has 70,000 free ones as .txt) and the reader lays out the pages itself.Updates on this reader and what comes next
I am adding features to this reader and building more open source e-paper projects, including Muon Sortes, the cosmic ray clock this all grew out of. Get an email when something ships.
Make it yours
You can use the firmware exactly as it is; it is a complete reader. If you want something different, it is trivial to change with Claude Code. Clone the repo, open the folder, and describe the change in plain English: "I wired the buttons to different pins," "I have a different e-paper panel instead," "add a menu item that shows tomorrow's weather," "download a text file from my server every morning." The code is small, every pin lives in include/pins.h, every setting lives in include/config.h, and the README explains how the pieces fit, so a change like that is usually one conversation. Ask for soldering instructions in the same conversation and it will walk you through your own pin map one wire at a time. PDF books go through the Python converter in the repo, which keeps figures and page layout better than plain text does.
The case can be as simple as two pieces of cardboard with a window cut for the panel and a hole for the buttons, which is what mine is. For a proper case, the case files come by email: leave your address at the top of this page and I will send them. A printed shell is an evening of work if you have a printer, and if you do not, ordering it from a cheap online CNC or print service runs about $15.
Speed read mode
The reader can also flash a book at you one, two or three words at a time, in one fixed spot on the screen, so your eyes never move. This is called RSVP (rapid serial visual presentation), and it is a strange thing to see on e-paper, which is supposed to be slow. Open the menu, pick Speed read, and pick a book. It starts from the page you are on and keeps your place in step with the normal page view, so you can switch between the two whenever you like.
Getting e-paper this fast took three tricks, and the numbers are specific to the 5.76 inch GDEH0576T81 in the photos. First, the SPI bus runs at 40 MHz while speed read is on, which gets a whole frame to the panel in 54 ms. Second, the panel stores several refresh waveforms (the timed voltage sequence that moves the ink) and picks one by temperature, colder meaning slower. Telling it the room is 40 C selects the shortest one it has, 367 ms. Third, and this is the one that made single words possible: the words are already solid black about 60 ms into that 367 ms waveform, and the rest is margin. So when a flash has to come faster than the full waveform allows, the firmware resets the panel's controller 60 ms in, which stops the drive, and sets it back up again.
| Where the time goes | Stock partial refresh | With the cut |
|---|---|---|
| Send the frame over SPI | 54 ms | 54 ms |
| Drive the ink | 367 ms | 60 ms |
| Set the controller up again | none | about 90 ms, mostly restarting its power supply |
| Per flash | about 420 ms | about 205 ms |
| Top speed at one word per flash | about 140 wpm | about 290 wpm |
The cut is automatic. Any flash that stays on screen for 450 ms or more gets the full waveform, so slow settings and the longer holds at sentence ends never use it; at two words and 250 wpm nothing is cut at all. Every 30 flashes or so, at the next sentence end, the reader does one full refresh (the black and white flash) to wipe the ghosts, and it never waits past 40.
RSVP_FULL_AFTER in include/config.h).
Speed read is 5.76 inch only for now, and it is hidden on the 7.5 inch panel until I have tested it on glass. On a different panel, the idea carries over but the numbers do not. Most SPI e-paper modules have a controller on the glass that plays back a stored waveform, and resetting it mid refresh should stop the drive on those too. What changes is where the waveform does its work: some start with a shake or a flash to black before they drive the new image, and cutting those early leaves gray or wrong pixels. To find your panel's cut, set speed read to one word, start with a long cut (the RSVP_CUT_MS setting, try 150) and step it down until the words stop reaching solid black, then back off. Ghosting at the end of each 30 flash cycle is the other limit; I stopped at 60 ms because below that the ghosting got distracting. Some controllers also let you load your own short waveform instead, which is cleaner than a cut. Color panels, grayscale, and boards built on the IT8951 controller are a poor fit: the first two have long waveforms, and the IT8951 has its own fast mode (A2) and is slow to reset.
Part 2: The automated news brief
The reader gets interesting once it fetches content on its own. The setup has three pieces: a scheduled agent that writes the brief, a small server that stores the latest copy, and the device pulling it over WiFi.
Claude Code routines handle the first piece. A routine is a Claude Code session that runs on a schedule in the cloud; you give it a prompt such as "research these six topics, write a 1500 word brief in plain text with short paragraphs, no markdown, and upload it to this endpoint," pick a cron schedule (mine runs three mornings a week), and give it network access plus an upload token stored as an environment variable. It runs unattended and posts the finished text.
The server can be almost anything that accepts an HTTP POST and serves a GET. I used a Cloudflare Worker, which is free at this volume and has no machine to maintain: one route accepts the upload behind a bearer token and writes the text to KV storage, the other serves the latest file behind a read token. A Raspberry Pi running a twenty-line Flask app on your home network does the same job if you would rather keep everything local. The device side is a single function: on boot or on a button press, join WiFi, GET the URL, write the text to flash, paginate, and show page one. Ask Claude to write both halves and to keep the brief format fixed at plain text with a known column width so the device never has to do layout work.
The firmware from the Install button leaves the Sync feeds item out of the menu, because it has nowhere to sync from until you have a server. Once you do, ask Claude Code to point NEWS_URL in include/config.h at it, put your read token in include/secrets.h, and flash from source. Sync feeds and Auto sync then show up in the menu.
Part 3: The Game Boy server and the Pokemon companion screen
This is the part the video is about. The reader hosts NES and Game Boy ROMs and serves a browser emulator to your phone over its own WiFi, keeps the saves so a laptop and a phone can share one game, and while Pokemon Red or Blue runs the e-ink turns into a live companion screen drawn with the game's own font, tiles and sprites: the Kanto map with your position, the party with HP bars, badges, money, the bag with Mart prices, the route you are on with its wild encounters and hidden items, and a battle view that scores your moves against the enemy's types. The firmware, the browser page and the design docs are all in the public repo at github.com/AllanBinder/ereader (Apache 2.0). It ships no ROMs and no game assets; you bring your own dump and build the asset pack yourself from the game's disassembly.
pio run -e esp32s3 -t upload. That updates the firmware without touching your books or saves.third_party/pokered and run python3 tools/pokered_pack.py. It reads the font, town map, tilesets, sprites, wild tables and item lists straight out of the disassembly and writes build_pack/pokered.pack, about 240 KB. Pillow makes it faster; it works without it.ereader-games, password ereader1) or, if the reader knows your home WiFi from Part 2, open http://ereader.local/ on the same network. Upload the pack and your ROM through the page's file picker, tap the ROM, play.The reader never emulates anything. An e-paper panel cannot draw sixty frames a second and the ESP32 has no memory to spare, so the emulator (jsnes for NES, WasmBoy for Game Boy and Game Boy Color) runs in the phone's browser and the reader only stores and serves files. What makes the companion screen possible is that the page can read the emulator's memory. Once a second it takes the Game Boy's 8 KB of work RAM and posts it to the reader, and the firmware decodes it with addresses taken from the pokered disassembly: the party lives at one address, money at another, the current map and your step coordinates at two more. Pokemon Red never wrote any of this for a second screen; it just keeps its whole world in 8 KB, and the disassembly community mapped every byte of it. The panel redraws only when something you can see has changed, a partial refresh in about half a second, with a full refresh once a minute to keep the image clean.
On the reader the silkscreen right button pages from Home to Inventory and back, the left one goes the other way, up toggles the terrain view of the map you are standing on, and center leaves the games server. A battle takes the screen on its own and hands it back when the fight ends. On the phone the pad works on touch, and on a laptop the arrows or WASD move, X or E is A, Z or R is B, Enter is Start, Shift is Select. The speed button runs the game at 2x or 4x for grinding. The page saves the cartridge RAM to the reader whenever it changes, writes an autosave every minute, and offers Continue the next time any device opens that ROM.
docs/companion-dashboard-game-candidates-2026-09-13.md, hand the Pokemon files to a coding agent as the worked example, and ship a generator, never the assets or a ROM. I would love to see a Crystal or a Link's Awakening screen; open an issue or send a pull request.
Part 4: Where this could go
The part I keep thinking about is multiplayer. The games server already proves the shape: an ESP32 can run as a WiFi access point, so the reader broadcasts its own network and serves a web page to anyone who joins. Nobody installs an app: players scan a QR code on the e-paper, their phone opens a page served by the device, and the panel becomes a shared board on the table that everyone can see while phones hold the private hands. That covers a whole class of tabletop games (trivia, drafting, hidden role, bidding, word games) and the panel is a perfect scoreboard because it stays readable in daylight and holds the last state if someone knocks the power out. The same hardware could host a shared reading group where the device shows one page and each phone gets a vote on what happens next, or a quiz night where the question is on the glass and answers arrive over the local network.
I would like this to be an open source platform rather than one person's project. If you build a reader from this guide, or if you want to help define a small game API (device serves the board, phones post moves over HTTP, everything stays on the local network), come say hi in the _stition Discord, email me, or reply wherever you found the video. Ideas for games, case designs, panel choices, and power setups are all welcome. Pictures of your build are the best contribution of all.
Get notified
New firmware, case files, a bigger-screen version, and the next open source build I publish. Leave your email and you will hear about it first.