metronome/pico-scroll
Me Here 35726b57ac PM_G-1: scrolling boot splash (model name) + transient BPM flash on tempo nudge
The splash doubles as a liveness/pixel-map check (if 'PM-G1 GRID' reads correctly,
the firmware booted and the LED mapping is right). The BPM flash makes X/Y tempo
nudges visible from any view (previously invisible in Grid/Pendulum).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-05-31 21:08:33 -05:00
..
app.py PM_G-1: scrolling boot splash (model name) + transient BPM flash on tempo nudge 2026-05-31 21:08:33 -05:00
boot.py Add PM_G-1 "Grid" form factor (Pimoroni Pico Scroll Pack) + Rust core/driver plan 2026-05-31 20:30:15 -05:00
code.py Add PM_G-1 "Grid" form factor (Pimoroni Pico Scroll Pack) + Rust core/driver plan 2026-05-31 20:30:15 -05:00
programs.json Add PM_G-1 "Grid" form factor (Pimoroni Pico Scroll Pack) + Rust core/driver plan 2026-05-31 20:30:15 -05:00
README.md Add PM_G-1 "Grid" form factor (Pimoroni Pico Scroll Pack) + Rust core/driver plan 2026-05-31 20:30:15 -05:00

PM_G-1 "Grid" — CircuitPython edition (Pimoroni Pico Scroll Pack · RP2040)

The CircuitPython firmware for the Pimoroni Pico Scroll Pack (PIM545) 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.