# PM_K‑1 "Kit" — VARASYS PolyMeter firmware for the Raspberry Pi Pico

MicroPython firmware that turns a **Raspberry Pi Pico** on the **52Pi EP‑0172 "Pico
Breadboard Kit Plus"** into a touchscreen polymeter metronome. It runs the *same program
strings* as <https://metronome.varasys.io> — design a groove in the web editor, copy its
program string, paste it into `PROGRAMS` in `main.py`, and it plays here.

Everything is in one file: `main.py` (ST7796 display driver, GT911 touch, WS2812 RGB,
buzzer, joystick, the polymeter engine — no external libraries).

## The board (EP‑0172) — fixed pinout

| Component | Pico pins |
|---|---|
| 3.5″ ST7796 320×480 display | SPI0 — SCK `GP2`, MOSI `GP3`, CS `GP5`, DC `GP6`, RST `GP7` |
| GT911 capacitive touch | I2C0 — SDA `GP8`, SCL `GP9` (addr 0x5D) |
| WS2812 RGB LED | `GP12` |
| Buzzer | `GP13` |
| Button A / Button B | `GP15` / `GP14` |
| PSP joystick | X = `ADC0`/`GP26`, Y = `ADC1`/`GP27` |

The components are wired on the board — you don't breadboard anything; just seat the Pico.

## Flash it — TWO separate steps

> ⚠️ **`main.py` is NOT a drag-and-drop file.** The `RPI-RP2` drive that appears in BOOTSEL mode
> is the bootloader, and it *only* accepts a `.uf2` firmware file — anything else (like `main.py`)
> is silently discarded on the next reboot. You first flash MicroPython with a `.uf2` (drag-and-drop),
> and *then* copy `main.py` over the USB serial link with Thonny or mpremote. Two different steps.

### Step 1 — install MicroPython (drag-and-drop a `.uf2`, one time)

1. Download the MicroPython firmware **`.uf2`** for your board:
   - Pico / Pico W → <https://micropython.org/download/RPI_PICO/> (or `RPI_PICO_W`)
   - Pico 2 / Pico 2 W → <https://micropython.org/download/RPI_PICO2/>
2. Hold **BOOTSEL**, plug into USB → the `RPI-RP2` drive appears.
3. **Drag the `.uf2` file onto that drive.** It copies, the Pico reboots on its own, and the drive
   **disappears** — that's correct and means MicroPython is installed. (Don't use BOOTSEL again unless
   you're reinstalling the firmware.)

### Step 2 — copy `main.py` (over USB serial, NOT to a drive)

After step 1 the Pico runs MicroPython and **no longer shows up as a USB drive** — so you can't drag
files to it. Use a tool that talks to it over USB serial:

- **Thonny (easiest):** install [Thonny](https://thonny.org), plug the Pico in normally, then
  bottom-right click the interpreter selector → **MicroPython (Raspberry Pi Pico)** (you should see
  a `>>>` prompt in the Shell). Open `main.py`, then **File ▸ Save as… ▸ Raspberry Pi Pico** and save
  it as exactly **`main.py`**.
- **mpremote (command line):** `pip install mpremote` then `mpremote cp main.py :main.py`

Reset (replug) and it boots straight into the metronome.

## Controls

- **Touch:** on‑screen `<<` / `>||` / `>>` (prev · play/stop · next) and `−` / `TAP` / `+`.
- **Joystick:** up/down = tempo (push far for ±5), left/right = previous/next groove.
- **Button A (GP15):** play / stop. **Button B (GP14):** tap tempo.
- **RGB LED** flashes each beat (amber = accent, cyan = normal, violet = ghost); the
  **buzzer** clicks with matching pitch.

## Add your own grooves

Edit the `PROGRAMS` list near the top of `main.py` — each entry is `("Name", "program string")`.
Get program strings from the web editor's program box (e.g. `v1;t120;kick:4;snare:4=.X.X;hat:4/2`).
Supported: tempo `t<bpm>`, lanes `sound:grouping[/sub][=pattern][~][!]`, pattern chars
`X` accent · `x` normal · `g` ghost · `.` `-` `_` rest, grouped meters like `3+3+2`, polymeter `~`.
(Per‑lane dB gain `@n` is parsed but ignored — the buzzer is mono.)

## If something looks off — calibration

All the knobs are flags in the `CONFIG` block at the top of `main.py`:

- **Colours look negative / washed out:** toggle `INVERT_COLORS`.
- **Red and blue swapped:** set `SWAP_RB = True`.
- **Taps land in the wrong place:** set `TOUCH_DEBUG = True`, reset, watch the raw
  coordinates over the USB serial (Thonny shell) as you tap the corners, then set
  `TOUCH_SWAP_XY` / `TOUCH_INVERT_X` / `TOUCH_INVERT_Y` to match.
- **Joystick reversed:** toggle `JOY_INVERT_X` / `JOY_INVERT_Y`; widen `JOY_DEADZONE` if it drifts.
- **Screen stays black:** the backlight is hardwired on, so this usually means the SPI init
  didn't take — drop `SPI_BAUD` to `24_000_000` and retry.
- **Garbled / wrong size image:** your panel lot may be a 240×320 ILI9341 instead of the
  320×480 ST7796. This firmware targets the ST7796 you have (you said 320×480); if a unit
  ever ships ILI9341, set `WIDTH,HEIGHT = 240,320` and use an ILI9341 init sequence.

## Notes

- Audio is a single passive buzzer, so coincident lane hits play one click at the highest
  priority (accent > normal > ghost); the RGB + screen still show the combined activity.
- The scheduler is non‑blocking and timed off `time.ticks_us()`, so tempo stays steady while
  the screen and inputs update.

Hardware reference: [52Pi EP‑0172 wiki](https://wiki.52pi.com/index.php?title=EP-0172) ·
[vendor code](https://github.com/geeekpi/pico_breakboard_kit). VARASYS — Simplifying Complexity.
