Commit graph

29 commits

Author SHA1 Message Date
Me Here
cb54b4d689 Preserve notation + grammar feature work (verified complete + green)
The parallel agent's full session, committed now that it's solo:
- Grammar: flam/drag/roll ornaments (f/F d/D z/Z, per-lane orns channel) across
  src/engine.js, pico-cp/pico-explorer/pico-scroll app.py, pico/main.py, rust/track-format,
  + golden vectors / conformance (tests/, rust/track-format/tests).
- Live-sync deep-sync: SysEx 0x44 SLSYNC + 0x45 LOGSYNC (docs/livesync-protocol.md, src/livesync.js).
- PM_E-2 notation: web engine (pm_e-2.html, build/deploy/index/embed wiring) + Rust device port
  (pm-ui draw_notation rewrite + LaneView.groups, pm-kit ViewMode, uisim notesim).

Verified: node tests/run.mjs 47 pass / 1 known; ./rust/run.sh green; pm-kit firmware + uisim compile.
2026-06-02 13:45:26 -05:00
Me Here
8f4264f4d2 pm-kit: defmt+probe-rs diagnostics + flip-link toolchain
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>
2026-06-01 08:30:35 -05:00
Me Here
8067820d19 site: Rust section now describes the live metronome (was bring-up image)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-01 00:19:38 -05:00
Me Here
8b4fca2a74 deploy: serve rust/pm-kit/pm-kit.uf2 (RP2350 Rust firmware download)
Copies the built Rust .uf2 to the web root when present, so it can be flashed from
the website (alongside the CircuitPython firmware downloads). Conditional — only
served if rust/pm-kit/build.sh has produced it.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-05-31 20:49:49 -05:00
Me Here
400d896518 Add PM_G-1 "Grid" form factor (Pimoroni Pico Scroll Pack) + Rust core/driver plan
New form factor: a plain RP2040 Pico + Pico Scroll Pack (PIM545) -- a 17x7
single-colour LED matrix + 4 buttons. The 7x17 matrix maps onto the editor's
lane x step pad grid.

- pico-scroll/: CircuitPython firmware (DEVICE_ID "G"). Engine/scheduler/SysEx/
  live-sync copied verbatim from pico-explorer (engine byte-identical, so it stays
  on the track-format conformance lineage); vendored bulk-framebuffer IS31FL3731
  driver (pins/map verified from pimoroni-pico); three LED views (Grid/Pendulum/BPM);
  4-button input. Audio over USB-MIDI (no onboard speaker); optional P_BUZZER.
- grid.html + info-grid.html: widget page (canvas mirrors the 3 LED views) + spec
  page with a ~$29 BOM.
- Registered in build.sh (precompile + ASCII assert + pm_g1_circuitpy.zip), deploy.sh,
  embed.js, embed.html, index.html gallery, and both editors' FW_PATHS (device id G).
- docs/rust-port.md: core/driver architecture (pm-core no_std engine+protocol; per-board
  drivers behind embedded-hal/embedded-graphics traits). CLAUDE.md + livesync-protocol.md
  note the new edition + device id.

Python firmware stays in parallel with Rust (no abandonment yet).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-05-31 20:30:15 -05:00
Me Here
05ce1d5ce4 Landing page: explorer.html widget mockup
A visual mockup of the Pimoroni Explorer Kit (PIM744) - yellow PCB body,
6 coloured buttons (A/B/C left, X/Y/Z right) flanking the central 320x240 LCD,
piezo + mini-breadboard at the bottom, USB-C / RP2350 silkscreen.

Canvas mirrors the firmware UI: VARASYS logo + version + run-state dot in the
header (3-channel lerp for the per-beat pulse, no more red-channel-only blend
bug); setlist tab + track name + big BPM + bar/time meters; pad grid up to
6 lanes with main-beat squares + subdivision circles + vertical gridlines.

Inputs: A = play/stop, B = tap, C = next setlist; X/Z = prev/next track with
350 ms first-repeat + 120 ms repeat; Y = -1 bpm (after 1.5 s held step = -5);
X+Z chord within 100 ms = +1 bpm (mirrors Y). Keyboard: A B C X Y Z + space.

