#!/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)