Files
seedbox/tools/wiring-src/render.js
Gee 2196633ed5
Some checks failed
check / check (push) Has been cancelled
Seedbox v0.1 + firmware, generic kit/synth, ROOT/SCALE pages
First commit of the repo. Contents beyond the v0.1 simulator and layout:

- Full Pico 2 W firmware (firmware/app, drivers, engine port, host test).
- BANK page and 404 mode A/B removed; learned pads play exactly what was learned.
- 404/MiniFreak renamed to KIT/SYNTH throughout (jacks, code, sim, docs,
  layout labels; wiring rebuilt).
- ROLL returns to page select after a re-roll; a freshly learned track turns on.
- LCD contrast 66.
- ROOT and SCALE pages: 21 scales, AUTO = the seed picks; global and sticky.

Intended music change: the scale table grew from 8 to 21 and AUTO picks from
all of them, so every seed's scale changed. Vectors regenerated with
npm run vectors, plus new key-override cases. Flash record is now version 2.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-11 20:39:36 +03:00

247 lines
24 KiB
JavaScript
Raw Permalink 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.
(function(){
var L=LAYOUT, NS='http://www.w3.org/2000/svg';
function css(n){ return getComputedStyle(document.documentElement).getPropertyValue(n).trim(); }
function el(tag,a,p,txt){ var e=document.createElementNS(NS,tag); for(var k in a) e.setAttribute(k,a[k]); if(txt!=null) e.textContent=txt; p.appendChild(e); return e; }
function rowName(r){ return r<26 ? String.fromCharCode(65+r) : 'A'+String.fromCharCode(65+r-26); }
function pos(h){ return rowName(h[1])+(h[0]+1); }
function H(p){ return /^P\d+$/.test(p) ? pos(L.wires[+p.slice(1)-1].h) : p; }
var COL={red:'--w-red',black:'--w-black',yellow:'--w-yellow',green:'--w-green',blue:'--w-blue'};
var cutKey={}; L.cuts.forEach(function(c){ cutKey[c[0]+','+c[1]]=1; });
function strips(svg,X,C,strong){
for(var r=0;r<L.H;r++){
var start=0;
for(var c=0;c<=L.W;c++){
if(c===L.W || cutKey[c+','+r]){
if(c>start){ var x0=Math.min(X(start),X(c-1))-0.42, x1=Math.max(X(start),X(c-1))+0.42;
el('rect',{x:x0,y:r-0.36,width:x1-x0,height:0.72,rx:0.2,fill:C.copper,opacity:strong?1:0.28},svg); }
start=c+1;
}
}
}
}
function holes(svg,X,C){ for(var r=0;r<L.H;r++) for(var c=0;c<L.W;c++) el('circle',{cx:X(c),cy:r,r:0.16,fill:C.hole},svg); }
function labels(svg,X,C,flip){
var g=el('g',{'font-family':css('--f-mono'),'font-size':'0.55',fill:C.muted},svg);
for(var c=0;c<L.W;c++) if(c%2===0 || c===L.W-1){ el('text',{x:X(c),y:-1.75,'text-anchor':'middle'},g,String(c+1)); el('text',{x:X(c),y:L.H+0.9,'text-anchor':'middle'},g,String(c+1)); }
for(var r=0;r<L.H;r++){ el('text',{x:-1.3,y:r+0.2,'text-anchor':'middle'},g,rowName(r)); el('text',{x:L.W+0.3,y:r+0.2,'text-anchor':'middle'},g,rowName(r)); }
}
function frame(svg){ svg.setAttribute('viewBox','-2.4 -2.6 '+(L.W+3.8)+' '+(L.H+4.0)); }
var U1label=(L.parts.filter(function(p){ return p.id==='U1'; })[0]||{}).label||'';
function drawTop(){
var svg=document.getElementById('top'); svg.innerHTML=''; frame(svg);
var C={copper:css('--copper'),hole:css('--hole'),muted:css('--muted'),part:css('--part'),pink:css('--part-ink'),link:css('--link'),warn:css('--warn'),board:css('--board'),edge:css('--board-edge'),ink:css('--ink')};
var X=function(c){ return c; };
el('rect',{x:-0.8,y:-0.5,width:L.W+0.6,height:L.H+0.3,rx:0.4,fill:C.board,stroke:C.edge,'stroke-width':0.12},svg);
strips(svg,X,C,false); holes(svg,X,C); labels(svg,X,C);
L.cuts.forEach(function(c){ var g={stroke:C.warn,'stroke-width':0.1,opacity:0.7}; el('line',Object.assign({x1:c[0]-0.22,y1:c[1]-0.22,x2:c[0]+0.22,y2:c[1]+0.22},g),svg); el('line',Object.assign({x1:c[0]-0.22,y1:c[1]+0.22,x2:c[0]+0.22,y2:c[1]-0.22},g),svg); });
var f=css('--f-mono');
L.parts.forEach(function(p){
if(p.kind==='pico'){
el('rect',{x:11.3,y:-0.55,width:8.4,height:20.1,rx:0.4,fill:C.part,opacity:0.92},svg);
el('rect',{x:14.3,y:-1.35,width:2.4,height:1.35,rx:0.2,fill:'#9AA3AD'},svg); el('text',{x:15.5,y:-0.55,'text-anchor':'middle','font-family':f,'font-size':'0.42',fill:'#111'},svg,'USB');
el('text',{x:15.5,y:1.6,'text-anchor':'middle','font-family':f,'font-size':'0.62',fill:C.pink},svg,'PICO 2W');
p.pins.forEach(function(pp){ var left=pp.h[0]===12;
el('rect',{x:pp.h[0]-0.32,y:pp.h[1]-0.32,width:0.64,height:0.64,fill:'#111',stroke:'#D4AF37','stroke-width':0.08},svg);
el('text',{x:left?pp.h[0]+0.55:pp.h[0]-0.55,y:pp.h[1]+0.16,'text-anchor':left?'start':'end','font-family':f,'font-size':'0.42',fill:C.pink},svg,pp.n); });
} else if(p.kind==='dip8'){
el('rect',{x:4.25,y:19.55,width:2.5,height:3.9,rx:0.15,fill:C.part},svg);
el('path',{d:'M 5 19.55 a 0.5 0.5 0 0 0 1 0',fill:'#555'},svg);
el('text',{x:5.5,y:21.7,'text-anchor':'middle','font-family':f,'font-size':'0.42',fill:C.pink,transform:'rotate(90 5.5 21.6)'},svg,U1label);
p.pins.forEach(function(pp){ el('rect',{x:pp.h[0]-0.25,y:pp.h[1]-0.18,width:0.5,height:0.36,fill:'#BFC6CD'},svg); });
el('text',{x:3.55,y:20.15,'text-anchor':'end','font-family':f,'font-size':'0.4',fill:C.ink},svg,'1');
} else {
var a=p.pins[0].h, b=p.pins[1].h, horiz=a[1]===b[1], mx=(a[0]+b[0])/2, my=(a[1]+b[1])/2, len=horiz?Math.abs(b[0]-a[0]):Math.abs(b[1]-a[1]);
el('line',{x1:a[0],y1:a[1],x2:b[0],y2:b[1],stroke:'#9AA3AD','stroke-width':0.12},svg);
var bw=p.kind==='cap'?0.7:0.62, bh=Math.min(len-0.5,p.kind==='diode'?0.7:2.2);
var body=p.kind==='res'?'#C9A26B':p.kind==='diode'?'#D9663A':'#3D7BC9';
if(horiz){ el('rect',{x:mx-bh/2,y:my-bw/2,width:bh,height:bw,rx:0.25,fill:body,stroke:'#00000055','stroke-width':0.05},svg);
el('text',{x:mx,y:my-0.5,'text-anchor':'middle','font-family':f,'font-size':'0.42',fill:C.ink},svg,p.id); }
else el('rect',{x:a[0]-bw/2,y:my-bh/2,width:bw,height:bh,rx:0.25,fill:body,stroke:'#00000055','stroke-width':0.05,'stroke-dasharray':p.opt?'0.2 0.12':''},svg);
if(p.kind==='diode'){ var ky=p.pins[0].n==='K'?p.pins[0].h[1]:p.pins[1].h[1]; el('rect',{x:a[0]-bw/2,y:(ky<my?my-bh/2:my+bh/2-0.16),width:bw,height:0.16,fill:'#111'},svg); }
if(!horiz) el('text',{x:a[0]+0.48,y:my+0.15,'font-family':f,'font-size':'0.42',fill:C.ink},svg,p.id+(p.opt?'*':''));
}
p.pins.forEach(function(pp){ if(p.kind!=='pico') el('circle',{cx:pp.h[0],cy:pp.h[1],r:0.13,fill:'#D4AF37'},svg); });
});
L.jumpers.forEach(function(j){
el('line',{x1:j.a[0],y1:j.a[1],x2:j.b[0],y2:j.b[1],stroke:C.link,'stroke-width':0.2,'stroke-linecap':'round',opacity:0.9},svg);
[j.a,j.b].forEach(function(h){ el('circle',{cx:h[0],cy:h[1],r:0.2,fill:C.link},svg); });
});
L.wires.forEach(function(w,i){
var col=css(COL[w.col]);
el('circle',{cx:w.h[0],cy:w.h[1],r:0.3,fill:col,stroke:'#fff','stroke-width':0.07},svg);
var right=w.h[0]>=20, tx=w.h[0]+(right?0.42:-0.42);
el('text',{x:tx,y:w.h[1]-0.3,'text-anchor':right?'start':'end','font-family':f,'font-size':'0.48','font-weight':'700',fill:C.ink},svg,'P'+(i+1));
});
var rails=[[25,'5 V'],[26,'GND'],[27,'3V3']];
rails.forEach(function(r){ el('text',{x:L.W+1.15,y:r[0]+0.2,'font-family':f,'font-size':'0.45',fill:C.warn},svg,r[1]); });
}
function drawBottom(){
var svg=document.getElementById('bottom'); svg.innerHTML=''; frame(svg);
var C={copper:css('--copper'),hole:css('--hole'),muted:css('--muted'),warn:css('--warn'),board:css('--board'),edge:css('--board-edge'),part:css('--part')};
var X=function(c){ return L.W-1-c; };
el('rect',{x:-0.8,y:-0.5,width:L.W+0.6,height:L.H+0.3,rx:0.4,fill:C.board,stroke:C.edge,'stroke-width':0.12},svg);
strips(svg,X,C,true); holes(svg,X,C); labels(svg,X,C);
el('rect',{x:X(19)-0.5,y:-0.55,width:8.4,height:20.1,rx:0.4,fill:'none',stroke:C.muted,'stroke-width':0.08,'stroke-dasharray':'0.3 0.2'},svg);
el('text',{x:X(15.5),y:-0.85,'text-anchor':'middle','font-family':css('--f-mono'),'font-size':'0.42',fill:C.muted},svg,'Pico outline (other side), USB at this edge');
L.cuts.forEach(function(c){ var x=X(c[0]);
el('rect',{x:x-0.45,y:c[1]-0.45,width:0.9,height:0.9,rx:0.15,fill:C.board},svg);
el('circle',{cx:x,cy:c[1],r:0.34,fill:'none',stroke:C.warn,'stroke-width':0.14},svg); });
var cl=document.getElementById('cutlist'); cl.innerHTML='';
var groups={}; L.cuts.forEach(function(c){ (groups[c[0]]=groups[c[0]]||[]).push(c[1]); });
Object.keys(groups).forEach(function(k){ var rs=groups[k].sort(function(a,b){return a-b;}); var li=document.createElement('li');
li.textContent='Hole '+(+k+1)+(rs.length>1?' on strips '+rowName(rs[0])+' to '+rowName(rs[rs.length-1])+' ('+rs.length+' cuts)':' on strip '+rowName(rs[0])+' (1 cut)'); cl.appendChild(li); });
}
function tables(){
var pl=document.getElementById('partlist'); pl.innerHTML='';
function row(tb,cells,mcols){ var tr=document.createElement('tr'); cells.forEach(function(c,i){ var td=document.createElement('td'); if(mcols.indexOf(i)>=0) td.className='m'; if(c && c.nodeType) td.appendChild(c); else td.textContent=c; tr.appendChild(td); }); tb.appendChild(tr); }
var notes={U1:'6N137 in a DIP-8 socket. Notch toward strip U, pin 1 at hole U5. Pin 7 (enable) is tied to pin 8 by the U10–V10 link.',R1:'MIDI IN current limit. 3-hole span: stand it upright, or use a small ⅛ W part flat. If learning ever misses notes, use 150 Ω.',D1:'Band (cathode) on V4, the opto LED anode side. Stands upright (1-hole span).',R2:'Opto output pull-up to 3.3 V',C1:'6N137 supply bypass, right beside the chip: U11 is its 5 V (pin 8) strip, X11 its GND (pin 5) strip. Required. Fit it after the beep test.',R4:'MIDI OUT KIT, TX line (RC). Lies flat along strip X, across the cut at X23 (4-hole span, ¼ W fits). SEED hangs right above it.',R5:'MIDI OUT KIT, 3.3 V line (RA). ½ W: a mono plug in the jack shorts it to ground.',R6:'MIDI OUT SYNTH, TX line (RC)',R7:'MIDI OUT SYNTH, 3.3 V line (RA). ½ W, same reason as R5.'};
row(pl,['Pico 2W','2 × 20-pin female header','A13–T13 and A20–T20 (pins 1–20 down the left, 40–21 down the right)','USB end flush with the top edge of the board, past strip A'],[2]);
L.parts.forEach(function(p){ if(p.kind==='pico') return;
row(pl,[p.id,p.label,p.kind==='dip8'?'U5–X5, U8–X8':p.pins.map(function(pp){ return pos(pp.h); }).join(' – '),notes[p.id]||''],[2]); });
L.jumpers.forEach(function(j){ row(pl,['Link','wire',pos(j.a)+' – '+pos(j.b),j.n],[2]); });
var picoAt={}; L.parts[0].pins.forEach(function(pp){ picoAt[pp.h[1]+(pp.h[0]===12?'L':'R')]=pp.n; });
function pinFor(h){ var r=h[1]; if(r>=0 && r<=19) return picoAt[r+(h[0]<15?'L':'R')]; if(r===25) return '5 V strip'; if(r===26) return 'GND strip'; if(r===27) return '3V3 strip';
return {'0,24':'via R1 to opto','0,22':'opto cathode','25,23':'via R4 (10 Ω) from GP0','21,21':'via R5 (33 Ω) from 3V3','30,20':'via R6 (10 Ω) from GP4','30,21':'via R7 (33 Ω) from 3V3'}[h[0]+','+h[1]]||''; }
var wl=document.getElementById('wirelist'); wl.innerHTML='';
L.wires.forEach(function(w,i){ var s=document.createElement('span'); var sw=document.createElement('span'); sw.className='sw'; sw.style.background='var('+COL[w.col]+')'; s.appendChild(sw); s.appendChild(document.createTextNode(w.col));
row(wl,['P'+(i+1),pos(w.h),s,pinFor(w.h),w.to],[0,1]); });
}
function drawMatrix(){ // drawn from the BACK (lug side), so the columns are mirrored: col 4 on the left, KICK top-right
var svg=document.getElementById('matrix'); svg.innerHTML=''; svg.setAttribute('viewBox','0 0 700 330');
var C={y:css('--w-yellow'),g:css('--w-green'),ink:css('--ink'),muted:css('--muted'),part:css('--part'),line:css('--line')}, f=css('--f-mono');
var names=[['KICK','KICK 2','SNARE',null],['HAT','HAT 16','PERC','GHOST'],['BASS','MEL A','MEL B','PAD']];
var x0=110, dx=118, y0=84, dy=80, rowEnd=560;
function bxOf(c){ return x0+(3-c)*dx; }
for(var c=0;c<4;c++){ var cx=bxOf(c)-38; el('line',{x1:cx,y1:c===3?y0+dy-28:y0-10,x2:cx,y2:y0+2*dy+40,stroke:C.g,'stroke-width':3},svg);
el('text',{x:cx,y:y0+2*dy+60,'text-anchor':'middle','font-family':f,'font-size':12,'font-weight':700,fill:C.ink},svg,'Col '+(c+1)+' → '+H('P'+(32+c))); }
for(var r=0;r<3;r++){ var ry=y0+r*dy-18, left=bxOf(r===0?2:3)+9;
el('line',{x1:left,y1:ry,x2:rowEnd,y2:ry,stroke:C.y,'stroke-width':3},svg);
el('text',{x:rowEnd+6,y:ry+4,'font-family':f,'font-size':12,'font-weight':700,fill:C.ink},svg,'Row '+(r+1)+' → '+H('P'+(29+r)));
for(c=0;c<4;c++){ var bx=bxOf(c), by=y0+r*dy;
if(!names[r][c]){ el('rect',{x:bx-12,y:by-16,width:24,height:32,rx:4,fill:'none',stroke:C.muted,'stroke-width':1.2,'stroke-dasharray':'4 3'},svg);
el('text',{x:bx,y:by+4,'text-anchor':'middle','font-family':f,'font-size':10,fill:C.ink},svg,'RUN');
el('text',{x:bx,y:by+34,'text-anchor':'middle','font-family':f,'font-size':9,fill:C.muted},svg,'toggle, not in matrix'); continue; }
el('circle',{cx:bx,cy:by,r:17,fill:C.part},svg);
el('text',{x:bx,y:by+34,'text-anchor':'middle','font-family':f,'font-size':11,fill:C.muted},svg,names[r][c]);
var lRow=bx+9, lDio=bx-9, colX=bx-38;
el('circle',{cx:lRow,cy:by,r:3.2,fill:'#D4AF37'},svg); el('circle',{cx:lDio,cy:by,r:3.2,fill:'#D4AF37'},svg);
el('line',{x1:lRow,y1:by-3,x2:lRow,y2:ry,stroke:C.y,'stroke-width':2},svg);
el('line',{x1:lDio,y1:by,x2:colX,y2:by,stroke:'#9AA3AD','stroke-width':1.5},svg);
el('rect',{x:colX+4,y:by-4,width:18,height:8,rx:2,fill:'#D9663A'},svg); el('rect',{x:colX+4,y:by-4,width:4,height:8,fill:'#111'},svg);
}
}
el('text',{x:x0-60,y:22,'font-family':f,'font-size':12,'font-weight':700,fill:C.ink},svg,'Seen from the BACK (lug side): KICK is top-right.');
el('text',{x:x0-60,y:38,'font-family':f,'font-size':10,fill:C.muted},svg,'Diode band → column wire. Lid flipped left to right, back wall still at the top.');
}
function drawDin(){ // 3.5 mm TRS panel jacks, Type A, lugs seen from inside the box
var svg=document.getElementById('din'); svg.innerHTML='';
var f=css('--f-mono'), ink=css('--ink'), m=css('--muted');
var jacks=[{n:'IN',x:52,w:{T:['--w-blue','P2'],R:['--w-blue','P1']}},{n:'OUT KIT',x:150,w:{T:['--w-blue','P3'],R:['--w-red','P4'],S:['--w-black','P5']}},{n:'OUT SYNTH',x:248,w:{T:['--w-blue','P6'],R:['--w-red','P7'],S:['--w-black','P8']}}];
var LUG={T:[-20,'T·5'],R:[0,'R·4'],S:[20,'S·2']};
jacks.forEach(function(j){
el('rect',{x:j.x-30,y:30,width:60,height:34,rx:4,fill:'#2C3238'},svg);
el('circle',{cx:j.x,cy:47,r:9,fill:'none',stroke:'#9AA3AD','stroke-width':2},svg);
Object.keys(LUG).forEach(function(k){ var lx=j.x+LUG[k][0], used=j.w[k];
el('rect',{x:lx-3,y:64,width:6,height:12,fill:'#C9CFD5'},svg);
if(used){ el('line',{x1:lx,y1:76,x2:lx,y2:100,stroke:css(used[0]),'stroke-width':4,'stroke-linecap':'round'},svg);
el('text',{x:lx,y:112,'text-anchor':'middle','font-family':f,'font-size':11,'font-weight':700,fill:ink},svg,H(used[1])); }
else el('text',{x:lx,y:90,'text-anchor':'middle','font-family':f,'font-size':8,fill:m},svg,'—');
el('text',{x:lx,y:124,'text-anchor':'middle','font-family':f,'font-size':8,fill:m},svg,LUG[k][1]); });
el('text',{x:j.x,y:142,'text-anchor':'middle','font-family':f,'font-size':11,fill:ink},svg,j.n); });
el('text',{x:150,y:14,'text-anchor':'middle','font-family':f,'font-size':9,fill:m},svg,'Type A · T tip = pin 5 · R ring = 4 · S sleeve = 2');
}
function pinRow(id,pins,w){
var svg=document.getElementById(id); svg.innerHTML=''; var f=css('--f-mono'), ink=css('--ink');
var n=pins.length, sp=Math.min(36,260/n), x0=150-sp*(n-1)/2;
pins.forEach(function(p,i){ var x=x0+i*sp;
el('rect',{x:x-6,y:14,width:12,height:12,fill:'#111',stroke:'#D4AF37','stroke-width':1.5},svg);
el('line',{x1:x,y1:26,x2:x,y2:52,stroke:p[1]?css(p[1]):'none','stroke-width':4,'stroke-linecap':'round'},svg);
el('text',{x:x,y:10,'text-anchor':'middle','font-family':f,'font-size':n>6?8:9,fill:ink},svg,p[0]);
el('text',{x:x,y:68,'text-anchor':'middle','font-family':f,'font-size':10,'font-weight':700,fill:ink},svg,H(p[2]||'')); });
}
function drawMisc(){
var svg=document.getElementById('misc'); svg.innerHTML=''; var f=css('--f-mono'), ink=css('--ink'), m=css('--muted');
function pot(x,label,wp){ el('circle',{cx:x,cy:42,r:20,fill:'#2C3238'},svg); el('text',{x:x,y:14,'text-anchor':'middle','font-family':f,'font-size':10,fill:ink},svg,label);
[[-12,'--w-black','P25'],[0,'--w-blue',wp],[12,'--w-red','P24']].forEach(function(l){ el('rect',{x:x+l[0]-2.5,y:62,width:5,height:12,fill:'#C9CFD5'},svg); el('line',{x1:x+l[0],y1:74,x2:x+l[0],y2:96,stroke:css(l[1]),'stroke-width':4,'stroke-linecap':'round'},svg);
el('text',{x:x+l[0],y:108,'text-anchor':'middle','font-family':f,'font-size':9,'font-weight':700,fill:ink},svg,H(l[2])); }); }
pot(45,'ENERGY','P22'); pot(115,'DRIFT','P23');
el('circle',{cx:190,cy:42,r:16,fill:'#2C3238'},svg); el('text',{x:190,y:14,'text-anchor':'middle','font-family':f,'font-size':10,fill:ink},svg,'SEED');
[[-7,'--w-yellow','P26'],[7,'--w-black','P28']].forEach(function(l){ el('line',{x1:190+l[0],y1:58,x2:190+l[0],y2:96,stroke:css(l[1]),'stroke-width':4,'stroke-linecap':'round'},svg); el('text',{x:190+l[0],y:108,'text-anchor':'middle','font-family':f,'font-size':9,'font-weight':700,fill:ink},svg,H(l[2])); });
el('rect',{x:240,y:30,width:34,height:24,rx:3,fill:'#2C3238'},svg); el('text',{x:257,y:14,'text-anchor':'middle','font-family':f,'font-size':10,fill:ink},svg,'RUN');
[[-11,null,''],[0,'--w-yellow','P27'],[11,'--w-black','P28']].forEach(function(l){ el('rect',{x:257+l[0]-2.5,y:54,width:5,height:10,fill:'#C9CFD5'},svg); if(l[1]){ el('line',{x1:257+l[0],y1:64,x2:257+l[0],y2:96,stroke:css(l[1]),'stroke-width':4,'stroke-linecap':'round'},svg); el('text',{x:257+l[0],y:108,'text-anchor':'middle','font-family':f,'font-size':9,'font-weight':700,fill:ink},svg,H(l[2])); } });
el('text',{x:150,y:138,'text-anchor':'middle','font-family':f,'font-size':9,fill:m},svg,'lugs facing down, seen from the front');
}
/* ---------- Wire map: every panel wire, by part, with its board hole ---------- */
var WMAP=[ // [pad, part, lug, short label]
['P29','Buttons','Row 1 · KICK, KICK 2, SNARE','ROW 1'],['P30','Buttons','Row 2 · HAT, HAT 16, PERC, GHOST','ROW 2'],['P31','Buttons','Row 3 · BASS, MEL A, MEL B, PAD','ROW 3'],
['P32','Buttons','Col 1 · KICK, HAT, BASS (diode band side)','COL 1'],['P33','Buttons','Col 2 · KICK 2, HAT 16, MEL A','COL 2'],['P34','Buttons','Col 3 · SNARE, PERC, MEL B','COL 3'],['P35','Buttons','Col 4 · GHOST, PAD','COL 4'],
['P26','SEED','one lug','SEED'],['P27','RUN toggle','middle lug (it sits in the button grid, row 1 / col 4)','RUN'],['P28','SEED + RUN','ground: SEED other lug, RUN one outer lug','GND BUS'],
['P20','Encoder','VCC (3.3 V, never 5 V)','ENC VCC'],['P21','Encoder','GND','ENC GND'],['P19','Encoder','SW','ENC SW'],['P18','Encoder','SIB','ENC SIB'],['P17','Encoder','SIA','ENC SIA'],
['P22','ENERGY pot','middle lug','ENERGY'],['P23','DRIFT pot','middle lug','DRIFT'],['P24','Pots','right lugs, both (3.3 V)','POTS +'],['P25','Pots','left lugs, both (AGND)','POTS −'],
['P14','LCD','1 · VCC (3.3 V)','LCD VCC'],['P15','LCD','2 · GND','LCD GND'],['P10','LCD','3 · SCE','LCD SCE'],['P9','LCD','4 · RST','LCD RST'],['P11','LCD','5 · D/C','LCD D/C'],['P12','LCD','6 · DN (MOSI)','LCD DN'],['P13','LCD','7 · SCLK','LCD SCLK'],['P16','LCD','8 · LED, through a 330 Ω resistor (if dark, move to any AA hole)','LCD LED'],
['P2','MIDI IN jack','tip','IN tip'],['P1','MIDI IN jack','ring','IN ring'],
['P3','OUT KIT jack','tip','KIT tip'],['P4','OUT KIT jack','ring','KIT ring'],['P5','OUT KIT jack','sleeve','KIT slv'],
['P6','OUT SYNTH jack','tip','SYN tip'],['P7','OUT SYNTH jack','ring','SYN ring'],['P8','OUT SYNTH jack','sleeve','SYN slv']
];
function wireOf(p){ return L.wires[+p.slice(1)-1]; }
function drawMap(){
var svg=document.getElementById('wmap'); if(!svg) return; svg.innerHTML='';
var LM=10.5, RM=10.5, f=css('--f-mono'), ink=css('--ink');
svg.setAttribute('viewBox',(-LM)+' -3.2 '+(L.W+LM+RM)+' '+(L.H+4.6));
el('rect',{x:-0.8,y:-0.5,width:L.W+0.6,height:L.H+0.3,rx:0.4,fill:css('--board'),stroke:css('--board-edge'),'stroke-width':0.12,opacity:0.55},svg);
for(var r=0;r<L.H;r++) el('line',{x1:-0.4,y1:r,x2:L.W-0.6,y2:r,stroke:css('--copper'),'stroke-width':0.5,opacity:0.18},svg);
el('rect',{x:11.3,y:-0.55,width:8.4,height:20.1,rx:0.4,fill:css('--part'),opacity:0.85},svg);
el('text',{x:15.5,y:9.5,'text-anchor':'middle','font-family':f,'font-size':'1.1','font-weight':700,fill:css('--part-ink')},svg,'PICO');
el('text',{x:15.5,y:-1.2,'text-anchor':'middle','font-family':f,'font-size':'0.7',fill:css('--muted')},svg,'USB edge');
el('rect',{x:3.6,y:19.6,width:3.8,height:3.8,rx:0.2,fill:css('--part'),opacity:0.85},svg);
el('text',{x:5.5,y:21.8,'text-anchor':'middle','font-family':f,'font-size':'0.6',fill:css('--part-ink')},svg,'opto');
// strip letters on both sides, hole numbers along the bottom
for(r=0;r<L.H;r++){ el('text',{x:-1.0,y:r+0.22,'text-anchor':'end','font-family':f,'font-size':'0.5',fill:css('--muted')},svg,rowName(r)); el('text',{x:L.W-0.1,y:r+0.22,'font-family':f,'font-size':'0.5',fill:css('--muted')},svg,rowName(r)); }
for(var c=0;c<L.W;c+=2) el('text',{x:c,y:L.H+0.9,'text-anchor':'middle','font-family':f,'font-size':'0.5',fill:css('--muted')},svg,String(c+1));
var sides={L:[],R:[]};
WMAP.forEach(function(m){ var w=wireOf(m[0]); (w.h[0]<=12?sides.L:sides.R).push({m:m,w:w}); });
['L','R'].forEach(function(sd){
var list=sides[sd].sort(function(a,b){ return a.w.h[1]-b.w.h[1] || (sd==='L'?b.w.h[0]-a.w.h[0]:a.w.h[0]-b.w.h[0]); }), last=-9, k;
for(k=0;k<list.length;k++){ list[k].ly=Math.max(list[k].w.h[1],last+1.05); last=list[k].ly; }
var cap=L.H-0.6; // keep labels inside the board's height: push the stack up from the bottom
for(k=list.length-1;k>=0;k--){ list[k].ly=Math.min(list[k].ly,cap); cap=list[k].ly-1.05; }
list.forEach(function(o){
var h=o.w.h, col=css(COL[o.w.col]), ly=o.ly;
var lx=sd==='L'?-1.9:L.W+0.9;
el('polyline',{points:h[0]+','+h[1]+' '+(sd==='L'?-0.6:L.W-0.4)+','+ly+' '+lx+','+ly,fill:'none',stroke:col,'stroke-width':0.13,opacity:0.9},svg);
el('circle',{cx:h[0],cy:h[1],r:0.36,fill:col,stroke:'#fff','stroke-width':0.08},svg);
var t=el('text',{x:sd==='L'?lx-0.25:lx+0.25,y:ly+0.25,'text-anchor':sd==='L'?'end':'start','font-family':f,'font-size':'0.72',fill:ink},svg);
var a=document.createElementNS(NS,'tspan'); a.setAttribute('font-weight','700'); a.textContent=o.m[3]+' '; t.appendChild(a);
var b=document.createElementNS(NS,'tspan'); b.setAttribute('fill',css('--accent')); b.setAttribute('font-weight','700'); b.textContent=pos(h); t.appendChild(b);
});
});
}
function checklist(){
var tb=document.getElementById('wcheck'); if(!tb) return; tb.innerHTML='';
var done={}; try{ done=JSON.parse(localStorage.getItem('seedbox.wires')||'{}')||{}; }catch(e){}
var prev='';
WMAP.forEach(function(m){
var w=wireOf(m[0]), tr=document.createElement('tr'), part=m[1]===prev?'':m[1]; prev=m[1];
if(part) tr.className='grp';
var td0=document.createElement('td'), cb=document.createElement('input'); cb.type='checkbox'; cb.checked=!!done[m[0]]; cb.setAttribute('aria-label','Done: '+m[1]+' '+m[2]);
cb.addEventListener('change',function(){ done[m[0]]=cb.checked; tr.classList.toggle('done',cb.checked); try{ localStorage.setItem('seedbox.wires',JSON.stringify(done)); }catch(e){} });
td0.appendChild(cb); tr.appendChild(td0); tr.classList.toggle('done',cb.checked);
var td1=document.createElement('td'); td1.className='part'; td1.textContent=part; tr.appendChild(td1);
var td2=document.createElement('td'); td2.textContent=m[2]; tr.appendChild(td2);
var td3=document.createElement('td'), sw=document.createElement('span'); sw.className='sw'; sw.style.background='var('+COL[w.col]+')'; td3.appendChild(sw); td3.appendChild(document.createTextNode(w.col)); tr.appendChild(td3);
var td4=document.createElement('td'); td4.className='hole'; td4.textContent=pos(w.h); tr.appendChild(td4);
tb.appendChild(tr);
});
}
function all(){
drawMap(); checklist(); drawTop(); drawBottom(); tables(); drawMatrix(); drawDin();
pinRow('lcd',[['1 VCC','--w-red','P14'],['2 GND','--w-black','P15'],['3 SCE','--w-blue','P10'],['4 RST','--w-blue','P9'],['5 D/C','--w-blue','P11'],['6 DN','--w-blue','P12'],['7 SCLK','--w-blue','P13'],['8 LED','--w-red','P16']]);
pinRow('enc',[['VCC','--w-red','P20'],['GND','--w-black','P21'],['SW','--w-green','P19'],['SIB','--w-green','P18'],['SIA','--w-green','P17']]);
drawMisc();
}
all();
try{ window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change',all); }catch(e){}
})();