imrishabh18/pcbgolf
A complete 4-layer PCBGolf controller PCB with STM32H7 MCU, USB/SD and CAN interfaces, power regulation, protection, connectors, switches, LEDs, clocking, and supporting passives.
- Version
- 1.6.1
- License
- unset
- Stars
- 0
saved-autorouter.ts
/** Restore externally routed copper while keeping the complete authored circuit.
* Unlike this core version's pcbRouteCache, this adapter preserves net separation.
* Pass makeSavedAutorouter(cache) as the board/phase autorouter configuration.
*/
export function makeSavedAutorouter(cache: any) {
const close = (a: any, b: any) => Math.hypot(a.x - b.x, a.y - b.y) < 0.0001
return {
algorithmFn: async (srj: any) => {
const handlers: Record<string, Array<(event: any) => void>> = {}
return {
on(event: string, callback: (event: any) => void) {
;(handlers[event] ??= []).push(callback)
},
stop() {},
start() {
try {
const traces: any[] = []
const usedNets = new Set<string>()
for (const connection of srj.connections) {
const candidates = Object.entries(cache.nets).filter(([, value]: any) =>
connection.pointsToConnect.every((point: any) =>
value.ports.some((port: any) => close(point, port) &&
(!point.port_selector || port.selectors.includes(point.port_selector) ||
point.port_selector.startsWith(port.reference + "."))) ||
(!point.port_selector && value.routes.some((saved: any) =>
saved.route.some((contact: any) => close(point, contact))))))
if (candidates.length !== 1) {
throw new Error(`Saved routing does not match current pins/placement for ${connection.name}; regenerate routing`)
}
const [netName, net]: any = candidates[0]
if (usedNets.has(netName)) continue
usedNets.add(netName)
if (!net.routes.length && connection.pointsToConnect.length > 1) {
throw new Error(`No saved copper for ${netName}`)
}
for (const [index, saved] of net.routes.entries()) {
const route = saved.route.map((p: any) => ({ ...p }))
// Endpoint IDs supplement the geometric contacts where an
// external router ends exactly at a logical port center.
for (const [end, key] of [[0, "start_pcb_port_id"], [route.length - 1, "end_pcb_port_id"]] as const) {
const point = route[end]
const port = connection.pointsToConnect.find((p: any) => close(point, p))
if (port?.pcb_port_id && point.route_type === "wire") point[key] = port.pcb_port_id
}
traces.push({
type: "pcb_trace",
pcb_trace_id: `saved_${net.id}_${index}`,
connection_name: connection.name,
source_trace_id: connection.source_trace_id,
route,
})
}
}
for (const cb of handlers.complete ?? []) cb({ traces })
} catch (error) {
for (const cb of handlers.error ?? []) cb({ error })
}
},
}
},
}
}