Skip to main content

Wiring

:::info Source of truth These pin assignments are the rendering of meta/shared/hardware.toml, the single authoritative contract. runtime (the SPI driver + keymap) and the ESP-32 firmware generate their constants from the same file. Do not edit pins here independently — change hardware.toml and regenerate. :::

Overview

USB-C (5V) ──────────────────────────────► RPi Zero 2W

GPIO ◄───────────── Buttons (×7)
SPI ──────────────► GDEM0397T81P (3.3V)

SPI — Display

The GDEM0397T81P (800×480) communicates with the Pi over SPI at 3.3V logic (/dev/spidev0.0). Pins are Raspberry Pi BCM numbers.

SignalBCM pinNotes
MOSI10 (SPI0 MOSI)Data to display (DIN)
SCLK11 (SPI0 SCLK)Clock
CS8 (SPI0 CE0)Chip select
DC25Data/Command select
RST17Hardware reset
BUSY24Panel busy (active-high)

GPIO — Buttons

Seven buttons, each active-low with an internal pull-up and a 30 ms debounce. The keysym is injected on the X stack; the in-engine path queues the Ren'Py event instead.

ButtonBCM pinKeysymRen'Py eventESP-32 dev pin
Up5Upfocus_up32
Down6Downfocus_down33
Left13Leftfocus_left25
Right19Rightfocus_right26
A16spacedismiss (advance)27
B20Escapegame_menu (back)14
Start21Returnselect / confirm12

Power

The Pi is powered via its USB-C port. The battery connects directly without a power management IC in the current revision (an IP5306 is planned for a future revision).

Changing a pin

Pins are never edited in a downstream repo directly. meta/shared/hardware.toml is the single source of truth; every consumer regenerates its own constants from it, and CI fails the build if any committed file drifts out of sync. To move a signal:

:::warning The build does NOT read hardware.toml The image bakes in committed, pre-generated files — not the contract. hardware.toml is only their upstream source, linked by a manual gen step you must run in each consumer repo. Editing the contract alone changes nothing in the image until you regenerate and rebuild. And the pins that actually drive the panel and buttons at runtime live in runtime (src/spi_driver/contract.h, src/input/keymap.py), not in config.txtconfig.txt only enables the SPI bus and sets boot-time button pull-ups. Regenerating buildroot_os alone is not enough; you must regenerate runtime too (Step 2). :::

1. Edit the contract

Change the value in meta/shared/hardware.toml:

# Example: move the display RESET line from BCM 17 to BCM 27
[spi]
rst = 27

# Example: remap the "a" button to BCM 12
[[button]]
name = "a"
bcm = 12

:::warning Which pins are actually movable The three hardware SPI0 signals — mosi (BCM 10), sclk (BCM 11), and cs (BCM 8, CE0) — are fixed to their ALT0 function pins on the Pi. Changing those numbers in the contract will not rewire hardware SPI0; it only relabels the documentation. Moving them for real means switching to software SPI or SPI1, which is a driver change, not a contract edit.

The freely reassignable GPIOs are the display's dc / rst / busy (driven via libgpiod) and all seven buttons. Keep off the SPI0/UART pins and other special-function lines when picking new numbers. :::

2. Regenerate the derived files in each consumer

Each repo has a generator that renders committed files from the contract:

# buildroot_os — regenerates board/inky/config.txt (SPI + button pull-ups)
# and the in-engine input_hook.rpy button map.
cd buildroot_os && python3 scripts/gen_hardware.py

# runtime — regenerates the keymap and the SPI driver's pin header.
cd runtime && make gen

buildroot_os runs a parity check automatically on every build (./br.sh calls scripts/gen_hardware.py --check before Buildroot runs), so forgetting to regenerate buildroot_os's own files fails the build rather than shipping stale. But that check does not cover runtime — a forgotten make gen there is caught only by runtime's own CI (make gen-check), so regenerate both by hand. Both checks also skip silently if the meta repo isn't checked out beside these repos, and INKY_SKIP_CHECKS=1 bypasses the buildroot_os one.

:::note Not the same as version pins buildroot_os/scripts/check_pins.py verifies software version pins against meta/versions.env — unrelated to GPIO pins despite the name. GPIO pin parity is gen_hardware.py --check. :::

3. Rebuild and re-flash

The regenerated config.txt sets the boot-time pull-ups and SPI bus; the runtime picks up the new GPIO/SPI numbers from its regenerated constants. Rebuild the hardware image and write it to the card:

cd buildroot_os && ./build.sh pi
sudo dd if=output/images/sdcard.img of=/dev/sdX bs=4M conv=fsync status=progress

See Flashing InkyOS to an SD card for the full flashing procedure. Then rewire the panel and buttons to match the new assignments before booting.