Skip to content

Audio

Spec hygiene (CLAUDE.md rule 1). This document does not restate canonical values (sample rate, register count, speaker spec). Those live in CLAUDE.md’s Canonical Hardware Specification. Any value inline is a bug — fix it.


The KN-86’s audio chain produces YM2149 PSG-style synthesis (3 tone channels + noise + envelope generator, 14-register Yamaha programming model — software emulation, not original silicon) at 44.1 kHz mono PCM, output through a class-D I2S DAC/amp into a single mono speaker with a switched 3.5 mm TRS jack for headphones.

For canonical chip family, channel count, register count, sample rate, and speaker spec, see CLAUDE.md Canonical Hardware Specification — Audio + Speaker rows.


nOSh (Pi) --UART PSG_REG_WRITE--> Pi Pico 2 firmware
|
| YM2149 emulator
| (full register state +
| envelope + LFSR noise)
|
v
I2S out (PIO + DMA, 44.1 kHz mono PCM)
|
v
MAX98357A
(I2S DAC + class-D amp)
|
+-------------+
|
v
3.5 mm TRS jack (switched)
|
plug inserted? -- no --> 28 mm 8 Ω 2 W speaker
|
yes
|
v
headphones (speaker disconnected)

Per ADR-0017, PSG synthesis runs as firmware on the Pi Pico 2, not as a userspace process on the Pi:

  • Pico maintains the full YM2149 register state (14 registers, envelope generator, LFSR noise).
  • Pi sends register-write commands over UART (PSG_REG_WRITE, PSG_BULK_WRITE, PSG_RESET — see software/api-reference/grammars/coprocessor-protocol.md).
  • Pico applies them and continues generating samples at 44.1 kHz.
  • Output to the MAX98357A via PIO-driven I2S + DMA.

Why Pico-side, not Pi-side. The argument for Pi-side was “an A53 @ 1 GHz is overkill for a 1 MHz logic chip’s worth of synthesis.” The argument for Pico-side won: synthesis cost isn’t the issue — output cadence is. A 44.1 kHz I2S sample stream cannot underrun. Once Pi rendering pressure rises (Clip playback, algorithmic art, large bitmap blits), the audio thread loses scheduling slots and underruns become the failure mode. Dedicated silicon eliminates the failure mode by construction.

In the desktop emulator, PSG synthesis stays in the runtime (runtime/src/psg.c) and routes through the in-process coproc.c stub — same FFI surface, no real Pico.


Adafruit MAX98357A I2S DAC/amp breakout. Single-chip I2S receiver + ΔΣ DAC + class-D amplifier. Drives 8 Ω speakers up to ~3 W from a 5 V rail; we operate it well under that ceiling at 2 W into the 28 mm 8 Ω speaker.

SignalFromNotes
BCLKPico 2 GPIO (TBD at F2 firmware bring-up)Bit clock.
LRCLK / WSPico 2 GPIO (TBD at F2 firmware bring-up)Word select / left-right clock.
DINPico 2 GPIO (TBD at F2 firmware bring-up)Serial data.
VIN5 V rail (shared with Pi VIN)See power.md.
GNDCommon groundCommon ground domain with Pi + Pico.

The pre-ADR-0017 wiring (Pi GPIO I2S pins + hifiberry-dac device-tree overlay) is superseded. Pi-side audio device-tree overlay is no longer required — the Pi does not generate audio. Specific Pico GPIOs are finalised at F2 firmware bring-up — TBD, will live with the Pico 2 coprocessor firmware under hosts/device/firmware/ in the kn-86 monorepo.


  • Speaker — 28 mm round driver, 8 Ω, 2 W. Mono. Mounts in a base-panel pocket behind a small grille cutout (see enclosure.md).
  • 3.5 mm TRS PCB-mount jack — switched. Inserting a plug breaks a normally-closed contact and disconnects the internal speaker so headphones get clean output without parallel-driving the speaker. The jack and speaker are wired off the MAX98357A’s amp output; the switch is a passive mechanical contact in the jack, not a runtime decision.

A 3.5 mm TRRS PCB-mount 4-pole jack (BOM line 16) handles linked-play between two decks — separate from the headphone jack.


End-to-end audio latency (nOSh-issued PSG register write → audible tone): target <30 ms (ADR-0017 Known Unknown #5; software/api-reference/grammars/coprocessor-protocol.md §7).

Dominated by:

  • UART transit at 1 Mbps — hundreds of µs.
  • Pico command processing — tens of µs.
  • I2S output buffer depth — configurable; 5–20 ms typical.

Bring-up at Stage 1c measures real round-trip and either confirms the budget or escalates.


Audio current draw is part of the post-coprocessor envelope on the main 5 V rail (Pi + Pico + MAX98357A all draw from it). See power.md for the full envelope and CLAUDE.md Battery row for the runtime band. The MAX98357A is efficient class-D — typical draw scales with output volume; quiet output is single-digit mA.


The MAX98357A breakout mounts on the interior plate near the speaker. The speaker mounts in a base-panel pocket; the TRS and TRRS jacks are panel-mount through cutouts in the base panel. See enclosure.md.


Stage 2 in build-specification.md §4. Run Stage 1c first (coprocessor.md) — the Pico must be alive before audio can be brought up against its I2S output.

  1. Solder the MAX98357A breakout to three Pico 2 GPIO pins for I2S (BCLK / LRCLK / DIN) plus 5 V (shared 5V rail) and GND. Specific Pico GPIOs finalised at F2.
  2. Wire the speaker and 3.5 mm TRS jack to the amp’s differential outputs. The TRS jack’s normally-closed contact disconnects the speaker on plug insert.
  3. Test-play a YM2149 reference pattern: nOSh issues PSG_REG_WRITE frames over UART to set up channel A with a steady tone (e.g. 440 Hz square), then PSG_RESET to silence. Validate clean audio + clean silence on reset.

A separate non-PSG path — short PCM sound clips for distinct moments — is documented at software/runtime/pcm-voice-bark.md. PCM voice bark shares the MAX98357A output stage but bypasses the YM2149 emulator on the Pico (PCM samples DMA’d straight to I2S).


BOM lines in sourcing-guide.md:

  • 13 — Adafruit MAX98357A I2S DAC/amp breakout, 1× ($10). Adafruit direct (clones on Amazon/AliExpress vary in quality — characterise against an Adafruit reference before substituting).
  • 14 — 28 mm round speaker, 8 Ω, 2 W, 2× ($3 ea). Amazon 6-pack or eBay.
  • 15 — 3.5 mm TRS PCB-mount switched stereo jack, 2× ($1 ea). Adafruit / Amazon.
  • 16 — 3.5 mm TRRS PCB-mount 4-pole jack (linked-play), 1× ($1). Adafruit.