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)