Devesh36/pocket-audio-player
A portable, rechargeable microSD audio player built around an RP2040, SPI flash, USB‑C charging/power management, LCD/button controls, PCM5102A I²S DAC, and TPA6132A headphone amplifier in a 3D‑printed enclosure.
- Version
- 1.0.12
- License
- unset
- Stars
- 0
fresh-router.ts
import {routingSignature} from "./board-router";
import {
AutoroutingPipelineSolver9_PreloadedTraceGraph,
type SimpleRouteJson,
} from "@tscircuit/capacity-autorouter";
// Route copper with tscircuit, or replay a candidate snapshot of the same input.
// A connection already joined by explicit traces or internal pin groups needs
// no additional copper. Keep its geometry in the obstacle list for other nets.
function alreadyConnected(connection: SimpleRouteJson["connections"][number]) {
const parent = new Map<string,string>();
const root = (id:string):string => parent.has(id) ? root(parent.get(id)!) : id;
for (const group of connection.externallyConnectedPointIds ?? []) {
for (const id of group.slice(1)) {
const a=root(id), b=root(group[0]);
if(a!==b) parent.set(a,b);
}
}
const ids = connection.pointsToConnect.map(point=>point.pointId ?? point.pcb_port_id);
return ids.every(id=>typeof id === "string") && ids.length > 0 &&
ids.every(id=>root(id!)===root(ids[0]!));
}
export async function createFreshRouter(input: SimpleRouteJson) {
const connections=input.connections.filter(connection=>!alreadyConnected(connection));
const automaticNames=new Set(connections.map(connection=>connection.name));
const srj = {
...input,
layerCount: input.layerCount,
minViaDiameter:0.35,minViaPadDiameter:0.35,min_via_pad_diameter:0.35,
minViaHoleDiameter:0.2,min_via_hole_diameter:0.2,
minViaEdgeToPadEdgeClearance:0.15,allowViaInPad:false,
minTraceToHoleEdgeClearance:0.3,
connections,
differentialPairs: input.differentialPairs?.filter(pair=>pair.connectionNames.every(name=>automaticNames.has(name))),
};
const solver = new AutoroutingPipelineSolver9_PreloadedTraceGraph(srj, {
effort: 1,
});
const listeners = new Map<string, ((event: any) => void)[]>();
const emit = (type: string, event: any) =>
listeners.get(type)?.forEach((fn) => fn(event));
let stopped = false;
return {
on(type: string, fn: (event: any) => void) {
listeners.set(type, [...(listeners.get(type) ?? []), fn]);
},
stop() {
stopped = true;
},
start() {
const step = () => {
if (stopped) return;
try {
const batchStart=Date.now();
for (let i = 0; i < 20000 && !solver.solved && !solver.failed && Date.now()-batchStart<20; i++)
solver.step();
emit("progress", {
progress: solver.computeProgress(),
solverName: solver.getSolverName(),
phase: solver.getCurrentPhase(),
});
if (solver.failed)
emit("error", {
error: new Error(solver.error ?? "tscircuit routing failed"),
});
else if (solver.solved){
const traces=solver.getOutputSimplifiedPcbTraces();
const bunRuntime=(globalThis as any).Bun;
if(bunRuntime)bunRuntime.write("routing/fresh-result.json",JSON.stringify({signature:routingSignature(input),traces})).then(()=>emit("complete",{traces}));
else emit("complete",{traces});
}
else setTimeout(step, 0);
} catch (error) {
emit("error", { error });
}
};
setTimeout(step, 0);
},
getOutputSimpleRouteJson() {
return solver.getOutputSimpleRouteJson();
},
};
}