metronome/pico-scroll/README.md
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

67 lines
4 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# PM_G-1 "Grid" — CircuitPython edition (Pimoroni Pico Scroll Pack · RP2040)
The **CircuitPython** firmware for the [Pimoroni Pico Scroll Pack (PIM545)](https://shop.pimoroni.com/products/pico-scroll-pack)
on a plain **Raspberry Pi Pico**, set up as a self-contained appliance. Sibling to the PM_K-1 build
in `../pico-cp/` and PM_X-1 in `../pico-explorer/` — **same engine, same program strings, same
`programs.json`, same web editor, same live-sync protocol.**
This board is a **17 × 7 single-colour (white) LED matrix** (IS31FL3731 over I²C) **+ 4 buttons
(A/B/X/Y)** — *no touchscreen, no joystick, no RGB LED, and no onboard speaker.* It's the smallest,
most minimal form factor: the 7-row × 17-column grid **is** the editor's lane × step pad grid in
miniature. Editing happens in the web editor with **Live sync** on; the device mirrors changes in
real time and emits its own play/stop/bpm/sel deltas back.
**Audio** is over **USB-MIDI** — turn on the editor's **🎹 Device audio** to hear the clicks through
your computer's speakers. The Scroll Pack has no buzzer; if you solder a piezo to a free GPIO, set
`P_BUZZER` near the top of `app.py` to that pin to get an on-device click.
## Views (button **B** cycles)
| View | What the 17 × 7 matrix shows |
| ---- | ---------------------------- |
| **Grid** (default) | Each lane is a **row** (top 7), each step a **column**; brightness = accent (bright) / normal / ghost (dim). A bright **playhead** column tracks the beat. Bars with ≤ 17 steps are centred one-column-per-step; longer bars are scaled to fit (multiple steps may share a column — no steps are dropped). |
| **Pendulum** | A single column **bounces** left↔right across the bar like a metronome arm, with a full-height flash on each beat (accent = brightest). Glanceable from across a room. |
| **BPM** | The current tempo as three 3 × 5 digits. |
## Controls
| Button | Tap | Hold |
| ------ | --- | ---- |
| **A** | play / stop | **≥ 0.6 s:** cycle view (Grid → Pendulum → BPM) |
| **B** | next track | **≥ 0.6 s:** next set list |
| **X** | tempo 1 | auto-repeat (after ~1.5 s the step grows to 5) |
| **Y** | tempo + 1 | auto-repeat (after ~1.5 s the step grows to + 5) |
Tap tempo lives in the web editor; the built-in playlists (Styles / Practice / Song) are baked into
firmware and your own set lists arrive in `/programs.json` over USB-MIDI. The mapping is deliberately
simple (this is a UI prototype) — all four buttons and their pins are at the top of `app.py`, easy to
re-bind.
## Pinout (verified against the Pimoroni `pico_scroll` library)
| Signal | Pico pin |
| ------ | -------- |
| Button A / B / X / Y | GP12 / GP13 / GP14 / GP15 |
| Matrix I²C SDA / SCL | GP4 / GP5 |
| IS31FL3731 address | `0x74` |
| (optional piezo) | any free GPIO → set `P_BUZZER` |
## Flashing
1. Hold **BOOTSEL**, plug the Pico in, and drag on **CircuitPython for Raspberry Pi Pico** (the same
10.2.x build the Kit uses). The drive remounts as `CIRCUITPY`.
2. Download **`/pm_g1_circuitpy.zip`** from <https://metronome.varasys.io> and unzip its contents onto
`CIRCUITPY` (`code.py`, `boot.py`, `app.mpy`, `programs.json`, fonts/icons, `editor.html`).
3. Reset. By default the firmware owns the drive (appliance mode); **hold button A while plugging in**
to make the drive writable again (editor mode).
The application is the precompiled **`app.mpy`** (the ~25 KB `app.py` source is too big to compile
on-device without OOM). Firmware updates are **one click** from the editor (⋯ → Update firmware),
pushed over USB-MIDI as an A/B update with automatic rollback — the device reports id **`G`** so the
editor sends the Grid build. Unbrickable: BOOTSEL + drag a `.uf2` always restores it.
## Status
This is the **CircuitPython prototype** used to nail down the LED-grid UI on real hardware. The
production firmware target is the native-Rust engine (one `pm-core` + per-board drivers — see
`docs/rust-port.md`); the Python builds stay as the simple, no-toolchain option in parallel.