Adopt proper embedded tooling for the blank-screen debug (user has a Pi Debug Probe):
- flip-link linker (baked into pm-rust:2): stack overflow faults cleanly instead of
silently corrupting .bss/.data (the SPI buffer -> black screen class of bug).
- defmt + defmt-rtt + panic-probe: firmware logs boot/heap-free/display/parse/loop
heartbeat over RTT; panics print message+location. .cargo runner = probe-rs run.
- Restore the full live metronome (from 08b0940) as the instrumented target.
- deploy + serve pm-kit.elf (probe-rs decodes defmt strings from the ELF).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
A third implementation of the track DSL alongside engine.js and app.py, validated
against the same tests/fixtures/track-format.json:
- rust/track-format/: pure parse()/serialize() codec (std + alloc for now; no_std is
a later refinement). Ports the app.py/engine.js semantics exactly — grouping,
subdivisions, swing, ghost, polymeter, euclid, GM note-number aliases, unknown->beep,
default groove (group-start accents), tempo clamp, empty->beep, and the playback-flow
tokens (rep/end/relative-goto). Carries vol/cd too, so it's the most spec-complete
of the three.
- tests/conformance.rs: the Rust adapter — reads the shared fixtures, asserts each
case's normalized form (number-tolerant deep-equal) + serialize idempotency.
- rust/Containerfile + run.sh: Rust toolchain in a container (mirrors hardware/eda/),
with the thumbv8m.main-none-eabihf target for the eventual RP2350 firmware. Never
on the host.
Verified: ./rust/run.sh -> cargo test -> conformance + idempotent both pass.
docs/rust-port.md Stage 1 marked done.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>