#!/usr/bin/env python3
"""PM_K-1 RP2350 core (SKiDL): MCU + QSPI flash + 12MHz crystal (MCLK-less) + USB + boot/reset + SWD.

Run INSIDE the EDA container:
    cd hardware/eda && ./run.sh python3 ../eda/circuits/mcu_core.py
Outputs ERC + hardware/kicad/mcu_core.net.

VERIFIED
  * RP2350A pinout: the authoritative KiCad MCU_RaspberryPi:RP2350A library symbol
    (datasheet-derived). Power/clock/QSPI/USB/debug pins referenced by NUMBER, GPIO by name.
  * Minimal design per RP "Hardware design with RP2350" (RP-008280): core SMPS
    VREG_LX -> 3.3uH -> DVDD, VREG_FB sense to DVDD; VREG_AVDD via 33ohm+4.7uF RC filter;
    100nF per power pin; W25Q128JVS QSPI flash (Fig 8 pinout); BOOTSEL = QSPI_SS via 1k +
    button; RUN 10k pull-up + reset button; USB D+/D- via 27ohm series.
  * CLOCK = 12MHz crystal, MCLK-LESS: RP2350 generates I2S BCK/LRCK/DIN; the PCM5102A
    derives its own clock (internal PLL), so no separate audio oscillator and no MCLK net.

CONFIRM AT LAYOUT (flagged, not guessed): crystal load-cap value (~15pF, per chosen
crystal) + possible XOUT series R; QFN-60 footprint variant; and the USB-C connector +
USBLC6-2 ESD + CC resistors (a small USB sub-block; parts in BOM) -- their pinouts to be
verified then. Here USB exits via 27ohm series to USB_DP_CONN/USB_DM_CONN.

GPIO MAP (DESIGN.md s7.1 + audio control): see assignments at the bottom.
"""
import os
from skidl import *
set_default_tool(KICAD9)
P = Pin.types
R = Part("Device","R", dest=TEMPLATE, footprint="Resistor_SMD:R_0402_1005Metric")
def C(v, fp="Capacitor_SMD:C_0402_1005Metric"): return Part("Device","C", value=v, footprint=fp)

# ---- nets ----
p3v3, gnd, dvdd, vbus = Net("+3V3"), Net("GND"), Net("DVDD"), Net("VBUS_5V")
for n in (p3v3, vbus): n.drive = POWER
gnd.drive = POWER; dvdd.drive = POWER
xin, xout = Net("XIN"), Net("XOUT")
qsck,qd0,qd1,qd2,qd3,qcs = (Net("QSPI_SCLK"),Net("QSPI_SD0"),Net("QSPI_SD1"),Net("QSPI_SD2"),Net("QSPI_SD3"),Net("QSPI_SS"))
usb_dp_c, usb_dm_c = Net("USB_DP_CONN"), Net("USB_DM_CONN")
# audio + control (shared with audio chain / interconnect by name)
i2s_bck,i2s_lrck,i2s_din = Net("I2S_BCK"),Net("I2S_LRCK"),Net("I2S_DIN")
sel_linst,mute_en,gndlift_en,dac_xsmt = Net("SEL_LINST"),Net("MUTE_EN"),Net("GNDLIFT_EN"),Net("DAC_XSMT")
sig_led,clip_led,gndlift_sw,lineinst_sw = Net("SIG_LED"),Net("CLIP_LED"),Net("GNDLIFT_SW"),Net("LINEINST_SW")
spi_sck,spi_mosi,lcd_cs,lcd_dc,lcd_rst = Net("SPI_SCK"),Net("SPI_MOSI"),Net("LCD_CS"),Net("LCD_DC"),Net("LCD_RST")
i2c_sda,i2c_scl,ws2812,btn_a,btn_b,joy_x,joy_y = (Net("I2C_SDA"),Net("I2C_SCL"),Net("WS2812"),
    Net("BTN_A"),Net("BTN_B"),Net("JOY_X"),Net("JOY_Y"))

# ---- RP2350A (authoritative KiCad symbol) ----
rp = Part("MCU_RaspberryPi","RP2350A", footprint="Package_DFN_QFN:QFN-60-1EP_7x7mm_P0.4mm_EP3.6x3.6mm", ref="U1")

# power: IOVDD x6, DVDD x3, plus the special supplies (by pin number)
for n in (1,11,20,30,38,45): rp[n] += p3v3      # IOVDD
for n in (6,23,39): rp[n] += dvdd               # DVDD (1.1V core out)
rp[53] += p3v3; rp[54] += p3v3; rp[49] += p3v3  # USB_OTP_VDD, QSPI_IOVDD, VREG_VIN
rp[47] += gnd; rp[61] += gnd                    # VREG_PGND, GND/EP
# core SMPS: VREG_LX(48) -> 3.3uH -> DVDD ; VREG_FB(50) senses DVDD
lcore = Part("Device","L", value="3.3uH", footprint="Inductor_SMD:L_0806_2016Metric", ref="L1")
rp[48] += lcore[1]; lcore[2] += dvdd; rp[50] += dvdd
ccore = C("1uF","Capacitor_SMD:C_0402_1005Metric"); dvdd += ccore[1]; ccore[2] += gnd
cvin = C("4.7uF","Capacitor_SMD:C_0805_2012Metric"); rp[49] += cvin[1]; cvin[2] += gnd
# VREG_AVDD(46): 33ohm + 4.7uF RC filter from 3V3
rav = R(value="33"); cav = C("4.7uF","Capacitor_SMD:C_0805_2012Metric")
p3v3 += rav[1]; rav[2] += rp[46]; rp[46] += cav[1]; cav[2] += gnd
# ADC_AVDD(44): ferrite/0R + 100nF
rad = R(value="0"); cad = C("100nF"); p3v3 += rad[1]; rad[2] += rp[44]; rp[44] += cad[1]; cad[2] += gnd
# bulk decoupling (per-power-pin 100nF; placement is a layout concern)
for _ in range(6):
    c = C("100nF"); p3v3 += c[1]; c[2] += gnd
