|
246 | 246 | .srcard .use{font-size:13px;color:var(--dim);margin-top:6px} |
247 | 247 | .srcard .use b{color:var(--phos)} |
248 | 248 | .srsvg svg{width:100%;height:auto;max-width:270px;display:block;margin:8px auto 2px} |
| 249 | +/* dedicated mode simulators */ |
| 250 | +.simgrid{display:grid;gap:16px} |
| 251 | +@media(min-width:760px){.simgrid{grid-template-columns:1fr 1fr}} |
| 252 | +.simcard{background:var(--bg2);border:1px solid var(--line);border-radius:12px;padding:16px} |
| 253 | +.simcard h4{font-family:'Chakra Petch';margin:0 0 12px;font-size:15px;display:flex;gap:8px;align-items:baseline;flex-wrap:wrap} |
| 254 | +.simcard h4 .full{font-size:11px;color:var(--muted);font-family:'IBM Plex Mono'} |
| 255 | +.simcard .sn{font-size:12.5px;color:var(--muted);margin-top:12px;min-height:34px;line-height:1.5} |
| 256 | +.simcard .sn b{color:var(--ink)} |
| 257 | +.simcard .led{width:38px;height:46px;font-size:18px} |
| 258 | +.ptap{display:flex;gap:10px;justify-content:center;margin-top:10px} |
| 259 | +.ptap .t{display:flex;flex-direction:column;align-items:center;gap:2px} |
| 260 | +.ptap .t .ar{color:var(--amber);font-size:13px;line-height:1} |
| 261 | +.ptap .t .v{width:30px;height:26px;border-radius:6px;border:1px solid var(--line2);background:var(--panel);display:flex;align-items:center;justify-content:center;font-family:'IBM Plex Mono';font-size:13px;color:var(--dim);transition:.15s} |
| 262 | +.ptap .t .v.on{background:rgba(255,194,77,.16);color:var(--amber);border-color:var(--amber);box-shadow:var(--glow-amber)} |
| 263 | +.sout{display:flex;gap:5px;justify-content:center;margin-top:10px;min-height:26px;flex-wrap:wrap;align-items:center} |
| 264 | +.sout .lb{font-family:'IBM Plex Mono';font-size:11px;color:var(--dim)} |
| 265 | +.sout .b{width:23px;height:23px;border-radius:6px;background:rgba(56,226,208,.12);border:1px solid var(--phos-dim);display:flex;align-items:center;justify-content:center;font-family:'IBM Plex Mono';font-size:12px;color:var(--phos)} |
249 | 266 | @media(prefers-reduced-motion:reduce){*{animation-duration:.001s!important;transition-duration:.001s!important}} |
250 | 267 | :focus-visible{outline:2px solid var(--phos);outline-offset:2px} |
251 | 268 | </style> |
@@ -719,6 +736,12 @@ <h4>PIPO <span class="full">parallel-in, parallel-out</span></h4> |
719 | 736 | </div> |
720 | 737 | </div> |
721 | 738 |
|
| 739 | + <div class="panel" style="margin-top:20px"> |
| 740 | + <div class="panel-title">Simulate each mode <span class="num">interactive</span></div> |
| 741 | + <div class="hint" style="margin-bottom:16px">Each type driven its own way — feed data how that mode expects, clock it, and read the note. <span style="color:var(--phos)">Teal = serial</span>, <span style="color:var(--amber)">amber = parallel</span>.</div> |
| 742 | + <div class="simgrid" id="srSims"></div> |
| 743 | + </div> |
| 744 | + |
722 | 745 | <div class="panel" style="margin-top:20px"> |
723 | 746 | <div class="panel-title">Simulate it — the universal shift register <span class="num">live</span></div> |
724 | 747 | <div class="hint" style="margin-bottom:16px">Pick a mode, set the inputs, press CLOCK. <b style="color:var(--phos)">Repeat shift-right</b> with a serial stream = SISO (watch serial out) / SIPO (read all cells). <b style="color:var(--amber)">Load then shift</b> = PISO. <b style="color:var(--amber)">Load then read</b> = PIPO.</div> |
@@ -1500,6 +1523,88 @@ <h2>Cheat sheet & self-test.</h2> |
1500 | 1523 | $('#srClear').addEventListener('click',()=>{cells=[0,0,0,0];render();outEl.textContent='–';}); |
1501 | 1524 | setMode('right'); render(); |
1502 | 1525 | })(); |
| 1526 | + |
| 1527 | +/* ---------- FOUR DEDICATED MODE SIMULATORS ---------- */ |
| 1528 | +(function(){ |
| 1529 | + const host=$('#srSims'); if(!host)return; |
| 1530 | + const META={ |
| 1531 | + siso:{title:'SISO',full:'serial-in · serial-out', sIn:true, pIn:false, sOut:true, pOut:false, |
| 1532 | + hint:'Toggle the serial input, press CLOCK to push it in at Q0. Each clock, one bit exits at Q3 (serial out).'}, |
| 1533 | + sipo:{title:'SIPO',full:'serial-in · parallel-out', sIn:true, pIn:false, sOut:false, pOut:true, |
| 1534 | + hint:'Clock four bits in serially. After each clock all four cells are readable at once at the parallel taps — that is the serial→parallel conversion.'}, |
| 1535 | + piso:{title:'PISO',full:'parallel-in · serial-out', sIn:false, pIn:true, sOut:true, pOut:false, |
| 1536 | + hint:'Set the four P bits, press LOAD (all in on one clock), then press CLOCK to shift them out one bit per clock — parallel→serial.'}, |
| 1537 | + pipo:{title:'PIPO',full:'parallel-in · parallel-out', sIn:false, pIn:true, sOut:false, pOut:true, |
| 1538 | + hint:'Set the four P bits and press LOAD. All four go in and are readable at once — a one-clock storage register.'} |
| 1539 | + }; |
| 1540 | + function mkSwitch(label,cb){ |
| 1541 | + const t=document.createElement('div');t.className='tog'; |
| 1542 | + t.innerHTML=`<div class="lab">${label}</div><div class="switch" role="switch" tabindex="0"><div class="knob"></div><span class="st o">1</span><span class="st z">0</span></div>`; |
| 1543 | + const sw=t.querySelector('.switch');let v=0; |
| 1544 | + const tog=()=>{v^=1;sw.classList.toggle('hi',!!v);cb(v);}; |
| 1545 | + sw.addEventListener('click',tog);sw.addEventListener('keydown',e=>{if(e.key===' '||e.key==='Enter'){e.preventDefault();tog();}}); |
| 1546 | + return t; |
| 1547 | + } |
| 1548 | + function build(mode){ |
| 1549 | + const M=META[mode]; |
| 1550 | + const cells=[0,0,0,0]; let par=[0,0,0,0]; let sin=0; let hist=[]; |
| 1551 | + const card=document.createElement('div'); card.className='simcard'; |
| 1552 | + const h=document.createElement('h4'); h.innerHTML=`${M.title} <span class="full">${M.full}</span>`; card.appendChild(h); |
| 1553 | + // cell row |
| 1554 | + const rw=document.createElement('div'); rw.className='row'; rw.style.justifyContent='center'; rw.style.gap='8px'; |
| 1555 | + if(M.sIn){const a=document.createElement('span');a.className='hint mono';a.style.color='var(--phos)';a.textContent='in →';rw.appendChild(a);} |
| 1556 | + const row=document.createElement('div'); row.className='ledrow'; |
| 1557 | + for(let i=0;i<4;i++){const d=document.createElement('div');d.className='led';d.innerHTML='0';row.appendChild(d);} |
| 1558 | + rw.appendChild(row); |
| 1559 | + if(M.sOut){const o=document.createElement('span');o.className='hint mono';o.style.color='var(--phos)';o.textContent='→ out';rw.appendChild(o);} |
| 1560 | + card.appendChild(rw); |
| 1561 | + // parallel-out taps |
| 1562 | + let taps=null; |
| 1563 | + if(M.pOut){ taps=document.createElement('div'); taps.className='ptap'; |
| 1564 | + for(let i=0;i<4;i++){const t=document.createElement('div');t.className='t';t.innerHTML='<span class="ar">↓</span><span class="v">0</span>';taps.appendChild(t);} card.appendChild(taps); |
| 1565 | + const cap=document.createElement('div');cap.className='hint mono';cap.style.textAlign='center';cap.style.color='var(--amber)';cap.style.fontSize='10px';cap.textContent='parallel out';card.appendChild(cap); |
| 1566 | + } |
| 1567 | + // serial-out strip |
| 1568 | + let sout=null; |
| 1569 | + if(M.sOut){ sout=document.createElement('div'); sout.className='sout'; sout.innerHTML='<span class="lb">serial out:</span>'; card.appendChild(sout); } |
| 1570 | + // controls |
| 1571 | + if(M.pIn){ |
| 1572 | + const pr=document.createElement('div');pr.className='row';pr.style.justifyContent='center';pr.style.gap='8px';pr.style.marginTop='14px'; |
| 1573 | + par.forEach((_,i)=>pr.appendChild(mkSwitch('P'+i,v=>{par[i]=v;}))); |
| 1574 | + card.appendChild(pr); |
| 1575 | + } |
| 1576 | + const ctl=document.createElement('div');ctl.className='row';ctl.style.justifyContent='center';ctl.style.gap='10px';ctl.style.marginTop='16px';ctl.style.flexWrap='wrap'; |
| 1577 | + if(M.sIn){ ctl.appendChild(mkSwitch('SERIAL IN',v=>{sin=v;})); } |
| 1578 | + if(M.pIn){ const lb=document.createElement('button');lb.className='btn sm';lb.textContent='LOAD';lb.addEventListener('click',doLoad);ctl.appendChild(lb); } |
| 1579 | + const ck=document.createElement('button');ck.className='clockbtn';ck.innerHTML='<span class="ico">↻</span> CLOCK ▲';ck.addEventListener('click',doClock); |
| 1580 | + if(mode!=='pipo') ctl.appendChild(ck); |
| 1581 | + const cl=document.createElement('button');cl.className='btn ghost sm';cl.textContent='Clear';cl.addEventListener('click',doClear);ctl.appendChild(cl); |
| 1582 | + card.appendChild(ctl); |
| 1583 | + // note |
| 1584 | + const sn=document.createElement('div');sn.className='sn';sn.innerHTML=M.hint;card.appendChild(sn); |
| 1585 | + |
| 1586 | + function paint(){ [...row.children].forEach((c,i)=>{c.className='led'+(cells[i]?' on':'');c.textContent=cells[i];}); |
| 1587 | + if(taps)[...taps.children].forEach((t,i)=>{const v=t.querySelector('.v');v.textContent=cells[i];v.classList.toggle('on',!!cells[i]);}); } |
| 1588 | + function paintSout(){ if(sout)sout.innerHTML='<span class="lb">serial out:</span>'+hist.slice(-8).map(b=>`<div class="b">${b}</div>`).join(''); } |
| 1589 | + function flash(){ [...row.children].forEach((c,i)=>c.animate([{transform:'translateY(-5px)',opacity:.5},{transform:'none',opacity:1}],{duration:reduce?1:200,delay:i*25})); } |
| 1590 | + function doClock(){ |
| 1591 | + if(mode==='siso'||mode==='sipo'){ const out=cells[3]; cells.unshift(sin); cells.pop(); |
| 1592 | + if(mode==='siso'){ hist.push(out); paintSout(); sn.innerHTML=`Shift: <b>${sin}</b> entered Q0, bits moved right, <b>${out}</b> exited at Q3.`; } |
| 1593 | + else { sn.innerHTML=`Shifted <b>${sin}</b> in. All four cells are now available in parallel: <b>${cells.join('')}</b>.`; } |
| 1594 | + } else if(mode==='piso'){ const out=cells[3]; cells.unshift(0); cells.pop(); hist.push(out); paintSout(); |
| 1595 | + sn.innerHTML=`Shifting out: <b>${out}</b> left at Q3 (0 fills in at Q0). Keep clocking to stream all bits out.`; } |
| 1596 | + paint(); flash(); |
| 1597 | + } |
| 1598 | + function doLoad(){ cells.splice(0,4,...par); paint(); flash(); |
| 1599 | + if(mode==='pipo') sn.innerHTML=`Loaded <b>${par.join('')}</b> in one clock — all four bits are out at once (parallel in, parallel out).`; |
| 1600 | + else sn.innerHTML=`Loaded <b>${par.join('')}</b> in parallel. Now press CLOCK to shift them out serially.`; |
| 1601 | + } |
| 1602 | + function doClear(){ cells.splice(0,4,0,0,0,0); hist=[]; paint(); paintSout(); sn.innerHTML=M.hint; } |
| 1603 | + paint(); paintSout(); |
| 1604 | + return card; |
| 1605 | + } |
| 1606 | + ['siso','sipo','piso','pipo'].forEach(m=>host.appendChild(build(m))); |
| 1607 | +})(); |
1503 | 1608 | })(); |
1504 | 1609 | </script> |
1505 | 1610 | </body> |
|
0 commit comments