Split the CircuitPython firmware into a tiny stable loader (code.py) + the application (app.py, carries APP_VERSION). The editor's ⋯ → "⬆ Update firmware" queries the device version (SysEx 0x02 -> 0x03 reply), fetches the latest app from the site (/pico-cp-app.py), shows device-vs-latest, and pushes the new app.py over USB-MIDI (SysEx 0x20). The device installs it to a trial slot (old build kept as app.bak), reboots, and the loader AUTO-ROLLS-BACK to app.bak if the new build fails to start; a build that runs cleanly ~5s is confirmed (clears /trial). No BOOTSEL, no dragging; Chromium/Firefox. app.py forced to pure ASCII so it pushes raw (no base64); SysEx buffer raised to 60KB. build.sh/deploy.sh: bundle code.py+app.py and serve /pico-cp-app.py. Docs updated. Verified in CPython: version reply, update install+reboot+ACK, rollback file dance; editor loads clean with the updater wired. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
173 lines
12 KiB
HTML
173 lines
12 KiB
HTML
<!DOCTYPE html>
|
||
<html lang="en">
|
||
<head>
|
||
<meta charset="UTF-8" />
|
||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||
<title>VARASYS PM_K‑1 Kit — wiring, parts & firmware (Raspberry Pi Pico build)</title>
|
||
<meta name="description" content="PM_K‑1 Kit — build a touchscreen polymeter metronome from a Raspberry Pi Pico on the 52Pi EP‑0172 breadboard kit (3.5in ST7796 cap‑touch, joystick, RGB, buzzer). Pinout, parts list, and the MicroPython firmware to flash." />
|
||
<link rel="icon" type="image/svg+xml" href="data:image/svg+xml;base64,@BUILD:favicon@">
|
||
<script>
|
||
(function(){ try{ var p = localStorage.getItem("metronome.theme");
|
||
if (p!=="light" && p!=="dark" && p!=="system") p = "system";
|
||
document.documentElement.dataset.theme = p==="system" ? (matchMedia("(prefers-color-scheme: light)").matches ? "light" : "dark") : p;
|
||
} catch(e){ document.documentElement.dataset.theme = "dark"; } })();
|
||
</script>
|
||
<style>
|
||
/*@BUILD:include:src/base.css@*/
|
||
:root{ --bg1:#12151c; --bg2:#05070a; --txt:#c7d0db; --muted:#7f8b9a; --link:#6cb6ff;
|
||
--panel-bg:#161b22; --panel-bd:#2a313c; --field-bg:#0e1116; --field-bd:#2a313c; --silk:#aab2bc; }
|
||
:root[data-theme="light"]{ --bg1:#f5f8fc; --bg2:#dde4ec; --txt:#1e2630; --muted:#5c6776; --link:#1769c4;
|
||
--panel-bg:#ffffff; --panel-bd:#d2dae4; --field-bg:#f1f4f8; --field-bd:#d2dae4; }
|
||
body{ margin:0; min-height:100vh; padding:22px 16px 56px; color:var(--txt);
|
||
background:radial-gradient(circle at 50% -8%, var(--bg1), var(--bg2)); }
|
||
a{ color:var(--link); }
|
||
main{ width:100%; max-width:980px; margin:0 auto; }
|
||
.info-hero{ text-align:center; padding:16px 8px 2px; }
|
||
.info-hero h1{ font-size:clamp(24px,5vw,36px); margin:0; letter-spacing:-.01em; }
|
||
.info-hero .sub{ margin:9px auto 0; max-width:64ch; font-size:14.5px; }
|
||
.steps{ width:100%; max-width:760px; margin:8px auto 0; color:var(--muted); font-size:14px; line-height:1.6; }
|
||
.steps li{ margin:5px 0; }
|
||
.steps code, .about code, .sub code { background:var(--field-bg); border:1px solid var(--field-bd); border-radius:5px; padding:1px 5px; font-size:12.5px; }
|
||
.dl{ display:inline-flex; align-items:center; gap:7px; margin:4px 10px 4px 0; padding:9px 14px; border-radius:10px;
|
||
background:linear-gradient(180deg,#34c6ff,var(--cyan)); color:#04121b; font-weight:700; text-decoration:none; font-size:13.5px; }
|
||
.dl.alt{ background:var(--field-bg); color:var(--txt); border:1px solid var(--field-bd); font-weight:600; }
|
||
</style>
|
||
</head>
|
||
<body>
|
||
|
||
/*@BUILD:include:src/header.html@*/
|
||
|
||
<main>
|
||
<section class="info-hero">
|
||
<h1>PM_K‑1 Kit</h1>
|
||
<p class="sub">Build it yourself: a Raspberry Pi Pico on the 52Pi breadboard kit becomes a touchscreen polymeter metronome — same engine, same program strings, with MicroPython firmware you flash in two minutes.</p>
|
||
</section>
|
||
|
||
/*@BUILD:include:src/infoembed.html@*/
|
||
|
||
<section class="about">
|
||
<h2>What it is</h2>
|
||
<div class="ff-tags"><span class="hw">Buildable now</span><span>Raspberry Pi Pico</span><span>52Pi EP‑0172 kit</span><span>~$45 incl. Pico</span></div>
|
||
<p>This is the first member of the family you can actually build today from off‑the‑shelf parts: a
|
||
<b>Raspberry Pi Pico</b> seated on the <b>52Pi EP‑0172 "Pico Breadboard Kit Plus"</b>, which carries a
|
||
3.5″ <b>ST7796</b> 320×480 capacitive‑touch screen (<b>GT911</b>), a PSP <b>joystick</b>, a <b>WS2812 RGB</b>
|
||
LED, a <b>buzzer</b> and two buttons — all pre‑wired, so you don't solder anything; you just seat the Pico
|
||
and copy one file onto it.</p>
|
||
<p>It runs the same <b>polymeter engine</b> and the same <b>program strings</b> as the web editor: design a
|
||
groove on the site, copy its program string into the firmware's <code>PROGRAMS</code> list, and it plays on
|
||
the device. Tap the screen, nudge tempo with the joystick; the RGB flashes each beat (amber accent / cyan
|
||
normal / violet ghost) and the buzzer clicks. Powered over the Pico's USB.</p>
|
||
</section>
|
||
|
||
<details class="spec" open>
|
||
<summary>Wiring — the EP‑0172 fixed pinout (Raspberry Pi Pico)</summary>
|
||
<div class="spec-body">
|
||
<p class="sub">Everything is wired on the board; this is just what the firmware drives. No breadboarding required.</p>
|
||
<table class="bom">
|
||
<thead><tr><th>Component</th><th>Raspberry Pi Pico pins</th></tr></thead>
|
||
<tbody>
|
||
<tr class="grp"><td colspan="2">Display — 3.5″ ST7796, 320×480 (SPI0)</td></tr>
|
||
<tr><td class="part">SCK / MOSI</td><td>GP2 / GP3</td></tr>
|
||
<tr><td class="part">CS / DC / RST</td><td>GP5 / GP6 / GP7</td></tr>
|
||
<tr class="grp"><td colspan="2">Touch — GT911 capacitive (I2C0)</td></tr>
|
||
<tr><td class="part">SDA / SCL <span class="spec">— addr 0x5D</span></td><td>GP8 / GP9</td></tr>
|
||
<tr class="grp"><td colspan="2">Controls & feedback</td></tr>
|
||
<tr><td class="part">PSP joystick X / Y</td><td>ADC0 (GP26) / ADC1 (GP27)</td></tr>
|
||
<tr><td class="part">Button A (play/stop) / Button B (tap)</td><td>GP15 / GP14</td></tr>
|
||
<tr><td class="part">WS2812 RGB LED</td><td>GP12</td></tr>
|
||
<tr><td class="part">Buzzer</td><td>GP13</td></tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
</details>
|
||
|
||
<details class="spec" open>
|
||
<summary>Parts</summary>
|
||
<div class="spec-body">
|
||
<p class="sub">An off‑the‑shelf kit, not a custom board — ballpark one‑off prices (USD).</p>
|
||
<table class="bom">
|
||
<thead><tr><th>Part</th><th class="q">Qty</th><th class="c">~$</th></tr></thead>
|
||
<tbody>
|
||
<tr><td class="part">Raspberry Pi Pico (or Pico W / Pico 2) <span class="spec">— the brain</span></td><td class="q">1</td><td class="c">5</td></tr>
|
||
<tr><td class="part">52Pi EP‑0172 "Pico Breadboard Kit Plus" <span class="spec">— 3.5″ ST7796 cap‑touch, GT911, PSP joystick, WS2812 RGB, buzzer, 2 buttons, breadboard, acrylic panel</span></td><td class="q">1</td><td class="c">38</td></tr>
|
||
<tr><td class="part">USB cable <span class="spec">— power + flashing</span></td><td class="q">1</td><td class="c">2</td></tr>
|
||
<tr class="total"><td>Total (one‑off)</td><td class="q"></td><td class="c">≈ $45</td></tr>
|
||
</tbody>
|
||
</table>
|
||
<p class="sub" style="margin-top:10px">Reference: <a href="https://wiki.52pi.com/index.php?title=EP-0172" target="_blank" rel="noopener">52Pi EP‑0172 wiki</a>
|
||
· <a href="https://github.com/geeekpi/pico_breakboard_kit" target="_blank" rel="noopener">vendor code</a>. Lots may ship the screen as ST7796 (320×480) — this build targets that.</p>
|
||
</div>
|
||
</details>
|
||
|
||
<details class="spec" open>
|
||
<summary>Firmware — flash it in two minutes</summary>
|
||
<div class="spec-body">
|
||
<p>
|
||
<a class="dl" href="/pico-main.py" download="main.py">Download main.py ↓</a>
|
||
<a class="dl alt" href="https://codeberg.org/VARASYS/metronome/src/branch/main/pico" target="_blank" rel="noopener">Source + README ↗</a>
|
||
</p>
|
||
<p class="sub"><b>Two separate steps</b> — and <b><code>main.py</code> is not a drag‑and‑drop file.</b> The
|
||
<code>RPI‑RP2</code> drive only accepts a <code>.uf2</code> firmware file; a <code>.py</code> copied there is
|
||
discarded on reboot. You drag‑and‑drop the firmware once, then copy <code>main.py</code> over USB serial.</p>
|
||
<ol class="steps">
|
||
<li><b>Install MicroPython</b> (drag‑and‑drop, one time): hold <b>BOOTSEL</b>, plug the Pico into USB, and drop
|
||
the MicroPython <code>.uf2</code> onto the <code>RPI‑RP2</code> drive
|
||
(<a href="https://micropython.org/download/RPI_PICO/" target="_blank" rel="noopener">Pico</a> /
|
||
<a href="https://micropython.org/download/RPI_PICO2/" target="_blank" rel="noopener">Pico 2</a>). It reboots
|
||
on its own and the drive disappears — that's correct.</li>
|
||
<li><b>Copy <code>main.py</code></b> (the Pico is no longer a USB drive, so use a serial tool):
|
||
in <a href="https://thonny.org" target="_blank" rel="noopener">Thonny</a> pick the interpreter
|
||
<i>MicroPython (Raspberry Pi Pico)</i>, then <i>File ▸ Save as ▸ Raspberry Pi Pico</i> as <code>main.py</code>;
|
||
or <code>mpremote cp main.py :main.py</code>.</li>
|
||
<li>Reset — it boots straight into the metronome.</li>
|
||
<li>Add your own grooves by pasting program strings from the editor into the <code>PROGRAMS</code> list at the
|
||
top of <code>main.py</code>. If colours, touch, or the joystick look off, flip a flag in the
|
||
<code>CONFIG</code> block (see the README's calibration notes).</li>
|
||
</ol>
|
||
<p class="sub">It's one self‑contained file — the ST7796 driver, GT911 touch, WS2812 RGB, buzzer and the
|
||
polymeter engine, no external libraries.</p>
|
||
</div>
|
||
</details>
|
||
|
||
<details class="spec">
|
||
<summary>CircuitPython edition — self‑contained appliance (USB drive · push programming · MIDI audio · practice log)</summary>
|
||
<div class="spec-body">
|
||
<p class="sub">An alternative firmware that turns the Pico into a self‑contained appliance: it mounts as a
|
||
<b>USB drive</b> carrying the firmware, your tracks and an offline copy of this editor; drives a full
|
||
lanes/pads touchscreen; <b>logs your practice</b> to <code>history.json</code> on the device; takes new
|
||
set lists <b>pushed from the editor over USB‑MIDI</b>; and plays out your <b>computer's speakers over
|
||
USB‑MIDI</b>. By default the firmware owns the drive (read‑only to the computer — so it can log and
|
||
can't be accidentally erased); hold <b>button A</b> at power‑on for editor mode (drive writable). The
|
||
MicroPython firmware above stays the simple, rock‑solid option.</p>
|
||
<p>
|
||
<a class="dl" href="/pm_k1_circuitpy.zip" download>Download CircuitPython bundle ↓</a>
|
||
<a class="dl alt" href="https://codeberg.org/VARASYS/metronome/src/branch/main/pico-cp" target="_blank" rel="noopener">Source + README ↗</a>
|
||
</p>
|
||
<ol class="steps">
|
||
<li>Flash <b>CircuitPython</b> (<a href="https://circuitpython.org/board/raspberry_pi_pico/" target="_blank" rel="noopener">raspberry_pi_pico</a>)
|
||
via BOOTSEL, unzip the bundle onto <code>CIRCUITPY</code>, and power‑cycle. It boots into appliance mode.</li>
|
||
<li><b>Program it from the web:</b> build a set list in the <a href="/editor.html">editor</a> (Chrome/Edge/Firefox),
|
||
then the set‑list <b>⋯</b> menu → <b>📟 Save to device</b>. It's pushed over USB‑MIDI and the device shows
|
||
<b>Saved ✓</b>. (Fallback for any browser: it downloads <code>programs.json</code> — boot holding A and drag it on.)</li>
|
||
<li><b>Play through your computer:</b> click <b>🎹 Device audio</b>, then press play on the device — the full
|
||
groove sounds through your speakers over USB‑MIDI, in sync; the screen shows a <b>MIDI</b> badge and the buzzer mutes.</li>
|
||
<li><b>Practice log:</b> plays over 5 s appear at the bottom of the screen (time · BPM · duration · track); tap a row twice to delete.</li>
|
||
<li><b>Firmware updates:</b> ⋯ menu → <b>⬆ Update firmware</b> — it checks your version, pushes the latest over USB‑MIDI, and the device A/B‑updates with automatic rollback if a build won't boot.</li>
|
||
</ol>
|
||
</div>
|
||
</details>
|
||
|
||
<p class="sub" style="max-width:760px;margin:14px auto 0">Embed this widget elsewhere with one <code><div></code> + a script —
|
||
see <a href="/embed.html">the embed docs</a>.</p>
|
||
</main>
|
||
|
||
/*@BUILD:include:src/footer.html@*/
|
||
|
||
<script>
|
||
const APP_VERSION = "v0.0.1-dev";
|
||
window.INFO_DEVICE = { file:"/kit.html", name:"PM_K‑1 Kit" };
|
||
/*@BUILD:include:src/infoembed.js@*/
|
||
/*@BUILD:include:src/chrome.js@*/
|
||
</script>
|
||
</body>
|
||
</html>
|