imrishabh18/rp2040-motor-controller
A library of PCB component definitions covering MOSFETs, motor drivers, USB-PD control, sensors, current monitors, transistors, diodes, resistors, speakers, connectors, and mirrored bottom-side logos, with pin mappings, footprints, and 3D models.
- Version
- 1.0.55
- License
- unset
- Stars
- 5
scripts/prepare-top-branches.py
"""Attach new sensor branches to retained copper instead of rerouting backbones."""
import copy
import json
import runpy
from pathlib import Path
from shapely.geometry import LineString, Point
from copper_geometry import trace_segments
env=runpy.run_path('scripts/rebase-top-assembly.py')
check=runpy.run_path('scripts/find-top-pad-conflicts.py')
plan=check['plan']; net=check['net']; after=env['after']; before=env['before']; mapping=env['mapping']; points=env['new_points']
lookup={value[:2]: key for key,value in after.items()}
changed={e['id'] for e in json.loads(Path('dist/top-assembly/changed-routes.json').read_text())}
traces={t['pcb_trace_id']:t for t in plan['traces']}
leaf_ids=[]
def attach(trace, port):
start=points[port]; origin=Point(start['x'],start['y']); candidates=[]
for other in plan['traces']:
if other['pcb_trace_id'] in changed or net(other)!=net(trace): continue
for a,b,layer,width in trace_segments(other['route']):
line=LineString([a,b]); goal=line.interpolate(line.project(origin)); distance=origin.distance(goal)
candidates.append((distance+(0 if layer==start['layer'] else .8),goal.x,goal.y,layer,other['pcb_trace_id']))
assert candidates, trace['pcb_trace_id']
_,x,y,layer,backbone=min(candidates)
trace['route']=[{'route_type':'wire','x':start['x'],'y':start['y'],'layer':start['layer'],'width':.15},
{'route_type':'wire','x':x,'y':y,'layer':layer,'width':.15}]
trace['connectsTo']=[port]
leaf_ids.append(trace['pcb_trace_id'])
print('New branch',trace['pcb_trace_id'],after[port],'joins',backbone,(x,y,layer))
for id,pin in [('top_assembly_267',8),('top_assembly_272',4),('top_assembly_273',5)]:
attach(traces[id],lookup['U_PD_MON',pin])
for id,component in [('top_assembly_142','C_ENCODER'),('top_assembly_258','C_ENCODER_BULK')]:
attach(traces[id],lookup[component,2])
# Reuse the old 3.3-V probe's supply branch as ordinary masked copper feeding the
# monitor bypass. No test pad or solder-mask opening is retained.
baseline=json.loads(Path('dist/baseline/route-plan.json').read_text())
old_probe=next(key for key,value in before.items() if value[0]=='TP_3V3')
old_trace=next(t for t in baseline['traces'] if old_probe in t.get('connectsTo',[]))
old_point=env['old_points'][old_probe]; supply=traces['top_assembly_270']; cap=lookup['C_PD_MON',1]
supply['route']=copy.deepcopy(old_trace['route'])
for endpoint in [supply['route'][0],supply['route'][-1]]:
if abs(endpoint['x']-old_point['x'])+abs(endpoint['y']-old_point['y'])<1e-5:
endpoint.update(x=points[cap]['x'],y=points[cap]['y'],layer='top')
supply['connectsTo']=[cap if p==old_probe else mapping[p] for p in old_trace['connectsTo']]
Path('dist/top-assembly/route-plan.json').write_text(json.dumps(plan,indent=2))
Path('dist/top-assembly/leaf-routes.json').write_text(json.dumps(leaf_ids))
