ShiboSoftwareDev/mspm0g3507-gameboy-handheld
An AO3400A N-channel MOSFET for power switching and an AP2112K-3.3TRG1 LDO regulator providing a regulated 3.3 V output, both in compact SMD packages.
- Version
- 1.2.1
- License
- unset
- Stars
- 0
scripts/generate-assembly-files.mjs
import { readFileSync, writeFileSync } from "node:fs"
import { convertCircuitJsonToPickAndPlaceCsv } from "circuit-json-to-pnp-csv"
const circuitPath = process.argv[2] ?? "dist/index/circuit.json"
const circuit = JSON.parse(readFileSync(circuitPath, "utf8"))
const sourceComponents = circuit.filter(
(element) => element.type === "source_component" && element.ftype !== "simple_test_point",
)
// C965805 is a symmetric two-pad LED package, so the generic orientation
// analyzer cannot derive a corner-style pin-1 frame. The imported EasyEDA
// footprint places cathode/pin 1 on the left and slightly below pin 2.
const powerLed = sourceComponents.find((component) => component.name === "D_POWER")
const powerLedPcb = circuit.find(
(element) => element.type === "pcb_component" && element.source_component_id === powerLed?.source_component_id,
)
const powerLedPads = circuit.filter(
(element) => element.type === "pcb_smtpad" && element.pcb_component_id === powerLedPcb?.pcb_component_id,
)
const powerLedPin1 = powerLedPads.find((pad) => pad.port_hints?.includes("pin1"))
const powerLedPin2 = powerLedPads.find((pad) => pad.port_hints?.includes("pin2"))
if (!powerLedPcb || !powerLedPin1 || !powerLedPin2 || !(powerLedPin1.x < powerLedPin2.x)) {
throw new Error("Could not verify D_POWER cathode/pin-1 orientation")
}
powerLedPcb.pin1_location = "leftside_bottom"
powerLedPcb.supplier_pin1_location_map = {
...powerLedPcb.supplier_pin1_location_map,
jlcpcb: "leftside_bottom",
}
writeFileSync(circuitPath, `${JSON.stringify(circuit, null, 2)}\n`)
const comments = {
J_USB_C: "USB-C receptacle",
R_USB_DM_JOIN: "USB D- reversible-contact crossover",
R_VBUS_A_LINK: "USB-C VBUS orientation link",
R_VBUS_B_LINK: "USB-C VBUS orientation link",
U_USB_ESD: "USB ESD protection",
U_USB_UART: "USB-to-UART bootloader bridge",
R_USB_CC1: "USB-C CC1 pull-down",
R_USB_CC2: "USB-C CC2 pull-down",
C_USB_UART: "USB-UART decoupling",
R_UART_TX: "UART TX protection resistor",
R_UART_RX: "UART RX protection resistor",
J_BATTERY: "Protected 1S LiPo connector with 10k NTC",
U_BATTERY_CHARGER: "USB power-path LiPo charger",
C_CHARGER_INPUT: "Charger input capacitor",
C_CHARGER_BATTERY: "Charger battery capacitor",
C_CHARGER_SYSTEM: "Charger system-output capacitor",
R_CHARGE_CURRENT: "LiPo charge-current programming resistor",
R_INPUT_CURRENT_LIMIT: "USB input-current-limit programming resistor",
R_CHARGE_TIMER: "Charge safety-timer programming resistor",
SW_POWER: "Main slide power switch",
U_3V3_BUCK_BOOST: "Fixed 3.3V buck-boost regulator",
R_POWER_ENABLE_LINK: "Regulator enable link",
L_3V3_BUCK_BOOST: "3.3V buck-boost inductor",
C_3V3_INPUT: "3.3V regulator input bulk capacitor",
C_3V3_INPUT_BYPASS: "3.3V regulator input bypass capacitor",
C_3V3_OUTPUT_A: "3.3V regulator output capacitor",
C_3V3_OUTPUT_B: "3.3V regulator output capacitor",
U_BACKLIGHT_BOOST: "Fixed 5V display-backlight boost regulator",
L_BACKLIGHT_BOOST: "Display-backlight boost inductor",
C_BACKLIGHT_BOOST_INPUT: "Display-backlight boost input capacitor",
C_BACKLIGHT_5V_OUTPUT: "Display-backlight 5V output capacitor",
R_GND_USB_LINK: "USB ground-domain star link",
R_GND_POWER_LINK: "Power ground-domain star link",
R_GND_MCU_LINK: "MCU ground-domain star link",
R_GND_CONTROLS_LINK: "Controls ground-domain star link",
R_GND_DISPLAY_LINK: "Display ground-domain star link",
R_GND_IO_LINK: "User-I/O ground-domain star link",
U_MCU: "80MHz Arm Cortex-M0+ MCU",
C_MCU_BULK: "MCU supply bulk capacitor",
C_MCU_BYPASS: "MCU supply bypass capacitor",
C_MCU_VCORE: "MCU VCORE capacitor",
R_RESET_PULLUP: "Reset pull-up",
C_RESET: "Reset filter capacitor",
SW_RESET: "Reset tactile switch",
R_BOOT_PULLDOWN: "ROM BSL invoke pull-down",
SW_BOOT: "ROM BSL invoke tactile switch",
SW_UP: "D-pad up tactile switch",
SW_DOWN: "D-pad down tactile switch",
SW_LEFT: "D-pad left tactile switch",
SW_RIGHT: "D-pad right tactile switch",
SW_A: "A action tactile switch",
SW_B: "B action tactile switch",
SW_START: "Start tactile switch",
SW_SELECT: "Select tactile switch",
J_DISPLAY_FPC: "50-pin 0.5mm top-contact display FPC connector",
R_DISPLAY_5V_LINK: "Display backlight 5V link",
R_BACKLIGHT_K1: "Display backlight LEDK1 current limiter",
R_BACKLIGHT_K2: "Display backlight LEDK2 current limiter",
R_BACKLIGHT_K3: "Display backlight LEDK3 current limiter",
R_BACKLIGHT_K4: "Display backlight LEDK4 current limiter",
U_BACKLIGHT_SWITCH: "Display backlight PWM switch",
R_BACKLIGHT_GATE_PULLDOWN: "Display backlight gate pull-down",
R_POWER_LED: "Power LED resistor",
D_POWER: "Green power LED",
R_RGB_RED: "RGB debug LED red resistor",
R_RGB_GREEN: "RGB debug LED green resistor",
R_RGB_BLUE: "RGB debug LED blue resistor",
D_USER_RGB: "Common-cathode RGB user/debug LED",
J_AUDIO_MODULE: "JST-SH 4-pin external amplified-audio module connector",
}
const footprintsByMpn = {
"TYPE-C-31-M-12": "USB-C-SMD-16P+4TH",
"1206W4F0000T5E": "1206",
"0402WGF0000TCE": "0402",
"USBLC6-2SC6": "SOT-23-6",
CH340C: "SOP-16-150mil",
"0402WGF5101TCE": "0402",
CL05B104KO5NNNC: "0402",
"0402WGF1001TCE": "0402",
"0402WGF1000TCE": "0402",
"0402WGF3300TCE": "0402",
"0402WGF3301TCE": "0402",
"B3B-PH-SM4-TB(LF)(SN)": "JST-PH-3P-SMD",
BQ24075RGTR: "VQFN-16-3x3mm",
MSK12C02: "SMD-SLIDE-SWITCH",
TPS63031DSKR: "WSON-10-2.5x2.5mm",
FNR3015S1R5MT: "SMD-INDUCTOR-3x3mm",
TPS61240DRVR: "WSON-6-2x2mm",
CL10A475KO8NNNC: "0603",
CL10A106KP8NNNC: "0603",
MSPM0G3507SPTR: "LQFP-48-7x7mm",
CL10B474KA8NNNC: "0603",
"0402WGF4702TCE": "0402",
CL05B103KB5NNNC: "0402",
"TS342A2P-WZ": "SMD-TACT-2P",
"4*4*1.7 贴片": "SMD-TACT-4P-5.2x5.2mm",
"0402WGF1002TCE": "0402",
"0402WGF4701TCE": "0402",
"XL-1608SYGC-06": "0603-LED",
"SZYY1615RGB-A 4pin": "SMD-4P-1.6x1.5mm-RGB-LED",
"0.5K-AS-50PWBG": "FPC-0.5mm-50P-TOP-CONTACT",
AO3400A: "SOT-23",
"SM04B-SRSS-TB(LF)(SN)": "JST-SH-4P-SMD",
"ZX-HY2.0-4PZZ": "GROVE-2.0MM-4P-THT",
"PH2.54-1X20P-H25": "THT-1x20-P2.54mm-OD1.6-ID1.05",
}
const componentValue = (component) => {
if (component.display_resistance) return component.display_resistance
if (component.display_capacitance) return component.display_capacitance
if (component.ftype === "simple_push_button") return "SPST-NO"
if (component.name === "D_POWER") return "green"
if (component.name === "D_USER_RGB") return "RGB common cathode"
if (component.ftype === "simple_pin_header") return "1x20 2.54mm"
return component.manufacturer_part_number
}
const csvField = (value) => {
const text = String(value ?? "")
return /[",\n]/.test(text) ? `"${text.replaceAll('"', '""')}"` : text
}
const header = [
"Designator",
"Comment",
"Value",
"Footprint",
"JLCPCB Part #",
"Manufacturer Part Number",
]
const rows = sourceComponents.map((component) => {
const jlcPart = component.supplier_part_numbers?.jlcpcb?.[0]
const mpn = component.manufacturer_part_number
if (!comments[component.name]) throw new Error(`Missing BOM comment for ${component.name}`)
if (!jlcPart) throw new Error(`Missing JLCPCB part number for ${component.name}`)
if (!mpn) throw new Error(`Missing manufacturer part number for ${component.name}`)
if (!footprintsByMpn[mpn]) throw new Error(`Missing BOM footprint for ${component.name} (${mpn})`)
return [
component.name,
comments[component.name],
componentValue(component),
footprintsByMpn[mpn],
jlcPart,
mpn,
]
})
const bom = [header, ...rows].map((row) => row.map(csvField).join(",")).join("\n") + "\n"
const cpl = convertCircuitJsonToPickAndPlaceCsv(circuit, {
supplier: "jlcpcb",
requireSupplierRotation: true,
}).replaceAll("\r\n", "\n").trimEnd() + "\n"
writeFileSync("outputs/MSPM0G3507_GAMEBOY_JLCPCB_BOM.csv", bom)
writeFileSync("outputs/MSPM0G3507_GAMEBOY_JLCPCB_CPL.csv", cpl)
writeFileSync("manufacturing/bom.csv", bom)
writeFileSync("manufacturing/pick_and_place.csv", cpl)
console.log(`Generated ${rows.length} BOM placements and ${cpl.trim().split(/\r?\n/).length - 1} CPL placements`)