ShiboSoftwareDev/am625sip-linux-board

This code defines the physical footprint and pin layout for an AM625 System-in-Package (SIP) component, detailing pad positions, pin labels, and package outline for hardware integration.

Version
1.0.24
License
unset
Stars
0

scripts/build-microsd-cache.tsx

import { mkdirSync, writeFileSync } from "node:fs"
import { Circuit } from "@tscircuit/core"
import type { AnyCircuitElement } from "circuit-json"
import { MicroSdBlock } from "../subcircuits/microsd"
import { namespaceCachePcbTraceIds } from "./namespace-cache-pcb-trace-ids"

const CACHE_PATH = "subcircuits/cache/microsd.circuit.json"
const INTERNAL_TRACE_COUNT = 20

const LinkPad = ({ name, pcbY }: { name: string; pcbY: number }) => (
  <chip
    name={name}
    pcbX={-16}
    pcbY={pcbY}
    noSchematicRepresentation
    footprint={
      <footprint>
        <smtpad
          portHints={["pin1"]}
          shape="rect"
          width="0.8mm"
          height="0.8mm"
        />
      </footprint>
    }
  />
)

const getErrors = (circuitJson: AnyCircuitElement[]) =>
  circuitJson.filter(
    (element) =>
      element.type.endsWith("_error") || element.type === "pcb_placement_error",
  )

