# 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 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.