seveibar/f1c1990s-dev-board

This code manages the entire PCB assembly process for a computer hardware module, including component placement, schematic integration, automated routing, copper pouring, and design rule checks, focused on a four-layer carrier board with integrated support components and connectors.

Version
1.8.0
License
unset
Stars
0

assembly-metadata.ts

import modelMap from './assembly-models.json'
import partMap from './assembly-parts.json'

/** Restore assembly metadata after the imported module is inflated. This changes
 * only source part identifiers and CAD records, never pads, copper, or DRC. */
export function applyPartMetadata(board: any) {
  const parts=partMap as Record<string, any>
  const walk=(node:any)=>{
    const part=parts[node.props?.name]
    if(part){Object.assign(node.props,part);Object.assign(node._parsedProps,part)}
    for(const child of node.children??[])walk(child)
  }
  walk(board)
  for(const c of board.root.db.source_component.list()) {
    const part=parts[c.name]
    if(part)board.root.db.source_component.update(c.source_component_id,{
      manufacturer_part_number:part.manufacturerPartNumber,
      supplier_part_numbers:part.supplierPartNumbers,
    })
  }
}

export function applyCadMetadata(board:any) {
  const db=board.root.db, models=modelMap as Record<string,any>
  for(const c of db.source_component.list()) {
    // Bare debug holes are copper features and have no fitted 3D body.
    if(c.ftype==='simple_test_point') {
      const cad=db.cad_component.getWhere({source_component_id:c.source_component_id})
      if(cad)db.cad_component.delete(cad.cad_component_id)
      continue
    }
    const specification=models[c.name];if(!specification)continue
    const {rotationOffset=0,kind,model_source,...model}=specification
    const pcb=db.pcb_component.getWhere({source_component_id:c.source_component_id})
    if(!pcb || pcb.do_not_place)continue
    const bottom=pcb.layer==='bottom'
    const previous=db.cad_component.getWhere({source_component_id:c.source_component_id})
    const data={...model,show_as_bounding_box:false,
      source_component_id:c.source_component_id,pcb_component_id:pcb.pcb_component_id,
      position:{x:pcb.center.x,y:pcb.center.y,z:(bottom?-1:1)*0.7},
      rotation:{x:0,y:bottom?180:0,z:bottom?-(pcb.rotation+rotationOffset):pcb.rotation+rotationOffset},
      model_origin_alignment:'center_of_component_on_board_surface',
      anchor_alignment:'center_of_component_on_board_surface',
    }
    if(previous)db.cad_component.update(previous.cad_component_id,data)
    else db.cad_component.insert(data)
  }
}

/** Through-hole headers and bare breakout holes are not paste-in-hole parts.
 * The pinned inflator emits paste on both faces of those holes; retain only
 * the explicitly associated top-side SMT paste openings. Copper is untouched. */
export function applyAssemblyPasteMetadata(board:any) {
  const db=board.root.db
  for(const paste of db.pcb_solder_paste.list()) {
    const pad=paste.pcb_smtpad_id ? db.pcb_smtpad.get(paste.pcb_smtpad_id) : undefined
    if(!pad) { db.pcb_solder_paste.delete(paste.pcb_solder_paste_id); continue }
    if(pad.layer!=="top" || paste.layer!=="top")
      throw new Error("Single-sided assembly cannot contain bottom SMT paste")
  }
}