const main = async () => {
  const sourceCircuit = new Circuit()
  sourceCircuit.on("autorouting:start", (event: any) => {
    console.log(
      `source autorouting start: ${event.phaseName ?? "unphased"} (${event.simpleRouteJson.connections.length} connections)`,
    )
  })
  sourceCircuit.on("autorouting:end", (event: any) => {
    console.log(`source autorouting end: ${event.phaseName ?? "unphased"}`)
  })
  sourceCircuit.add(
    <board
      width="34mm"
      height="34mm"
      layers={4}
      defaultTraceWidth="0.08128mm"
      minTraceWidth="0.08128mm"
      minTraceToPadEdgeClearance="0.05mm"
      minPadEdgeToPadEdgeClearance="0.08128mm"
      minViaEdgeToPadEdgeClearance="0.08128mm"
      minViaHoleEdgeToViaHoleEdgeClearance="0.1016mm"
      minViaHoleDiameter="0.1mm"
      minViaPadDiameter="0.24mm"
      pcbStyle={{
        viaHoleDiameter: "0.1mm",
        viaPadDiameter: "0.24mm",
      }}
      autorouter="default"
    >
      <MicroSdBlock />
    </board>,
  )

  await sourceCircuit.renderUntilSettled()
  const sourceJson = sourceCircuit.getCircuitJson()
  const sourceErrors = getErrors(sourceJson)
  const sourceTraceCount = sourceJson.filter(
    (element) => element.type === "pcb_trace",
  ).length
  const cacheJson = namespaceCachePcbTraceIds(sourceJson.filter((element) => {
    const type = element.type
    return (
      (!type.startsWith("schematic_") || type === "schematic_component") &&
      !type.startsWith("cad_") &&
      !type.endsWith("_warning") &&
      type !== "pcb_debug_object" &&
      type !== "source_project_metadata"
    )
  }), "microsd")

  if (sourceErrors.length > 0 || sourceTraceCount !== INTERNAL_TRACE_COUNT) {
    writeFileSync(
      "/private/tmp/microsd-source-cache-failure.circuit.json",
      JSON.stringify(sourceJson),
    )
    console.error(
      JSON.stringify(
        {
          error: "microSD source-cache validation failed",
          sourceTraceCount,
          sourceErrors,
        },
        null,
        2,
      ),
    )
    process.exitCode = 1
    return
  }

  if (process.argv.includes("--source-only")) {
    mkdirSync("subcircuits/cache", { recursive: true })
    writeFileSync(CACHE_PATH, `${JSON.stringify(cacheJson, null, 2)}\n`)
    console.log(
      JSON.stringify(
        {
          cachePath: CACHE_PATH,
          sourceTraceCount,
          sourceElementCount: sourceJson.length,
          cacheElementCount: cacheJson.length,
          validation: "source-only",
        },
        null,
        2,
      ),
    )
    return
  }

  const parentCircuit = new Circuit()
  let parentAutoroutingConnectionCount = 0
  parentCircuit.on("autorouting:start", (event: any) => {
    parentAutoroutingConnectionCount += event.simpleRouteJson.connections.length
    console.log(
      `parent autorouting start: ${event.phaseName ?? "unphased"} (${event.simpleRouteJson.connections.length} connections)`,
    )
  })
  parentCircuit.on("autorouting:end", (event: any) => {
    console.log(`parent autorouting end: ${event.phaseName ?? "unphased"}`)
  })
  parentCircuit.add(
    <board
      width="44mm"
      height="36mm"
      layers={4}
      autorouter="default"
      schematicDisabled
      minTraceWidth="0.08128mm"
      minTraceToPadEdgeClearance="0.05mm"
      minPadEdgeToPadEdgeClearance="0.08128mm"
      minViaEdgeToPadEdgeClearance="0.08128mm"
      minViaHoleEdgeToViaHoleEdgeClearance="0.1016mm"
      minViaHoleDiameter="0.1mm"
      minViaPadDiameter="0.24mm"
    >
      <subcircuit
        name="MICROSD"
        circuitJson={cacheJson}
        pcbX={0}
        pcbY={0}
        schTraceAutoLabelEnabled
      />
      <LinkPad name="L_CMD" pcbY={9} />
      <LinkPad name="L_DAT0" pcbY={7} />
      <LinkPad name="L_CLK" pcbY={5} />
      <LinkPad name="L_VDD" pcbY={11.5} />
      <LinkPad name="L_GND" pcbY={-11} />
      <trace from=".L_CMD > .pin1" to=".MICROSD .X_SOC_CMD > .pin1" />
      <trace from=".L_DAT0 > .pin1" to=".MICROSD .X_SOC_DAT0 > .pin1" />
      <trace from=".L_CLK > .pin1" to=".MICROSD .X_SOC_CLK > .pin1" />
      <trace from=".L_VDD > .pin1" to=".MICROSD .X_VDD > .pin1" />
      <trace from=".L_GND > .pin1" to=".MICROSD .X_GND > .pin1" />
    </board>,
  )

  await parentCircuit.renderUntilSettled()
  const parentJson = parentCircuit.getCircuitJson()
  const parentErrors = getErrors(parentJson)
  const parentTraceCount = parentJson.filter(
    (element) => element.type === "pcb_trace",
  ).length
  const importedCenters = ["J1", "X_CMD", "X_DAT0", "X_CLK", "X_SOC_CMD", "X_SOC_DAT0", "X_SOC_CLK", "X_VDD", "X_GND"].map(
    (name) => {
      const sourceComponent = parentJson.find(
        (element) => element.type === "source_component" && element.name === name,
      )
      const pcbComponent = parentJson.find(
        (element) =>
          element.type === "pcb_component" &&
          sourceComponent?.type === "source_component" &&
          element.source_component_id === sourceComponent.source_component_id,
      )
      return {
        name,
        center: pcbComponent?.type === "pcb_component" ? pcbComponent.center : null,
      }
    },
  )

  if (
    parentErrors.length > 0 ||
    parentTraceCount !== INTERNAL_TRACE_COUNT + 5 ||
    parentAutoroutingConnectionCount !== 5
  ) {
    console.error(
      JSON.stringify(
        {
          error: "microSD imported-cache validation failed",
          parentTraceCount,
          parentAutoroutingConnectionCount,
          importedCenters,
          parentErrors,
        },
        null,
        2,
      ),
    )
    process.exitCode = 1
    return
  }

  mkdirSync("subcircuits/cache", { recursive: true })
  writeFileSync(CACHE_PATH, `${JSON.stringify(cacheJson, null, 2)}\n`)
  console.log(
    JSON.stringify(
      {
        cachePath: CACHE_PATH,
        sourceTraceCount,
        parentLinkTraceCount: 5,
        parentAutoroutingConnectionCount,
        importedCenters,
        sourceElementCount: sourceJson.length,
        cacheElementCount: cacheJson.length,
      },
      null,
      2,
    ),
  )
}

main().catch((error) => {
  console.error(error)
  process.exitCode = 1
})