tscircuit/ti

ti tscircuit library

Version
1.0.186
License
unset
Stars
0

tests/starter-footprints.test.tsx

/// <reference types="node" />

import assert from "node:assert/strict";
import { test } from "node:test";
import { Circuit } from "@tscircuit/core";
import ConsumerWirelessModule from "../examples/ConsumerWirelessModule.circuit.tsx";
import { LFB212G45SG8C341_FOOTPRINT } from "../lib/chips/jlcpcb-footprints.tsx";
import {
  CC2540F256RHAR,
  SN65LVDS31D,
  SN74LVC1G34DBVR,
  TMP103AYFF,
  TPD2E009DRTR,
  TPS25910RSA,
  TPS62086RLTR,
  W3006,
} from "../index.ts";

const starterChips = [
  ["TPS62086RLTR", TPS62086RLTR, 7, "C2071344"],
  ["TPS25910RSA", TPS25910RSA, 17, "C2649427"],
  ["SN65LVDS31D", SN65LVDS31D, 16, "C352934"],
  ["TPD2E009DRTR", TPD2E009DRTR, 3, "C3040101"],
  ["SN74LVC1G34DBVR", SN74LVC1G34DBVR, 5, "C840096"],
  ["TMP103AYFF", TMP103AYFF, 4, "C165141"],
  ["W3006", W3006, 2, "C5123155"],
  ["CC2540F256RHAR", CC2540F256RHAR, 41, "C22649"],
] as const;

const passiveComponentTypes = new Set([
  "simple_resistor",
  "simple_capacitor",
  "simple_inductor",
  "simple_diode",
]);

for (const [name, Chip, expectedPadCount, lcscPartNumber] of starterChips) {
  test(`${name} renders its imported JLCPCB footprint`, async () => {
    const circuit = new Circuit({
      platform: {
        routingDisabled: true,
        partsEngineDisabled: true,
        drcChecksDisabled: true,
      },
    });
    circuit.add(
      <board width={20} height={20} routingDisabled>
        <Chip name="U1" />
      </board>,
    );
    await circuit.renderUntilSettled();

    assert.deepEqual(
      circuit
        .getCircuitJson()
        .filter((element) => element.type.endsWith("_error")),
      [],
    );
    assert.equal(circuit.db.pcb_smtpad.list().length, expectedPadCount);
    assert.deepEqual(
      circuit.db.source_component.getWhere({ name: "U1" })
        ?.supplier_part_numbers,
      { jlcpcb: [lcscPartNumber] },
    );
  });
}

test("LFB212G45SG8C341 renders its imported JLCPCB footprint", async () => {
  const circuit = new Circuit({
    platform: {
      routingDisabled: true,
      partsEngineDisabled: true,
      drcChecksDisabled: true,
    },
  });
  circuit.add(
    <board width={20} height={20} routingDisabled>
      <chip
        name="FL1"
        manufacturerPartNumber="LFB212G45SG8C341"
        supplierPartNumbers={{ jlcpcb: ["C2650941"] }}
        footprint={LFB212G45SG8C341_FOOTPRINT}
        pinLabels={{ pin1: "GND", pin2: "OUT", pin3: "GND", pin4: "IN" }}
      />
    </board>,
  );
  await circuit.renderUntilSettled();

  assert.deepEqual(
    circuit
      .getCircuitJson()
      .filter((element) => element.type.endsWith("_error")),
    [],
  );
  assert.equal(circuit.db.pcb_smtpad.list().length, 4);
  assert.deepEqual(
    circuit.db.source_component.getWhere({ name: "FL1" })
      ?.supplier_part_numbers,
    { jlcpcb: ["C2650941"] },
  );
});

test("TMP103 ball numbers match the TI YFF pin assignment", async () => {
  const circuit = new Circuit({ platform: { pcbDisabled: true } });
  circuit.add(<TMP103AYFF name="U1" />);
  await circuit.renderUntilSettled();

  const component = circuit.db.source_component.getWhere({ name: "U1" });
  assert.ok(component);
  const pinNumber = (label: string) =>
    circuit.db.source_port
      .list({ source_component_id: component.source_component_id })
      .find((port) => port.port_hints?.includes(label))?.pin_number;

  assert.equal(pinNumber("SDA"), 1);
  assert.equal(pinNumber("V_PLUS"), 2);
  assert.equal(pinNumber("SCL"), 3);
  assert.equal(pinNumber("GND"), 4);
});