Landing page (index.html) Explorer pane now points at /explorer.html with
h:500 (the LCD is half-height of the Kit's so the widget is more compact).
The /info-explorer.html embed handler still works for the "Specs & info" link.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-30 20:55:20 -05:00
Me Here
3192f3debc PM_X-1 0.0.1: Pimoroni Explorer sibling firmware + Kit 0.0.23 device-id reply
Adds pico-explorer/ as a parallel CircuitPython firmware target alongside the 52Pi
Kit in pico-cp/. Same engine, same program-string grammar, same programs.json, same
live-sync protocol. Read-only on the device (no on-device beat editing); the web
editor's Live sync mirrors all edits in real time and the Explorer emits its own
play/stop/bpm/sel deltas back.

Hardware (Pimoroni Explorer PIM744):
- RP2350B + 2.8" ST7789V 320x240 LCD (8-bit parallel; CircuitPython's official
  board definition pre-builds the BusDisplay so we just use board.DISPLAY).
- 6 user buttons - A/B/C on the left of the screen, X/Y/Z on the right.
- Piezo speaker on GP12 (PWM) with amp enable on GP13.
- I2C QwSTEMMA on GP20/21 - reserved, unused by the firmware.
- No touchscreen, no joystick, no RGB LED. Run state shows on a tiny on-screen dot.

Buttons:
- A = play/stop. B = tap tempo. C = menu.
- X = prev track (hold-repeat). Z = next track (hold-repeat).
- Y = tempo -1 (hold-repeat; -5 after 1.5s).
- X+Z chord = tempo +1 (mirrors Y).
- In a menu: X/Z move the row cursor, Y decrements, A cycles/increments/selects,
  B = back, C = close.

Files added:
- pico-explorer/{boot.py, code.py, app.py, programs.json, README.md}.
  app.py = 1444 lines (~73KB source -> 29.8KB compiled .mpy).
- info-explorer.html.

Files touched:
- pico-cp/app.py: bump to 0.0.23. Version-query (SysEx 0x02 -> 0x03) reply now
  includes the device id as "K;<version>" (backward-compat: editor parses
  "contains ';'?" - old firmware sent bare version, treated as K).
- editor.html + editor-beta.html: _parseDeviceReply() splits id;version, FW_PATHS
  maps id to .py/.mpy URL pair, so Update firmware now pushes the right binary.
- build.sh + deploy.sh: precompile pico-explorer/app.py -> dist/explorer-app.mpy,
  zip pm_x1_circuitpy.zip alongside pm_k1_circuitpy.zip, ship
  pico-explorer-app.{py,mpy} next to pico-cp-app.{py,mpy}.
- docs/livesync-protocol.md: new section 7 - per-device emit/apply matrix.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-30 20:43:38 -05:00
Me Here
eae9057baf PM_E-1 beta: live-sync editor (editor-beta.html) mirroring a connected PM_K-1
New editor-beta.html: a bidirectional live mirror over the existing USB-MIDI
SysEx channel (0x7D). Either the website or the device can edit grooves, change
tempo/volume, start/stop, or select set-list items, and the other reflects it.

- src/livesync.js: LiveSync layer (opcodes 0x40 HELLO / 0x41 FULL / 0x42 DELTA /
  0x43 BYE) riding the existing _ensureMidi/_send/onDeviceMidi plumbing. Fine
  deltas for transport/bpm/vol/sel/beat, coalesced full-state for structural
  edits; echo suppression via origin + _applyingRemote guard; device-authoritative
  heartbeat reconciles drift. ?loopback=1 self-test mode (no hardware needed).
- editor-beta.html: copy of editor.html + "Live sync" toggle, SysEx routing,
  and broadcast hooks at each mutation choke point (guarded by _applyingRemote).
- docs/livesync-protocol.md: wire spec + firmware checklist for pico-cp/app.py
  (firmware half owned by the other instance — editor side + spec only here).
- build.sh / deploy.sh: add editor-beta.html to the build + version-stamp loops.

