The 320x240 landscape layout was too cramped vertically; multiple elements sat on the same Y rows, especially the BPM big-number area and the bar/time meters, plus the run dot collided with the MIDI/USB icons. Switching to portrait at 240x320 (display.rotation = 270; user holds the device with A/B/C buttons along the top) gives the same vertical real estate the PM_K-1 Kit's portrait UI uses, just narrower. Layout now mirrors the Kit: - y 0..28: header (logo + version + MIDI/USB icons + run dot) - y 44: BPM big (right) - y 50: elapsed time (left, FONT_M) - y 78: bar counter (left, FONT_M) - y 100: ramp / gap-trainer indicators - y 118: setlist tab + CONT (single row) - y 134: track title (FONT_M) - y 138+: pad grid (up to 6 lanes, taller rowh ceiling now 30px) Plus: - DISPLAY_ROTATION constant near the top of CONFIG so the user can flip it to 90 / 180 if their orientation differs. - Pad grid uses px0=48 (was 60) since the lane label column has less horizontal room at 240 width; max 6-char labels. - Removed the inline modal hints (e.g. "X/Z move, A select, C close") that would have collided with the modal titles at 240 width. The Help screen documents the modal nav pattern, which is consistent across modals. - HELP_PAGES page 1 leads with "Hold portrait with A/B/C on top." - README documents the rotation flag. Bumps Explorer to 0.0.2. .mpy can be pushed via the editor's Update firmware flow (device id reply = X;0.0.1 -> editor fetches the right .mpy). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
80 lines
4.2 KiB
Markdown
80 lines
4.2 KiB
Markdown
# PM_X-1 "Explorer" — CircuitPython edition (Pimoroni Explorer · RP2350)
|
||
|
||
The **CircuitPython** firmware for the [Pimoroni Explorer Kit (PIM744)](https://shop.pimoroni.com/products/explorer),
|
||
set up as a self-contained appliance. Sibling to the PM_K-1 build in `../pico-cp/` (the 52Pi EP-0172
|
||
kit) — same engine, same program strings, same `programs.json`, same web editor.
|
||
|
||
This board is a **2.8″ ST7789V LCD + 6 user buttons + piezo speaker** built around an RP2350B
|
||
(Pico 2 class chip). **No touchscreen, no joystick, no RGB LED.** Editing is done 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.
|
||
|
||
**Hold the device in portrait** with the A/B/C buttons along the top and X/Y/Z along the
|
||
bottom. The firmware drives the LCD as a **240 × 320 portrait** at `display.rotation = 270` —
|
||
same UI shape as the PM_K-1 Kit, just shorter. If the screen comes up upside-down on your
|
||
unit, change `DISPLAY_ROTATION` near the top of `app.py` to `90` (or `180` if rotated 180°)
|
||
and re-flash.
|
||
|
||
## Controls
|
||
|
||
| Button | Action |
|
||
| ------ | --------------------------------------------------------------------- |
|
||
| **A** | play / stop |
|
||
| **B** | tap tempo |
|
||
| **C** | menu (Settings / Help / About / Practice log) |
|
||
| **X** | prev track (hold to repeat) |
|
||
| **Y** | tempo −1 (hold to repeat; after ~1.5 s the step grows to −5) |
|
||
| **Z** | next track (hold to repeat) |
|
||
| **X + Z** | tempo +1 (chord; same hold-repeat as Y) |
|
||
|
||
In a menu: **X / Z** move the cursor up / down, **Y** decrements the focused value, **A** commits or
|
||
cycles, **B** = back, **C** = close.
|
||
|
||
## Install
|
||
|
||
1. **Flash CircuitPython for Pico 2 / RP2350.** Hold **BOOTSEL** on the Explorer, plug it in over
|
||
USB-C, drop the [Pimoroni Explorer (RP2350) CircuitPython `.uf2`](https://circuitpython.org/board/pimoroni_explorer2350/)
|
||
onto the `RP2350` drive. A `CIRCUITPY` drive appears.
|
||
2. **Copy the bundle onto `CIRCUITPY`** — `boot.py`, `code.py`, **`app.mpy`**, `programs.json`,
|
||
`font_s.bin` / `font_m.bin` / `font_l.bin`, `logo.bin` / `midi.bin` / `usb.bin`, `editor.html`
|
||
(offline editor). If an old `app.py` is on the drive, delete it.
|
||
3. **Power-cycle.** It boots into appliance mode and runs.
|
||
|
||
## Program it from the web
|
||
|
||
Open <https://metronome.varasys.io> in Chrome / Edge / Firefox. The set-list **⋯** menu →
|
||
**📟 Save to device** pushes a `programs.json` over USB-MIDI; the device persists it and reloads.
|
||
Click **🔗 Live sync** to mirror edits in real time.
|
||
|
||
## Pin reference
|
||
|
||
The display, buttons, and audio are wired into the board — no jumpers required. CircuitPython's
|
||
official board definition for `pimoroni_explorer2350` exposes `board.DISPLAY` pre-initialized, so
|
||
the firmware just uses it.
|
||
|
||
| Function | GPIO |
|
||
| ----------------- | -------- |
|
||
| Button A | GP16 |
|
||
| Button B | GP15 |
|
||
| Button C | GP14 |
|
||
| Button X | GP17 |
|
||
| Button Y | GP18 |
|
||
| Button Z | GP19 |
|
||
| Piezo audio (PWM) | GP12 |
|
||
| Piezo amp enable | GP13 |
|
||
| I²C SDA (QwSTEMMA) | GP20 |
|
||
| I²C SCL (QwSTEMMA) | GP21 |
|
||
| Display | `board.DISPLAY` (8080 parallel bus on GP26..GP39, initialized by board.c) |
|
||
|
||
## Calibration (flags at the top of `app.py`)
|
||
|
||
- **Speaker too loud / quiet:** the piezo + amp gain is fixed in hardware. `MUTE_SPEAKER`
|
||
silences the click; `SPEAKER_AUTO_MUTE` auto-mutes when a MIDI host is listening.
|
||
- **Buttons feel inverted:** the polarity is hard-coded to active-low (pull-up). If a button
|
||
fires on release instead of press, check the `BTN_*` pin map at the top of `app.py`.
|
||
- **Display orientation:** the board's CircuitPython init mounts the panel landscape
|
||
(320 × 240). If your screen looks rotated, that's a board.c-level thing — file a CircuitPython
|
||
bug, don't patch the firmware.
|
||
|
||
If `app.py` ever errors, CircuitPython prints the traceback **on the screen and over USB serial** —
|
||
send me that.
|