astra-abse/t113-s3

Allwinner T113-S3 / JLCPCB C5197687: native saved fanout, LCD top, storage right, 127 perimeter exits, 30 decoupling capacitors, connected GND planes; clean DRC and shorts, all 29 vias connected.

Version
1.2.0
License
MIT
Stars
0

scripts/test-bitmap-renderer.ts

import assert from "node:assert/strict";
import { mkdir, readFile, writeFile } from "node:fs/promises";
import type { AnyCircuitElement } from "circuit-json";
import { elements } from "./audit";
const json = JSON.parse(
  await readFile("dist/index/circuit.json", "utf8"),
) as AnyCircuitElement[];
const ports = elements(json, "pcb_port");
const sourcePorts = elements(json, "source_port");
const chip = elements(json, "source_component").find((c) => c.name === "U1")!;
const findPort = (n: number) =>
  ports.find(
    (p) =>
      p.source_port_id ===
      sourcePorts.find(
        (s) =>
          s.source_component_id === chip.source_component_id &&
          s.pin_number === n,
      )!.source_port_id,
  )!;
const ground = findPort(129),
  power = findPort(20);
const padFor = (id: string) =>
  elements(json, "pcb_smtpad").find((p) => p.pcb_port_id === id)!;
const originalPour = elements(json, "pcb_copper_pour").find(
  (p) => p.layer === "bottom",
)!;
const fixture = [
  ...json.filter((e) => e.type.startsWith("source_")),
  {
    ...elements(json, "pcb_board")[0],
    width: 4,
    height: 4,
    center: { x: 0, y: 0 },
  },
  { ...ground, x: -1, y: 0 },
  { ...power, x: 1, y: 0 },
  {
    ...padFor(ground.pcb_port_id),
    x: -1,
    y: 0,
    width: 0.5,
    height: 0.5,
    layer: "bottom",
  },
  {
    ...padFor(power.pcb_port_id),
    x: 1,
    y: 0,
    width: 0.5,
    height: 0.5,
    layer: "bottom",
  },
  {
    ...originalPour,
    brep_shape: {
      outer_ring: {
        vertices: [
          { x: -1.8, y: -1.8 },
          { x: 1.8, y: -1.8 },
          { x: 1.8, y: 1.8 },
          { x: -1.8, y: 1.8 },
        ],
      },
      inner_rings: [
        {
          vertices: [
            { x: 0.55, y: -0.45 },
            { x: 1.45, y: -0.45 },
            { x: 1.45, y: 0.45 },
            { x: 0.55, y: 0.45 },
          ],
        },
      ],
    },
  },
];
await mkdir("checks/bitmap-regression", { recursive: true });
for (const broken of [false, true]) {
  const f = structuredClone(fixture);
  if (broken) (f.at(-1) as any).brep_shape.inner_rings = [];
  const path = `checks/bitmap-regression/${broken ? "shorted" : "clear"}/circuit.json`;
  await mkdir(path.substring(0, path.lastIndexOf("/")), { recursive: true });
  await writeFile(path, JSON.stringify(f));
  const process = Bun.spawn(
    [
      "node_modules/.bin/tsci",
      "check",
      "shorts",
      path,
      "--mode",
      "pcb",
      "--layer",
      "bottom",
      "--pixels-per-mm",
      "100",
    ],
    { stdout: "pipe", stderr: "pipe" },
  );
  const [out, err, code] = await Promise.all([
    new Response(process.stdout).text(),
    new Response(process.stderr).text(),
    process.exited,
  ]);
  if (broken) {
    assert.match(out, /Detected [1-9]\d* short/);
    assert.notEqual(code, 0);
  } else {
    assert.equal(code, 0, err);
    assert.match(out, /No shorts detected/);
  }
  assert.doesNotMatch(err, /getContext|TypeError/);
  console.log(
    `${broken ? "Injected plane-to-power short detected" : "Isolated power pad within ground pour passes"} at 100 px/mm.`,
  );
}