krishnax12/watchy-eink-smartwatch
Unfinished prototype (not production-ready): 4 native DRC errors, 2 display-flex intersections, and missing antenna radiator copper remain
- Version
- 1.2.7
- License
- MIT
- Stars
- 1
scripts/usb-assembly.test.ts
import { expect, test } from "bun:test";
import type { AnyCircuitElement } from "circuit-json";
import {
applyToPoint,
compose,
rotateDEG,
translate,
} from "transformation-matrix";
import { BOARD_THICKNESS_MM } from "../pcb/board-stackup";
test("USB mounting rows and solder contacts register with the native footprint", async () => {
const circuit: AnyCircuitElement[] = await Bun.file(
"dist/index/circuit.json",
).json();
const connector = circuit.find(
(element) =>
element.type === "cad_component" &&
element.model_step_url?.endsWith("/EasyEDA_C91146_U_F_M5DD_Y_L.step"),
);
if (!connector || connector.type !== "cad_component") {
throw new Error("Missing USB model");
}
const origin = connector.model_origin_position;
if (!origin) throw new Error("Missing USB model origin");
const rotation = connector.rotation;
if (!rotation) throw new Error("Missing USB model rotation");
expect(rotation.x).toBe(0);
expect(rotation.y).toBe(0);
expect(rotation.z).toBe(270);
expect(origin.z).toBe(0);
expect(connector.position.z).toBeCloseTo(BOARD_THICKNESS_MM / 2, 6);
const modelToBoard = compose(
translate(connector.position.x, connector.position.y),
rotateDEG(rotation.z),
translate(-origin.x, -origin.y),
);
// Datums measured from the unmodified C91146 STEP. Both tab rows are
// registered symmetrically; residual row-spacing differences stay visible.
const mountingTabs = [
{ pin: "pin6", x: -3.625, y: 0 },
{ pin: "pin9", x: 3.625, y: 0 },
{ pin: "pin8", x: 2.425, y: -2.715 },
{ pin: "pin7", x: -2.425, y: -2.715 },
];
for (const tab of mountingTabs) {
const hole = circuit.find(
(element) =>
element.type === "pcb_plated_hole" &&
element.pcb_component_id === connector.pcb_component_id &&
element.port_hints?.includes(tab.pin),
);
if (!hole || hole.type !== "pcb_plated_hole") {
throw new Error(`Missing USB mounting hole ${tab.pin}`);
}
const center = applyToPoint(modelToBoard, tab);
expect(Math.abs(center.x - hole.x)).toBeLessThan(0.05);
expect(Math.abs(center.y - hole.y)).toBeLessThan(0.05);
}
// All five flat solder-contact undersides must land inside their copper
// pads, not just share a visually similar shell outline. STEP plane is Z=0.
for (const contact of [
{ pin: "pin1", x: 1.3 },
{ pin: "pin2", x: 0.65 },
{ pin: "pin3", x: 0 },
{ pin: "pin4", x: -0.65 },
{ pin: "pin5", x: -1.3 },
]) {
const pad = circuit.find(
(element) =>
element.type === "pcb_smtpad" &&
element.pcb_component_id === connector.pcb_component_id &&
element.port_hints?.includes(contact.pin),
);
if (!pad || pad.type !== "pcb_smtpad" || pad.shape !== "rect") {
throw new Error(`Missing USB signal pad ${contact.pin}`);
}
for (const x of [contact.x - 0.2, contact.x + 0.2]) {
for (const y of [-2.89, -2.315]) {
const corner = applyToPoint(modelToBoard, { x, y });
expect(Math.abs(corner.x - pad.x)).toBeLessThan(pad.width / 2);
expect(Math.abs(corner.y - pad.y)).toBeLessThan(pad.height / 2);
}
}
}
});