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

routing/ground-pour-selection.ts

import selection from './ground-pour-selection.json';

/** Frozen pour selection for the validated fixed route plan.
 * The independent copper audit records which pours belong to the connected
 * ground network. The current core generates 25 connected pours, so this step
 * removes none; it still fails closed if their geometry changes. No error record
 * is filtered, and normal DRC runs after this check.
 */
export function canonicalPour(pour: any): string {
  return JSON.stringify({layer:pour.layer,source_net_id:pour.source_net_id,shape:pour.brep_shape}, (_key,value)=>
    typeof value==='number'?Math.round(value*1e7)/1e7:value);
}

export function selectConnectedGroundPours(json: any[], regions: Array<{geometry:any;keep:boolean}>) {
  const pours=json.filter(e=>e.type==='pcb_copper_pour');
  const expected=new Map(regions.map(r=>[canonicalPour(r.geometry),r.keep]));
  if (pours.length!==regions.length || pours.some(p=>!expected.has(canonicalPour(p)))) {
    throw new Error('Ground pour geometry changed. Regenerate and audit routing/ground-pour-selection.json.');
  }
  return pours.filter(p=>!expected.get(canonicalPour(p))).map(p=>p.pcb_copper_pour_id);
}

export function installGroundPourFinalization(board: any) {
  if(!board || board.__groundPourSelectionInstalled)return;
  board.__groundPourSelectionInstalled=true;
  const original=board.doInitialPcbDesignRuleChecks.bind(board);
  board.doInitialPcbDesignRuleChecks=()=>{
    const db=board.root?.db;
    // Placement-only CLI renders intentionally have no routed copper.
    if(db && !board.root.pcbDisabled && !board.root.pcbRoutingDisabled) {
      const remove=selectConnectedGroundPours(db.toArray(),selection.regions);
      for(const id of remove)db.pcb_copper_pour.delete(id);
      // Remove annotations that referred to removed geometry, not checks.
      const deleted=new Set(remove);
      for(const trace of db.pcb_trace.list()) {
        if(trace.route.some((p:any)=>deleted.has(p.copper_pour_id))) {
          db.pcb_trace.update(trace.pcb_trace_id,{route:trace.route.map((p:any)=>{
            if(!deleted.has(p.copper_pour_id))return p;
            const {copper_pour_id,is_inside_copper_pour,...point}=p;return point;
          })});
        }
      }
    }
    return original();
  };
}