seveibar/am3352-dev-board-4layer-dogbone

Defines PCB footprints and pin mappings for a TI AM3352ZCZ100 processor, JST GH connectors, and assembly-part lookup helpers for capacitors, resistors, and headers.

Version
0.1.5
License
unset
Stars
0

scripts/pre-fab-review.py

"""Measure fabrication-review facts; this is not an electrical signoff."""
import json,math,hashlib,runpy
from pathlib import Path
from shapely.geometry import Point,box,LineString
from shapely.ops import unary_union
x=runpy.run_path('scripts/audit-copper.py');c=x['c'];sc={e['source_component_id']:e for e in c if e['type']=='source_component'};st={e['source_trace_id']:e for e in c if e['type']=='source_trace'};names={e['source_net_id']:e['name'] for e in c if e['type']=='source_net'}
def segments(name):
 return [(a,b) for t in c if t['type']=='pcb_trace' and any(names.get(n)==name for n in st.get(t.get('source_trace_id'),{}).get('connected_source_net_ids',[])) for a,b in zip(t['route'],t['route'][1:]) if a['route_type']==b['route_type']=='wire' and a['layer']==b['layer'] and (a['x'],a['y'])!=(b['x'],b['y'])]
power={}
for name in ['SW1','SW2','SW3','VIN_5V','SYS_5V','VDD_MPU','VDD_CORE','DDR_1V5']:
 ss=segments(name);power[name]={'totalSegmentLengthMm':sum(math.dist((a['x'],a['y']),(b['x'],b['y'])) for a,b in ss),'widthsMm':sorted({a['width'] for a,b in ss})}
board=box(-35,-30,35,30);holes=[Point(e['x'],e['y']).buffer(e['hole_diameter']/2) for e in c if e['type']=='pcb_hole'];hole=unary_union(holes)
edge=min((g.distance(board.boundary),m[2]) for g,m in zip(x['shapes'],x['meta']));hc=min((g.distance(hole),m[2]) for g,m in zip(x['shapes'],x['meta']))
drills=[(e['x'],e['y'],e['hole_diameter'],e['pcb_via_id']) for e in c if e['type']=='pcb_via'];drillgap=min((math.hypot(a[0]-b[0],a[1]-b[1])-(a[2]+b[2])/2,a[3],b[3]) for i,a in enumerate(drills) for b in drills[i+1:])
usb={n:{'lengthMm':sum(math.dist((a['x'],a['y']),(b['x'],b['y'])) for a,b in segments(n)),'layers':sorted({a['layer'] for a,b in segments(n)})} for n in ['USB0_DP','USB0_DM']}
r={'circuitSha256':hashlib.sha256(Path('dist/index/circuit.json').read_bytes()).hexdigest(),'reviewDisposition':'HOLD: electrical-layout and manufacturing review required','powerRouting':power,'usb':usb,'componentsWithoutMPN':[e['name'] for e in sc.values() if not e.get('manufacturer_part_number')],'minimumCopperToBoardEdgeMm':edge,'minimumCopperToNonPlatedHoleMm':hc,'minimumViaDrillEdgeGapMm':drillgap,'viaHoleDiametersMm':sorted({d[2] for d in drills})}
Path('design/pre-fab-review.json').write_text(json.dumps(r,indent=2)+'\n');print(json.dumps({k:v for k,v in r.items() if k!='componentsWithoutMPN'},indent=2));print('Missing MPN:',len(r['componentsWithoutMPN']))