muse/book-reading-clip-lamp
A 60‑mm ESP32‑S3 lamp-head PCB combining USB‑C battery charging/power regulation, OV5640 autofocus camera interfacing, I²S microphone and differential speaker audio, six‑LED boost-driven reading light, buttons, status indicators, and battery monitoring.
- Version
- 0.2.5
- License
- unset
- Stars
- 0
fresh-routing.ts
Schematic
import { AutoroutingPipelineSolver9_PreloadedTraceGraph, type SimpleRouteJson, type SimplifiedPcbTrace } from "@tscircuit/capacity-autorouter"
/** Fresh routing for this dense, two-sided board. Keep the normal topology,
* detailed routing, repair, width expansion and final core DRC. Only omit
* optional trace/via simplification, whose search takes excessive time here.
* The detailed routed paths and vias remain; no clearance rule or DRC is disabled.
* Saved copper is still guarded by saved-routing.ts on ordinary builds.
*/
export async function routeFreshBoard(input:SimpleRouteJson) {
const solver = new AutoroutingPipelineSolver9_PreloadedTraceGraph(input)
for (const step of solver.pipelineDef) {
if (!["traceSimplificationSolver","mutatedPreloadedTraceSimplificationSolver"].includes(step.solverName)) continue
// The public pipeline stage class has a heterogeneous constructor union.
// Adapt only this identified stage; all other stages stay unchanged.
const Base = step.solverClass as any
step.solverClass = class ConservativeSimplification extends Base {
constructor(config:Record<string,unknown>) {
super({...config, iterations:0, enableCrossingViaReduction:false})
this.MAX_SIMPLIFICATION_PIPELINE_LOOPS = 0
}
} as any
}
type Event = {type:string;traces?:SimplifiedPcbTrace[];error?:unknown;message?:string}
const listeners = new Map<string,Array<(event:Event)=>void>>()
let stopped=false
let previousPhase=""
const emit=(name:string,event:Event)=>listeners.get(name)?.forEach(fn=>fn(event))
return {
on(name:string,callback:(event:Event)=>void) {listeners.set(name,[...(listeners.get(name)??[]),callback])},
start() {
const tick=()=>{
if((globalThis as unknown as {process?:{env?:Record<string,string>}}).process?.env?.LAMP_CAPTURE_INPUT === "1"){emit("complete",{type:"complete",traces:[]});return}
if(stopped)return
try {
const phase=solver.getCurrentPhase()
if(phase!==previousPhase){console.info(`[lamp routing] ${phase}`);previousPhase=phase}
const until=Date.now()+30
do {solver.step()} while(!solver.solved&&!solver.failed&&Date.now()<until)
if(solver.failed){emit("error",{type:"error",error:solver.error,message:String(solver.error)});return}
if(solver.solved){emit("complete",{type:"complete",traces:solver.getOutputSimplifiedPcbTraces()});return}
setTimeout(tick,0)
}catch(error){emit("error",{type:"error",error,message:String(error)})}
}
tick()
},
stop(){stopped=true},
}
}