Editor side only; pico-cp/app.py untouched.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-05-30 09:09:37 -05:00
Me Here
7481f91935 PM_K-1 0.0.10: ship precompiled app.mpy (fixes boot OOM) + push .mpy over the air
The single-file app grew to ~57KB; CircuitPython compiling it at boot fragments the
RP2040 heap so badly that the fonts can't get a contiguous block (161KB free, yet a
~16KB alloc fails). Fix: precompile to app.mpy (Adafruit mpy-cross for CP 10.2.1, emits
CircuitPython mpy v6) so the device loads bytecode without compiling -> no fragmentation.

- build.sh precompiles pico-cp/app.py -> dist/app.mpy via tools/mpy-cross (gitignored
  binary); the bundle ships app.mpy (NOT app.py); serves pico-cp-app.mpy + pico-cp-app.py
  (the .py only for the editor's version regex + as readable reference).
- Loader (code.py) imports app.mpy and rolls back app.bak as .mpy.
- One-click updater now pushes the .mpy: editor base64-encodes it and sends it over the
  existing flow-controlled chunked transport (512-char = mult-of-4 chunks); the device
  base64-decodes each chunk to /app.new and verifies the CircuitPython .mpy header
  (magic 'C', v6, >=4KB) before the A/B install. Version still read from the served .py.

Verified: mpy-cross emits magic 'C'/v6; build produces a 21.8KB app.mpy; editing-logic
harness + scene render still pass; and a simulated push (base64 -> 57 chunks -> a2b_base64)
reassembles the .mpy byte-exact and passes the device's header check.

One-time recovery: delete app.py from the drive, copy app.mpy + code.py from the new zip.
After that, updates are one-click again (and can't brick: header check + A/B rollback).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-29 14:01:57 -05:00
Me Here
e8945ee1d1 PM_K-1: one-click A/B firmware updates over USB-MIDI (+ version check)
Split the CircuitPython firmware into a tiny stable loader (code.py) + the application (app.py,
carries APP_VERSION). The editor's ⋯ → "⬆ Update firmware" queries the device version (SysEx 0x02
-> 0x03 reply), fetches the latest app from the site (/pico-cp-app.py), shows device-vs-latest, and
pushes the new app.py over USB-MIDI (SysEx 0x20). The device installs it to a trial slot (old build
kept as app.bak), reboots, and the loader AUTO-ROLLS-BACK to app.bak if the new build fails to start;
a build that runs cleanly ~5s is confirmed (clears /trial). No BOOTSEL, no dragging; Chromium/Firefox.
app.py forced to pure ASCII so it pushes raw (no base64); SysEx buffer raised to 60KB.

build.sh/deploy.sh: bundle code.py+app.py and serve /pico-cp-app.py. Docs updated.

Verified in CPython: version reply, update install+reboot+ACK, rollback file dance; editor loads clean
with the updater wired.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-29 06:55:58 -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
Me Here
eecea625d3 Add PM_K-1 "Kit" — buildable Pico touchscreen unit + MicroPython firmware
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>
2026-05-28 16:10:31 -05:00
Me Here
9e5c79b3b2 Split each form factor into a lean widget page + a separate info page
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>
2026-05-28 14:18:23 -05:00
Me Here
1c74100065 Restructure (2a): shared chrome on every page; merge Open=Info into one page per form factor
- 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>
2026-05-28 09:31:39 -05:00
Me Here
be00ebf097 Restructure (1/2): Concepts = landing with live embeds; shared chrome partials; Showcase redesign
- 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>
2026-05-28 09:09:51 -05:00
Me Here
17053719f1 New Stage (foot-pedal) + Showcase (RGB pendulum); fix audio/visual sync
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>
2026-05-28 08:40:20 -05:00
Me Here
ce6166a721 Rename "Stage" -> "Teacher" (studio/lesson console); free the Stage name
The full-feature desktop console (big TFT, arcade buttons, instrument pass-through)
is repositioned as the "Teacher" for studio desks and lessons:
- stage.html -> teacher.html, info-stage.html -> info-teacher.html (git mv)
- all links/paths, the embed variant (stage -> teacher), nav, cards, embed docs,
  README, build.sh + deploy.sh updated; deploy cleans the stale live stage files
The "Stage" name is now free for a forthcoming foot-pedal stompbox (/stage.html).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-28 08:16:15 -05:00
Me Here
f0cc30f373 Dedicated landing page at /; move the editor to /editor.html
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>
2026-05-26 12:19:24 -05:00
Me Here
d78fb762e5 Per-version info pages; move Stage BOM out to info-stage; add Micro BOM
Each form factor now has an information page (purpose + live embedded widget),
with priced BOMs only on the buildable hardware (Stage ≈$59, Micro ≈$28):
- info-editor.html / info-initial.html — purpose only (web app / concept)
- info-stage.html — purpose + the priced BOM moved out of stage.html
- info-micro.html — purpose + a new ~$28 practice-unit BOM
stage.html drops the BOM panel (+ its .bom CSS) and gains a "Spec & BOM" link;
the shared .bom/.sub table CSS lives in src/base.css. "Info" added to every
page nav and to the concept cards. Wired into build.sh + deploy.sh.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-26 12:02:17 -05:00
Me Here
fc05cfe4c7 Site phase 2: embeddable widget standard (?embed=1 + embed.js + embed.html)
- Every form factor supports ?embed=1: a head flag (set on <html>, no flash)
  strips the site chrome (base.css [data-embed]) + page-specific panels, leaving
  just the widget, and posts its height so the host can auto-size it.
- Config/settings string preloads via the existing #p=/#sl= hash. Added that
  hash handling to micro.html (it previously only loaded built-in tracks).
- New embed.js loader: <div data-varasys-metronome="micro" data-patch="…"> + one
  <script> → an auto-sizing iframe to <page>?embed=1#p=…. New embed.html documents
  it and dogfoods a live embedded widget.
- "Embed" nav link added across pages; build.sh/deploy.sh build embed.html and
  serve embed.js.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-26 11:46:26 -05:00
Me Here
6568076563 Site phase 1: standard VARASYS header + nav; editor → PE-1; Concepts library
- Shared site header in src/base.css (.site-head/.site-nav/.brand-logo + theme-
  aware logo + .tbtn). Applied to player/stage/micro (replacing their text
  topbars) so the VARASYS logo + tagline + Editor/Concepts nav is on every page.
- Rebrand the editor: "Stackable Metronome" → "PE-1 — PolyMeter Editor" (title +
  h1), with a Concepts link in its header.
- New concepts.html — the PolyMeter Concepts library: cards for the editor and
  each form factor (PM-1 Initial/Stage, PM-µ Micro) + a "more coming" card.
- build.sh + deploy.sh build/deploy concepts.html; deploy.sh now loops over pages.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-26 11:38:50 -05:00
Me Here
9d48edf7e0 Rename as-built → stage.html; add micro.html (minimal home-practice unit)
- Rename player-asbuilt.html → stage.html (the pedalboard build). Update
  build.sh + deploy.sh (deploy now also removes the old player-asbuilt.html
  from the web root) and the cross-links in player.html / stage.html.
- New /micro.html — a stripped-down home-practice metronome on the same RP2040
  firmware. Hardware is just: ONE depressable scroll/rotary encoder, a red
  7-segment LED display, a speaker, and USB-C for power. The encoder does
  everything: spin = tempo, press = start/stop, hold + spin = switch track
  (the LED shows the track number, with BPM / TRACK / ▶ indicators). Tracks =
  the editor's seed grooves flattened (23). Shares src/engine.js, setlists.js,
  base.css; synth-only; steady practice loop (ramps/bars ignored).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-26 09:45:58 -05:00
Me Here
df213272ae Add "as-built" player variant: mono 128×64 OLED + 16-px WS2812 beat bar
New /player-asbuilt.html showing the PM-1 with parts you'd actually solder
for an RP2040 build, alongside the idealized /player.html:

- 128×64 MONOCHROME OLED (SSD1306 class): rendered as a true 1-bit
  framebuffer — drawn, then thresholded to crisp on/off pixels and scaled
  with image-rendering:pixelated — so the cramped real layout is honest
  (position / big BPM / grouping / scrolling name / bar·beat).
- Fixed 16-px WS2812 ("NeoPixel") RGB beat bar on a strip PCB: lights the
  first beatsPerBar slots (cyan downbeats, amber group-starts, dim others),
  the rest dark — showing the fixed-count hardware honestly.
- EC11 rotary encoder you actually turn (wheel / vertical drag) for tempo,
  tactile buttons, MAX98357A-style speaker grille, USB-C, PWR LED, matte case.

Shares the same firmware via src/engine.js + src/setlists.js (same seed set
lists, same scheduler); only the panel rendering differs. The device is fixed
dark hardware; the page chrome follows light/dark/system. build.sh + deploy.sh
now assemble/serve all three pages; player.html links to it ("As-built ↗").

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-26 06:57:57 -05:00
Me Here
632890c812 Add build step (inline assets at build); drop "mockup" from the main app
The source index.html now keeps small @BUILD:* markers instead of the
~250KB of base64 blobs (audio samples, logos, favicon), which move to
assets/. build.sh inlines them into a self-contained dist/index.html
(+ dist/player.html); deploy.sh runs the build first and serves dist/.
dist/ is git-ignored. Keeps the single-file deploy while stopping the
samples from eating the editing budget.

Also reframe the main page as the full web app (it is not a mockup —
only the play-only player.html device is): drop "Mockup" from the title,
the source comment, and the README intro; add Build/Files docs and
correct the "no build step" claim.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-25 15:21:28 -05:00
Me Here
ec23da5164 Add hardware-device player mockup at /player.html
A self-contained simulator of the RP2040 "PM-1" unit: it plays the share
language (synth voices, same scheduler) and drives an OLED + beat-LED
display like the firmware would. Loads from a #p=/#sl= link, the editor's
saved set lists (localStorage), or a pasted patch / set-list code — with
validation. Transport: play/stop, prev/next item, tempo ±, tap; bar-count
segments auto-advance. deploy.sh now version-stamps and publishes it too.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-25 15:04:17 -05:00
Me Here
ba752745b7 Per-lane enable (replacing mute), feature boxes, set-list continue mode, external QR
- Each meter lane has an 'enable' checkbox right after its number (default on,
  green-dim row when off); replaces the right-side 'mute'. Renamed mute→enabled
  throughout (scheduler, snapshot, share '!' flag, 1–9 keys, now-playing). Old
  saved data still loads (back-compat).
- Features area redesigned into highlighting boxes (Gap trainer / Tempo ramp /
  Timers); trainer & ramp boxes light up + un-dim when enabled.
- Set list 'Continue' mode: per-item countdown (saved in each item, 'cd' token),
  and when a playing item's countdown hits 0 it auto-loads the next — so a list
  with countdowns plays straight through.
- Removed the in-app QR (vendored qrcode.js); 'QR ↗' now opens api.qrserver.com
  with the link, behind a banner warning it's a third party (verify it decodes).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-24 18:47:16 -05:00
Me Here
5320da4325 Add QR share dialog (vendored qrcode.js) + README documenting the language
- Share menu now opens a dialog with a copyable link AND a QR code (scan to open
  on a phone); generated locally by vendored qrcode-generator (MIT). deploy.sh
  publishes qrcode.js alongside index.html.
- README documents the share language grammar, sounds, URL forms, shortcuts,
  versioning and deploy.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-24 17:34:26 -05:00
Me Here
a7770eaf47 Add versioning: VERSION file, dev/formal stamping, release.sh
- VERSION holds the formal version (0.0.1), single source of truth.
- deploy.sh stamps the served HTML: "X.Y.Z" on a clean commit tagged v<VERSION>,
  else "X.Y.Z-dev.<utc-ts>.<sha>[.dirty]".
- index.html shows the build version in the header badge (APP_VERSION).
- release.sh cuts a formal release (sets VERSION + tags v<VERSION>).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-24 16:59:31 -05:00
Me Here
49c8584c8c Add stackable metronome mockup and Caddy deploy script
index.html: single-file browser mockup of the polymetric groove trainer —
stackable meter lanes, subdivisions, odd-meter grouping, per-beat patterns,
GM percussion voices, true ratio polyrhythm (poly toggle), presets, set
lists with a recordable practice log, and keyboard shortcuts.

deploy.sh: copies index.html into the Caddy web root that serves
https://metronome.varasys.io (no restart needed).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-24 14:25:42 -05:00