shibosoftwaredev/f1c100s-linux-nema17-stepper-controller
A four-layer NEMA 17 motor-controller PCB combining an Allwinner F1C100S Linux computer, USB‑PD/buck power system, W5500 Ethernet, STM32 real-time motion control, DRV8825 stepper driver, protection/temperature/current telemetry, USB interfaces, and local LED/buzzer diagnostics.
- Version
- 0.4.56
- License
- unset
- Stars
- 0
scripts/prepare-focused-bulk-review.py
"""Minimal bulk-capacitor relocation from the published copper, not trial routes."""
from route_geometry import *
c=load_circuit('routing/review-placement.circuit.json');root=connectivity(c)
assert json.loads(Path('review-placement.json').read_text()).get('C_VM_BULK',{}).get('layer')=='top','Hardware placement is not enabled in the schematic-only checkpoint'
mapping=json.loads(Path('routing/net-map.json').read_text())['roots'];ports={e['pcb_port_id']:e for e in c if e['type']=='pcb_port'}
names={e['source_component_id']:e['name'] for e in c if e['type']=='source_component'}
pc={e['pcb_component_id']:names[e['source_component_id']] for e in c if e['type']=='pcb_component'}
physical=json.loads(Path('../../checkpoints/nema17-before-rishabh-review-v053-DuFOGi/restore-verified/routing/physical-copper.json').read_text())
def wire(n,l,w,points):return dict(net=n,layer=l,width=w,points=points)
manual=[
wire('N101','top',.5,[(20.65,-1.85),(20.65,-6.3),(20.65,-5.7)]),
wire('N101','bottom',.5,[(20.65,-5.7),(20.65,-10.96),(18.3,-10.96)]),
wire('N101','top',.5,[(18.3,-10.96),(16,-10.96),(16,-7),(14.1,-7),(14.1,-6.6),(13.8,-6.6),(13.8,-6)]),
wire('N101','bottom',.5,[(13.8,-6),(13.8,-7.2),(10.8,-7.2),(10.8,-6.6)]),
wire('N101','top',.5,[(10.8,-6.6),(10.8,-7.2),(10.9,-7.18)]),
wire('N62','top',.8,[(18.4,-3.197581),(18.2,-5),(18.2,-5.6)]),
wire('N62','bottom',.8,[(18.2,-5),(18.2,-6),(18.35,-6.5),(18.35,-9.3),(16.65,-10.4),(16.852419,-10)]),
wire('N179','top',.8,[(18.4,-9.902419),(19.25,-9.3)]),
wire('N179','top',.8,[(14.592402,-5),(15.992402,-5)]),
wire('N178','top',.5,[(11.207598,-5),(12.607598,-5)]),
wire('N179','bottom',.8,[(10.147581,-10),(12.35,-10.4)]),
wire('N166','top',.15,[(6.81,-3.5),(6.81,-2.2)]),
wire('N118','top',.25,[(9.51,-4.7),(10.45,-3.8)])]
vias=[dict(net='N62',x=18.2,y=-5),dict(net='N62',x=18.2,y=-5.6),dict(net='N118',x=10.45,y=-3.8)]
vias += [dict(net='N101',x=x,y=y) for x,y in [(13.8,-6),(13.8,-6.6),(10.8,-7.2),(10.8,-6.6)]]
vias += [dict(net='N101',x=x,y=y) for x,y in [(20.65,-6.3),(20.65,-5.7),(18.3,-10.96)]]
old=[v for v in physical['vias'] if v['net']=='N118' and math.dist((v['x'],v['y']),(10.3533,-4.7016))<1e-7]
assert len(old)==1;physical['vias'].remove(old[0])
shapes=[(w['net'],[w['layer']],LineString(w['points']).buffer(w['width']/2)) for w in manual]
shapes += [(v['net'],LAYERS,Point(v['x'],v['y']).buffer(.225)) for v in vias]
moves=set(json.loads(Path('review-placement.json').read_text()))
for e in c:
if e['type']=='pcb_smtpad' and pc.get(e['pcb_component_id']) in moves:
n=mapping[root(ports[e['pcb_port_id']]['source_port_id'])];shapes.append((n,[e['layer']],geometry(e)))
removed=[];kept=[]
for w in physical['wires']:
g=LineString(w['points']).buffer(w['width']/2)
clash=any(n!=w['net'] and w['layer'] in ls and g.distance(h)<.1001 for n,ls,h in shapes)
clash|=any(v['net']!=w['net'] and g.distance(Point(v['x'],v['y']))<.354 for v in vias)
if clash:
assert w['width']<.299 or (w['net']=='N101' and w['layer']=='top' and abs(w['width']-.5)<1e-7),('Power path needs an explicit redesign, not automatic deletion',w)
removed.append(w)
else:kept.append(w)
physical['wires']=kept+manual;physical['vias']+=vias
Path('routing/focused-bulk-seed.json').write_text(json.dumps(physical,indent=2)+'\n')
report=dict(authoredWires=manual,authoredVias=vias,removedSegments=removed,relocatedVias=old,method='published v0.4.53 copper plus local outer-layer power extensions')
Path('reports/bulk-top-preparation.json').write_text(json.dumps(report,indent=2)+'\n')
Path('reports/bulk-top-physical-islands.json').write_text(json.dumps(dict(removedForManualEscapes=removed),indent=2)+'\n')
print(json.dumps(dict(retainedWires=len(kept),removedWires=len(removed),affectedNets=sorted({w['net'] for w in removed}))))