pixalynx/pixal-gps
These files define two separate printed circuit boards: a small, two-layer battery cartridge with protection circuitry and contact pads for a pouch cell, and a larger, two-layer wireless charging dock featuring USB-C input, a resonant coil, and wireless power transmission components.
- Version
- 0.1.2
- License
- unset
- Stars
- 0
scripts/widen-power-legs.py
#!/usr/bin/env python3
"""Widen the imported power legs after a Freerouting pass.
The router works at 0.20 mm for the power rails so it can leave 0.30 mm QFN lands; afterwards every power leg is
set to TARGET width, the board is rebuilt, and any leg named in a clearance error is stepped back down until the
build is DRC clean. Usage: python3 scripts/widen-power-legs.py tracker
"""
import json, subprocess, sys, re
board = sys.argv[1] if len(sys.argv) > 1 else 'tracker'
POWER = {'VSYS', 'VBAT', 'VBUS_QI', 'VDD_NRF', 'RECT', 'VBUSOUT', 'AC1', 'AC2', 'COIL1'}
STEPS = [0.3, 0.25, 0.2]
path = f'routing/{board}-routes.json'
routes = json.load(open(path))
legs = {l['id']: l for l in routes['legs']}
for l in legs.values():
if l['net'] in POWER and l['width'] < STEPS[0]: l['width'] = STEPS[0]
def build():
json.dump(routes, open(path, 'w'), indent=1)
subprocess.run(['bunx', 'tsci', 'build', f'{board}.circuit.tsx'], capture_output=True, text=True)
c = json.load(open(f'dist/{board}/circuit.json'))
other = [e['type'] + ': ' + (e.get('message') or '')[:160] for e in c if e['type'].endswith('_error')]
subprocess.run(['python3', 'scripts/check-clearance.py', f'dist/{board}/circuit.json', '--json', f'tmp/{board}-clearance.json'], capture_output=True, text=True)
findings = json.load(open(f'tmp/{board}-clearance.json'))
offenders = set()
for d, layer, kind, a, b in findings:
cands = [n for n in (a, b) if n in legs]
if not cands: other.append(f'clearance {kind} {a} / {b}: {d} mm (not an imported leg)'); continue
# narrow the wider imported leg first; a tie narrows both
w = max(legs[n]['width'] for n in cands)
offenders |= {n for n in cands if legs[n]['width'] >= w - 1e-9}
return offenders, other
for it in range(6):
offenders, other = build()
print(f'iteration {it}: {len(offenders)} legs in clearance errors, {len(other)} other errors')
if not offenders: break
for name in offenders:
l = legs[name]; nxt = [s for s in STEPS if s < l['width'] - 1e-9]
if not nxt: print(' cannot narrow', name, l['width']); continue
l['width'] = nxt[0]; print(f" {name} ({l['net']}) -> {l['width']}")
json.dump(routes, open(path, 'w'), indent=1)
widths = {}
for l in legs.values():
if l['net'] in POWER: widths.setdefault(l['net'], []).append(l['width'])
print({n: sorted(set(w)) for n, w in widths.items()})
if other: print('other errors:', *other[:6], sep='\n ')