615 lines
32 KiB
Python
615 lines
32 KiB
Python
#!/usr/bin/env python3
|
|
"""
|
|
Generate KiCad 7 schematic and project files for Baby Mobile Audio Board.
|
|
|
|
Design: ATmega328P + W25Q128 SPI Flash + PAM8302A Class-D Amp + MOSFET motor driver
|
|
Power: 2x AA batteries (1.8V-3.3V), optimized for long runtime
|
|
Audio: 30+ min at 8kHz/8-bit mono via 16MB SPI flash
|
|
"""
|
|
|
|
import uuid
|
|
import json
|
|
import os
|
|
|
|
def uid():
|
|
return str(uuid.uuid4())
|
|
|
|
# ============================================================
|
|
# SCHEMATIC GENERATION
|
|
# ============================================================
|
|
|
|
def generate_schematic():
|
|
"""Generate the complete .kicad_sch file."""
|
|
|
|
# We use net labels for connections instead of routing every wire.
|
|
# This keeps the schematic clean and KiCad resolves connectivity by label name.
|
|
|
|
sch = []
|
|
sch.append(f"""(kicad_sch (version 20230121) (generator "custom_generator")
|
|
|
|
(uuid "{uid()}")
|
|
(paper "A3")
|
|
|
|
(title_block
|
|
(title "Baby Mobile Audio Board")
|
|
(date "2026-03-08")
|
|
(rev "1.0")
|
|
(comment 1 "ATmega328P + W25Q128 + PAM8302A")
|
|
(comment 2 "2xAA Battery Powered - Long Runtime Design")
|
|
(comment 3 "8-ohm 0.25W Speaker, DC Motor, 8 Buttons")
|
|
(comment 4 "Arduino Compatible (8MHz Internal Osc)")
|
|
)
|
|
""")
|
|
|
|
# ---- LIB_SYMBOLS ----
|
|
sch.append(" (lib_symbols")
|
|
sch.append(_sym_atmega328p())
|
|
sch.append(_sym_w25q128())
|
|
sch.append(_sym_pam8302a())
|
|
sch.append(_sym_nmos())
|
|
sch.append(_sym_capacitor())
|
|
sch.append(_sym_resistor())
|
|
sch.append(_sym_diode_schottky())
|
|
sch.append(_sym_inductor())
|
|
sch.append(_sym_switch())
|
|
sch.append(_sym_conn2())
|
|
sch.append(_sym_conn3())
|
|
sch.append(_sym_conn6())
|
|
sch.append(_sym_led())
|
|
sch.append(_sym_pwr_flag())
|
|
sch.append(" )") # end lib_symbols
|
|
|
|
# ---- COMPONENT INSTANCES ----
|
|
# Layout regions (KiCad uses mm, origin top-left):
|
|
# Power supply section: x=30, y=30
|
|
# MCU (ATmega328P): x=130, y=90
|
|
# SPI Flash (W25Q128): x=230, y=60
|
|
# Audio section (PAM8302A): x=230, y=140
|
|
# Motor driver: x=130, y=190
|
|
# Buttons (8x): x=30, y=80-180
|
|
# ISP Header: x=230, y=200
|
|
# Serial Header: x=30, y=200
|
|
|
|
# ---- POWER SUPPLY SECTION ----
|
|
# Battery connector J1
|
|
sch.append(_instance("baby_mobile:Conn_2Pin", "J1", "BATTERY", "Connector_JST:JST_PH_S2B-PH-K_1x02_P2.00mm_Horizontal",
|
|
25, 35, 0))
|
|
# Main decoupling C1: 100uF electrolytic
|
|
sch.append(_instance("baby_mobile:Capacitor", "C1", "100uF", "Capacitor_THT:CP_Radial_D5.0mm_P2.00mm",
|
|
55, 35, 0))
|
|
# Decoupling C2: 100nF ceramic near MCU VCC
|
|
sch.append(_instance("baby_mobile:Capacitor", "C2", "100nF", "Capacitor_SMD:C_0805_2012Metric",
|
|
100, 30, 0))
|
|
# Decoupling C3: 100nF ceramic near MCU AVCC
|
|
sch.append(_instance("baby_mobile:Capacitor", "C3", "100nF", "Capacitor_SMD:C_0805_2012Metric",
|
|
115, 30, 0))
|
|
# Power switch SW_PWR
|
|
sch.append(_instance("baby_mobile:Switch", "SW9", "PWR", "Button_Switch_THT:SW_SPDT_CK-JS102011SAQN",
|
|
40, 25, 0))
|
|
|
|
# ---- MCU: ATmega328P-AU ----
|
|
sch.append(_instance("baby_mobile:ATmega328P-AU", "U1", "ATmega328P-AU", "Package_QFP:TQFP-32_7x7mm_P0.8mm",
|
|
130, 90, 0))
|
|
# Reset pullup R_RST: 10K
|
|
sch.append(_instance("baby_mobile:Resistor", "R1", "10K", "Resistor_SMD:R_0805_2012Metric",
|
|
95, 55, 0))
|
|
# Reset capacitor C_RST: 100nF
|
|
sch.append(_instance("baby_mobile:Capacitor", "C4", "100nF", "Capacitor_SMD:C_0805_2012Metric",
|
|
95, 65, 0))
|
|
|
|
# ---- SPI FLASH: W25Q128JVSIQ ----
|
|
sch.append(_instance("baby_mobile:W25Q128", "U2", "W25Q128JVSIQ", "Package_SO:SOIC-8_3.9x4.9mm_P1.27mm",
|
|
230, 60, 0))
|
|
# Flash decoupling C5: 100nF
|
|
sch.append(_instance("baby_mobile:Capacitor", "C5", "100nF", "Capacitor_SMD:C_0805_2012Metric",
|
|
255, 50, 0))
|
|
|
|
# ---- AUDIO AMP: PAM8302A ----
|
|
sch.append(_instance("baby_mobile:PAM8302A", "U3", "PAM8302A", "Package_SO:SOIC-8_3.9x4.9mm_P1.27mm",
|
|
230, 140, 0))
|
|
# Input coupling cap C6: 1uF
|
|
sch.append(_instance("baby_mobile:Capacitor", "C6", "1uF", "Capacitor_SMD:C_0805_2012Metric",
|
|
200, 135, 0))
|
|
# RC low-pass filter on PWM: R_LPF + C_LPF
|
|
# f_c = 1/(2*pi*R*C) ~ 3.4kHz with 4.7K + 10nF
|
|
sch.append(_instance("baby_mobile:Resistor", "R2", "4.7K", "Resistor_SMD:R_0805_2012Metric",
|
|
185, 135, 0))
|
|
sch.append(_instance("baby_mobile:Capacitor", "C7", "10nF", "Capacitor_SMD:C_0805_2012Metric",
|
|
192, 145, 0))
|
|
# Amp supply bypass C8: 10uF
|
|
sch.append(_instance("baby_mobile:Capacitor", "C8", "10uF", "Capacitor_SMD:C_0805_2012Metric",
|
|
255, 130, 0))
|
|
# Speaker connector J2
|
|
sch.append(_instance("baby_mobile:Conn_2Pin", "J2", "SPEAKER", "Connector_JST:JST_PH_S2B-PH-K_1x02_P2.00mm_Horizontal",
|
|
265, 145, 0))
|
|
# Shutdown pulldown R_SD: 100K (default ON, MCU can shut down)
|
|
sch.append(_instance("baby_mobile:Resistor", "R3", "100K", "Resistor_SMD:R_0805_2012Metric",
|
|
210, 150, 0))
|
|
|
|
# ---- MOTOR DRIVER ----
|
|
# N-ch MOSFET Q1
|
|
sch.append(_instance("baby_mobile:NMOS", "Q1", "AO3400A", "Package_TO_SOT_SMD:SOT-23",
|
|
140, 190, 0))
|
|
# Gate resistor R_GATE: 100 ohm
|
|
sch.append(_instance("baby_mobile:Resistor", "R4", "100R", "Resistor_SMD:R_0805_2012Metric",
|
|
120, 190, 0))
|
|
# Gate pulldown R_GPD: 100K
|
|
sch.append(_instance("baby_mobile:Resistor", "R5", "100K", "Resistor_SMD:R_0805_2012Metric",
|
|
130, 200, 0))
|
|
# Flyback diode D1
|
|
sch.append(_instance("baby_mobile:Diode_Schottky", "D1", "SS14", "Diode_SMD:D_SMA",
|
|
155, 180, 90))
|
|
# Motor connector J3
|
|
sch.append(_instance("baby_mobile:Conn_2Pin", "J3", "MOTOR", "Connector_JST:JST_PH_S2B-PH-K_1x02_P2.00mm_Horizontal",
|
|
160, 170, 0))
|
|
|
|
# ---- 8 BUTTONS ----
|
|
button_pins = ["BTN1", "BTN2", "BTN3", "BTN4", "BTN5", "BTN6", "BTN7", "BTN8"]
|
|
for i, name in enumerate(button_pins):
|
|
y = 75 + i * 15
|
|
sch.append(_instance("baby_mobile:Switch", f"SW{i+1}", name, "Button_Switch_SMD:SW_SPST_TL3342",
|
|
30, y, 0))
|
|
|
|
# ---- STATUS LED ----
|
|
sch.append(_instance("baby_mobile:LED", "D2", "LED", "LED_SMD:LED_0805_2012Metric",
|
|
85, 190, 0))
|
|
sch.append(_instance("baby_mobile:Resistor", "R6", "1K", "Resistor_SMD:R_0805_2012Metric",
|
|
75, 190, 0))
|
|
|
|
# ---- ISP HEADER (2x3) ----
|
|
sch.append(_instance("baby_mobile:Conn_6Pin", "J4", "ISP", "Connector_PinHeader_2.54mm:PinHeader_2x03_P2.54mm_Vertical",
|
|
250, 200, 0))
|
|
|
|
# ---- SERIAL HEADER (3-pin: GND, TX, RX) ----
|
|
sch.append(_instance("baby_mobile:Conn_3Pin", "J5", "SERIAL", "Connector_PinHeader_2.54mm:PinHeader_1x03_P2.54mm_Vertical",
|
|
30, 210, 0))
|
|
|
|
# ---- NET LABELS ----
|
|
# Power nets
|
|
net_labels = [
|
|
# Power distribution
|
|
("VCC", 55, 25), ("VCC", 100, 25), ("VCC", 115, 25),
|
|
("VCC", 130, 50), ("VCC", 255, 45), ("VCC", 255, 125),
|
|
("VCC", 95, 50), ("VCC", 160, 165),
|
|
("GND", 55, 45), ("GND", 100, 40), ("GND", 115, 40),
|
|
("GND", 130, 130), ("GND", 255, 70), ("GND", 255, 155),
|
|
("GND", 95, 70), ("GND", 140, 205), ("GND", 192, 155),
|
|
|
|
# SPI bus
|
|
("SPI_MOSI", 165, 85), ("SPI_MOSI", 215, 55),
|
|
("SPI_MISO", 165, 90), ("SPI_MISO", 215, 60),
|
|
("SPI_SCK", 165, 95), ("SPI_SCK", 215, 65),
|
|
("FLASH_CS", 165, 80), ("FLASH_CS", 215, 50),
|
|
|
|
# Audio
|
|
("AUDIO_PWM", 165, 100), ("AUDIO_PWM", 175, 135),
|
|
("AMP_SD", 165, 105), ("AMP_SD", 210, 145),
|
|
|
|
# Motor
|
|
("MOTOR_PWM", 165, 110), ("MOTOR_PWM", 110, 190),
|
|
|
|
# Buttons (directly named for MCU pins mapping)
|
|
("BTN1", 45, 75), ("BTN1", 95, 85),
|
|
("BTN2", 45, 90), ("BTN2", 95, 90),
|
|
("BTN3", 45, 105), ("BTN3", 95, 95),
|
|
("BTN4", 45, 120), ("BTN4", 95, 100),
|
|
("BTN5", 45, 135), ("BTN5", 95, 105),
|
|
("BTN6", 45, 150), ("BTN6", 95, 110),
|
|
("BTN7", 45, 165), ("BTN7", 95, 115),
|
|
("BTN8", 45, 180), ("BTN8", 95, 120),
|
|
|
|
# ISP
|
|
("SPI_MOSI", 240, 195), ("SPI_MISO", 240, 200),
|
|
("SPI_SCK", 240, 205), ("RESET", 240, 210),
|
|
("RESET", 95, 60),
|
|
|
|
# Serial
|
|
("TXD", 40, 210), ("RXD", 40, 215),
|
|
("TXD", 95, 75), ("RXD", 95, 80),
|
|
|
|
# LED
|
|
("LED_OUT", 65, 190), ("LED_OUT", 95, 125),
|
|
]
|
|
|
|
for name, x, y in net_labels:
|
|
sch.append(f""" (label "{name}" (at {x} {y} 0) (effects (font (size 1.27 1.27))) (uuid "{uid()}"))""")
|
|
|
|
# ---- TEXT NOTES ----
|
|
notes = [
|
|
(15, 15, "POWER: 2xAA (1.8V-3.3V) → Long runtime design"),
|
|
(15, 18, "MCU: ATmega328P-AU @ 8MHz internal osc, Arduino compatible"),
|
|
(200, 15, "FLASH: W25Q128 16MB = ~33 min @ 8kHz 8-bit PCM"),
|
|
(200, 18, "AMP: PAM8302A Class-D, 90% efficient, Vmin=2.0V"),
|
|
(15, 220, "BUTTONS: Internal pull-ups, active LOW, PCINT wake-from-sleep"),
|
|
(120, 220, "MOTOR: AO3400A logic-level N-MOSFET, PWM speed control"),
|
|
(15, 225, "ESTIMATED RUNTIME: Audio+Motor ~23h, Audio only ~200h, Sleep ~years"),
|
|
]
|
|
for x, y, text in notes:
|
|
sch.append(f""" (text "{text}" (at {x} {y} 0)
|
|
(effects (font (size 1.5 1.5)) (justify left))
|
|
(uuid "{uid()}")
|
|
)""")
|
|
|
|
sch.append(")") # end kicad_sch
|
|
return "\n".join(sch)
|
|
|
|
|
|
# ============================================================
|
|
# SYMBOL DEFINITIONS
|
|
# ============================================================
|
|
|
|
def _sym_atmega328p():
|
|
return f"""
|
|
(symbol "baby_mobile:ATmega328P-AU" (in_bom yes) (on_board yes)
|
|
(property "Reference" "U" (at 0 26 0) (effects (font (size 1.27 1.27))))
|
|
(property "Value" "ATmega328P-AU" (at 0 24 0) (effects (font (size 1.27 1.27))))
|
|
(property "Footprint" "Package_QFP:TQFP-32_7x7mm_P0.8mm" (at 0 0 0) (effects (font (size 1.27 1.27)) hide))
|
|
(property "Datasheet" "" (at 0 0 0) (effects (font (size 1.27 1.27)) hide))
|
|
(symbol "ATmega328P-AU_0_1"
|
|
(rectangle (start -17 23) (end 17 -23) (stroke (width 0.254) (type default)) (fill (type background)))
|
|
)
|
|
(symbol "ATmega328P-AU_1_1"
|
|
(pin power_in line (at -7 -26 90) (length 3) (name "GND" (effects (font (size 1 1)))) (number "3" (effects (font (size 1 1)))))
|
|
(pin power_in line (at -5 -26 90) (length 3) (name "GND2" (effects (font (size 1 1)))) (number "5" (effects (font (size 1 1)))))
|
|
(pin power_in line (at -3 26 270) (length 3) (name "VCC" (effects (font (size 1 1)))) (number "4" (effects (font (size 1 1)))))
|
|
(pin power_in line (at -1 26 270) (length 3) (name "AVCC" (effects (font (size 1 1)))) (number "6" (effects (font (size 1 1)))))
|
|
(pin passive line (at 1 26 270) (length 3) (name "AREF" (effects (font (size 1 1)))) (number "21" (effects (font (size 1 1)))))
|
|
(pin bidirectional line (at -20 15 0) (length 3) (name "PD0/RXD" (effects (font (size 1 1)))) (number "30" (effects (font (size 1 1)))))
|
|
(pin bidirectional line (at -20 12.5 0) (length 3) (name "PD1/TXD" (effects (font (size 1 1)))) (number "31" (effects (font (size 1 1)))))
|
|
(pin bidirectional line (at -20 10 0) (length 3) (name "PD2/INT0" (effects (font (size 1 1)))) (number "32" (effects (font (size 1 1)))))
|
|
(pin bidirectional line (at -20 7.5 0) (length 3) (name "PD3/INT1" (effects (font (size 1 1)))) (number "1" (effects (font (size 1 1)))))
|
|
(pin bidirectional line (at -20 5 0) (length 3) (name "PD4" (effects (font (size 1 1)))) (number "2" (effects (font (size 1 1)))))
|
|
(pin bidirectional line (at -20 2.5 0) (length 3) (name "PD5/OC0B" (effects (font (size 1 1)))) (number "9" (effects (font (size 1 1)))))
|
|
(pin bidirectional line (at -20 0 0) (length 3) (name "PD6/OC0A" (effects (font (size 1 1)))) (number "10" (effects (font (size 1 1)))))
|
|
(pin bidirectional line (at -20 -2.5 0) (length 3) (name "PD7" (effects (font (size 1 1)))) (number "11" (effects (font (size 1 1)))))
|
|
(pin bidirectional line (at 20 15 180) (length 3) (name "PB0" (effects (font (size 1 1)))) (number "12" (effects (font (size 1 1)))))
|
|
(pin bidirectional line (at 20 12.5 180) (length 3) (name "PB1/OC1A" (effects (font (size 1 1)))) (number "13" (effects (font (size 1 1)))))
|
|
(pin bidirectional line (at 20 10 180) (length 3) (name "PB2/SS" (effects (font (size 1 1)))) (number "14" (effects (font (size 1 1)))))
|
|
(pin bidirectional line (at 20 7.5 180) (length 3) (name "PB3/MOSI" (effects (font (size 1 1)))) (number "15" (effects (font (size 1 1)))))
|
|
(pin bidirectional line (at 20 5 180) (length 3) (name "PB4/MISO" (effects (font (size 1 1)))) (number "16" (effects (font (size 1 1)))))
|
|
(pin bidirectional line (at 20 2.5 180) (length 3) (name "PB5/SCK" (effects (font (size 1 1)))) (number "17" (effects (font (size 1 1)))))
|
|
(pin bidirectional line (at 20 -2.5 180) (length 3) (name "PC0/ADC0" (effects (font (size 1 1)))) (number "23" (effects (font (size 1 1)))))
|
|
(pin bidirectional line (at 20 -5 180) (length 3) (name "PC1/ADC1" (effects (font (size 1 1)))) (number "24" (effects (font (size 1 1)))))
|
|
(pin bidirectional line (at 20 -7.5 180) (length 3) (name "PC2/ADC2" (effects (font (size 1 1)))) (number "25" (effects (font (size 1 1)))))
|
|
(pin bidirectional line (at 20 -10 180) (length 3) (name "PC3/ADC3" (effects (font (size 1 1)))) (number "26" (effects (font (size 1 1)))))
|
|
(pin bidirectional line (at 20 -12.5 180) (length 3) (name "PC4/SDA" (effects (font (size 1 1)))) (number "27" (effects (font (size 1 1)))))
|
|
(pin bidirectional line (at 20 -15 180) (length 3) (name "PC5/SCL" (effects (font (size 1 1)))) (number "28" (effects (font (size 1 1)))))
|
|
(pin input line (at -20 -10 0) (length 3) (name "~{{RESET}}" (effects (font (size 1 1)))) (number "29" (effects (font (size 1 1)))))
|
|
(pin input line (at -20 -15 0) (length 3) (name "XTAL1" (effects (font (size 1 1)))) (number "7" (effects (font (size 1 1)))))
|
|
(pin output line (at -20 -17.5 0) (length 3) (name "XTAL2" (effects (font (size 1 1)))) (number "8" (effects (font (size 1 1)))))
|
|
)
|
|
)"""
|
|
|
|
def _sym_w25q128():
|
|
return f"""
|
|
(symbol "baby_mobile:W25Q128" (in_bom yes) (on_board yes)
|
|
(property "Reference" "U" (at 0 9 0) (effects (font (size 1.27 1.27))))
|
|
(property "Value" "W25Q128JVSIQ" (at 0 7 0) (effects (font (size 1.27 1.27))))
|
|
(property "Footprint" "Package_SO:SOIC-8_3.9x4.9mm_P1.27mm" (at 0 0 0) (effects (font (size 1.27 1.27)) hide))
|
|
(property "Datasheet" "" (at 0 0 0) (effects (font (size 1.27 1.27)) hide))
|
|
(symbol "W25Q128_0_1"
|
|
(rectangle (start -7 6) (end 7 -6) (stroke (width 0.254) (type default)) (fill (type background)))
|
|
)
|
|
(symbol "W25Q128_1_1"
|
|
(pin input line (at -10 4 0) (length 3) (name "~{{CS}}" (effects (font (size 1 1)))) (number "1" (effects (font (size 1 1)))))
|
|
(pin output line (at -10 1.5 0) (length 3) (name "DO/IO1" (effects (font (size 1 1)))) (number "2" (effects (font (size 1 1)))))
|
|
(pin input line (at -10 -1.5 0) (length 3) (name "~{{WP}}/IO2" (effects (font (size 1 1)))) (number "3" (effects (font (size 1 1)))))
|
|
(pin power_in line (at -10 -4 0) (length 3) (name "GND" (effects (font (size 1 1)))) (number "4" (effects (font (size 1 1)))))
|
|
(pin input line (at 10 -4 180) (length 3) (name "DI/IO0" (effects (font (size 1 1)))) (number "5" (effects (font (size 1 1)))))
|
|
(pin input line (at 10 -1.5 180) (length 3) (name "CLK" (effects (font (size 1 1)))) (number "6" (effects (font (size 1 1)))))
|
|
(pin input line (at 10 1.5 180) (length 3) (name "~{{HOLD}}/IO3" (effects (font (size 1 1)))) (number "7" (effects (font (size 1 1)))))
|
|
(pin power_in line (at 10 4 180) (length 3) (name "VCC" (effects (font (size 1 1)))) (number "8" (effects (font (size 1 1)))))
|
|
)
|
|
)"""
|
|
|
|
def _sym_pam8302a():
|
|
return f"""
|
|
(symbol "baby_mobile:PAM8302A" (in_bom yes) (on_board yes)
|
|
(property "Reference" "U" (at 0 11 0) (effects (font (size 1.27 1.27))))
|
|
(property "Value" "PAM8302A" (at 0 9 0) (effects (font (size 1.27 1.27))))
|
|
(property "Footprint" "Package_SO:SOIC-8_3.9x4.9mm_P1.27mm" (at 0 0 0) (effects (font (size 1.27 1.27)) hide))
|
|
(property "Datasheet" "" (at 0 0 0) (effects (font (size 1.27 1.27)) hide))
|
|
(symbol "PAM8302A_0_1"
|
|
(rectangle (start -8 8) (end 8 -8) (stroke (width 0.254) (type default)) (fill (type background)))
|
|
)
|
|
(symbol "PAM8302A_1_1"
|
|
(pin input line (at -11 5 0) (length 3) (name "~{{SD}}" (effects (font (size 1 1)))) (number "1" (effects (font (size 1 1)))))
|
|
(pin power_in line (at -11 2 0) (length 3) (name "VDD" (effects (font (size 1 1)))) (number "2" (effects (font (size 1 1)))))
|
|
(pin power_in line (at -11 -1 0) (length 3) (name "GND" (effects (font (size 1 1)))) (number "3" (effects (font (size 1 1)))))
|
|
(pin input line (at -11 -4 0) (length 3) (name "A+" (effects (font (size 1 1)))) (number "4" (effects (font (size 1 1)))))
|
|
(pin input line (at -11 -7 0) (length 3) (name "A-" (effects (font (size 1 1)))) (number "5" (effects (font (size 1 1)))))
|
|
(pin output line (at 11 2 180) (length 3) (name "VO+" (effects (font (size 1 1)))) (number "8" (effects (font (size 1 1)))))
|
|
(pin output line (at 11 -1 180) (length 3) (name "VO-" (effects (font (size 1 1)))) (number "7" (effects (font (size 1 1)))))
|
|
(pin power_in line (at 11 -4 180) (length 3) (name "PAD" (effects (font (size 1 1)))) (number "6" (effects (font (size 1 1)))))
|
|
)
|
|
)"""
|
|
|
|
def _sym_nmos():
|
|
return f"""
|
|
(symbol "baby_mobile:NMOS" (in_bom yes) (on_board yes)
|
|
(property "Reference" "Q" (at 3 0 0) (effects (font (size 1.27 1.27))))
|
|
(property "Value" "AO3400A" (at 5 -2.5 0) (effects (font (size 1.27 1.27))))
|
|
(property "Footprint" "Package_TO_SOT_SMD:SOT-23" (at 0 0 0) (effects (font (size 1.27 1.27)) hide))
|
|
(property "Datasheet" "" (at 0 0 0) (effects (font (size 1.27 1.27)) hide))
|
|
(symbol "NMOS_0_1"
|
|
(polyline (pts (xy -0.5 0.5) (xy -0.5 -0.5)) (stroke (width 0.33) (type default)) (fill (type none)))
|
|
(polyline (pts (xy -0.5 -2) (xy -0.5 2)) (stroke (width 0.254) (type default)) (fill (type none)))
|
|
(polyline (pts (xy 0 -2.5) (xy 0 -1.5)) (stroke (width 0) (type default)) (fill (type none)))
|
|
(polyline (pts (xy 0 1.5) (xy 0 2.5)) (stroke (width 0) (type default)) (fill (type none)))
|
|
(polyline (pts (xy 0 0) (xy -1.5 0)) (stroke (width 0) (type default)) (fill (type none)))
|
|
)
|
|
(symbol "NMOS_1_1"
|
|
(pin passive line (at 0 5 270) (length 2.5) (name "D" (effects (font (size 1 1)))) (number "3" (effects (font (size 1 1)))))
|
|
(pin input line (at -4 0 0) (length 2.5) (name "G" (effects (font (size 1 1)))) (number "1" (effects (font (size 1 1)))))
|
|
(pin passive line (at 0 -5 90) (length 2.5) (name "S" (effects (font (size 1 1)))) (number "2" (effects (font (size 1 1)))))
|
|
)
|
|
)"""
|
|
|
|
def _sym_capacitor():
|
|
return f"""
|
|
(symbol "baby_mobile:Capacitor" (in_bom yes) (on_board yes)
|
|
(property "Reference" "C" (at 2 0 0) (effects (font (size 1.27 1.27))))
|
|
(property "Value" "C" (at 2 -2 0) (effects (font (size 1.27 1.27))))
|
|
(property "Footprint" "" (at 0 0 0) (effects (font (size 1.27 1.27)) hide))
|
|
(property "Datasheet" "" (at 0 0 0) (effects (font (size 1.27 1.27)) hide))
|
|
(symbol "Capacitor_0_1"
|
|
(polyline (pts (xy -1.5 1) (xy 1.5 1)) (stroke (width 0.4) (type default)) (fill (type none)))
|
|
(polyline (pts (xy -1.5 -1) (xy 1.5 -1)) (stroke (width 0.4) (type default)) (fill (type none)))
|
|
)
|
|
(symbol "Capacitor_1_1"
|
|
(pin passive line (at 0 3.5 270) (length 2.5) (name "1" (effects (font (size 1 1)))) (number "1" (effects (font (size 1 1)))))
|
|
(pin passive line (at 0 -3.5 90) (length 2.5) (name "2" (effects (font (size 1 1)))) (number "2" (effects (font (size 1 1)))))
|
|
)
|
|
)"""
|
|
|
|
def _sym_resistor():
|
|
return f"""
|
|
(symbol "baby_mobile:Resistor" (in_bom yes) (on_board yes)
|
|
(property "Reference" "R" (at 2 0 0) (effects (font (size 1.27 1.27))))
|
|
(property "Value" "R" (at 2 -2 0) (effects (font (size 1.27 1.27))))
|
|
(property "Footprint" "" (at 0 0 0) (effects (font (size 1.27 1.27)) hide))
|
|
(property "Datasheet" "" (at 0 0 0) (effects (font (size 1.27 1.27)) hide))
|
|
(symbol "Resistor_0_1"
|
|
(rectangle (start -1 2.5) (end 1 -2.5) (stroke (width 0.254) (type default)) (fill (type background)))
|
|
)
|
|
(symbol "Resistor_1_1"
|
|
(pin passive line (at 0 5 270) (length 2.5) (name "1" (effects (font (size 1 1)))) (number "1" (effects (font (size 1 1)))))
|
|
(pin passive line (at 0 -5 90) (length 2.5) (name "2" (effects (font (size 1 1)))) (number "2" (effects (font (size 1 1)))))
|
|
)
|
|
)"""
|
|
|
|
def _sym_diode_schottky():
|
|
return f"""
|
|
(symbol "baby_mobile:Diode_Schottky" (in_bom yes) (on_board yes)
|
|
(property "Reference" "D" (at 2 0 0) (effects (font (size 1.27 1.27))))
|
|
(property "Value" "SS14" (at 2 -2 0) (effects (font (size 1.27 1.27))))
|
|
(property "Footprint" "Diode_SMD:D_SMA" (at 0 0 0) (effects (font (size 1.27 1.27)) hide))
|
|
(property "Datasheet" "" (at 0 0 0) (effects (font (size 1.27 1.27)) hide))
|
|
(symbol "Diode_Schottky_0_1"
|
|
(polyline (pts (xy -1.5 1) (xy 0 -1) (xy 1.5 1) (xy -1.5 1)) (stroke (width 0.2) (type default)) (fill (type none)))
|
|
(polyline (pts (xy -1.5 -1) (xy 1.5 -1)) (stroke (width 0.3) (type default)) (fill (type none)))
|
|
)
|
|
(symbol "Diode_Schottky_1_1"
|
|
(pin passive line (at 0 3.5 270) (length 2.5) (name "A" (effects (font (size 1 1)))) (number "1" (effects (font (size 1 1)))))
|
|
(pin passive line (at 0 -3.5 90) (length 2.5) (name "K" (effects (font (size 1 1)))) (number "2" (effects (font (size 1 1)))))
|
|
)
|
|
)"""
|
|
|
|
def _sym_inductor():
|
|
return f"""
|
|
(symbol "baby_mobile:Inductor" (in_bom yes) (on_board yes)
|
|
(property "Reference" "L" (at 2 0 0) (effects (font (size 1.27 1.27))))
|
|
(property "Value" "L" (at 2 -2 0) (effects (font (size 1.27 1.27))))
|
|
(property "Footprint" "" (at 0 0 0) (effects (font (size 1.27 1.27)) hide))
|
|
(property "Datasheet" "" (at 0 0 0) (effects (font (size 1.27 1.27)) hide))
|
|
(symbol "Inductor_0_1"
|
|
(arc (start 0 2.5) (mid 0.75 1.875) (end 0 1.25) (stroke (width 0.254) (type default)) (fill (type none)))
|
|
(arc (start 0 1.25) (mid 0.75 0.625) (end 0 0) (stroke (width 0.254) (type default)) (fill (type none)))
|
|
(arc (start 0 0) (mid 0.75 -0.625) (end 0 -1.25) (stroke (width 0.254) (type default)) (fill (type none)))
|
|
(arc (start 0 -1.25) (mid 0.75 -1.875) (end 0 -2.5) (stroke (width 0.254) (type default)) (fill (type none)))
|
|
)
|
|
(symbol "Inductor_1_1"
|
|
(pin passive line (at 0 5 270) (length 2.5) (name "1" (effects (font (size 1 1)))) (number "1" (effects (font (size 1 1)))))
|
|
(pin passive line (at 0 -5 90) (length 2.5) (name "2" (effects (font (size 1 1)))) (number "2" (effects (font (size 1 1)))))
|
|
)
|
|
)"""
|
|
|
|
def _sym_switch():
|
|
return f"""
|
|
(symbol "baby_mobile:Switch" (in_bom yes) (on_board yes)
|
|
(property "Reference" "SW" (at 0 3 0) (effects (font (size 1.27 1.27))))
|
|
(property "Value" "SW" (at 0 -3 0) (effects (font (size 1.27 1.27))))
|
|
(property "Footprint" "" (at 0 0 0) (effects (font (size 1.27 1.27)) hide))
|
|
(property "Datasheet" "" (at 0 0 0) (effects (font (size 1.27 1.27)) hide))
|
|
(symbol "Switch_0_1"
|
|
(circle (center -2 0) (radius 0.4) (stroke (width 0) (type default)) (fill (type none)))
|
|
(circle (center 2 0) (radius 0.4) (stroke (width 0) (type default)) (fill (type none)))
|
|
(polyline (pts (xy -1.6 0) (xy 1.6 1)) (stroke (width 0.254) (type default)) (fill (type none)))
|
|
)
|
|
(symbol "Switch_1_1"
|
|
(pin passive line (at -5 0 0) (length 3) (name "1" (effects (font (size 1 1)))) (number "1" (effects (font (size 1 1)))))
|
|
(pin passive line (at 5 0 180) (length 3) (name "2" (effects (font (size 1 1)))) (number "2" (effects (font (size 1 1)))))
|
|
)
|
|
)"""
|
|
|
|
def _sym_conn2():
|
|
return f"""
|
|
(symbol "baby_mobile:Conn_2Pin" (in_bom yes) (on_board yes)
|
|
(property "Reference" "J" (at 0 4 0) (effects (font (size 1.27 1.27))))
|
|
(property "Value" "Conn_2" (at 0 -4 0) (effects (font (size 1.27 1.27))))
|
|
(property "Footprint" "" (at 0 0 0) (effects (font (size 1.27 1.27)) hide))
|
|
(property "Datasheet" "" (at 0 0 0) (effects (font (size 1.27 1.27)) hide))
|
|
(symbol "Conn_2Pin_0_1"
|
|
(rectangle (start -2 3) (end 2 -3) (stroke (width 0.254) (type default)) (fill (type background)))
|
|
)
|
|
(symbol "Conn_2Pin_1_1"
|
|
(pin passive line (at -5 1.5 0) (length 3) (name "1" (effects (font (size 1 1)))) (number "1" (effects (font (size 1 1)))))
|
|
(pin passive line (at -5 -1.5 0) (length 3) (name "2" (effects (font (size 1 1)))) (number "2" (effects (font (size 1 1)))))
|
|
)
|
|
)"""
|
|
|
|
def _sym_conn3():
|
|
return f"""
|
|
(symbol "baby_mobile:Conn_3Pin" (in_bom yes) (on_board yes)
|
|
(property "Reference" "J" (at 0 5.5 0) (effects (font (size 1.27 1.27))))
|
|
(property "Value" "Conn_3" (at 0 -5.5 0) (effects (font (size 1.27 1.27))))
|
|
(property "Footprint" "" (at 0 0 0) (effects (font (size 1.27 1.27)) hide))
|
|
(property "Datasheet" "" (at 0 0 0) (effects (font (size 1.27 1.27)) hide))
|
|
(symbol "Conn_3Pin_0_1"
|
|
(rectangle (start -2 4) (end 2 -4) (stroke (width 0.254) (type default)) (fill (type background)))
|
|
)
|
|
(symbol "Conn_3Pin_1_1"
|
|
(pin passive line (at -5 2.5 0) (length 3) (name "1" (effects (font (size 1 1)))) (number "1" (effects (font (size 1 1)))))
|
|
(pin passive line (at -5 0 0) (length 3) (name "2" (effects (font (size 1 1)))) (number "2" (effects (font (size 1 1)))))
|
|
(pin passive line (at -5 -2.5 0) (length 3) (name "3" (effects (font (size 1 1)))) (number "3" (effects (font (size 1 1)))))
|
|
)
|
|
)"""
|
|
|
|
def _sym_conn6():
|
|
return f"""
|
|
(symbol "baby_mobile:Conn_6Pin" (in_bom yes) (on_board yes)
|
|
(property "Reference" "J" (at 0 9 0) (effects (font (size 1.27 1.27))))
|
|
(property "Value" "ISP_2x3" (at 0 -9 0) (effects (font (size 1.27 1.27))))
|
|
(property "Footprint" "" (at 0 0 0) (effects (font (size 1.27 1.27)) hide))
|
|
(property "Datasheet" "" (at 0 0 0) (effects (font (size 1.27 1.27)) hide))
|
|
(symbol "Conn_6Pin_0_1"
|
|
(rectangle (start -3 8) (end 3 -8) (stroke (width 0.254) (type default)) (fill (type background)))
|
|
)
|
|
(symbol "Conn_6Pin_1_1"
|
|
(pin passive line (at -6 5 0) (length 3) (name "MISO" (effects (font (size 1 1)))) (number "1" (effects (font (size 1 1)))))
|
|
(pin passive line (at 6 5 180) (length 3) (name "VCC" (effects (font (size 1 1)))) (number "2" (effects (font (size 1 1)))))
|
|
(pin passive line (at -6 0 0) (length 3) (name "SCK" (effects (font (size 1 1)))) (number "3" (effects (font (size 1 1)))))
|
|
(pin passive line (at 6 0 180) (length 3) (name "MOSI" (effects (font (size 1 1)))) (number "4" (effects (font (size 1 1)))))
|
|
(pin passive line (at -6 -5 0) (length 3) (name "~{{RST}}" (effects (font (size 1 1)))) (number "5" (effects (font (size 1 1)))))
|
|
(pin passive line (at 6 -5 180) (length 3) (name "GND" (effects (font (size 1 1)))) (number "6" (effects (font (size 1 1)))))
|
|
)
|
|
)"""
|
|
|
|
def _sym_led():
|
|
return f"""
|
|
(symbol "baby_mobile:LED" (in_bom yes) (on_board yes)
|
|
(property "Reference" "D" (at 2 0 0) (effects (font (size 1.27 1.27))))
|
|
(property "Value" "LED" (at 2 -2 0) (effects (font (size 1.27 1.27))))
|
|
(property "Footprint" "" (at 0 0 0) (effects (font (size 1.27 1.27)) hide))
|
|
(property "Datasheet" "" (at 0 0 0) (effects (font (size 1.27 1.27)) hide))
|
|
(symbol "LED_0_1"
|
|
(polyline (pts (xy -1.5 1) (xy 0 -1) (xy 1.5 1) (xy -1.5 1)) (stroke (width 0.2) (type default)) (fill (type none)))
|
|
(polyline (pts (xy -1.5 -1) (xy 1.5 -1)) (stroke (width 0.3) (type default)) (fill (type none)))
|
|
)
|
|
(symbol "LED_1_1"
|
|
(pin passive line (at 0 3.5 270) (length 2.5) (name "A" (effects (font (size 1 1)))) (number "1" (effects (font (size 1 1)))))
|
|
(pin passive line (at 0 -3.5 90) (length 2.5) (name "K" (effects (font (size 1 1)))) (number "2" (effects (font (size 1 1)))))
|
|
)
|
|
)"""
|
|
|
|
def _sym_pwr_flag():
|
|
return f"""
|
|
(symbol "baby_mobile:PWR_FLAG" (power) (in_bom no) (on_board no)
|
|
(property "Reference" "#FLG" (at 0 0 0) (effects (font (size 1.27 1.27)) hide))
|
|
(property "Value" "PWR_FLAG" (at 0 3 0) (effects (font (size 1.27 1.27))))
|
|
(property "Footprint" "" (at 0 0 0) (effects (font (size 1.27 1.27)) hide))
|
|
(property "Datasheet" "" (at 0 0 0) (effects (font (size 1.27 1.27)) hide))
|
|
(symbol "PWR_FLAG_0_1"
|
|
(polyline (pts (xy 0 0) (xy 0 1.5)) (stroke (width 0) (type default)) (fill (type none)))
|
|
(polyline (pts (xy -1 1.5) (xy 0 3) (xy 1 1.5) (xy -1 1.5)) (stroke (width 0) (type default)) (fill (type none)))
|
|
)
|
|
(symbol "PWR_FLAG_1_1"
|
|
(pin power_out line (at 0 0 90) (length 0) (name "pwr" (effects (font (size 1 1)))) (number "1" (effects (font (size 1 1)))))
|
|
)
|
|
)"""
|
|
|
|
|
|
def _instance(lib_id, ref, value, footprint, x, y, angle):
|
|
"""Generate a component instance."""
|
|
return f""" (symbol (lib_id "{lib_id}") (at {x} {y} {angle}) (unit 1)
|
|
(in_bom yes) (on_board yes) (dnp no)
|
|
(uuid "{uid()}")
|
|
(property "Reference" "{ref}" (at {x} {y-3} 0) (effects (font (size 1.27 1.27))))
|
|
(property "Value" "{value}" (at {x} {y+3} 0) (effects (font (size 1.27 1.27))))
|
|
(property "Footprint" "{footprint}" (at {x} {y} 0) (effects (font (size 1.27 1.27)) hide))
|
|
(property "Datasheet" "" (at {x} {y} 0) (effects (font (size 1.27 1.27)) hide))
|
|
)"""
|
|
|
|
|
|
# ============================================================
|
|
# PROJECT FILE
|
|
# ============================================================
|
|
|
|
def generate_project():
|
|
return json.dumps({
|
|
"meta": {
|
|
"filename": "baby-mobile.kicad_pro",
|
|
"version": 1
|
|
},
|
|
"board": {
|
|
"design_settings": {
|
|
"defaults": {
|
|
"board_outline_line_width": 0.1,
|
|
"copper_line_width": 0.2,
|
|
"copper_text_size_h": 1.5,
|
|
"copper_text_size_v": 1.5,
|
|
"other_line_width": 0.15
|
|
},
|
|
"rules": {
|
|
"min_copper_edge_clearance": 0.3,
|
|
"min_hole_clearance": 0.25,
|
|
"min_track_width": 0.2,
|
|
"min_via_annular_width": 0.13,
|
|
"min_via_diameter": 0.6,
|
|
"solder_mask_to_copper_clearance": 0
|
|
}
|
|
},
|
|
"layer_presets": []
|
|
},
|
|
"libraries": {
|
|
"pinned_footprint_libs": [],
|
|
"pinned_symbol_libs": []
|
|
},
|
|
"net_settings": {
|
|
"classes": [{
|
|
"bus_width": 12,
|
|
"clearance": 0.2,
|
|
"diff_pair_gap": 0.25,
|
|
"diff_pair_via_gap": 0.25,
|
|
"diff_pair_width": 0.2,
|
|
"line_style": 0,
|
|
"microvia_diameter": 0.3,
|
|
"microvia_drill": 0.1,
|
|
"name": "Default",
|
|
"pcb_color": "rgba(0, 0, 0, 0.000)",
|
|
"schematic_color": "rgba(0, 0, 0, 0.000)",
|
|
"track_width": 0.3,
|
|
"via_diameter": 0.6,
|
|
"via_drill": 0.3,
|
|
"wire_width": 6
|
|
}]
|
|
},
|
|
"schematic": {
|
|
"legacy_lib_dir": "",
|
|
"legacy_lib_list": []
|
|
},
|
|
"sheets": [["", ""]]
|
|
}, indent=2)
|
|
|
|
|
|
# ============================================================
|
|
# MAIN
|
|
# ============================================================
|
|
|
|
if __name__ == "__main__":
|
|
outdir = "/home/claude/baby-mobile-pcb"
|
|
|
|
# Generate schematic
|
|
sch = generate_schematic()
|
|
with open(os.path.join(outdir, "baby-mobile.kicad_sch"), "w") as f:
|
|
f.write(sch)
|
|
print(f"Written: baby-mobile.kicad_sch ({len(sch)} bytes)")
|
|
|
|
# Generate project file
|
|
proj = generate_project()
|
|
with open(os.path.join(outdir, "baby-mobile.kicad_pro"), "w") as f:
|
|
f.write(proj)
|
|
print(f"Written: baby-mobile.kicad_pro ({len(proj)} bytes)")
|
|
|
|
print("Done! Open baby-mobile.kicad_pro in KiCad 7+")
|