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();
		},
	};
}