Build Specification
Spec hygiene (CLAUDE.md rule 1). This document does not restate concrete hardware values (display resolution, grid dimensions, battery capacity, current draw, clock speeds, case dimensions, etc.). Those live in CLAUDE.md’s Canonical Hardware Specification table. When a value is needed here, it is referenced as “see CLAUDE.md Canonical Hardware Specification.” If a number ever appears inline in this doc, it is a bug — file an issue and fix it.
Reading order. This document is the system-level overview — topology, BOM context, assembly plan, dev-vs-prod-mode. For deep detail on a specific hardware subsystem, jump to the per-component spec page:
processor.md— Pi Zero 2 W (primary processor)coprocessor.md— Pi Pico 2 (realtime I/O)primary-display.md— Elecrow 7” IPSauxiliary-display.md— CIPHER-LINE SSD1322 OLEDkeyboard.md— custom mech keeb (31-key, TERM included)audio.md— YM2149 PSG → I2S → MAX98357A → speaker/jackcartridge-interface.md— SD-sled cartridges (USB-MSC)power.md— LiPo + 5V rail + runtime envelopeenclosure.md— Pelican 1170 + 3D-printed inset panelsEach component page consolidates its ADR(s), the relevant BOM rows from
sourcing-guide.md, and the relevant bring-up stage below.
1. Pi Zero 2 W Overview
Section titled “1. Pi Zero 2 W Overview”The KN-86 Deckline runs on the Raspberry Pi Zero 2 W as its sole production and prototype compute platform. The Zero 2 W is a full ARM Cortex-A53 Linux single-board computer small enough to mount inside the Pelican 1170 hardcase’s foam-lined interior, yet capable of driving the Elecrow 7” IPS display over HDMI, running a Linux userspace nOSh process, and handling all audio synthesis and peripheral I/O through off-the-shelf USB and I2S modules. For the exact display resolution, text grid, and other canonical device-spec values, see CLAUDE.md.
For the canonical processor specification, RAM, connectivity summary, display driver target, audio chain, peripherals, case dimensions, battery capacity, runtime, and ship target, see CLAUDE.md Canonical Hardware Specification. This document references those values; it does not restate them.
The Zero 2 W platform replaces an earlier microcontroller-based exploration that was archived in April 2026. That work lives under docs/_archive/hardware/ and docs/_archive/adr/ADR-0003-firmware-update-mechanism.md — retained for historical context only. The earlier target was dropped because the Elecrow 7” IPS display we settled on uses HDMI rather than a dedicated LCD bus, and the Zero 2 W’s Linux userspace model makes the system image update path, USB HID keyboard integration, and cartridge filesystem all dramatically simpler than they would have been on a bare-metal platform.
Why Zero 2 W and not Zero W / Pi 4 / Zero 2 W variants
Section titled “Why Zero 2 W and not Zero W / Pi 4 / Zero 2 W variants”- Zero W (original): Insufficient compute for the desktop emulator path; nOSh’s UI animations and PSG synthesis benefit meaningfully from the Cortex-A53 quad core.
- Pi 4: Overpowered and too physically large to fit the Pelican 1170’s interior envelope. Power draw would also compromise the battery runtime target.
- Zero 2 WH (pre-soldered header variant): Functionally identical to Zero 2 W for our purposes; either is acceptable at bench-rig scale. The build uses whichever is available.
2. Hardware Topology
Section titled “2. Hardware Topology”The KN-86 is a collection of off-the-shelf modules wired into the Pi Zero 2 W through standard interfaces. There is no custom main-board PCB — the build is constructed on a small interconnect plate with screw terminals and JST-PH harnesses. This is deliberate: it keeps the v0.1 build accessible to anyone with basic soldering skills and avoids the lead-time risk of PCB fabrication.
+----------------------------------------------------------------------+| KN-86 DECKLINE || || Elecrow 7" IPS <--HDMI-- Pi Zero 2 W <--USB OTG--> internal hub || (primary disp) (Linux + nOSh) | || +--+ || | | | || | v v || | QMK Kbd Controller || | (custom mech keeb, || | ADR-0018, 31-key) || | | || | v || | USB-to-SD bridge IC || | + push-push SD socket || | (cartridge interface, || | ADR-0019) || | || UART0 @ 1 Mbps (per ADR-0017) || v || Pi Pico 2 (RP2350) || realtime I/O coprocessor || (ADR-0017; cart-bus role removed by ADR-0019) || / | || SPI I2S || v v || SSD1322 OLED MAX98357A || (CIPHER-LINE, (I2S DAC, || ADR-0015) class-D amp) || | || speaker / 3.5mm TRS || || 3x 18650 --> Waveshare UPS Module 3S --> 5V/5A rail (whole device || (12.6V via barrel-jack charge in) incl. 7" display) || |+----------------------------------------------------------------------+The topology was revised on 2026-04-24 per ADR-0017 to introduce the Pi Pico 2 coprocessor between the Pi and the realtime peripherals (originally: DMG cartridge bus, I2S audio, SSD1322 OLED). Later that same day, ADR-0019 superseded ADR-0013’s DMG cartridge format with a full-size SD card carried in a custom clamshell sled — read by the Pi via USB mass storage through a card reader bridge IC on the internal USB hub, not through the Pico 2. The Pico 2 retains its audio (I2S to MAX98357A) and CIPHER-LINE OLED responsibilities under ADR-0017; only the cart-bus responsibility moved off the Pico. Pre-ADR-0017 history: the Pi drove SPI0 to the OLED and I2S to the MAX98357A directly. See docs/software/api-reference/grammars/coprocessor-protocol.md for the UART command protocol byte-level spec; the cart-related frame types in that protocol (CART_DETECT, CART_READ_BANK, CART_READ_SRAM, CART_WRITE_SRAM, CART_RESET) are now obsolete under ADR-0019 and are subject to a follow-up cleanup.
Subsystem roles
Section titled “Subsystem roles”| Subsystem | Module | Role | Interface |
|---|---|---|---|
| Compute (primary) | Pi Zero 2 W | Linux userspace, nOSh process, SDL3 rendering, mission board, deck state, Fe VM execution. Sends realtime-I/O commands to the Pico 2 coprocessor over UART0. | Host |
| Coprocessor (realtime I/O) | Pi Pico 2 (RP2350) | Owns YM2149 PSG synthesis with I2S out to MAX98357A and the SSD1322 CIPHER-LINE OLED driver. Accepts high-level commands from Pi over UART0. See ADR-0017 and docs/software/api-reference/grammars/coprocessor-protocol.md. The DMG cartridge bus responsibility originally assigned to the Pico 2 in ADR-0017 was removed by ADR-0019 (cartridge interface moves to a USB-mass-storage SD card via the internal hub bridge IC; the Pico 2 no longer touches the cartridge bus). | UART0 @ 1 Mbps from Pi |
| Display (primary) | Elecrow 7” IPS | Framebuffer surface for SDL3 output | HDMI (mini-HDMI adapter) |
| Display (auxiliary) — CIPHER-LINE | 3.12” SSD1322 OLED (see CLAUDE.md Aux Display row) | Cipher voice surface (exclusive) + utility surfaces (battery, timer, mode, TERM hint, seed capture, mission meta). See ADR-0015. Driven from the Pico 2 SPI bus, not Pi SPI0, per ADR-0017. | 4-wire SPI from Pico 2 |
| Input | Custom mech keeb (RP2040-class QMK controller — Adafruit KB2040 for v0.1, Sea-Picro fallback per ADR-0024) on a custom-fab unified 31-key PCB (preferred) or split-layout PCB reconnected under a single keyplate (fallback). See ADR-0018 (build pattern) and ADR-0024 (controller pin). | 31-key matrix scanner, USB HID keyboard, LIS3DH accelerometer host (ADR-0023) | USB-C HID → internal USB hub → Pi OTG |
| Accelerometer | STMicroelectronics LIS3DH (3-axis MEMS, ±4g, 25 Hz ODR), reflowed on the keyboard PCB next to the keyboard MCU and sharing its I²C bus. See ADR-0023. | Motion-event extraction (peak-magnitude threshold + 4-bucket classifier) on the keyboard MCU; reported to the Pi as a vendor-defined HID report on the existing keyboard interface. Drives the firmware-internal nOSh ambient CRT-glitch system. v1 firmware-only — no cart FFI. | I²C on keyboard MCU; vendor HID report over the same USB HID interface as the keyboard |
| USB hub (internal) | TUSB2036 / FE1.1s or equivalent 2-to-4 port USB 2.0 hub IC on the interior plate | Fans Pi OTG out to keyboard controller (ADR-0018) + USB-to-SD card reader bridge IC (ADR-0019, the cartridge interface) + future internal USB peripherals | USB 2.0 |
| Cartridge interface | Full-size SD card via USB mass storage. Push-push surface-mount SD socket + USB-to-SD card reader bridge IC (e.g., Genesys GL3224 / GL3232, Realtek RTS5129 — specific part TBD per ADR-0019 Open Q §1) on a small internal PCB at the back of the slot. See ADR-0019. | Loads .kn86 cartridges as files from the SD filesystem; per-cartridge save data lives as a file on the same SD. Replaces the v0.1 microSD-resident cartridges and the (now superseded) ADR-0013 DMG/MBC5/edge-connector path. ADR-0019 also removes the cart-bus responsibility from the Pico 2 (ADR-0017 partially superseded). | USB mass storage via internal hub |
| Audio synthesis | Pi Pico 2 (firmware) | YM2149 PSG emulation, envelope generation, atomic register writes (PSG_REG_WRITE / PSG_BULK_WRITE). Pre-ADR-0017 baseline ran on the Pi (emu2149 port, on-CPU); moved to the Pico 2 for deterministic 44.1 kHz output independent of Linux scheduler jitter. Audio + OLED responsibilities remain on the Pico 2 under ADR-0017 even after ADR-0019 removed the cart bus from the Pico’s scope. | Pico 2 firmware → I2S |
| Audio output | MAX98357A | I2S digital-to-analog conversion + class-D amplification | I2S from Pico 2 (was Pi GPIO pre-ADR-0017) |
| Speaker | Round driver (see CLAUDE.md for size / impedance / wattage) | Mono speaker; collapses directional audio when headphones absent | Amp output |
| Audio jack | 3.5mm TRS | Switched jack; inserting a plug disconnects the internal speaker | Amp output passthrough |
| Power | Waveshare UPS Module 3S + 3× 18650 (see CLAUDE.md) per ADR-0038 | One board: charge + cell protection + 5 V/5 A regulation + INA219 battery monitor. 12.6 V barrel-jack charge in; 5 V/5 A rail powers the whole device incl. the 7” display. | 12.6 V barrel input, 5 V rail to Pi + display + amp + hub, INA219 on I²C |
| Storage | microSD | A/B slot layout per ADR-0011, cartridge filesystem, deckstate, saves | microSD socket |
| Case | Pelican 1170 Protector Case + 3D-printed inset panels | See CLAUDE.md for dimensions and material. Off-the-shelf black polypropylene shell; printed PLA/PETG insets carry primary display bezel, CIPHER-LINE bezel (above key plate, per ADR-0015), key plate, cartridge-slot retainer, and port cutouts; Pelican foam is cut to seat components. | — |
Why a USB HID keyboard over direct GPIO matrix
Section titled “Why a USB HID keyboard over direct GPIO matrix”The Zero 2 W’s GPIO header is usable for a key matrix but introduces three problems: (1) it monopolises pins we’d otherwise reserve for I2S and future peripherals; (2) it requires userspace debounce, key-repeat, and hold-detection code that is already solved in stock QMK on any QMK-compatible keyboard controller; (3) it couples key scanning latency to Linux userspace scheduling. Routing the matrix through a QMK-compatible controller that presents as a USB HID keyboard lets us buy all of that for free, and gives us a consistent input surface between the emulator (where a desktop keyboard is the input) and the device (where the keyboard controller enumerates as a keyboard). Per ADR-0018 the keyboard is built as a custom mechanical keyboard using the mech-keeb DIY ecosystem — hot-swap Choc v1 sockets, stock QMK firmware, a QMK-compatible RP2040-class controller (Adafruit KB2040 for v0.1; Sea-Picro fallback) per ADR-0024, and an internal USB hub IC to fan the Pi’s single OTG port out to the keyboard plus the cartridge bridge (ADR-0011). No external USB cables.
Per ADR-0011, the USB HID choice pushes one constraint onto the system image update system: the attention gesture (SYS+LINK held at boot) cannot be detected by an early-boot GPIO scan because the keys are USB HID, not GPIO. The system-image-update gate waits for USB enumeration before scanning. See ADR-0011 “Early-boot key-scan timing” for the full treatment.
Accelerometer (driven via the keyboard MCU per ADR-0023)
Section titled “Accelerometer (driven via the keyboard MCU per ADR-0023)”Per ADR-0023, the KN-86 carries a STMicroelectronics LIS3DH 3-axis MEMS accelerometer reflowed onto the keyboard PCB next to the keyboard MCU and sharing the controller’s I²C bus. Canonical sensor values are in CLAUDE.md’s Accelerometer row.
The host-MCU choice mirrors the keyboard-matrix choice (§“Why a USB HID keyboard over direct GPIO matrix” above): a microcontroller absorbs the real-time peripheral I/O so Linux userspace doesn’t have to. The keyboard MCU samples at 25 Hz, runs a peak-magnitude threshold detector with a 0.4 g floor, classifies each event into one of four magnitude buckets (light / medium / heavy / extreme), and emits a vendor-defined HID report on the existing keyboard interface. The Pi sees discrete motion events plus the bucket — never raw samples. nOSh consumes the events through the firmware-internal ambient CRT-glitch system (off by default; configurable Off / Low / Medium / High; persisted at /home/shared/nosh-config.toml). v1 is firmware-only; no NoshAPI FFI exposes motion to cartridge authors.
Three carve-outs are mandatory and not setting-dependent: (1) when the active cartridge is Marty Glitch, motion-glitches hard-clamp to Off because broadcast-corruption is Marty’s diegetic identity; (2) when the cell runtime raises nosh_set_tempo_critical(true) for ICE Breaker / Drift / Shellfire critical phases, motion-glitches suppress; (3) when a PROMPTS modal, the Lisp REPL, or nEmacs is the focused surface, motion-glitches suppress. Audio frame budget is structurally protected — the Pico 2 coprocessor (ADR-0017) owns the YM2149 audio callback path and the glitch system has no path to it.
The accelerometer’s active draw at 25 Hz ODR is ~11 µA per the LIS3DH datasheet — effectively zero against the post-coprocessor 145–235 mA typical band. No measurable battery-runtime impact at any setting.
Cartridge system
Section titled “Cartridge system”For v0.1 bench-rig builds, cartridges are filesystem entries on the device’s boot microSD — physical cartridges are not yet wired up. The committed cartridge physical format for production is ADR-0019: a full-size SD card carried in a custom two-piece clamshell shell (~58 × 65 × 8 mm), read by the Pi as USB mass storage through a card reader bridge IC on the internal USB hub planned in ADR-0018. Per-cartridge save data lives as a file on the cart’s own SD filesystem; Universal Deck State remains on the device’s microSD per ADR-0011. The .kn86 container format (ADR-0006) and the capability model (ADR-0001, docs/software/runtime/orchestration.md) are unchanged regardless of physical container. ADR-0019 supersedes the earlier ADR-0013 (DMG 32-pin pinout + MBC5 mapper + CR2032-backed on-cart SRAM); the bring-up tasks for the SD-sled cartridge interface are listed in ADR-0019 as CART-01 through CART-07.
CIPHER-LINE auxiliary display (driven via Pi Pico 2 per ADR-0017)
Section titled “CIPHER-LINE auxiliary display (driven via Pi Pico 2 per ADR-0017)”Per ADR-0015, the KN-86 has a second, smaller display — the CIPHER-LINE — mounted above the key plate. It is an SSD1322-driven 256×64 yellow OLED that carries the Cipher voice exclusively (no Cipher glyphs ever render on the primary 80×25 grid) plus a fixed set of utility surfaces (battery, timer, mode chip, TERM hint, seed capture, mission meta). Canonical module values are in CLAUDE.md’s Auxiliary Display row.
Per ADR-0017 (2026-04-24), the SSD1322 panel’s 4-wire SPI bus is driven by the Pi Pico 2 coprocessor — not by the Pi Zero 2 W’s SPI0. The Pi sends high-level OLED commands (OLED_SET_ROW, OLED_SCROLL_ROW, OLED_FILL, OLED_CLEAR) to the Pico over UART0; the Pico runs the SPI bus to the panel and executes the ticker scroll animation autonomously. This keeps the OLED cadence rock-steady regardless of Pi rendering load. The Pi’s SPI0 and SPI1 are freed up for future peripherals.
The Pico’s SPI pin assignment to the SSD1322 is finalised at F2 firmware bring-up (kn86-pico/); the Pico has 26 usable GPIOs and ample SPI flexibility, so any consistent set works. Same applies to the DC and RST control lines.
| Signal | Pico GPIO | Notes |
|---|---|---|
| MOSI | TBD at F2 bring-up | One of Pico’s SPI MOSI-capable pins. |
| SCLK | TBD at F2 bring-up | One of Pico’s SPI SCLK-capable pins. |
| CS | TBD at F2 bring-up | Any GPIO; tied to the Pico’s selected SPI peripheral. |
| DC (data/command) | TBD at F2 bring-up | Any GPIO. |
| RST (reset) | TBD at F2 bring-up | Any GPIO. |
| VCC | 3.3 V | From Pico’s 3V3(OUT) pin. |
| GND | GND | — |
The Pi Zero 2 W and the Pico 2 both have 3.3 V rails, but the SSD1322 module is powered from the Pico’s 3.3 V output now that the SPI lines also originate from the Pico — keeping all OLED-related signals and power on a single ground domain.
3. Power and Battery
Section titled “3. Power and Battery”The KN-86 runs on a single-cell LiPo with USB-C charging. Runtime, battery capacity, and typical current draw values are canonical — see CLAUDE.md Canonical Hardware Specification for the specific numbers. This section covers only the topology.
Power path
Section titled “Power path”12.6 V 2 A -> Waveshare UPS Module 3S -> 5 V / 5 A railbarrel in (3x 18650 in series, |(DC5521) charge + protect + reg, +--> Pi Zero 2 W (5V VIN) onboard INA219) +--> MAX98357A (5V VIN) | +--> Pi Pico 2 (5V VBUS) | +--> Elecrow 7" display (5V in) v +--> internal USB hub IC 3.3 V/300 mA aux out (Pico 3V3 OUT -> CIPHER-LINE OLED, ADR-0015)The Waveshare UPS Module 3S is a single board that subsumes charging, cell protection, and 5 V regulation (per ADR-0038). It charges the 3× 18650 series pack from 12.6 V 2 A on a DC5521 barrel jack (not USB-C) and regulates a stable 5 V / 5 A main rail. It is a true UPS — charge + output run simultaneously, important for the ADR-0011 update flow where the device is attached during flashing. Onboard chips: S-8254AA (protection), SY8286 (5 V reg), HY2213 (balancing), INA219 (monitor), RT9193 (3.3 V reg); protection covers overcharge / over-discharge / overcurrent / short / reverse, and the 18650 holders are reverse-polarity-safe.
The 5 V / 5 A rail powers the entire device, including the Elecrow 7” primary display — the display is no longer on its own v0.1 supply (ADR-0038). Typical 5 V-rail draw with the display active is ~1.5–2 A; the display is the dominant load.
Pi Pico 2 coprocessor (per ADR-0017, post-ADR-0019 scope): the Pico draws from the 5 V rail via VBUS, regulates internally, and drives the CIPHER-LINE OLED off its own 3.3 V output. Active draw at 150 MHz with the realtime workload (PIO state machines for I2S audio output + main-loop OLED ticker; the DMG cart-bus role from ADR-0017 was removed by ADR-0019) is ~25–55 mA typical, dropping to <5 mA in dormant mode. Runtime is display-dominated under ADR-0038: ~4–5 h with the 7” display active, ~10–12 h electronics-only — see CLAUDE.md Battery row. The display-on-battery change is an accepted cost of ADR-0038; mitigations include backlight dim/blank at idle (now the highest-leverage saving), higher-capacity matched 18650 cells, and the Pico dormant-mode gating already in the design. Bring-up at Stage 4 validates the rail draw with the display on and electronics-only.
CIPHER-LINE OLED (per ADR-0015 + ADR-0017): the SSD1322 module pulls ~10–30 mA typical and ~40 mA peak (high-brightness, full-field update). Per ADR-0017 the OLED is powered from the Pico’s 3.3 V output (the SPI lines also originate on the Pico, so power and signal stay on a single ground domain). The OLED’s own draw is unchanged.
Low-battery behaviour
Section titled “Low-battery behaviour”Battery state is read from the UPS module’s onboard INA219 over I²C (voltage/current/power) per ADR-0038 — this replaces the prior resistor-divider + MCP3008 ADC plan. nOSh polls at ~1 Hz and derives state-of-charge from the 3S pack voltage (9.0–12.6 V). It displays a low-battery glyph in the status bar (Row 0) below a threshold, writes a best-effort deckstate checkpoint near the end of useful capacity, and initiates a clean shutdown before the UPS module’s S-8254AA protection circuit cuts power.
Idle behaviour
Section titled “Idle behaviour”Idle power savings on Zero 2 W are modest compared to a bare-metal MCU — the Linux kernel cannot reach deep sleep without framebuffer and USB-gadget teardown. nOSh implements a soft idle: dim or blank the Elecrow backlight (now the highest-leverage saving since the display is the dominant load under ADR-0038), pause PSG audio output, reduce the SDL render cadence, and let the kernel idle the CPU. Any HID event wakes the full rendering path.
4. Assembly Plan
Section titled “4. Assembly Plan”v0.1 is a bench-rig build, not a production-grade assembly. The plan is deliberately linear — no parallelised workstreams, no custom fab dependencies.
Stage 0 — Bring-up
Section titled “Stage 0 — Bring-up”- Flash a blank microSD per the ADR-0011 partition layout (use
tools/sd-provision/provision.shonce Wave 2 lands; manually partition otherwise). - Boot the Zero 2 W headless, verify network over Wi-Fi, SSH in.
- Install the kn86 userspace (scp from dev box, per ADR-0011 “Dev ergonomics”).
Stage 1 — Display (primary)
Section titled “Stage 1 — Display (primary)”- Power the Elecrow 7” IPS from the KN-86 main 5 V rail (Waveshare UPS Module 3S, per ADR-0038 — the display is on the battery; Stage 4 brings up the rail). For an early display-only bench check before Stage 4, a temporary bench 5 V supply is acceptable, but the committed topology powers the display from the main rail.
- Connect mini-HDMI from the Pi to the Elecrow input.
- Edit
/boot/config.txtto force HDMI at the native resolution (see CLAUDE.md for the target) and disable HDMI compensation modes. - Boot, verify SDL3 can render at the intended framebuffer size, and verify the text grid lays out correctly with the Row 0 / Row 24 firmware-reserved rows as specified in CLAUDE.md Canonical Hardware Specification.
Stage 1b — Display (auxiliary, CIPHER-LINE)
Section titled “Stage 1b — Display (auxiliary, CIPHER-LINE)”Added per ADR-0015. Per ADR-0017 (2026-04-24), the SSD1322 SPI bus is now driven by the Pi Pico 2 coprocessor — not by the Pi’s SPI0. Run Stage 1c (below) first to bring up the Pico, then complete this stage with the OLED wired to the Pico’s SPI pins (TBD at F2 firmware bring-up). The validation goals below — panel wakes, glyph rendering, layout test, brightness measurement — are unchanged; only the SPI host and the device-tree-overlay step are obsolete.
- Wire the SSD1322 3.12” 256×64 OLED module to the Pi Pico 2’s SPI header (per ADR-0017; specific Pico GPIOs finalised at F2 firmware bring-up). Use short jumper leads with Dupont header connectors for v0.1; a JST-PH harness is a later polish pass. The pre-ADR-0017 wiring (Pi GPIO10/11/8/25/24) is no longer applicable.
- Pi-side SPI0 device-tree-overlay enablement is no longer required for CIPHER-LINE — the Pi does not drive the OLED bus. Free SPI0 on the Pi remains available for a future peripheral.
- Run the SSD1322 init sequence from the driver shipped with nOSh — confirms the panel wakes, accepts the oscillator / GPIO / segment-remap configuration, and responds to a framebuffer write. v0.1 uses 8 bpp grayscale mode on the SSD1322 with a single-level palette (monochrome yellow, matching the amber aesthetic); later firmware revisions may exploit the SSD1322’s 16-level grayscale for CIPHER-LINE typewriter fade transitions.
- Render the four-row test layout described in ADR-0015 §Layout: status strip on Row 1, Cipher scrollback on Rows 2–3, contextual surface on Row 4. Verify the Press Start 2P 8×8 glyphs read at normal sight distance from the operator’s typical hand position.
- Measure the 3.3 V rail current with CIPHER-LINE idle and with a full-field update cycle. Record the measurement against the 10–30 mA typical / 40 mA peak estimate in §3 Power. If real draw exceeds the peak estimate by a material margin, flag the CLAUDE.md Battery row for re-evaluation per ADR-0015 Known Unknown #3.
- With CIPHER-LINE physically in hand, measure the bezel cutout dimensions against the printed inset panel CAD; update the panel CAD as needed. Bezel cutout dimensions are flagged TBD in ADR-0015 Known Unknown #2 until this step completes.
Stage 1c — Coprocessor (Pi Pico 2)
Section titled “Stage 1c — Coprocessor (Pi Pico 2)”Added per ADR-0017. Although this stage is presented after Stage 1b for chronological reasons (1b landed with ADR-0015, 1c lands with ADR-0017), the Pi Pico 2 must be flashed and the UART handshake verified BEFORE Stage 1b’s OLED bring-up can complete post-ADR-0017. Run 1c first in practice.
- Mount the Pi Pico 2 (RP2350) on the internal sub-board alongside the Pi Zero 2 W. Power the Pico from the 5 V rail via its VBUS pin; common ground with the Pi.
- Wire UART0 between Pi and Pico: Pi GPIO14 (TX) → Pico GPIO1 (RX); Pi GPIO15 (RX) ← Pico GPIO0 (TX); common ground. Wire Pi GPIO22 → Pico BOOTSEL and Pi GPIO23 → Pico RESET for the Pi-mediated firmware update flow (per ADR-0017 §6).
- Wire the Pico’s peripheral pins (specific GPIOs finalised at F2 firmware bring-up, see
kn86-pico/):- SPI bus to the SSD1322 OLED — see Stage 1b above.
- I2S output to the MAX98357A — overrides the Pi-side I2S routing referenced in Stage 2 below.
- (Cart-bus pins are not used.) Per ADR-0019, the cartridge interface is a USB-MSC SD card reader on the internal hub — not on the Pico. The DMG-cart-bus role originally assigned to the Pico in ADR-0017 was removed by ADR-0019; the Pico’s PIO state machines and GPIO budget cover I2S + OLED with comfortable headroom.
- Flash the Pico firmware (
kn86-pico/, F2 deliverable) using the Pi-mediated bootmode flow described in ADR-0017 §6: the Pi pulses BOOTSEL, asserts RESET, releases RESET, copies the UF2 image to the Pico’s USB-MSC mount, then resets into the new firmware. The first prototype build can also use direct USB-attachedpicotool loadfrom the dev box for faster iteration. - Verify the UART handshake. Power-cycle the Pi; nOSh sends
HELLOand expects aHELLOreply with the Pico’s role byte set, followed byVERSION_QUERY/VERSION_RESPONSE. If the handshake fails within 1 s of nOSh start, debug per the §5.3 bootstrap sequence indocs/software/api-reference/grammars/coprocessor-protocol.md. Successful handshake leaves the linkoperational; nOSh begins periodic heartbeats per Coprocessor Protocol §5.2. - Joint power measurement. Measure the 5 V rail draw with the Pico active, audio output enabled (e.g. PSG playing a steady tone via
PSG_REG_WRITE), and the CIPHER-LINE OLED ticker animating. Record against the ~25–55 mA Pico-side estimate in §3 Power. If joint draw exceeds the post-coprocessor envelope (~235 mA typical) by a material margin, escalate to Josh — the CLAUDE.md Battery row and ADR-0017’s Trade-off Analysis get revisited. - Cartridge bus verification at this stage is no longer applicable — the cartridge is a USB-MSC SD card mounted by the Pi via the internal hub bridge IC (ADR-0019), not driven by the Pico. End-to-end cartridge bring-up is covered by the SD-sled stage (
udevinsertion event → mount →.kn86cart load) called out in the cartridge-interface row of the §2 Subsystem Roles table; see ADR-0019 CART-01 through CART-07 for the bring-up checklist.
Stage 2 — Audio
Section titled “Stage 2 — Audio”Per ADR-0017, the MAX98357A I2S DAC/amp is driven by the Pi Pico 2 coprocessor — not the Pi. Run Stage 1c first to bring up the Pico; this stage’s wiring and validation use the Pico-side I2S.
- Solder the MAX98357A breakout to three Pico 2 GPIO pins for I2S (BCK / LRCK / DIN) plus 5 V (from the shared 5 V rail) and GND. Specific Pico GPIOs are finalised at F2 firmware bring-up — the Pico has dedicated PIO state machines for the I2S output. Pre-ADR-0017 wiring (Pi GPIO I2S pins +
hifiberry-dacdevice-tree overlay) is no longer applicable. - Pi-side device-tree audio overlay is no longer required — the Pi does not generate audio. The
hifiberry-dacoverlay step from earlier revisions is obsolete. - Wire the speaker and 3.5 mm TRS jack to the amp’s differential outputs. The TRS jack has a normally-closed contact that disconnects the speaker when a plug is inserted. Unchanged from pre-ADR-0017.
- Test-play a YM2149 reference pattern: have nOSh issue
PSG_REG_WRITEframes over UART to set up channel A with a steady tone (e.g. 440 Hz square), thenPSG_RESETto silence. The full synth-to-speaker chain is validated by clean audio output and clean silence on reset. End-to-end audio latency target is <30 ms (per ADR-0017 §Known Unknowns #5; Coprocessor Protocol §7).
Stage 3 — Input
Section titled “Stage 3 — Input”Per ADR-0018, the 31-key input is built as a custom mechanical keyboard. The exact controller part, PCB path (unified custom-fab vs. split-reconnected), and internal USB hub IC are selected by the hardware agent during bring-up; the steps below apply to either PCB path.
- Fab or acquire the 31-key PCB per ADR-0018 Option B (custom-fab unified) or Option C (split-reconnected). Populate with Kailh Choc v1 hot-swap sockets, 1N4148 diodes, the LIS3DH accelerometer (ADR-0023), and the Adafruit KB2040 RP2040-class controller per ADR-0024 (Sea-Picro is the named fallback if KB2040 supply contracts).
- Flash stock QMK with the 31-key keymap (
firmware/kn86-keyboard/keymap.cor the controller’s equivalent) perdocs/software/runtime/input-dispatch.md§3. - Mount the internal USB hub IC (TUSB2036, FE1.1s, or equivalent) on the interior plate. Wire the hub’s upstream port to the Pi Zero 2 W’s OTG port and a downstream port to the keyboard controller.
- Install 31 Choc v1 switches in the hot-swap sockets; install MBK keycaps (blank in v0.1; legends are a polish pass).
- Verify
/dev/input/event*enumerates on the Pi and all 31 keys register correctly. Confirm debounce behaviour and the 1.75U EVAL bar registers on a single switch event.
Stage 4 — Power
Section titled “Stage 4 — Power”Per ADR-0038, the power subsystem is a single Waveshare UPS Module 3S on 3× 18650 cells.
- Seat 3× genuine matched 18650 cells in the UPS module’s reverse-polarity-safe holders; confirm orientation before powering.
- Wire the UPS module’s 5 V / 5 A output to the Pi + amp + Pico 5 V rails, the internal USB hub, and the Elecrow 7” display (the display is now on the main rail).
- Wire the Pi’s I²C bus to the UPS module’s INA219; verify nOSh reads voltage/current/power and derives state-of-charge for the Row-0 battery glyph.
- Expose the 12.6 V DC5521 barrel jack on the Pelican shell edge via a panel-mount connector. The Pelican wall is drilled only for the panel-mount connector; no structural modification. Verify charging from a 12.6 V 2 A adapter while the device runs (true-UPS charge + output).
- Resolve the on/off control mechanism against the UPS module (TBD per ADR-0038 §Decision item 8 — the prior latching slide switch on a PowerBoost rail is removed).
- Measure rail draw under typical load with the display on and electronics-only; confirm both fall within the CLAUDE.md Battery-row bands.
Stage 5 — Enclosure
Section titled “Stage 5 — Enclosure”- Design and print the inset panels in PLA or PETG (material TBD during bring-up; both are cheap enough to test): a lid panel carrying the Elecrow display bezel and a Kinoshita wordmark deboss; a base panel carrying the key plate, the CIPHER-LINE bezel cutout mounted above the key plate (per ADR-0015), the cartridge-slot opening sized for the SD-sled shell (~60 × 10 mm per ADR-0019, with an internal pocket for the SD-socket PCB at the back of the slot), and port cutouts; and any interior brackets needed to seat the Pi, amp board, battery, CIPHER-LINE OLED module, and SD-socket PCB. Panels fit the Pelican 1170 interior envelope (see CLAUDE.md for dimensions). Slot depth budget: shell depth (~65 mm) + SD socket depth + PCB clearance, against the 80 mm interior depth — verify against the rest of the component layout (battery, speaker, amp, Pi mounting pocket).
- Cut the Pelican foam to seat the Pi Zero, the Waveshare UPS Module 3S, the 3× 18650 cell holder, amp, speaker, and the cell pack in the base; cut the lid foam to accept the primary display module behind the bezel panel. The CIPHER-LINE module seats in a base-panel-side pocket behind its bezel cutout. The Pelican shell itself is never machined or modified. (The 3× 18650 holder takes more interior volume than the prior LiPo pouch — verify the fit against the ~80 mm interior depth, per ADR-0038.)
- Heat-set M2.5 brass inserts into the printed inset panels for screw mounts.
- Fit components into the foam cavities and fasten the panels over them. Route the HDMI ribbon, audio leads, and the CIPHER-LINE SPI harness between base and lid along the Pelican hinge line with service slack so the case can open and close without strain.
- Latch the case closed and run a full first-boot sequence end-to-end — verify both the primary display and CIPHER-LINE come up cleanly.
What v0.1 intentionally defers
Section titled “What v0.1 intentionally defers”- Custom PCB. All interconnects are off-the-shelf modules on an interior plate with JST-PH harnesses.
- Keycap legends. v0.1 can ship with blank MBK keycaps; UV-printed legends are a polish pass.
Elecrow power integration.No longer deferred — per ADR-0038, the 5 V/5 A Waveshare UPS rail powers the display directly. The display is on the main rail from v0.1.- Cartridge physical format. Cartridges are microSD-resident filesystem objects in v0.1; the production cartridge format (full-size SD card in a custom two-piece clamshell shell, read via USB mass storage through a card reader bridge IC on the ADR-0018 internal hub) is committed as ADR-0019 and lands in a future bring-up wave (see ADR-0019 §“Follow-on work” — CART-01 through CART-07).
5. Developer-mode vs. Production-mode
Section titled “5. Developer-mode vs. Production-mode”Both modes ship the same nOSh binary and the same kn86 filesystem. The difference is a single boot-time flag read from /boot/kn86-mode.txt (FAT32 partition p1 per ADR-0011), with these effects:
| Concern | Developer mode | Production mode |
|---|---|---|
| nEmacs REPL access | Enabled. The on-device Lisp REPL and structural editor are reachable through the nEmacs UX described in ADR-0008. | Disabled. The REPL is unreachable from normal navigation; editing is read-only. |
| Filesystem access from nEmacs | Read and write access to /home/shared and any mounted cartridge. | Read-only on everything except the deckstate writer path (owned by nOSh, not by the Lisp surface). |
| Serial console on GPIO UART | Enabled. Easy debugging from the bench rig. | Disabled. Header pins are still present but no getty is attached. |
| SSH access over Wi-Fi | Enabled. This is the daily driver for dev iteration — see ADR-0011 “Dev ergonomics”. | Disabled. SSH service is masked; Wi-Fi is still used for time sync and OTA updates. |
| Firmware update system | Same as production. ADR-0011 update flow (USB-MSC, A/B tryboot, desktop flasher) works identically. | Same as production. |
| Power / audio / display topology | Identical. | Identical. |
Why a single binary
Section titled “Why a single binary”Two binaries (debug and release) would drift. The mode flag is a narrow, well-audited boundary: nOSh reads it once at start-up, clamps a handful of privileged operations behind it, and never re-reads it during the session. Mode transitions happen only at power-cycle.
Switching modes
Section titled “Switching modes”- Dev → Prod: edit
/boot/kn86-mode.txt(either in-place on a mounted SD or via the updater MSC mount). Reboot. - Prod → Dev: physically access the SD, edit the file, reboot. No in-device path — production mode cannot re-enable itself into dev mode without SD access. That physical-access barrier is deliberate.
6. References
Section titled “6. References”- CLAUDE.md Canonical Hardware Specification — single source of truth for all concrete hardware values (processor, primary display, auxiliary display, text grid, font, colour, display modes, keys, audio chip, speaker, battery, case, ship target). Every spec value in this document is a reference to that table.
docs/adr/ADR-0011-device-firmware-update-system.md— system image update architecture (Draft; scheduled for Wave 2 implementation). Covers SD partition layout,.kn86fwformat, updater image, attention gesture, A/B tryboot, and desktop flasher.docs/adr/ADR-0015-cipher-line-auxiliary-display.md— CIPHER-LINE auxiliary OLED (SSD1322 3.12” 256×64), Cipher-exclusivity boundary, NoshAPI primitives. Source for this document’s Stage 1b and the §2 CIPHER-LINE subsection. (Per ADR-0017, the SPI driver path moved from Pi to Pico — see ADR-0017 reference below.)docs/adr/ADR-0017-realtime-io-coprocessor.md— Pi Pico 2 (RP2350) realtime I/O coprocessor for YM2149 PSG synthesis and SSD1322 OLED driver. (The DMG cartridge bus role originally part of ADR-0017 was removed by ADR-0019; cartridges are now USB-MSC SD cards on the internal hub.) Source for the post-coprocessor topology diagram in §2, the Coprocessor row in the Subsystem Roles table, the §3 power-draw delta, and Stage 1c. Companion:docs/software/api-reference/grammars/coprocessor-protocol.md(UART command protocol byte-level spec).docs/software/api-reference/grammars/coprocessor-protocol.md— Pi ↔ Pico UART wire-format spec. Frame layouts, error codes, session lifecycle, audio latency budget. F1 deliverable of ADR-0017.docs/adr/ADR-0018-custom-mechanical-keyboard-build.md— custom mechanical keyboard build for the 31-key input subsystem; source for the Input row in the Subsystem Roles table and the keyboard-controller / hub references in this doc.docs/device/hardware/sourcing-guide.md— BOM, suppliers, lead times, cost summary, sourcing risks.docs/software/runtime/input-dispatch.md— 31-key layout, matrix, event model, hold detection.docs/software/runtime/orchestration.md— software model that the hardware hosts.docs/_archive/hardware/KN-86-Modern-Build-Specification.md— archived prior-era build spec (superseded by this document; retained for historical context only, do not edit).docs/_archive/adr/ADR-0003-firmware-update-mechanism.md— archived prior-era system image update exploration (superseded by ADR-0011; retained for historical context only).