for _ in range(2):
    c = C("100nF"); dvdd += c[1]; c[2] += gnd

# ---- 12MHz crystal (MCLK-less) ----
rp[21] += xin; rp[22] += xout
xtal = Part("Device","Crystal", value="12MHz", footprint="Crystal:Crystal_SMD_3225-4Pin_3.2x2.5mm", ref="Y1")
xin += xtal[1]; xout += xtal[2]
cx1 = C("15pF"); cx2 = C("15pF"); xin += cx1[1]; cx1[2] += gnd; xout += cx2[1]; cx2[2] += gnd

# ---- QSPI flash W25Q128JVS (pinout per RP2350 hw-design Fig 8) ----
FL = Part(name="W25Q128JVS", tool=SKIDL, dest=TEMPLATE, ref_prefix="U",
    footprint="Package_SO:SOIC-8_5.23x5.23mm_P1.27mm",
    pins=[Pin(num=1,name="CS",func=P.INPUT),Pin(num=2,name="IO1",func=P.BIDIR),Pin(num=3,name="IO2",func=P.BIDIR),
          Pin(num=4,name="GND",func=P.PWRIN),Pin(num=5,name="IO0",func=P.BIDIR),Pin(num=6,name="CLK",func=P.INPUT),
          Pin(num=7,name="IO3",func=P.BIDIR),Pin(num=8,name="VCC",func=P.PWRIN)])
fl = FL(ref="U2")
fl["CLK"]+=qsck; fl["IO0"]+=qd0; fl["IO1"]+=qd1; fl["IO2"]+=qd2; fl["IO3"]+=qd3; fl["CS"]+=qcs
fl["VCC"]+=p3v3; fl["GND"]+=gnd
cfl = C("100nF"); p3v3 += cfl[1]; cfl[2] += gnd
rp[56]+=qsck; rp[57]+=qd0; rp[59]+=qd1; rp[58]+=qd2; rp[55]+=qd3; rp[60]+=qcs   # QSPI_SCLK/SD0/SD1/SD2/SD3/SS

# ---- BOOTSEL: QSPI_SS -> 1k -> button -> GND ----
rboot = R(value="1k"); swboot = Part("Switch","SW_Push", footprint="Button_Switch_SMD:SW_SPST_SKQG_WithStem", ref="SW1")
qcs += rboot[1]; rboot[2] += swboot[1]; swboot[2] += gnd

# ---- RUN: 10k pull-up + reset button + 100nF ----
rrun = R(value="10k"); swrun = Part("Switch","SW_Push", footprint="Button_Switch_SMD:SW_SPST_SKQG_WithStem", ref="SW2")
p3v3 += rrun[1]; rrun[2] += rp[26]; rp[26] += swrun[1]; swrun[2] += gnd
crun = C("100nF"); rp[26] += crun[1]; crun[2] += gnd

# ---- SWD debug header (SWDIO/SWCLK/GND/3V3) ----
swd = Part("Connector_Generic","Conn_01x04", footprint="Connector_PinHeader_1.27mm:PinHeader_1x04_P1.27mm_Vertical", ref="J2")
swd[1]+=p3v3; swd[2]+=rp[25]; swd[3]+=rp[24]; swd[4]+=gnd       # SWDIO=25, SWCLK=24

# ---- USB D+/D- via 27ohm series (USB-C connector + ESD = separate sub-block) ----
rdp = R(value="27"); rdm = R(value="27")
rp[52]+=rdp[1]; rdp[2]+=usb_dp_c        # USB_DP
rp[51]+=rdm[1]; rdm[2]+=usb_dm_c        # USB_DM

# ---- GPIO assignments (DESIGN.md s7.1 + audio control) ----
rp["GPIO2"]+=spi_sck; rp["GPIO3"]+=spi_mosi; rp["GPIO5"]+=lcd_cs; rp["GPIO6"]+=lcd_dc; rp["GPIO7"]+=lcd_rst
rp["GPIO8"]+=i2c_sda; rp["GPIO9"]+=i2c_scl
rp["GPIO10"]+=i2s_bck; rp["GPIO11"]+=i2s_lrck; rp["GPIO13"]+=i2s_din
rp["GPIO12"]+=ws2812
rp["GPIO14"]+=btn_b; rp["GPIO15"]+=btn_a
rp["GPIO16"]+=sel_linst; rp["GPIO17"]+=gndlift_en; rp["GPIO18"]+=mute_en
rp["GPIO19"]+=sig_led; rp["GPIO20"]+=clip_led
rp["GPIO21"]+=gndlift_sw; rp["GPIO22"]+=lineinst_sw
rp["GPIO26/ADC0"]+=joy_x; rp["GPIO27/ADC1"]+=joy_y
rp["GPIO0"]+=dac_xsmt

ERC()
out = os.path.abspath(os.path.join(os.path.dirname(__file__), "..", "..", "kicad", "mcu_core.net"))
generate_netlist(file_=out)
print("MCU core netlist ->", out)
