Speaker rename (production device has a full audio circuit, not a buzzer): - MUTE_BUZZER -> MUTE_SPEAKER, self.buz -> self.spk, P_BUZ -> P_SPK - New SPEAKER_AUTO_MUTE flag (default True): mute the speaker when a MIDI host is detected (the old hardcoded behavior; now a setting). Gapless seam between tracks (Continue): - _prepare_next() pre-parses the next playlist item during the LAST bar so the swap is allocation-free. _do_advance() swaps lanes/bpm/bars/ramp/trainer in with lanes[0]['next'] = seam_t (the wall-clock time of the boundary step we just hit), no _reset_clock - the next tick fires step 0 of the new track exactly at the boundary. tick() breaks out at the seam so the old voice's boundary beat is NOT fired (it'd be the new track's step 0 a few ms later). Visuals (build_grid + draws) are deferred one display-refresh cycle behind the audio via _need_redraw, so the audio doesn't wait for them. Continuous ramp: - Replaced the bar-boundary set_bpm step with per-master-step linear interpolation: bpm = _ramp_base + amt * ((m_steps/mlen) % bars) / ramp.every (clamped 30..300). The integer-clamped bpm glides smoothly across the segment. draw_bpm() is now lazy (skips the bitmap alloc if the displayed integer hasn't changed), and the periodic meter tick in run() also redraws BPM so the big number follows the ramp. MIDI Clock Out (master): - New flags: MIDI_CHANNEL (default 10 = GM drum), MIDI_CLOCK_OUT (default OFF), MIDI_CLOCK_OUT_TRANSPORT (default ON). midi_send() now uses the configured channel. In tick(), when running + MIDI_CLOCK_OUT, stream 0xF8 at 24 PPQN with the interval computed live from self.bpm (so it follows the continuous ramp). toggle() sends 0xFA on Start and 0xFC on Stop when transport is enabled. Verified in harness: seam keeps lanes[0]['next'] = seam_t (no _reset_clock); ramp 80 glides via +0.25/step (visible as 80->81 in 4 master steps at rmp80/4/4); Clock Out math sound (60/120/180 BPM -> 41.67/20.83/13.89 ms tick interval). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
143 lines
9.5 KiB
HTML
143 lines
9.5 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, speaker). Pinout, parts list, and the precompiled CircuitPython firmware bundle." />
|
||
<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 a precompiled CircuitPython firmware bundle and one‑click updates over USB‑MIDI.</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>speaker</b> and two buttons — all pre‑wired, so you don't solder anything; you just seat the Pico
|
||
and drop the firmware bundle onto its USB drive.</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 and <b>Save to device</b> over USB‑MIDI (or edit on the device's touchscreen — beats,
|
||
lanes, playlists), and it plays standalone. Tap the screen, nudge tempo with the joystick; the RGB shows
|
||
run/stop and the beat pulse, and the speaker 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">Speaker</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, speaker, 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 — self‑contained appliance (USB drive · on‑device editing · push programming · MIDI audio · practice log)</summary>
|
||
<div class="spec-body">
|
||
<p class="sub">The firmware turns the Pico into a self‑contained appliance: it mounts as a
|
||
<b>USB drive</b> carrying the (precompiled) firmware, your tracks and an offline copy of this editor; drives
|
||
a full lanes/pads touchscreen with <b>on‑device editing</b> (tap beats, tap an instrument for the lane
|
||
editor, add/remove lanes, save/revert); <b>logs your practice</b> to <code>history.json</code>; 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).</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 speaker 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>
|