#!/Applications/KiCad/KiCad.app/Contents/Frameworks/Python.framework/Versions/3.9/bin/python3
"""Build independent A2 PCB from localized A1 plus a routed 3V3 LDO branch."""
from pathlib import Path
import wx
_app=wx.App(False)
import pcbnew

HERE=Path(__file__).resolve().parent
SOURCE=HERE/'baseline/lamp_buck_lmr51450_a4_frontend.kicad_pcb'
BOARD=HERE/'power_board/lamp_buck_lmr51450_a6_local_ldo.kicad_pcb'
b=pcbnew.LoadBoard(str(SOURCE))
libroot=Path('/Applications/KiCad/KiCad.app/Contents/SharedSupport/footprints')
components=[
    ('Package_TO_SOT_SMD','SOT-23-5','U4','AP2112K-3.3TRG1 candidate',20.0,55.0,180.0),
    ('Capacitor_SMD','C_0603_1608Metric','C15','1uF 10V X7R input bypass',23.9,55.0,0.0),
    ('Capacitor_SMD','C_0603_1608Metric','C16','1uF 10V X7R output bypass',15.9,54.5,180.0),
]
nets={name:b.FindNet("/"+name) for name in ['SYS_5V0_ALWAYS_ON','CTRL_3V3','GND']}
if any(net is None for net in nets.values()): raise SystemExit('required A1 net missing')
new={}
for lib,item,ref,value,x,y,rot in components:
    fp=pcbnew.FootprintLoad(str(libroot/f'{lib}.pretty'),item)
    if fp is None: raise SystemExit(f'cannot load {lib}:{item}')
    fp.SetReference(ref); fp.SetValue(value)
    fp.SetPosition(pcbnew.VECTOR2I(pcbnew.FromMM(x),pcbnew.FromMM(y)))
    fp.SetOrientationDegrees(rot)
    if ref=='C15': fp.Reference().SetPosition(pcbnew.VECTOR2I(pcbnew.FromMM(23.5),pcbnew.FromMM(59.0)))
    if ref=='C16': fp.Reference().SetPosition(pcbnew.VECTOR2I(pcbnew.FromMM(15.9),pcbnew.FromMM(52.5)))
    b.Add(fp); new[ref]=fp
padnets={
    'U4':{'1':'SYS_5V0_ALWAYS_ON','2':'GND','3':'SYS_5V0_ALWAYS_ON','5':'CTRL_3V3'},
    'C15':{'1':'SYS_5V0_ALWAYS_ON','2':'GND'},
    'C16':{'1':'CTRL_3V3','2':'GND'},
}
for ref,mapping in padnets.items():
    for pad in new[ref].Pads():
        if pad.GetNumber() in mapping: pad.SetNet(nets[mapping[pad.GetNumber()]])

IU=1_000_000
pt=lambda x,y: pcbnew.VECTOR2I(round(x*IU),round(y*IU))
def route(net,layer,points,width=0.25):
    for (x1,y1),(x2,y2) in zip(points,points[1:]):
        t=pcbnew.PCB_TRACK(b); t.SetStart(pt(x1,y1)); t.SetEnd(pt(x2,y2))
        t.SetLayer(layer); t.SetWidth(pcbnew.FromMM(width)); t.SetNet(nets[net]); b.Add(t)
def via(net,x,y,diam=0.6,drill=0.3):
    v=pcbnew.PCB_VIA(b); v.SetPosition(pt(x,y)); v.SetWidth(pcbnew.FromMM(diam)); v.SetDrill(pcbnew.FromMM(drill))
    v.SetLayerPair(pcbnew.F_Cu,pcbnew.B_Cu); v.SetNet(nets[net]); b.Add(v)

# 5V follows the left edge on F.Cu, then uses B.Cu to pass below the J2 monitor
# signals and returns to F.Cu beside C15/U4. J2 pin 1 is through-hole, so the
# CTRL_3V3 return can use a separate short B.Cu link without crossing monitors.
route('SYS_5V0_ALWAYS_ON',pcbnew.F_Cu,[(8.0,25.0),(4.0,25.0),(4.0,64.0)],0.25)
via('SYS_5V0_ALWAYS_ON',4.0,64.0)
via('SYS_5V0_ALWAYS_ON',23.5,55.1)
route('SYS_5V0_ALWAYS_ON',pcbnew.B_Cu,[(4.0,64.0),(21.8,60.2),(24.0,58.0),(23.5,55.1)],0.25)
route('SYS_5V0_ALWAYS_ON',pcbnew.F_Cu,[(23.5,55.1),(23.125,55.0)],0.25)
# C15, U4 VIN and U4 EN share the always-on source; EN is hard-enabled.
route('SYS_5V0_ALWAYS_ON',pcbnew.F_Cu,[(23.125,55.0),(21.137,55.95)],0.25)
route('SYS_5V0_ALWAYS_ON',pcbnew.F_Cu,[(23.125,55.0),(23.125,53.2),(22.0,53.2),(21.137,54.05)],0.25)
# U4 VOUT and C16 connect on F.Cu; a via and B.Cu trace reach J2 pin 1 from
# below the adjacent voltage/current monitor traces.
route('CTRL_3V3',pcbnew.F_Cu,[(18.863,55.95),(16.8,55.2)],0.25)
route('CTRL_3V3',pcbnew.F_Cu,[(18.863,55.95),(16.675,55.95),(16.675,54.5)],0.25)
via('CTRL_3V3',16.8,55.2)
via('CTRL_3V3',16.5,48.0)
route('CTRL_3V3',pcbnew.B_Cu,[(16.8,55.2),(16.5,48.0)],0.25)
route('CTRL_3V3',pcbnew.F_Cu,[(16.5,48.0),(16.5,49.0)],0.25)
# Each bypass ground gets a nearby via into the common B.Cu GND plane.
route('GND',pcbnew.F_Cu,[(21.137,55.0),(20.4,55.0)])
route('GND',pcbnew.F_Cu,[(24.675,55.0),(25.3,55.0)])
route('GND',pcbnew.F_Cu,[(15.125,54.5),(14.4,54.5)])
via('GND',20.4,55.0);via('GND',25.3,55.0);via('GND',14.4,54.5)

pcbnew.ZONE_FILLER(b).Fill(b.Zones())
pcbnew.SaveBoard(str(BOARD),b)
print(f'updated {BOARD}: added and connected U4/C15/C16 on a new SYS_5V0_ALWAYS_ON branch')
