shibosoftwaredev/f1c100s-linux-nema17-stepper-controller

Compact four-layer NEMA 17 carrier PCB combining an F1C100S Linux SoC, USB-C PD power and buck regulation, W5500 10/100 Ethernet, STM32 safety/motion control, and DRV8825 stepper-driver hardware with protection, sensing, connectors, and dual-sided SMT assembly.

Version
0.4.15
License
unset
Stars
0

nema17-fixed-router.ts

import savedRoutes from "./nema17-route-pool.json"
import { writeFileSync } from "node:fs"

/**
 * Deterministic fabrication router for the 42.3 mm NEMA17 carrier.
 *
 * The routes were generated with fanout-aware capacity-router passes and are
 * checked into the package so local and tscircuit.com builds do not rerun a
 * several-minute dense-board search. Final DRC and shorts checks still inspect
 * every emitted segment and via.
 */
export async function nema17FixedRouter(input: any) {
  if (process.env.TSCI_CAPTURE_ROUTER_INPUT)
    writeFileSync(process.env.TSCI_CAPTURE_ROUTER_INPUT, `${JSON.stringify(input, null, 2)}\n`)
  const handlers: Record<string, Array<(event: any) => void>> = {
    complete: [], error: [], progress: [],
  }
  let isRouting = false
  // The input traces are the F1C100S module's already-emitted child copper.
  // They are routing obstacles, not parent routes to return again. Returning
  // them here would duplicate the module fanout in the parent subcircuit.
  const requestedNames = new Set((process.env.TSCI_ROUTE_NAMES ?? "").split(",").filter(Boolean))
  const selectedRoutes = process.env.TSCI_EMPTY_CARRIER_ROUTER
    ? []
    : process.env.TSCI_ROUTE_NAMES !== undefined
      ? (savedRoutes as any[]).filter((trace) => requestedNames.has(trace.connection_name))
      : savedRoutes as any[]
  const currentPortLocations = new Map<string, { x: number; y: number }>()
  for (const connection of input.connections ?? [])
    for (const point of connection.pointsToConnect ?? [])
      if (point.pcb_port_id)
        currentPortLocations.set(point.pcb_port_id, { x: point.x, y: point.y })
  const traces = selectedRoutes.map((trace, index) => ({
    ...trace,
    pcb_trace_id: `nema17_route_${index}`,
    route: trace.route.map((point: any) => {
      if (point.route_type === "via") return {
        ...point,
        via_diameter: 0.45,
        via_hole_diameter: 0.3,
      }
      const portId = point.start_pcb_port_id ?? point.end_pcb_port_id
      const current = portId ? currentPortLocations.get(portId) : undefined
      return current ? { ...point, x: current.x, y: current.y } : point
    }),
  }))

  return {
    input,
    get isRouting() { return isRouting },
    on(event: string, handler: (event: any) => void) {
      handlers[event]?.push(handler)
    },
    start() {
      isRouting = true
      queueMicrotask(() => {
        if (!isRouting) return
        isRouting = false
        for (const handler of handlers.complete)
          handler({ type: "complete", traces })
      })
    },
    stop() { isRouting = false },
    solveSync() { return traces },
  }
}