AnasSarkiz/muse-voice-remote

Muse Voice Remote — bare ESP32-S3R8, 155 TOP JLCPCB parts with real supplier CAD, native 3D assembly and GLB exports. Revised 17 mm case allocation; 0.30 mm via drill /0.45 mm pad. Checked prototype PCB; mechanical, RF and MUSE qualification pending.

Version
1.3.2
License
unset
Stars
0

scripts/route-region-graph.py

#!/usr/bin/env python3
"""Connect signal islands through exact top/bottom free regions and legal vias."""
import argparse,pathlib,heapq,math,os,json
h=pathlib.Path(__file__).with_name('finish-unrouted.py');api={'__file__':str(h)};exec(h.read_text().split('\n# A FreeRouting pattern')[0],api)
from shapely.geometry import Point,box
from shapely.ops import nearest_points
from precise_path import visible_path
p=argparse.ArgumentParser();p.add_argument('--net',required=True);p.add_argument('--repair-power-plane',action='store_true');p.add_argument('--start',nargs=2,type=float,required=True);p.add_argument('--end',nargs=2,type=float,required=True);a=p.parse_args();pc=api['pcbnew'];path=api['path'];before=path.read_bytes();old=api['check']();b=pc.LoadBoard(str(path));ts=list(b.GetTracks());fs=list(b.GetFootprints());ps=[p for f in fs for p in f.Pads()];code=next(n.GetNetCode() for n in b.GetNetsByNetcode().values() if n.GetNetname()==a.net);
if a.repair_power_plane:
 source=h.read_text().split('\n# A FreeRouting pattern')[0].replace('if net not in {"GND","V3_3"} and any(', 'if False and net not in {"GND","V3_3"} and any(');exec(source,api)
o,v=api['obstacles'](b,a.net);outer=box(-32.25,-23.25,32.25,23.25);regions=[]
for layer in ([0,2,3] if a.repair_power_plane else [0,3]):
 free=outer.difference(o[layer].context);polys=list(free.geoms) if free.geom_type=='MultiPolygon' else [free]
 regions.extend((layer,r) for r in polys if r.area>.000001)
legal=outer.difference(v.context).buffer(-.002);adj=[[] for _ in regions];print('Regions',len(regions),flush=True)
for i,(l,r) in enumerate(regions):
 for j,(m,s) in enumerate(regions[:i]):
  if l==m or not r.intersects(s):continue
  shared=r.intersection(s).intersection(legal)
  if shared.is_empty:continue
  point=nearest_points(Point(a.start),shared)[1];xy=(point.x,point.y)
  adj[i].append((j,xy));adj[j].append((i,xy))
starts=[i for i,(_,r) in enumerate(regions) if r.covers(Point(a.start))];goals={i for i,(_,r) in enumerate(regions) if r.covers(Point(a.end))};print('Endpoints',starts,goals,'edges',sum(map(len,adj)),flush=True)
q=[(0,i) for i in starts];heapq.heapify(q);cost={i:0 for i in starts};prev={};target=None
while q:
 c,i=heapq.heappop(q)
 if c>cost[i]:continue
 if i in goals:target=i;break
 for j,xy in adj[i]:
  nc=c+10+math.dist(xy,a.end)*.01
  if nc>=cost.get(j,math.inf):continue
  cost[j]=nc;prev[j]=(i,xy);heapq.heappush(q,(nc,j))
if target is None:raise RuntimeError('No connected exact layer-region path')
chain=[target]
while chain[-1] in prev:chain.append(prev[chain[-1]][0])
chain.reverse();start=tuple(a.start);segments=0;points=[]
for index,i in enumerate(chain):
 end=prev[chain[index+1]][1] if index+1<len(chain) else tuple(a.end)
 route=visible_path(regions[i][1],start,end)
 for x,y in zip(route,route[1:]):
  if math.dist(x,y)<.000001:continue
  t=pc.PCB_TRACK(b);t.SetStart(api['vector'](x));t.SetEnd(api['vector'](y));t.SetLayer(api['layers'][regions[i][0]]);t.SetWidth(pc.FromMM(.15));t.SetNetCode(code);b.Add(t);segments+=1
 if index+1<len(chain):
  via=pc.PCB_VIA(b);via.SetPosition(api['vector'](end));via.SetViaType(pc.VIATYPE_THROUGH);via.SetLayerPair(pc.F_Cu,pc.B_Cu)
  for layer in api['layers']:via.SetWidth(layer,pc.FromMM(.45))
  via.SetDrill(pc.FromMM(.3));via.SetNetCode(code);b.Add(via);points.append(end)
 start=end
pc.SaveBoard(str(path),b);after=api['check']()
if (not a.repair_power_plane and len(after['unconnected_items'])>=len(old['unconnected_items'])) or any(v['type'] not in ['track_dangling','via_dangling'] for v in after['violations']):path.write_bytes(before);raise RuntimeError('Independent native check rejected route; original restored')

if a.repair_power_plane:
 items={x.m_Uuid.AsString():x for x in list(b.GetTracks())+ps}
 pending=[items[r['items'][0]['uuid']].GetNetname() for r in after['unconnected_items']]
 if a.net in pending or any(n not in {'V3_3','LCD_DC','LCD_BL_ENABLE'} for n in pending):path.write_bytes(before);raise RuntimeError('Unexpected connectivity loss; restored')
 print('Intermediate plane repair required:',pending,flush=True)
print('Accepted',segments,'segments',len(points),'vias;',len(after['unconnected_items']),'pairs remain',flush=True);(api['root']/f'docs/region-route-{a.net}.json').write_text(json.dumps(dict(net=a.net,segments=segments,vias_native_mm=points,region_chain=chain),indent=2)+'\n');os._exit(0)