ShiboSoftwareDev/mspm0g3507-usb-c-dev-board

The circuit assembles a USB-C port with integrated ESD protection, power regulation, UART interface, and microcontroller (MSPM0G3507) with supporting components for USB data lines, CC termination, I2C, SPI, reset circuitry, and indicator LEDs.

Version
1.4.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")

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",
  U_3V3_REG: "3.3V LDO regulator",
  C_REG_IN_BULK: "LDO input bulk capacitor",
  C_REG_IN_BYPASS: "LDO input bypass capacitor",
  C_REG_OUT_BULK: "LDO output bulk capacitor",
  C_REG_OUT_BYPASS: "LDO output bypass capacitor",
  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",
  R_I2C_SDA_PULLUP: "I2C SDA pull-up",
  R_I2C_SCL_PULLUP: "I2C SCL pull-up",
  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_SPI_DISPLAY: "JST-SH 8-pin SPI display connector",
  J_I2C_JST_SH: "JST-SH 4-pin I2C connector",
  J_GROVE_I2C: "Seeed Grove-compatible I2C connector",
  J_TOP: "Top 1x20 GPIO header",
  J_BOTTOM: "Bottom 1x20 GPIO header",
}

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",
  "0402WGF3300TCE": "0402",
  "AP2112K-3.3TRG1": "SOT-23-5",
  CL10A475KO8NNNC: "0603",
  CL10A106KP8NNNC: "0603",
  MSPM0G3507SPTR: "LQFP-48-7x7mm",
  CL10B474KA8NNNC: "0603",
  "0402WGF4702TCE": "0402",
  CL05B103KB5NNNC: "0402",
  "TS342A2P-WZ": "SMD-TACT-2P",
  "0402WGF1002TCE": "0402",
  "0402WGF4701TCE": "0402",
  "XL-1608SYGC-06": "0603-LED",
  "SZYY1615RGB-A 4pin": "SMD-4P-1.6x1.5mm-RGB-LED",
  "SM08B-SRSS-TB(LF)(SN)": "JST-SH-8P-SMD",
  "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).replaceAll("\r\n", "\n").trimEnd() + "\n"

writeFileSync("outputs/MSPM0G3507_USB_C_JLCPCB_BOM.csv", bom)
writeFileSync("outputs/MSPM0G3507_USB_C_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`)