The editor's 'Device audio' now sends a MIDI Active-Sensing heartbeat (0xFE, every 250ms)
to the device while on. The firmware reads usb_midi.ports[0]; while it hears the heartbeat
(<1s) it shows a green 'MIDI' badge top-right and silences the buzzer (the computer plays);
~1s after it stops, it reverts to the buzzer and hides the badge. Manual MUTE_BUZZER still
works. Verified headless: host detected -> MIDI shown + buzzer duty 0; timeout -> reverts.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
User reported no computer audio + 'no device being controlled'. Add visibility to
diagnose: the button now shows the connected MIDI input's name (or 'no device'), the
toggle alert lists detected inputs, and the button pulses green on each Note-On
received — so it's clear whether the device is seen and whether notes are arriving.
Also call ensureAudio() in the message handler as a guard.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Firmware (pico-cp/code.py): on every click, send a USB-MIDI note-on per firing lane —
GM drum note by voice (SOUND_GM), velocity by level (accent/normal/ghost) — via the
default-enabled usb_midi.ports[1]. Polyphonic, so the computer plays the full groove.
New CONFIG: MIDI_ENABLED (default on), MUTE_BUZZER (silence the buzzer when using
computer audio).
Editor (editor.html): a '🎹 Device audio' toggle uses the Web MIDI API
(requestMIDIAccess) to voice incoming notes through the existing synth — Note-On ->
GM_NUM[note] / velocity-to-gain -> playInstrument(). The device is the clock; the
browser is the sound module, locked in sync. Chrome/Edge.
Verified: firmware emits the right notes (kick+hat on beat 1 of four-on-the-floor,
snare's rest skipped); editor loads clean with the toggle + handlers present. Docs
(info-kit, both READMEs) updated. The on-device buzzer/screen still work standalone.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Add to the editor's set-list ⋯ menu:
- 📟 Save to device — writes the active set list as programs.json (the same file the
PM_K-1 firmware reads). Uses the File System Access API to write straight onto the
CIRCUITPY drive (Chrome/Edge); falls back to a download to drag on. Reuses
setupToPatch() per item -> {title, programs:[{name, prog}]}.
- 📥 Load from device — reads a programs.json back into a new set list (patchToSetup
per item; reuses the existing import path).
Bundle the built editor.html into pm_k1_circuitpy.zip so the drive carries its own
offline programmer. info-kit + pico-cp/README document the workflow.
Verified: editor loads with no console errors; both menu buttons + all four functions
present; zip contains editor.html. (FSA save needs a real user gesture to test on-device.)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Editor: per-lane gain knob (drag/scroll/double-click, dB, applied at schedule
time — no stutter); program box now decodes base64 set-list codes + lints
(clear ✓/✗ message). When embedded it posts its program to the parent.
Landing (Concepts) rebuilt to the spec: description first, the EDITOR open by
default in a live viewport, a summary pane per form factor (click loads it into
the viewport), and a program I/O box that shows the current program decoded (not
base64), accepts plain text OR a base64 set-list code, lints it, loads it into
the viewport, and copies it. Viewport auto-sizes + reflects the device's posted
program. Engine codec inlined for decode/lint.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- Remove the VCSL sample kit entirely (editor 351K → 141K). All voices are
synthesized; the friendly GM names now alias to the punchier 808/909 renders
(KIT_ALIAS). build.sh drops the @BUILD:samples inlining; assets/samples.json gone.
- Conventions (backward-compatible): GM note-number aliases (36=kick…), '-'/'_'
rest aliases in step patterns, Euclidean (k,n[,rot]) shorthand.
- Per-lane gain in dB (@<db> in the grammar) applied as a velocity multiplier at
schedule time — no stutter; threaded through every host's buildMeters + the
editor's lanes (knob UI comes in Phase B).
- 15/15 engine round-trip tests pass; pages console-clean.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- Shared header/footer/chrome (src/header.html, src/footer.html, src/chrome.js)
now on every page: editor (header above its app toolbar), player, teacher,
stage, micro, showcase, embed. chrome.js defers to DOMContentLoaded so the
footer version stamps regardless of placement. Player's fullscreen toggle
relocated out of the header to a floating control.
- Open = Info: each form-factor page is self-contained — a more-detailed
description (.about) + an expandable "Spec & BOM" (<details class="spec">,
hidden in embed). info-*.html retired; build/deploy/README updated.
Next: teacher-style dimensioned front + top/side views + loading panels for
Stage, Micro and Showcase.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- Concepts is now the landing (/): index.html is the form-factor gallery with the
LIVE widget embedded in every box (editor/teacher/stage/micro/showcase/initial),
on the shared header/footer. concepts.html retired; every "Concepts" link → /.
- New shared chrome partials src/header.html, src/footer.html, src/chrome.js
(assembled by build.sh) + .site-foot / details.spec styles in base.css. Applied
to the landing + showcase this pass.
- Showcase redesign per spec: the pendulum bar IS the display — each lane's
subdivisions/accents ride along the rod as moving RGB light (all meters combined);
transparent outside the body (no black window); a printed tempo scale on the
vertical axis with a draggable weight to set tempo; start is an external button
(the real unit starts when lifted from its holder).
Next pass: roll the shared header/footer onto the remaining pages (incl. the editor
header-above-toolbar), merge Open=Info into one page per form factor with the
expandable Info & BOM, and add teacher-style dimensioned views to Stage/Micro/Showcase.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Sync: the visual playhead now advances on a latency-compensated clock
(currentTime − outputLatency||baseLatency) so the on-screen pulse lands when the
click is HEARD, not when it's queued — previously the visual could lead the audio
by the output buffer / Bluetooth latency (up to ~a subdivision). Applied to
editor, player, teacher, and the new pages; also bound the visual queue (vq trim).
No data races: single-threaded; only the rAF draw touches vqPtr/currentStep, and
each vq entry carries the exact scheduled time of its sound.
stage.html — foot-pedal stompbox: two heavy footswitches (Tap=tempo / hold=start-
stop, Next=item / hold=prev), 1/4" expression-pedal input → tempo sweep, big
floor-readable RGB beat light + angled TFT, analog instrument pass-through.
showcase.html — pyramid display piece: an RGB-light pendulum easing to each beat
plus per-lane segment rows showing subdivisions/accents/mutes (canvas).
Both: dual USB-C (data+power and power-thru) to daisy-chain off one source.
Wired into embed.js (stage, showcase variants), build.sh, deploy.sh, the
concepts gallery + landing cards, info-stage.html (~$52) + info-showcase.html
(~$39) with BOMs, and the README.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The site now opens on a proper front door: a hero (logo + tagline + pitch),
an "Open the Editor →" CTA, and form-factor cards (Editor, Stage, Micro, Embed)
linking out to each page + info. The PE-1 editor app moves from index.html to
editor.html; every "Editor"/"Open" link, the embed.js editor variant, and the
editor's own brand-logo (now → /) are repointed. build.sh + deploy.sh build and
publish both index.html (landing) and editor.html (app).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>