Develop the full Daisy Pod spike so it can be flashed the moment the board
arrives. Architecture: one shared engine, two front-ends.
- pm-synth: make it `#![no_std]` (mirroring track-format), routing float math
through `libm` so the SAME f32 code runs on the host and on the Daisy's
Cortex-M7F (hardware FPU — no fixed-point port needed). Add `Player`, a
self-running sequencer that owns the Synth + scheduled clicks and renders
sample-by-sample, looping at the pattern boundary. Integer-only hot path
(clicks pre-resolved to sample indices); exposes a `fired()` beat counter.
Add SPIKE_PROGRAM/SPIKE_BARS as the shared source of truth.
- synthrender: render the SAME Player to pm-daisy-preview.wav — the host-side
"simulator". Bit-identical preview of the hardware output (before its codec);
far more useful than chip emulation (Renode can't model the audio codec).
- pm-daisy (new, workspace-excluded firmware): thin BSP binary for the Daisy
Seed/Pod. embedded-alloc heap + board bring-up + SAI-DMA audio interrupt
feeding Player::next_sample() into stereo frames, USER LED flashing per click.
Audio loop follows the `daisy` crate's examples/audio.rs. Board revision
(codec) is a Cargo feature; README documents matching it + both flash paths
(probe-rs/RTT and USB DFU) + the QSPI-bootloader fallback.
Verified without hardware: host build + preview render (48 kHz, onsets on the
8th-note grid at 124 BPM); firmware cross-compiles + links for thumbv7em-none-
eabihf at ~87 KB (fits the 128 KB internal flash) across all three codec
revisions; track-format conformance + `node tests/run.mjs` (47 pass) still green.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
pm-synth: a polyphonic drum-voice synth, a faithful f32 port of engine.js DRUMS
(tone/ampEnv/v_noise/metalHat/clap recipes; RBJ biquads; exp envelopes). A Synth
mixes active Voices sample-by-sample (transport-agnostic: offline render now,
real-time device buffer fills later). All 808/909 + GM voices ported.
synthrender (host bin): parse a groove -> track-format schedule -> trigger voices
at click times -> 16-bit/48k mono WAV. Applies the editor default kit (kick->
kick909 etc.). Renders four demo grooves to audition off-bench.
This is the reusable half of the audio feature; the device port (no_std +
fixed-point/table osc, since the M0+ has no FPU) comes with the transport.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Rust sibling of pico-scroll/app.py — the PM_G-1 'Grid' 17x7 LED metronome on a
plain RP2040 Pico (thumbv6m, not the Pico 2). LED-first milestone:
- IS31FL3731 driver: vendored bulk 144-byte framebuffer, one I2C block write per
frame (port of the CircuitPython Matrix; the is31fl3731 crate isn't used).
- Polymeter scheduler driven by track-format::schedule::lane_durs (the cross-impl
contract) + per-lane step clocks + tempo ramp + gap-trainer.
- 4-button input (A play/stop·hold=view, B next-track·hold=next-setlist, X/Y tempo).
- Built-in set lists; 3 views: Ticker (default), Grid, Pendulum.
- Ticker (user-designed): name infinite-scrolls left; BPM pinned right rotated 90
CCW = hundreds dot-bar (1 dot/100) + last 2 digits rotated. 130 -> 1 dot + '30'.
- Build scaffolding: rp2040-hal 0.10 + boot2, memory.x, build.sh + uf2.py (RP2040
family id). thumbv6m-none-eabi added to rust/Containerfile. Excluded from the
host workspace like pm-kit. Compiles clean -> 48 KB pm-grid.uf2.
Audio (USB-MIDI; the board has no speaker), live-sync, firmware push, practice log
and playback-flow auto-advance are deferred to the next milestone (as on pm-kit).
Also: delete COORDINATION.md (solo now); docs/rust-port.md updated with pm-grid
status + corrected Grid driver-matrix row.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>