test("SN74LVC1G34 pins expose the TI logic aliases", async () => {
  const circuit = new Circuit({ platform: { pcbDisabled: true } });
  circuit.add(<SN74LVC1G34DBVR name="U1" />);
  await circuit.renderUntilSettled();

  const component = circuit.db.source_component.getWhere({ name: "U1" });
  assert.ok(component);
  const pinNumber = (label: string) =>
    circuit.db.source_port
      .list({ source_component_id: component.source_component_id })
      .find((port) => port.port_hints?.includes(label))?.pin_number;

  assert.equal(pinNumber("A"), 2);
  assert.equal(pinNumber("GND"), 3);
  assert.equal(pinNumber("Y"), 4);
  assert.equal(pinNumber("VCC"), 5);
});

test("the Consumer Wireless Module carries chip and passive footprints into PCB data", async () => {
  const circuit = new Circuit({
    platform: {
      routingDisabled: true,
      partsEngineDisabled: true,
      drcChecksDisabled: true,
    },
  });
  circuit.add(<ConsumerWirelessModule />);
  await circuit.renderUntilSettled();

  for (const [name, , expectedPadCount, lcscPartNumber] of starterChips.filter(
    ([chipName]) => chipName !== "W3006",
  )) {
    const sourceComponent = circuit.db.source_component
      .list()
      .find((component) =>
        component.supplier_part_numbers?.jlcpcb?.includes(lcscPartNumber),
      );
    assert.ok(sourceComponent, `${name} is missing from the starter design`);

    const pcbComponent = circuit.db.pcb_component.getWhere({
      source_component_id: sourceComponent.source_component_id,
    });
    assert.ok(pcbComponent, `${name} did not produce a PCB component`);
    assert.equal(
      circuit.db.pcb_smtpad.list({
        pcb_component_id: pcbComponent.pcb_component_id,
      }).length,
      expectedPadCount,
    );
  }

  const passiveComponents = circuit.db.source_component
    .list()
    .filter((component) => passiveComponentTypes.has(component.ftype));
  assert.equal(passiveComponents.length, 41);

  for (const sourceComponent of passiveComponents) {
    const pcbComponent = circuit.db.pcb_component.getWhere({
      source_component_id: sourceComponent.source_component_id,
    });
    assert.ok(
      pcbComponent,
      `${sourceComponent.name} did not produce a PCB component`,
    );
    assert.equal(
      circuit.db.pcb_smtpad.list({
        pcb_component_id: pcbComponent.pcb_component_id,
      }).length,
      2,
      `${sourceComponent.name} should have a two-pad footprint`,
    );
  }

  assert.equal(circuit.db.pcb_smtpad.list().length, 193);

  for (const [name, lcscPartNumber, expectedPadCount] of [
    ["CSD17313Q2", "C2863837", 8],
  ] as const) {
    const sourceComponent = circuit.db.source_component
      .list()
      .find((component) =>
        component.supplier_part_numbers?.jlcpcb?.includes(lcscPartNumber),
      );
    assert.ok(sourceComponent, `${name} is missing from the starter design`);
    const pcbComponent = circuit.db.pcb_component.getWhere({
      source_component_id: sourceComponent.source_component_id,
    });
    assert.ok(pcbComponent, `${name} did not produce a PCB component`);
    assert.equal(
      circuit.db.pcb_smtpad.list({
        pcb_component_id: pcbComponent.pcb_component_id,
      }).length,
      expectedPadCount,
    );
  }

  const csd17313q2 = circuit.db.source_component
    .list()
    .find((component) =>
      component.supplier_part_numbers?.jlcpcb?.includes("C2863837"),
    );
  assert.ok(csd17313q2);
  const mosfetPorts = circuit.db.source_port.list({
    source_component_id: csd17313q2.source_component_id,
  });
  assert.equal(
    mosfetPorts.filter((port) => port.port_hints?.includes("drain")).length,
    5,
  );
  assert.equal(
    mosfetPorts.filter((port) => port.port_hints?.includes("source")).length,
    2,
  );
  assert.equal(
    mosfetPorts.filter((port) => port.port_hints?.includes("gate")).length,
    1,
  );
  assert.ok(
    mosfetPorts.every(
      (port) =>
        !(
          port.port_hints?.includes("drain") &&
          port.port_hints?.includes("source")
        ),
    ),
  );

  const missingFootprints = circuit
    .getCircuitJson()
    .filter((element) => element.type === "pcb_missing_footprint_error");
  assert.equal(missingFootprints.length, 0);
});

test("the Consumer Wireless Module PCB is placed without autorouting", {
  timeout: 30_000,
}, async () => {
  const circuit = new Circuit({
    platform: {
      partsEngineDisabled: true,
    },
  });
  circuit.add(<ConsumerWirelessModule />);
  await circuit.renderUntilSettled();

  assert.deepEqual(
    circuit
      .getCircuitJson()
      .filter((element) => element.type.endsWith("_error")),
    [],
  );
  assert.equal(circuit.db.pcb_component.list().length, 52);
  assert.equal(circuit.db.pcb_smtpad.list().length, 193);
  assert.equal(circuit.db.pcb_trace.list().length, 0);
});