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",
)