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/fill-ground-plane.py

"""Fill zones from reloaded native CAD and optionally export router input."""
import argparse
import pathlib
import pcbnew

parser = argparse.ArgumentParser()
parser.add_argument("board", nargs="?", default="dist/MuseVoiceRemote-library.kicad_pcb")
parser.add_argument("--dsn")
args = parser.parse_args()
board = pcbnew.LoadBoard(args.board)
board.BuildConnectivity()
filler = pcbnew.ZONE_FILLER(board)
filler.Fill(board.Zones())
pcbnew.SaveBoard(args.board, board)
if args.dsn:
    if not pcbnew.ExportSpecctraDSN(board, args.dsn):
        raise RuntimeError("Native DSN export failed")
    path = pathlib.Path(args.dsn)
    text = path.read_text()
    if any(z.GetLayer() == pcbnew.In1_Cu and z.GetNetname() == "GND" for z in board.Zones()):
        old = "(layer In1.Cu\n      (type signal)"
        if old not in text:
            raise RuntimeError("Unexpected ground-layer DSN declaration")
        text = text.replace(old, "(layer In1.Cu\n      (type power)", 1)
        # FreeRouting 2.5 RouterSettings.initializeFromBoard explicitly sets
        # non-signal layers unroutable. A full-layer keepout would also block
        # through vias and must not be substituted for this layer declaration.
    path.write_text(text)
print("Native ground plane refilled; supplied component geometry retained.")