Commit graph

58 commits

Author SHA1 Message Date
Me Here
7ccc75e399 Phase 3: USB-MIDI audio — play the device through the computer's speakers
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>
2026-05-28 22:40:08 -05:00
Me Here
d558dccbde Phase 2: editor 'Save/Load to device' + bundle the editor on the drive
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>
2026-05-28 22:20:35 -05:00
Me Here
6edb89e33c PM_K-1 grid: smaller circles + align beats vertically across lanes
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>
2026-05-28 22:16:36 -05:00
Me Here
ec43c694a1 PM_K-1 CircuitPython: circle pad grid, small labels, dimmer LED, faster SPI
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>
2026-05-28 22:07:00 -05:00
Me Here
c499910df4 PM_K-1 CircuitPython: add the lanes/pads view
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>
2026-05-28 21:56:27 -05:00
Me Here
ffededd05b PM_K-1 CircuitPython: self-contained RGB LED + fix screen tearing
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>
2026-05-28 21:43:48 -05:00
Me Here
111da49b5a PM_K-1 CircuitPython: fix MemoryError + red/blue swap (from on-board test)
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>
2026-05-28 21:30:03 -05:00
Me Here
b419ad0daa Phase 1: CircuitPython firmware (USB-drive edition) for the Kit
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>
2026-05-28 21:10:34 -05:00