shibosoftwaredev/f1c100s-linux-nema17-stepper-controller

A four-layer NEMA 17 motor-controller PCB combining an Allwinner F1C100S Linux computer, USB‑PD/buck power system, W5500 Ethernet, STM32 real-time motion control, DRV8825 stepper driver, protection/temperature/current telemetry, USB interfaces, and local LED/buzzer diagnostics.

Version
0.4.56
License
unset
Stars
0

tests/assembly-stencil.test.ts

import { test, expect } from "bun:test"
import { pcb_solder_paste } from "circuit-json"
import { applyMissingRoundedPaste, roundedPadPaste } from "../assembly-stencil"
import { applyAssemblyPasteMetadata } from "../assembly-metadata"
import fixtureJson from "./fixtures/rounded-pad-baseline.json"
const baseline: any[] = fixtureJson

function fixture(elements: any[]) {
  const items = structuredClone(elements)
  const table = (type: string) => ({
    list: () => items.filter(e => e.type === type),
    get: (id: string) => items.find(e => e.type === type && e[`${type}_id`] === id),
    insert: (value: any) => { items.push(value); return value },
    delete: (id: string) => {
      const i = items.findIndex(e => e.type === type && e[`${type}_id`] === id)
      if (i >= 0) items.splice(i, 1)
    },
  })
  return { items, db: Object.fromEntries(["pcb_solder_paste", "pcb_smtpad", "pcb_component", "source_component"].map(type => [type, table(type)])) }
}

test("baseline reproduces 96 missing rounded-lead apertures; all are restored without editing other records", () => {
  const { items, db } = fixture(baseline)
  applyMissingRoundedPaste(db)
  expect(items.slice(0, baseline.length)).toEqual(baseline)
  const added = items.slice(baseline.length)
  expect(added).toHaveLength(96)
  for (const aperture of added) expect(pcb_solder_paste.safeParse(aperture).success).toBe(true)
  const sources = new Map(items.filter(e => e.type === "source_component").map(e => [e.source_component_id, e.name]))
  for (const [name, expected] of [["U_ETH", 48], ["U_MOTION", 20], ["U_MOTOR", 28]] as const) {
    const p = items.find(e => e.type === "pcb_component" && sources.get(e.source_component_id) === name)
    expect(added.filter(e => e.pcb_component_id === p.pcb_component_id)).toHaveLength(expected)
  }
  applyMissingRoundedPaste(db)
  expect(items).toHaveLength(baseline.length + 96)
})

test("rounded apertures retain final layer, rotation, center and land association", () => {
  for (const pad of baseline.filter(e => e.type === "pcb_smtpad" && ["pill", "rotated_pill"].includes(e.shape))) {
    const result = roundedPadPaste(pad as any)!
    expect(result.layer).toBe(pad.layer)
    expect(result.x).toBe(pad.x)
    expect(result.y).toBe(pad.y)
    expect(result.pcb_smtpad_id).toBe(pad.pcb_smtpad_id)
    expect(result.width).toBeCloseTo(pad.width * .7, 12)
    expect(result.height).toBeCloseTo(pad.height * .7, 12)
    if (result.shape === "rotated_pill") expect(result.ccw_rotation).toBe(pad.ccw_rotation)
  }
})

test("DNP, test features and mask-covered lands never acquire paste", () => {
  const elements: any[] = [
    { type: "source_component", source_component_id: "s", name: "DNP" },
    { type: "source_component", source_component_id: "t", name: "TP", ftype: "simple_test_point" },
    { type: "pcb_component", pcb_component_id: "p", source_component_id: "s", do_not_place: true },
    { type: "pcb_component", pcb_component_id: "q", source_component_id: "t" },
    ...["p", "q"].map(id => ({ type: "pcb_smtpad", pcb_smtpad_id: id, pcb_component_id: id, shape: "pill", x: 0, y: 0, width: 1, height: 2, radius: .5, layer: "bottom" })),
  ]
  const { items, db } = fixture(elements)
  applyMissingRoundedPaste(db)
  expect(items).toEqual(elements)
  expect(roundedPadPaste({ ...elements.at(-1), is_covered_with_solder_mask: true } as any)).toBeUndefined()
})

test("existing explicit aperture is retained instead of duplicated or resized", () => {
  const pad: any = baseline.find(e => e.type === "pcb_smtpad" && e.shape === "rotated_pill")
  const component: any = baseline.find(e => e.type === "pcb_component" && e.pcb_component_id === pad.pcb_component_id)
  const custom = { ...roundedPadPaste(pad)!, width: pad.width * .8 }
  const { items, db } = fixture([pad, component, custom])
  applyMissingRoundedPaste(db)
  expect(items).toEqual([pad, component, custom])
})

test("full paste pass removes inherited paste from bare test points and non-SMT features", () => {
  const source = { type: "source_component", source_component_id: "s", ftype: "simple_test_point" }
  const part = { type: "pcb_component", pcb_component_id: "p", source_component_id: "s" }
  const pad = { type: "pcb_smtpad", pcb_smtpad_id: "land", pcb_component_id: "p", layer: "top" }
  const paste = { type: "pcb_solder_paste", pcb_solder_paste_id: "paste", pcb_smtpad_id: "land", layer: "top" }
  const orphan = { type: "pcb_solder_paste", pcb_solder_paste_id: "pth", pcb_component_id: "p", layer: "top" }
  const { items, db } = fixture([source, part, pad, paste, orphan])
  applyAssemblyPasteMetadata({ root: { db } })
  expect(items).toEqual([source, part, pad])
})