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/set-fabrication-metadata.py
#!/usr/bin/env python3
"""Apply the selected manufacturer stackup and a board-level title.
This changes fabrication metadata/drawings only, never electronic footprints.
"""
import argparse,json,pathlib,os
import pcbnew
p=argparse.ArgumentParser();p.add_argument('board');a=p.parse_args();path=pathlib.Path(a.board)
board=pcbnew.LoadBoard(str(path));settings=board.GetDesignSettings()
settings.SetAuxOrigin(pcbnew.VECTOR2I(pcbnew.FromMM(-33),pcbnew.FromMM(24)))
drawings=list(board.GetDrawings())
title=next((t for t in drawings if isinstance(t,pcbnew.PCB_TEXT) and t.GetText()=='Muse Voice Remote'),None)
if title is None:
title=pcbnew.PCB_TEXT(board);title.SetText('Muse Voice Remote');board.Add(title)
title.SetPosition(pcbnew.VECTOR2I(pcbnew.FromMM(-32),pcbnew.FromMM(12)))
title.SetTextAngle(pcbnew.EDA_ANGLE(90,pcbnew.DEGREES_T))
title.SetTextSize(pcbnew.VECTOR2I(pcbnew.FromMM(.8),pcbnew.FromMM(.8)))
title.SetTextThickness(pcbnew.FromMM(.1));title.SetLayer(pcbnew.F_SilkS)
pcbnew.SaveBoard(str(path),board)
# pcbnew exposes stackup metadata inconsistently across KiCad builds. Serialize
# the native file-format descriptor and let KiCad parse/check it normally.
content=path.read_text()
stackup='''(stackup
(layer "F.SilkS" (type "Top Silk Screen"))
(layer "F.Paste" (type "Top Solder Paste"))
(layer "F.Mask" (type "Top Solder Mask") (thickness 0.01) (material "Solder mask") (epsilon_r 3.8) (loss_tangent 0.02))
(layer "F.Cu" (type "copper") (thickness 0.035))
(layer "dielectric 1" (type "prepreg") (thickness 0.0994) (material "3313 RC57%") (epsilon_r 4.1) (loss_tangent 0.02))
(layer "In1.Cu" (type "copper") (thickness 0.0152))
(layer "dielectric 2" (type "core") (thickness 0.7) (material "FR4") (epsilon_r 4.53) (loss_tangent 0.02))
(layer "In2.Cu" (type "copper") (thickness 0.0152))
(layer "dielectric 3" (type "prepreg") (thickness 0.0994) (material "3313 RC57%") (epsilon_r 4.1) (loss_tangent 0.02))
(layer "B.Cu" (type "copper") (thickness 0.035))
(layer "B.Mask" (type "Bottom Solder Mask") (thickness 0.01) (material "Solder mask") (epsilon_r 3.8) (loss_tangent 0.02))
(layer "B.Paste" (type "Bottom Solder Paste"))
(layer "B.SilkS" (type "Bottom Silk Screen"))
(copper_finish "ENIG")
(dielectric_constraints yes)
)'''
index=content.find('(stackup',content.index('(setup'))
if index>=0:
depth=0;quoted=False;escaped=False;end=None
for i in range(index,len(content)):
c=content[i]
if quoted:
if escaped:escaped=False
elif c=='\\':escaped=True
elif c=='"':quoted=False
elif c=='"':quoted=True
elif c=='(':depth+=1
elif c==')':
depth-=1
if depth==0:end=i+1;break
if end is None:raise RuntimeError('Unbalanced native stackup descriptor')
content=content[:index]+stackup+content[end:]
else:content=content.replace('(setup','(setup\n '+stackup,1)
path.write_text(content)
print('Applied JLC04101H-3313 stackup, ENIG and lower-left fabrication origin.',flush=True)
os._exit(0)