krishnax12/usb-c-control-dial

USB-C control dial PCB with an EC11 push encoder and a 16-LED ring for volume and brightness controls. Work in progress; firmware not included and not fabrication-ready.

Version
0.0.3
License
unset
Stars
1

scripts/check-repro.ts

import Flatten from "@flatten-js/core"
import type { AnyCircuitElement } from "circuit-json"
import {
  applyToPoint,
  compose,
  rotateDEG,
  translate,
} from "transformation-matrix"

const circuitJson: AnyCircuitElement[] = await Bun.file(
  new URL("../outputs/repro/circuit.json", import.meta.url),
).json()
const groundPours = circuitJson.filter(
  (
    element,
  ): element is Extract<
    AnyCircuitElement,
    { type: "pcb_copper_pour"; shape: "brep" }
  > =>
    element.type === "pcb_copper_pour" &&
    element.shape === "brep" &&
    element.layer === "inner1",
)
const copperPolygons = groundPours.map((pour) => {
  const polygon = new Flatten.Polygon(
    pour.brep_shape.outer_ring.vertices.map(
      (vertex) => new Flatten.Point(vertex.x, vertex.y),
    ),
  )
  for (const ring of pour.brep_shape.inner_rings ?? []) {
    polygon.addFace(
      ring.vertices.map((vertex) => new Flatten.Point(vertex.x, vertex.y)),
    )
  }
  return polygon
})
const cutouts = circuitJson.filter(
  (element) => element.type === "pcb_cutout" && element.shape === "rect",
)
const witnesses = cutouts.flatMap((cutout) => {
  const cutoutToBoardTransform = compose(
    translate(cutout.center.x, cutout.center.y),
    rotateDEG(cutout.rotation ?? 0),
  )
  const pcbComponent = circuitJson
    .filter((element) => element.type === "pcb_component")
    .find((element) => element.pcb_component_id === cutout.pcb_component_id)
  const sourceComponent = circuitJson
    .filter((element) => element.type === "source_component")
    .find(
      (element) =>
        element.source_component_id === pcbComponent?.source_component_id,
    )
  return [-1, 1].flatMap((sx) =>
    [-1, 1].flatMap((sy) => {
      const point = applyToPoint(cutoutToBoardTransform, {
        x: sx * cutout.width * 0.495,
        y: sy * cutout.height * 0.495,
      })
      return copperPolygons.some((polygon) =>
        polygon.contains(new Flatten.Point(point.x, point.y)),
      )
        ? [
            {
              component: sourceComponent?.name,
              cutoutId: cutout.pcb_cutout_id,
              point,
            },
          ]
        : []
    }),
  )
})
const diagnostics = circuitJson.filter((element) =>
  /error|warning/.test(element.type),
)
const report = {
  coreDependency: "https://pkg.pr.new/@tscircuit/core@9016814",
  jsonWasModifiedAfterRendering: false,
  pcbTraces: circuitJson.filter((element) => element.type === "pcb_trace")
    .length,
  rectangularCutouts: cutouts.length,
  witnesses,
  diagnosticCounts: Object.fromEntries(
    [...new Set(diagnostics.map((element) => element.type))].map((type) => [
      type,
      diagnostics.filter((element) => element.type === type).length,
    ]),
  ),
}
await Bun.write(
  new URL("../outputs/repro/verification.json", import.meta.url),
  JSON.stringify(report, null, 2),
)
console.log(JSON.stringify(report, null, 2))
if (witnesses.length === 0)
  throw new Error(
    "No copper-over-cutout witness found; this export does not establish the bug",
  )