ADR-0054: Audio subsystem — WM8960 stereo codec, 2″ full-range speaker, canonical headphone jack
Context
Section titled “Context”The prior KN-86 audio chain was a MAX98357A mono I2S DAC + class-D amplifier driving a 28 mm round driver, 8 Ω, 2 W, mono. YM2149 PSG synthesis runs on the Pi Pico 2 coprocessor (per ADR-0017); the Pico streams 16-bit PCM to the MAX98357A over I2S. The MAX98357A is strap-pin configured — gain and channel are set by hardware straps, so the chip needs no I²C register configuration.
A 3.5 mm switched TRS headphone jack existed only in the bench plan and was explicitly marked non-canonical pending Josh’s sign-off (the “Spec reconciliation” caveat in device/hardware/audio.md). The parent canonical-spec.md Canonical Hardware Specification did not carry it.
Two things motivated a rethink now:
- Better on-device sound. A 28 mm, 2 W driver is small and thin-sounding. A larger full-range driver gives the built-in speaker meaningfully more body and SPL headroom in a handheld the size of a Pelican 1170.
- A real stereo path on headphones. The realistic default for a portable deck is screen-on / sound-off — audio is a layer, not a requirement (cf. the DEPTHCHARGE de-hype, merged: DEPTHCHARGE no longer requires stereo-by-ear). But when an operator does plug in headphones, a codec that drives both a speaker amp and a stereo headphone amp gives a proper stereo image off one chip, and promotes the headphone jack from bench-only to a committed product surface.
Constraints
Section titled “Constraints”- Built-in audio stays mono — one internal speaker. Two drivers ~10 cm apart in a handheld give almost no stereo image, so on-device stereo is not worth the space.
- The Pico owns the audio path (I2S out per ADR-0017). Any new codec-config duty (I²C) should stay on the coprocessor so the whole audio chain lives on one MCU, unless bring-up finds a reason to move it to the Pi.
- The 18650 pack is the dominant space claim in the Pelican interior (ADR-0038); a deeper speaker must not fight it.
Decision
Section titled “Decision”Replace the MAX98357A + 28 mm 8 Ω 2 W mono speaker with a WM8960 stereo codec driving one Gikfun 2″ (≈50 mm) full-range 4 Ω 5 W driver for built-in mono audio, plus a canonical 3.5 mm switched stereo headphone jack off the codec’s headphone-amp output.
Concrete commitments:
- Speaker: one Gikfun 2″ (≈50 mm) full-range driver, 4 Ω, 5 W, single (mono built-in). Sourced as the Amazon Gikfun EK1949 pack of 2 — the device uses one; the second is a spare. Built-in audio remains mono (one driver).
- Codec/amp: WM8960 stereo codec. One chip provides a stereo DAC + a ~1 W class-D speaker amplifier + a stereo headphone amplifier. It is fed I2S by the Pico 2 (same I2S source as before). Unlike the strap-pin MAX98357A, the WM8960 requires I²C register configuration. The I²C master (Pi vs Pico) and the codec’s I²C address are finalized at bring-up; the expectation is that the Pico owns the I²C link to keep the whole audio path on the coprocessor, but this ADR does not hard-commit the master.
- Headphone jack: canonical. The 3.5 mm switched TRS jack — previously bench-only and non-canonical — is now canonical, wired stereo off the WM8960’s headphone-amp output. The built-in speaker auto-cuts when a plug is inserted (switched-jack normally-closed contact and/or the codec’s jack-detect — the exact mechanism is finalized at bring-up).
- The audio path is stereo-capable: mono sum to the built-in speaker, stereo to the headphone jack. (Optional per-voice PSG panning / ABC-ACB “Turbosound”-style stereo on the Pico mixer is possible but deferred — not required by any launch cart; see Consequences.)
Options considered
Section titled “Options considered”Option A: 2× MAX98357A driving two speakers for on-device stereo
Section titled “Option A: 2× MAX98357A driving two speakers for on-device stereo”Keep the MAX98357A family, add a second amp + second driver, get stereo on the built-in speakers.
Rejected because: two drivers ~10 cm apart in a handheld produce almost no perceptible stereo image, and the 2″ driver is ~25 mm deep — a second one doubles a space claim that already fights the 18650 pack (ADR-0038). The cost (board area, BOM, mechanical volume) buys a stereo effect the operator cannot hear at handheld distance.
Option B: Keep the MAX98357A for the speaker + a separate dedicated stereo DAC/headphone-amp for the jack
Section titled “Option B: Keep the MAX98357A for the speaker + a separate dedicated stereo DAC/headphone-amp for the jack”Retain the strap-pin MAX98357A for the built-in speaker, add a second dedicated stereo DAC + headphone amplifier just for the jack.
Rejected because: two chips and more board area to deliver what one codec delivers. The single-chip WM8960 (speaker amp + stereo headphone amp + stereo DAC) wins on integration even though its speaker amp is lower-power than the MAX98357A’s.
Option C: TAS5805M / TAS5825M stereo I²S DSP amplifier
Section titled “Option C: TAS5805M / TAS5825M stereo I²S DSP amplifier”A modern stereo class-D I²S amp with onboard DSP.
Rejected because: these parts are 20–30 W into a hungry PVDD rail — massive overkill for a 2″ full-range driver in a battery handheld, and they still don’t integrate the headphone-amp path the codec gives for free.
Option D: WM8960 stereo codec (CHOSEN)
Section titled “Option D: WM8960 stereo codec (CHOSEN)”One chip = stereo DAC + ~1 W class-D speaker amp + stereo headphone amp, fed I2S by the Pico, configured over I²C.
Chosen because: it collapses the built-in speaker amp and the stereo headphone path into a single part, gives a genuine stereo image where stereo is actually audible (headphones), and keeps the audio chain on the existing Pico I2S source. The accepted cost is a lower speaker-amp ceiling (~1 W vs the MAX98357A’s ~3.2 W) and a new I²C config duty — both acceptable for a handheld (see below).
Trade-off Analysis
Section titled “Trade-off Analysis”The WM8960’s speaker amplifier is ~1 W, quieter than the MAX98357A’s ~3.2 W into 8 Ω. This is the honest cost of the codec choice. It is acceptable because (1) the realistic default for the deck is screen-on / sound-off — built-in audio is a layer, not a headline feature; (2) the larger 2″ 4 Ω full-range driver is more efficient and fuller-sounding than the old 28 mm 8 Ω driver, which partly offsets the lower amp power; and (3) the win the codec buys — a real stereo headphone path from a single chip — is where audio quality actually matters for a solo operator. Against Options A/B/C, WM8960 is the only one-chip path to both a built-in speaker amp and a stereo headphone amp, and it reuses the existing Pico I2S source. The new I²C config step is a few lines of init and ~2 Pico pins; trivial against the integration it buys.
Consequences
Section titled “Consequences”Positive
Section titled “Positive”- One chip does speaker + stereo headphones. Stereo DAC + class-D speaker amp + stereo headphone amp in a single WM8960 — fewer parts than a MAX98357A-plus-separate-headphone-amp split.
- Real stereo where it’s audible. The headphone jack is stereo off the codec’s dedicated headphone amp — a proper image for a solo operator, versus a meaningless on-device stereo pair.
- Bigger, fuller built-in speaker. The 2″ full-range 4 Ω driver has more body and SPL headroom than the 28 mm 8 Ω driver.
- Headphone jack is now canonical. The bench-only, non-canonical jack becomes a committed product surface — the
audio.md“Spec reconciliation” caveat is retired. - Audio chain stays on the Pico. Same I2S source; the codec is fed by the same coprocessor path (ADR-0017).
Negative / accepted costs
Section titled “Negative / accepted costs”- Lower speaker-amp power. WM8960’s speaker amp is ~1 W vs the MAX98357A’s ~3.2 W — quieter built-in audio. Accepted for a handheld where sound is a layer.
- New I²C config duty. The WM8960 must be configured over I²C at init (register setup), where the MAX98357A needed none. This adds an I²C master duty (~2 pins) — expected on the Pico.
coprocessor-firmware.md’s “No I²C config required” statement becomes false and is corrected. - Pico pin budget grows slightly. The Pico gains an I²C master (~2 pins) for codec config on top of the I2S output pins. The pin budget is still fine, but the Pico pin map (I2S + I²C) must be frozen before soldering.
- Mechanical re-check. The 2″ / ~25 mm-deep driver is larger and deeper than the 28 mm driver — its seat in the base-panel speaker pocket and its clearance against the 18650 pack are confirmed at bring-up (
enclosure.md). - Electrical load change. 4 Ω (was 8 Ω) matches the codec/amp; higher current per watt, but low absolute in this envelope.
Follow-on work this ADR creates
Section titled “Follow-on work this ADR creates”- Stereo-capable path, panning deferred. The path is now stereo-capable (mono sum to speaker, stereo to headphones). Per-voice PSG panning / ABC-ACB “Turbosound”-style stereo on the Pico mixer is a deferred possibility, not specified here and not required by any launch cart.
- Freeze the Pico pin map (I2S + I²C) before hard-soldering the codec.
- Re-measure amp draw for the power envelope (ADR-0038) — WM8960 draw differs from the MAX98357A.
Documentation Updates (REQUIRED — part of the decision, not aspirational)
Section titled “Documentation Updates (REQUIRED — part of the decision, not aspirational)”Per canonical-spec.md Spec Hygiene Rule 3, this ADR lands with every dependent doc updated in the same PR:
-
docs/adr/README.md— add ADR-0054 to the index (Status: Accepted 2026-07-02). -
docs/device/hardware/audio.md— remove the “Spec reconciliation” non-canonical-jack caveat; update Role, signal-chain diagram, the MAX98357A section (→ WM8960 with I²C config + BCLK/LRCLK/DIN + SDA/SCL lines), Speaker-and-jack section, Power note, Mechanical note, Bring-up, PCM-voice-bark note, and Sourcing lines. -
docs/device/hardware/build-specification.md— topology ASCII diagram, Audio-output + Speaker + Coprocessor + Audio-synthesis table rows, power ASCII diagram, and Stage-2 audio bring-up prose (WM8960 + I²C config step; I2S pins plus I²C). -
docs/device/hardware/sourcing-guide.md— BOM lines 13/14 (WM8960 codec breakout; Gikfun 2″ 4 Ω 5 W, qty 1 + 1 spare), intro paragraph, and vendor/order-plan mentions. -
docs/device/os/coprocessor-firmware.md— ASCII diagrams + prose (I2S out target → WM8960); critical: the “No I²C config required” statement is corrected — the WM8960 requires an I²C control link for register setup. -
docs/device/os/kiosk-mode.md— “MAX98357A DAC/amp” → WM8960 codec. -
docs/device/os/power-idle.md— the two amp power-table rows → WM8960 (part relabeled; draw figures marked validate-at-bring-up). -
docs/_meta/definitive-articles.md— the one-line audio summary → WM8960 codec + Gikfun 2″ 4 Ω 5 W speaker + 3.5 mm stereo headphone jack. -
docs/definitive-guide.md— the audio summary line → WM8960 codec. -
docs/marketing/voice-bark-recording-guide.md— “28mm speaker” size tokens → “2″ speaker”; MAX98357A chip name → WM8960 (recording/acoustic guidance unchanged). -
docs/plans/2026-07-02-oled-8080-bench-bringup.md(deleted 2026-07-29; recover from git history) — MAX98357A chip-name mentions → WM8960. -
docs/research/KN-86-DOS-Easter-Egg-Research.md— MAX98357A chip-name mention → WM8960. - Secondary current-state references swept (same MAX98357A/28 mm → WM8960/Gikfun 2″ correction, current/forward-state only; frozen ADR bodies + genuine past-state left intact):
docs/software/runtime/pcm-voice-bark.md,docs/software/runtime/audio-pipeline.md,docs/software/runtime/orchestration.md,docs/software/runtime/prototype-architecture.md,docs/software/runtime/README.md,docs/software/api-reference/grammars/coprocessor-protocol.md,docs/software/cartridges/operator-manuals/ice-breaker-manual.md,docs/device/hardware/power.md,docs/device/hardware/coprocessor.md,docs/device/hardware/wiring-diagram.md,docs/device/hardware/enclosure.md,docs/device/hardware/README.md,docs/device/os/device-tree-overlays.md,docs/marketing/narrative/worldbook.md,docs/marketing/narrative/skills/kinoshita-narrative-pipeline/reference/kn86-feature-marketing.md,docs/influences/synthesis-batch8-architecture.md,docs/influences/research/tui-library-shortlist.md. - ADR inline amendment pointers — ADR-0017 (I2S target + new I²C config) and ADR-0038 (amp/speaker part in the power context) gain a brief dated ”— amended by ADR-0054” note where they name the MAX98357A / 28 mm speaker as the current audio part. Their historical reasoning is left intact. Other frozen accepted ADRs that name the MAX98357A in their own decision record (ADR-0019 / ADR-0021 / ADR-0023 / ADR-0027) are not edited — they are immutable, and ADR-0017’s amendment carries the forward pointer.
- canonical-spec.md Speaker + Audio rows — handled by the PM in the kinoshita umbrella repo (canonical-spec.md is not in this repo).
Action Items
Section titled “Action Items”Bring-up validations, tracked against the audio stage of device/hardware/build-specification.md §4:
- Codec I²C bring-up. Confirm the WM8960 configures over I²C from the chosen master (Pico expected); lock the I²C master and address.
- Speaker fit + clearance. Confirm the Gikfun 2″ (~25 mm deep) driver seats in the base-panel speaker pocket and clears the 18650 pack (
enclosure.md). - Headphone output. Validate stereo output off the WM8960 headphone amp into the 3.5 mm jack.
- Speaker auto-cut on insert. Confirm the built-in speaker mutes when a plug is inserted (switched-jack contact and/or codec jack-detect — lock the mechanism).
- Freeze the Pico pin map (I2S + I²C) before hard-soldering the codec.
- Re-measure amp draw for the power envelope (ADR-0038) — WM8960 draw differs from the MAX98357A; populate the
power-idle.mdmeasured-draw rows.
Narrative (for the design history)
Section titled “Narrative (for the design history)”The prior audio chain was a strap-pin MAX98357A mono amp driving a small 28 mm speaker, with a headphone jack that only ever lived in the bench plan. Two realizations moved us: a portable deck’s honest default is screen-on / sound-off, so audio is a layer rather than a headline — but when an operator plugs in headphones, they deserve real stereo, and on-device stereo across two drivers 10 cm apart is inaudible. A single WM8960 codec resolves both: it drives a bigger 2″ full-range built-in speaker (mono, where mono is all you’d hear anyway) and a stereo headphone amp off the same chip, fed by the same Pico I2S source. The costs are honest — the codec’s speaker amp is quieter than the MAX98357A’s, and unlike the strap-pin part it needs I²C configuration (a new ~2-pin duty, expected on the Pico) — and both are fine for a handheld. The headphone jack graduates from bench-only to canonical, stereo, with the speaker auto-cutting on insert. Per-voice PSG panning across the stereo field is now possible on the Pico mixer, but no launch cart needs it, so it stays deferred. Future readers should take three things: built-in audio is deliberately mono and modest; the stereo win is on headphones, from one chip; and the WM8960’s I²C-config requirement is the one genuinely new firmware duty this change introduces.