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>
Place step circles by proportional position in the bar (beat = column start) instead
of centring in per-lane slots, so same-meter lanes' beats land at the same x (e.g. the
8-step hat's beats sit directly under the 4-step kick/snare). Cap circle radius at 6
(was up to ~18). Verified by printing per-lane beat x-positions + rendering the grid.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
From on-board feedback (works well; minor tweaks):
- Pad grid uses circles now: big circle on each beat (division), small on the
subdivisions (vectorio.Circle — native, no extra cost), coloured/lit as before.
- Lane labels use a new small font (font_s.bin, ~12px via gen_font.py) so they're
half-size and show more of the voice name (e.g. 'hatClos').
- LED was blinding -> LED_BRIGHTNESS scale (default 0.15) applied on every write.
- Residual tearing -> SPI back to 62.5 MHz (vendor speed; smaller tear window on a
panel with no tearing-effect pin). Both are CONFIG flags.
Verified by rendering the full scene headless. font_s.bin added to gen_font.py + bundle.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Replace the single beat-dot row with a full pad grid: each lane is a row of step
pads coloured by dynamics (mute/normal/accent/ghost), with the playhead lit as it
plays (per-lane, so polymeter shows). Header (title/BPM/RUN/item) is compacted above
it; transport stays below. Pads are vectorio rects sharing one 8-colour palette and
recolour in place via color_index (cheap, tear-free); the grid only rebuilds on track
change. Caps at MAXLANES=5 rows (extra lanes still play). Verified by rendering the whole
displayio scene graph headless (layout + playhead lighting correct).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
From on-board feedback (memory + colours now good):
- LED: drive the WS2812 via the core neopixel_write module (no neopixel library to
install) — a tiny RGB class. Self-contained: it works straight from the bundle.
- Tearing: switch displayio to auto_refresh=False and push a complete frame only when
the scene changed (dirty flag, capped at the panel's refresh rate) so updates are
never shown mid-paint. Beat dots now recolour in place (vectorio color_index) instead
of being rebuilt every beat, shrinking the dirty region.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
On hardware the app rendered, beeped and took input, then died with MemoryError at
the text Bitmap alloc — the two ~37KB base64 font strings stayed pinned in RAM. Move
the fonts to small binary files read at boot (font_m.bin / font_l.bin), drop the
base64 + binascii, and gc.collect() before each text bitmap. code.py 56KB -> 20KB and
RAM use drops ~37KB+. Also: cyan rendered as yellow (R/B swapped) -> MADCTL 0x40 -> 0x48.
Bundle + README updated to include the font blobs. (LED still needs the neopixel lib.)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
New pico-cp/ — a CircuitPython port of the PM_K-1 firmware so the Pico mounts as a
CIRCUITPY drive carrying its code + tracks (the MicroPython pico/main.py stays the
simple fallback):
- pico-cp/code.py: displayio BusDisplay driving ST7796 via a custom init_sequence;
smooth anti-aliased text via displayio Bitmap+Palette (reuses the baked font blobs);
vectorio rects for dots/buttons; DIY GT911 touch (16-bit regs, edge-detected);
pwmio buzzer, analogio joystick, digitalio buttons, optional neopixel RGB; the
polymeter engine on a time.monotonic_ns scheduler. Reads /programs.json (falls back
to baked defaults); CircuitPython auto-reloads on file change.
- pico-cp/programs.json: the 23 default grooves. pico-cp/README.md: flash + calibrate.
- build.sh/deploy.sh: bundle + serve /pm_k1_circuitpy.zip. info-kit.html: experimental
'CircuitPython edition — USB drive' section.
Verified in CPython (stubbed displayio): init sequence well-formed, parser handles the
grooves incl. (3,8) euclid + @-4 gain, and code.py's actual make_text renders identical
smooth AA text. Hardware bits (panel/touch/MIDI) await on-board testing.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
README was stale (pre-dating several shipped changes). Rewrite it to match reality:
- voices are all synthesized now (KIT_ALIAS -> 808/909); drop the VCSL samples
narrative, the @BUILD:samples wording, and the sample credits.
- document the lean-widget + separate info-<device>.html page model (was 'Open=Info').
- add kit.html + all info-*.html to the Pages table; add the new src/ partials
(header/footer/chrome/progbox/infoembed), pico/ firmware, and pico-main.py to Files/Build.
- document the share-grammar additions: GM note numbers, Euclidean (k,n[,rot]), per-lane @<db> gain.
- add a 'Build it (hardware)' section for the PM_K-1 Kit + MicroPython firmware.
embed.js: add the 'kit' form factor to the variant map (it previously fell back to micro),
so data-varasys-metronome="kit" embeds kit.html as the README now documents.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Four firmware improvements (web simulator already had these):
- Smooth lettering: replace the upscaled 8x8 bitmap font (and the 7-seg BPM) with
baked anti-aliased proportional fonts (DejaVuSans-Bold 22 + 78), rendered by
blending fg over bg through a 16-entry alpha LUT. Generator: pico/gen_font.py.
- All grooves: PROGRAMS now carries the full web set list (23 grooves), not 5.
- Fix: the RGB LED stayed lit when stopped — the stop path now zeroes the colour
and the fade only runs while playing (led_off()).
- Fix: the on-screen play button played one beep then stopped — a finger held past
the old lockout re-fired the toggle. Touch is now edge-detected like the hardware
buttons (fires once on finger-down, ignores held).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
A user dropped main.py onto the RPI-RP2 BOOTSEL drive (which only accepts a .uf2)
and it vanished on reboot. Clarify in pico/README.md and info-kit.html that
flashing is two distinct steps: (1) drag-and-drop the MicroPython .uf2, then
(2) copy main.py over USB serial with Thonny/mpremote — the Pico is not a USB
drive once MicroPython is running.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The on-screen header showed VARASYS + the model; since the wordmark is already
silkscreened on the case/PCB, keep only the PM_K-1 KIT label on the display.
Applied to both pico/main.py (draw_static) and the kit.html web simulator.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
A new, first-actually-buildable form factor for the 52Pi EP-0172 "Pico Breadboard
Kit Plus" (Raspberry Pi Pico; 3.5" ST7796 320x480 cap-touch via GT911, PSP
joystick on ADC0/1, WS2812 RGB on GP12, buzzer GP13, buttons GP14/15):
- pico/main.py — one self-contained MicroPython file: ST7796 direct-draw driver,
GT911 touch (16-bit register addressing), WS2812 RGB (neopixel), PWM buzzer,
ADC joystick, buttons. It parses the project's own program-string language
(verified against the web engine's semantics) and runs a non-blocking
ticks_us scheduler with an on-screen touch UI. CONFIG flags cover panel /
colour / touch / joystick calibration. pico/README.md has flashing +
calibration steps.
- kit.html — lean widget that mirrors the firmware's on-screen UI (portrait
320x480 canvas) plus a joystick / RGB / buzzer / A-B buttons; plays via the
shared engine. info-kit.html — the real EP-0172 pinout, a parts list
(~$45 incl. Pico) and the firmware to flash (downloads /pico-main.py, links
the README + source).
- Landing + embed page list the Kit; build.sh/deploy.sh build the two pages and
serve pico/main.py as /pico-main.py for download.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Previously every device .html bundled its full narrative (purpose, BOM,
dimensioned drawings, embedding docs) inside a #techinfo block that embed
mode (?embed=1) only CSS-hid — so every embedder and every landing-page
iframe downloaded all of it (showcase 77%, teacher 49% of the file) for
content no embedder ever sees.
Now:
- <device>.html is the lean widget only: header + front view/controls +
title + summary + program box. ?embed=1 still collapses to the bare
widget; the heavy narrative is gone from the payload.
- info-<device>.html (new, one per form factor) carries all the words —
purpose, dimensions, priced BOM, embedding docs — and embeds the live
widget at the top via the existing iframe + auto-resize protocol
(new shared src/infoembed.html + src/infoembed.js).
- Each device links out to its info page ("…dimensions & BOM →"); the
landing panes and viewport bar now offer both Open ↗ and Specs & info ⓘ.
- Dropped the now-dead "Show info" toggle (CSS + progbox.js).
Branding: adopt the official VARASYS "tagline on the bottom" logos from the
brand kit (light-background variant now matches; dark already did). The
tagline is baked into the PNGs, so remove the CSS .brand-tag / .dev-tag
spans and the showcase canvas-drawn tagline. Brand cyan #0AB3F7 / navy
#1C283F already match the official palette.
build.sh / deploy.sh: build + deploy the six new info-*.html pages.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Logos: the brand is now a consistent lockup — wordmark image + a crisp CSS
"Simplifying Complexity" tagline — in the shared header, device silkscreens
(teacher/stage/micro), the player (was a CSS text box) and the showcase canvas
(was drawn text; now the real logo image + tagline). Cropped the baked tagline
out of logo-light.b64 so both themes render the tagline once. Renamed device
silk logos to .dev-logo so they no longer shrink the shared header logo.
Embeds: every form factor now loads its default set lists when embedded with no
config — and the Concepts landing embeds them that way (viewport loads
<device>?embed=1 with no forced #p=; the program box reflects what the device
reports and only overrides on explicit Load).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- Embed page: a form-factor dropdown that rewrites every snippet (drop-in +
plain iframe), the live demo, and the name for the chosen version; variant
table completed to all six.
- Display (Showcase): the tempo weight no longer flashes and is drawn BEHIND the
pendulum lights so it never hides a beat flash.
- Practice (Micro): a beat/sub-beat flash — the whole 14-seg display washes amber
on each step (subtle on sub-beats, brighter on the beat, full on the "1"),
latency-compensated like the other devices.
- Landing: Philosophy section moved above "Pick a form factor".
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- Add front + top/side dimensioned schematic views (inch + mm) inside the
"Show info" section of Stage (front + top-edge I/O), Practice (front bar +
both end faces), and Display (pyramid front + side profile). Shared .dview /
.dschem CSS in base.css.
- Fix: progbox.js now defers to DOM-ready, so the "Show info" toggle + #techinfo
are wired even when they sit after the page script (Stage/Practice/Player were
silently not toggling / ignoring ?info=1).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Each form-factor page is now plain by default: title + summary + the front view +
a program I/O box (shared src/progbox.* — paste a patch OR a base64 set-list code,
decoded + linted + loaded; copy; reflects the device state and posts it to an
embedding parent). All technical content — description, BOM, dimensions, top/side
views, embedding — hidden behind a "Show technical info" checkbox; ?info=1 opens it
checked. Teacher's top-edge view + dimensions are marked .tech so they hide too.
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>