abse/museair-usb
USB-C–powered ESP32-C3 controller board with AP63203 buck conversion, AP2112K 3.3V regulation, I²C SEN62 sensor interface, status LED, buttons, UART/I²C headers, and extensive decoupling.
- Version
- 0.5.7
- License
- unset
- Stars
- 0
scripts/apply-speaker-routing.mjs
// Audited routing replay for the speaker-side J7 revision. Geometry and nets
// must match exactly; placement changes require a fresh review.
import fs from 'node:fs'
import crypto from 'node:crypto'
const hash=v=>crypto.createHash('sha256').update(JSON.stringify(v)).digest('hex')
export const speakerRoutingFingerprint=records=>hash(records.filter(x=>['pcb_board','pcb_component','pcb_smtpad','pcb_plated_hole','pcb_hole','pcb_keepout','source_port','source_net','source_trace'].includes(x.type)))
export function repairSpeakerRouting(records){
const sc=records.find(x=>x.type==='source_component'&&x.name==='J7')
const pcb=records.find(x=>x.type==='pcb_component'&&x.source_component_id===sc?.source_component_id)
if(!pcb||pcb.rotation!==0||Math.abs(pcb.center.x-15.2)>1e-6||Math.abs(pcb.center.y-24.3)>1e-6)return null
// Permit only the two explicitly reviewed new NPTH/clearance features.
const holePoints=[[20.532,12.2728],[16.468,15.7272]]
const newHoles=records.filter(x=>x.type==='pcb_hole'&&holePoints.some(([px,py])=>Math.hypot(x.x-px,x.y-py)<1e-6))
if(newHoles.length){
if(newHoles.length!==2)throw Error('Missing light-pipe pin drill')
for(const [px,py] of holePoints){
const h=newHoles.find(x=>Math.hypot(x.x-px,x.y-py)<1e-6)
const k=records.find(x=>x.type==='pcb_keepout'&&Math.hypot(x.center.x-px,x.center.y-py)<1e-6)
if(h?.hole_diameter!==.6096||k?.shape!=='circle'||k.radius!==.6048||!['top','bottom'].every(l=>k.layers.includes(l)))throw Error('Light-pipe drill or copper clearance changed; review before replay')
}
}
const patch=JSON.parse(fs.readFileSync(new URL('./speaker-routing-reviewed.json',import.meta.url)))
if(speakerRoutingFingerprint(records.filter(x=>!(['pcb_hole','pcb_keepout'].includes(x.type)&&[[20.532,12.2728],[16.468,15.7272]].some(([px,py])=>Math.hypot((x.x??x.center?.x)-px,(x.y??x.center?.y)-py)<1e-6))))!==patch.geometry_and_net_fingerprint)throw Error('Speaker routing geometry or nets changed; review before replay')
for(let i=records.length-1;i>=0;i--)if(['pcb_trace','pcb_via'].includes(records[i].type))records.splice(i,1)
records.push(...structuredClone(patch.copper))
return [{repair:'Replay reviewed speaker-side J7 copper; Molex J7; rerouted speaker outputs, R7 clearance and shifted ground probe',rerouted_trace_ids:patch.rerouted_trace_ids}]
}