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/via-manifest.py

"""List filled/capped via requirements from the final rendered copper geometry."""
import csv, json, runpy
from pathlib import Path
from shapely.geometry import Point
x=runpy.run_path('scripts/audit-copper.py');c=x['c']
byid={e[e['type']+'_id']:e for e in c if e['type']+'_id' in e}
reserved=[] # Regenerated four-layer routing: do not use the parent's reserved sites.
pads=[p for p in c if p['type']=='pcb_smtpad'];rows=[];seen=set()
for v in c:
 if v['type']!='pcb_via':continue
 xy=(round(v['x'],6),round(v['y'],6))
 if xy in seen:continue
 seen.add(xy)
 hole=Point(*xy).buffer(v['hole_diameter']/2)
 hits=[p for p in pads if hole.intersection(x['padshape'](p)).area>1e-8]
 explicit=any(r.get('requiresFillAndCap') and abs(r['x']-xy[0])<.002 and abs(r['y']-xy[1])<.002 for r in reserved)
 if not hits and not explicit:continue
 refs=[];nets=set()
 for p in hits:
  port=x['ports'].get(p.get('pcb_port_id'))
  if not port:continue
  sp=byid[port['source_port_id']];sc=byid[sp['source_component_id']]
  refs.append(sc['name']+'.'+sp['name']);net=x['find'](sp['source_port_id']);nets.add(x['netnames'].get(net,net))
 if not nets:
  nets.update(r['net'] for r in reserved if abs(r['x']-xy[0])<.002 and abs(r['y']-xy[1])<.002)
 rows.append(dict(xMm=xy[0],yMm=xy[1],drillMm=v['hole_diameter'],padMm=v['outer_diameter'],net='; '.join(sorted(nets)),componentPads='; '.join(sorted(set(refs))),process='Filled and copper capped through via'))
rows.sort(key=lambda r:(r['net'],r['xMm'],r['yMm']))
Path('design/filled-vias.json').write_text(json.dumps({'coordinateOrigin':'PCB center, millimetres, native tscircuit coordinates','requirement':'Fabricator must review and apply fill and copper cap to these vias before assembly. This manifest accompanies the design; no fabrication release is implied.','vias':rows},indent=2)+'\n')
with open('design/filled-vias.csv','w',newline='') as f:
 writer=csv.DictWriter(f,fieldnames=['xMm','yMm','drillMm','padMm','net','componentPads','process']);writer.writeheader();writer.writerows(rows)
print('Filled/capped via manifest:',len(rows),'unique vias')