metronome/info-kit.html
Me Here fd8446658d PM_K-1 0.0.14: gapless seam + continuous ramp + MIDI Clock Out (master); speaker rename
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>
2026-05-30 07:11:19 -05:00

143 lines
9.5 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>VARASYS PM_K1 Kit — wiring, parts &amp; firmware (Raspberry Pi Pico build)</title>
<meta name="description" content="PM_K1 Kit — build a touchscreen polymeter metronome from a Raspberry Pi Pico on the 52Pi EP0172 breadboard kit (3.5in ST7796 captouch, 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_K1 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 oneclick updates over USBMIDI.</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 EP0172 kit</span><span>~$45 incl. Pico</span></div>
<p>This is the first member of the family you can actually build today from offtheshelf parts: a
<b>Raspberry Pi Pico</b> seated on the <b>52Pi EP0172 "Pico Breadboard Kit Plus"</b>, which carries a
3.5″ <b>ST7796</b> 320×480 capacitivetouch screen (<b>GT911</b>), a PSP <b>joystick</b>, a <b>WS2812 RGB</b>
LED, a <b>speaker</b> and two buttons — all prewired, 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 USBMIDI (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 EP0172 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 &amp; 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 offtheshelf kit, not a custom board — ballpark oneoff 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 EP0172 "Pico Breadboard Kit Plus" <span class="spec">— 3.5″ ST7796 captouch, 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 (oneoff)</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 EP0172 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 — selfcontained appliance (USB drive · ondevice editing · push programming · MIDI audio · practice log)</summary>
<div class="spec-body">
<p class="sub">The firmware turns the Pico into a selfcontained 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>ondevice 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 USBMIDI</b>; and plays out your <b>computer's speakers over
USBMIDI</b>. By default the firmware owns the drive (readonly to the computer — so it can log and
can't be accidentally erased); hold <b>button A</b> at poweron 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 powercycle. 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 setlist <b></b> menu → <b>📟 Save to device</b>. It's pushed over USBMIDI 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 USBMIDI, 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 USBMIDI, and the device A/Bupdates 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>&lt;div&gt;</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_K1 Kit" };
/*@BUILD:include:src/infoembed.js@*/
/*@BUILD:include:src/chrome.js@*/
</script>
</body>
</html>