MustafaMulla29/rp2040-bldc-motor-controller-new

A USB‑C PD–powered RP2040 BLDC motor controller PCB with 3.3 V logic, MCT8329A sensorless commutation, three MOSFET half-bridges, protected power switching, USB data, controls, and motor connectors.

Version
0.3.82
License
unset
Stars
0

circuit/saved-routing.ts

import plan from "./route-plan.json"

/** The saved result is valid only for this exact routing input. Core still
 * regenerates copper and runs its normal DRC on every build. */
export function canonicalRoutingInput(value: unknown): string {
  const normalize = (item: any, key?: string): any => {
    if (typeof item === "number") return Math.round(item * 1e8) / 1e8
    if (Array.isArray(item)) {
      if (key === "connectedTo" && item.every(id => typeof id === "string")) return [...new Set(item)].sort()
      return item.map(value => normalize(value))
    }
    if (item && typeof item === "object") return Object.fromEntries(
      Object.keys(item).sort().map(key => [key, normalize(item[key], key)]))
    return item
  }
  return JSON.stringify(normalize(value))
}
const expected = canonicalRoutingInput(plan.expectedInput)
export const savedRouting = async (input: unknown) => {
  if (!plan.traces.length) throw new Error("No saved routing exists. Generate and validate the routing plan first.")
  if (canonicalRoutingInput(input) !== expected) throw new Error(
    "PCB geometry, connections or routing rules changed. Regenerate and validate circuit/route-plan.json; do not replace expectedInput alone.")
  const listeners = new Map<string, Array<(event: any) => void>>()
  return {
    on(name: string, callback: (event: any) => void) { listeners.set(name, [...listeners.get(name) ?? [], callback]) },
    start() { for (const callback of listeners.get("complete") ?? []) callback({ traces: structuredClone(plan.traces) }) },
    stop() {},
  }
}