seveibar/pd-dual-stepper-controller
Bottom-side PCB silkscreen artwork consisting of embedded mirrored TS Circuit SVG logos, with via-clearance-aware lower-board placement.
- Version
- 0.1.0
- License
- unset
- Stars
- 0
scripts/build-dual.tsx
import { canonicalRoutingInput } from "../routing/saved-routing";
import { Circuit } from "tscircuit";
import Board from "../index.circuit";
import { mkdirSync, writeFileSync } from "node:fs";
import { convertCircuitJsonToPcbSvg, convertCircuitJsonToStackedSchematicSheetsSvg } from "circuit-to-svg";
const mode = process.argv[2] ?? "placement";
mkdirSync("dist/dual",{recursive:true});
let didCapture=false;
const capture = async(input:unknown) => {
didCapture=true;
writeFileSync("dist/dual/routing-input.json",JSON.stringify(input,null,2));
const listeners = new Map<string, Function>();
return {on(n:string,f:Function){listeners.set(n,f)}, stop(){}, start(){listeners.get("complete")?.({traces:[]})}};
};
const saved = async(input:unknown) => {
const plan = await Bun.file("routing/dual-route-plan.json").json();
if (canonicalRoutingInput(input) !== canonicalRoutingInput(plan.expectedInput)) throw Error("Dual routing input changed; regenerate and check the route plan.");
const listeners = new Map<string, Function>();
return {on(n:string,f:Function){listeners.set(n,f)}, stop(){}, start(){listeners.get("complete")?.({traces:structuredClone(plan.traces)})}};
};
const circuit = new Circuit({platform:{schematicDisabled:mode !== "schematic"}});
circuit.add(<Board routingDisabled={mode === "placement" || mode === "schematic"} routingAlgorithm={mode === "capture" ? capture as any : mode === "routed" ? saved as any : undefined} finalizeGroundPours={false}/>);
await circuit.renderUntilSettled();
const json = circuit.getCircuitJson();
writeFileSync(`dist/dual/${mode}.json`,JSON.stringify(json,null,2));
writeFileSync(mode === "routed" ? "dist/dual/pcb.svg" : `dist/dual/${mode}.svg`,convertCircuitJsonToPcbSvg(json,{width:1600,height:950}));
if(mode === "schematic") writeFileSync("dist/dual/schematic.svg",convertCircuitJsonToStackedSchematicSheetsSvg(json,{width:1600}));
const errors=json.filter(e=>e.type.endsWith("_error"));
writeFileSync(`dist/dual/${mode}-errors.json`,JSON.stringify(errors,null,2));
console.log(mode, json.length,"records;",errors.length,"diagnostics",Object.fromEntries([...new Set(errors.map(e=>e.type))].map(t=>[t,errors.filter(e=>e.type===t).length])));
if (mode === "routed" && errors.length) process.exitCode = 1;
if(mode === "capture" && !didCapture) throw Error("Capture callback did not run; resolve pre-routing diagnostics before using routing-input.json");