imrishabh18/pedometer
This code defines and assembles a simple radio receiver hardware circuit using specific imported capacitors, inductors, RF connectors, and oscillator components with precise footprints and schematic attributes.
- Version
- 1.1.3
- License
- unset
- Stars
- 0
scripts/audit-copper-clearance.ts
import {createHash} from 'node:crypto';
import {readFileSync,writeFileSync} from 'node:fs';
import {pointToSegmentDistance,segmentToBoxMinDistance,segmentToSegmentMinDistance} from '@tscircuit/math-utils';
const c:any[]=JSON.parse(readFileSync('dist/index/circuit.json','utf8'));
const bytype=(t:string)=>c.filter((e:any)=>e.type===t);
const sn=new Map(bytype('source_trace').flatMap((s:any)=>s.connected_source_port_ids.map((p:any)=>[p,s.connected_source_net_ids[0]])));
const pn=new Map(bytype('pcb_port').map((p:any)=>[p.pcb_port_id,sn.get(p.source_port_id)]));
const refs=new Map(bytype('source_component').map((p:any)=>[p.source_component_id,p.name]));
const comps=new Map(bytype('pcb_component').map((p:any)=>[p.pcb_component_id,refs.get(p.source_component_id)]));
const segs=bytype('pcb_trace').flatMap((t:any)=>t.route.flatMap((a:any,i:number)=>{const b=t.route[i+1];return a.route_type==='wire'&&b?.route_type==='wire'&&a.layer===b.layer?[{a,b,net:t.connection_name,id:t.pcb_trace_id}]:[]}));
const mins:any[]=[];
for(const p of bytype('pcb_smtpad')){
if(!pn.has(p.pcb_port_id))continue;
const distances=[];
for(const s of segs){
if(s.a.layer!==p.layer||s.net===pn.get(p.pcb_port_id))continue;
let d:number;
if(p.shape==='circle')d=pointToSegmentDistance(p,s.a,s.b)-p.radius;
else if(p.shape==='rect')d=segmentToBoxMinDistance(s.a,s.b,{center:p,width:p.width,height:p.height});
else if(p.shape==='pill'){
const r=Math.min(p.width,p.height)/2,dx=Math.max(0,p.width/2-r),dy=Math.max(0,p.height/2-r);
d=segmentToSegmentMinDistance(s.a,s.b,{x:p.x-dx,y:p.y-dy},{x:p.x+dx,y:p.y+dy})-r;
} else throw new Error(`Unsupported pad ${p.shape}`);
distances.push({mm:d-Math.max(s.a.width,s.b.width)/2,reference:comps.get(p.pcb_component_id),pad:p.port_hints,trace:s.id,layer:s.a.layer});
}
distances.sort((a,b)=>a.mm-b.mm);if(distances.length)mins.push(distances[0]);
}
mins.sort((a,b)=>a.mm-b.mm);
let traceMin={mm:Infinity,a:'',b:'',layer:''};
for(let i=0;i<segs.length;i++)for(let j=i+1;j<segs.length;j++){
const a=segs[i],b=segs[j];if(a.net===b.net||a.a.layer!==b.a.layer)continue;
const d=segmentToSegmentMinDistance(a.a,a.b,b.a,b.b)-(Math.max(a.a.width,a.b.width)+Math.max(b.a.width,b.b.width))/2;
if(d<traceMin.mm)traceMin={mm:d,a:a.id,b:b.id,layer:a.a.layer};
}
const report={circuitSha256:createHash('sha256').update(readFileSync('dist/index/circuit.json')).digest('hex'),padToTraceMinimum:mins[0],bgaPadToTraceMinimum:mins.find(p=>['U2','U3'].includes(p.reference)),traceToTraceMinimum:traceMin,closestPads:mins.slice(0,15)};
writeFileSync('review/copper-clearance.json',JSON.stringify(report,null,2));console.log(JSON.stringify(report,null,2));
if(report.padToTraceMinimum.mm<.09-1e-6 || report.traceToTraceMinimum.mm<.09-1e-6)throw new Error('Copper spacing below 0.09 mm');