ShiboSoftwareDev/nema8-20mm-usbc-pd-controller
A 20×20 mm four-layer USB‑C PD motor-controller PCB combining a CH32X035 MCU, TMC2209 stepper driver, protected power regulation, USB data/ESD protection, current sensing, and a four-pin motor connector.
- Version
- 1.0.7
- License
- unset
- Stars
- 0
scripts/evaluate-route-moves.mjs
import fs from "node:fs"
const inputPath = process.argv[2] ?? "dist/index/circuit.json"
const outputPath = process.argv[3] ?? "/private/tmp/route-candidate.circuit.json"
const moves = JSON.parse(process.env.ROUTE_MOVES ?? "[]")
const routeOverrides = JSON.parse(process.env.ROUTE_OVERRIDES ?? "{}")
const routePrefixes = JSON.parse(process.env.ROUTE_PREFIXES ?? "[]")
const removeVias = JSON.parse(process.env.ROUTE_REMOVE_VIAS ?? "[]")
const layerRemaps = JSON.parse(process.env.ROUTE_LAYER_REMAPS ?? "[]")
const circuit = JSON.parse(fs.readFileSync(inputPath, "utf8"))
for (const remap of layerRemaps) {
const trace = circuit.find(
(element) => element.type === "pcb_trace" && element.pcb_trace_id === remap.traceId,
)
if (!trace) continue
trace.route = trace.route.map((point) => {
if (point.route_type === "wire" && point.layer === remap.fromLayer) {
return { ...point, layer: remap.toLayer }
}
if (point.route_type === "via") {
return {
...point,
from_layer: point.from_layer === remap.fromLayer ? remap.toLayer : point.from_layer,
to_layer: point.to_layer === remap.fromLayer ? remap.toLayer : point.to_layer,
}
}
return point
})
}
for (const removal of removeVias) {
const [x, y] = removal.at
const epsilon = removal.epsilon ?? 0.02
const trace = circuit.find(
(element) => element.type === "pcb_trace" && element.pcb_trace_id === removal.traceId,
)
if (trace) trace.route = trace.route.filter((point) => !(point.route_type === "via" &&
Math.abs(point.x - x) < epsilon && Math.abs(point.y - y) < epsilon))
for (let index = circuit.length - 1; index >= 0; index--) {
const element = circuit[index]
if (element.type === "pcb_via" && element.pcb_trace_id === removal.traceId &&
Math.abs(element.x - x) < epsilon && Math.abs(element.y - y) < epsilon) circuit.splice(index, 1)
}
}
for (const element of circuit) {
if (element.type !== "pcb_trace" || !routeOverrides[element.pcb_trace_id]) continue
element.route = routeOverrides[element.pcb_trace_id]
}
for (const patch of routePrefixes) {
const trace = circuit.find(
(element) => element.type === "pcb_trace" && element.pcb_trace_id === patch.traceId,
)
if (trace) trace.route = [...patch.route, ...trace.route.slice(patch.keepFromIndex)]
}
const overriddenTraceIds = new Set(Object.keys(routeOverrides))
for (let index = circuit.length - 1; index >= 0; index--) {
const element = circuit[index]
if (element.type === "pcb_via" && overriddenTraceIds.has(element.pcb_trace_id)) {
circuit.splice(index, 1)
}
}
let nextViaId = 10000
for (const [traceId, route] of Object.entries(routeOverrides)) {
for (const point of route) {
if (point.route_type !== "via") continue
circuit.push({
type: "pcb_via",
pcb_via_id: `pcb_via_eval_${nextViaId++}`,
pcb_trace_id: traceId,
x: point.x,
y: point.y,
hole_diameter: point.via_hole_diameter ?? 0.3,
outer_diameter: point.via_diameter ?? 0.45,
layers: ["top", "inner1", "inner2", "inner3", "inner4", "inner5", "inner6", "bottom"],
from_layer: "top",
to_layer: "bottom",
subcircuit_id: "subcircuit_source_group_0",
})
}
}
for (const move of moves) {
const [fromX, fromY] = move.from
const [toX, toY] = move.to
const epsilon = move.epsilon ?? 0.02
for (const element of circuit) {
if (element.type === "pcb_trace" && element.pcb_trace_id === move.traceId) {
element.route = element.route.map((point) =>
Math.abs(point.x - fromX) < epsilon && Math.abs(point.y - fromY) < epsilon
? { ...point, x: toX, y: toY }
: point,
)
}
if (
element.type === "pcb_via" &&
element.pcb_trace_id === move.traceId &&
Math.abs(element.x - fromX) < epsilon &&
Math.abs(element.y - fromY) < epsilon
) {
element.x = toX
element.y = toY
}
}
}
fs.writeFileSync(outputPath, `${JSON.stringify(circuit)}\n`)