Skip to content

feat: implement tripad footprint configuration#538

Open
victorjzq wants to merge 3 commits intotscircuit:mainfrom
victorjzq:feat/tripad
Open

feat: implement tripad footprint configuration#538
victorjzq wants to merge 3 commits intotscircuit:mainfrom
victorjzq:feat/tripad

Conversation

@victorjzq
Copy link
Contributor

Summary

  • Implements the tripad footprint for 3-pad SMD packages (similar to TO-252/D-PAK style)
  • Two small signal pads on the left (pins 1 & 3), one larger thermal/tab pad on the right (pin 2)
  • Fully configurable via parameters: w (width), h (height), p (pitch between small pads), pw/ph (small pad width/height), lw/lh (large pad width/height)
  • Supports string-based instantiation: fp.string("tripad"), fp.string("tripad_w5_h4.5_p2.54")
  • Includes silkscreen outline and pin 1 indicator notch

Default dimensions

Based on common tripad footprints found in the wild:

  • Overall width: 4.7mm, height: 4.0mm
  • Small pad pitch: 2.3mm, pad size: 1.5mm × 1.5mm
  • Large pad: 2.5mm × 3.5mm

Test plan

  • tripad default — generates 3 pads, matches SVG snapshot
  • tripad custom dimensions — string params work correctly
  • tripad pin numbering — pin 1/3 on left (negative X), pin 2 on right, pin 1 above pin 3, large pad bigger than small pads
  • tripad direct call with custom params — direct function call works
  • All 383 existing tests continue to pass (including footprint-completeness)

/claim #7

Adds a tripad footprint for 3-pad SMD packages (e.g. TO-252/D-PAK style).
Features two small signal pads on the left side and a larger thermal/tab
pad on the right. Configurable via w, h, p, pw, ph, lw, lh parameters.

Closes tscircuit#7
Comment on lines +1 to +65
import { test, expect } from "bun:test"
import { convertCircuitJsonToPcbSvg } from "circuit-to-svg"
import { fp } from "../src/footprinter"
import { tripad } from "../src/fn/tripad"

test("tripad default", () => {
const circuitJson = fp.string("tripad").circuitJson()
const pads = circuitJson.filter((e) => e.type === "pcb_smtpad")
expect(pads.length).toBe(3)
const svgContent = convertCircuitJsonToPcbSvg(circuitJson)
expect(svgContent).toMatchSvgSnapshot(import.meta.path, "tripad_default")
})

test("tripad custom dimensions", () => {
const circuitJson = fp.string("tripad_w5_h4.5_p2.54").circuitJson()
const pads = circuitJson.filter((e) => e.type === "pcb_smtpad")
expect(pads.length).toBe(3)
const svgContent = convertCircuitJsonToPcbSvg(circuitJson)
expect(svgContent).toMatchSvgSnapshot(
import.meta.path,
"tripad_custom_dimensions",
)
})

test("tripad pin numbering", () => {
const result = tripad({ fn: "tripad" })
const pads = result.circuitJson.filter((e) => e.type === "pcb_smtpad")
expect(pads.length).toBe(3)

// Pin 1 is top-left small pad (highest y)
const pin1 = pads.find(
(e) => e.type === "pcb_smtpad" && e.port_hints?.includes("1"),
)
const pin2 = pads.find(
(e) => e.type === "pcb_smtpad" && e.port_hints?.includes("2"),
)
const pin3 = pads.find(
(e) => e.type === "pcb_smtpad" && e.port_hints?.includes("3"),
)

expect(pin1).toBeDefined()
expect(pin2).toBeDefined()
expect(pin3).toBeDefined()

// Pin 1 and 3 are on the left (negative x), pin 2 is on the right (positive x)
if (pin1 && pin2 && pin3) {
expect((pin1 as any).x).toBeLessThan((pin2 as any).x)
expect((pin3 as any).x).toBeLessThan((pin2 as any).x)
// Pin 1 is above pin 3
expect((pin1 as any).y).toBeGreaterThan((pin3 as any).y)
// Pin 2 (large pad) is centered vertically
expect((pin2 as any).y).toBe(0)
// Large pad is bigger than small pads
expect((pin2 as any).width).toBeGreaterThan((pin1 as any).width)
expect((pin2 as any).height).toBeGreaterThan((pin1 as any).height)
}
})

test("tripad direct call with custom params", () => {
const result = tripad({ fn: "tripad", w: "6mm", h: "5mm", p: "3mm" })
const pads = result.circuitJson.filter((e) => e.type === "pcb_smtpad")
expect(pads.length).toBe(3)
const svgContent = convertCircuitJsonToPcbSvg(result.circuitJson)
expect(svgContent).toMatchSvgSnapshot(import.meta.path, "tripad_custom_call")
})
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This test file violates the rule that a *.test.ts file may have AT MOST one test(...) call. The file contains 4 test cases: 'tripad default', 'tripad custom dimensions', 'tripad pin numbering', and 'tripad direct call with custom params'. According to the rule, after the first test, the user should split into multiple numbered files like tripad1.test.ts, tripad2.test.ts, etc. To fix this, create separate test files: tripad1.test.ts (for 'tripad default'), tripad2.test.ts (for 'tripad custom dimensions'), tripad3.test.ts (for 'tripad pin numbering'), and tripad4.test.ts (for 'tripad direct call with custom params').

Spotted by Graphite (based on custom rule: Custom rule)

Fix in Graphite


Is this helpful? React 👍 or 👎 to let us know.

@victorjzq
Copy link
Contributor Author

Hey @seveibar — tripad implementation with CI green. Ready for review!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant