imrishabh18/rp2040-motor-controller
An RP2040-based NEMA17 stepper-motor controller with USB-C programming and PD motor-power negotiation, DRV8825 dual H-bridge drive, current/temperature telemetry, protected power filtering, status RGB LED, buzzer alarm, and optional magnetic encoder.
- Version
- 1.0.41
- License
- unset
- Stars
- 3
scripts/reroute-revision.tsx
import { Circuit } from "tscircuit";
import { AutoroutingPipelineSolver } from "@tscircuit/capacity-autorouter";
import { writeFileSync, mkdirSync } from "node:fs";
import Board from "../index.circuit";
mkdirSync("dist/revision",{recursive:true});
const circuit = new Circuit();
const route = async (input: any) => {
writeFileSync("dist/revision/routing-input.json", JSON.stringify(input,null,2));
const handlers = new Map<string,Function>();
return {
on(name:string, fn:Function){handlers.set(name,fn)}, stop(){},
async start(){
try {
const solver=new AutoroutingPipelineSolver(input,{effort:2});
// One simplification pass; all downstream width, DRC and power stages still run.
const simplify=solver.pipelineDef.find(step=>step.solverName==='traceSimplificationSolver')!;
const params=simplify.getConstructorParams;
simplify.getConstructorParams=(state:any)=>{const args=params(state) as any[];args[0].iterations=1;args[0].enableCrossingViaReduction=false;return args as any;};
const Simplifier=simplify.solverClass as any;
simplify.solverClass=class extends Simplifier {
constructor(...args:any[]){super(...args);this.MAX_SIMPLIFICATION_PIPELINE_LOOPS=1;}
_step(){
// Bound optional via merging: this library revision can cycle between
// equivalent via positions. Every downstream DRC/width stage still runs.
if(this.currentPhase==='via_merging' && this.activeSubSolver?.iterations>=100){
console.log('Ending optional via merging after 100 iterations');
this.activeSubSolver.solved=true;
}
super._step();
}
} as any;
let last=Date.now(),lastPhase="";
const started = Date.now();
while(!solver.solved && !solver.failed){
if (Date.now()-started > 1_800_000) throw new Error("Routing exceeded thirty minutes");
const until=Date.now()+100;
while(Date.now()<until && !solver.solved && !solver.failed) solver.step();
if(solver.getCurrentPhase()!==lastPhase || Date.now()-last>15000){
const phase=solver.getCurrentPhase();
if(phase!==lastPhase && solver.highDensityStitchSolver?.solved) {
try { writeFileSync(`dist/revision/checkpoint-${phase}.json`,JSON.stringify({expectedInput:input,traces:solver.getPrePowerTraceOutputSimplifiedPcbTraces()},null,2)); } catch(error) { console.log('Checkpoint unavailable:',String(error)); }
}
lastPhase=phase;last=Date.now();
const sub=solver.traceSimplificationSolver;
console.log(lastPhase,solver.iterations,solver.computeProgress(),sub?{simplificationPhase:sub.currentPhase,loop:sub.simplificationPipelineLoops}:null);
}
await Bun.sleep(0);
}
if(!solver.solved) throw new Error(String(solver.error));
const output:any=solver.getOutputSimpleRouteJson();
const traces=output.traces ?? output;
// The fabrication stack uses drilled through vias, not blind/buried vias.
// Preserve the route's wire layers; declare each physical via's full span.
for(const t of traces) for(const p of t.route ?? []) if(p.route_type==='via'){p.from_layer='top';p.to_layer='bottom';}
writeFileSync("dist/revision/route-plan.json",JSON.stringify({expectedInput:input,traces},null,2));
handlers.get("complete")?.({traces});
} catch(error){console.error(error);process.exit(1)}
}
};
};
circuit.add(<Board finalizeGroundPours={false} routingAlgorithm={route as any}/>);
await circuit.renderUntilSettled();
const json=circuit.getCircuitJson();
writeFileSync('dist/revision/circuit.json',JSON.stringify(json,null,2));
const errors = json.filter(x => x.type.endsWith('_error'));
console.log('Errors:', errors);
if (errors.length) process.exitCode = 1;
