From f51d4d8613be7972c9d975df8bda733d61e9820a Mon Sep 17 00:00:00 2001 From: Devesh36 <142524747+Devesh36@users.noreply.github.com> Date: Sat, 6 Dec 2025 21:58:27 +0530 Subject: [PATCH 1/2] Add UTDFN-4-EP footprint and tests --- src/fn/index.ts | 1 + src/fn/utdfn4ep.ts | 79 +++++++++++++++++++ tests/__snapshots__/utdfn4ep_default.snap.svg | 1 + .../__snapshots__/utdfn4ep_overrides.snap.svg | 1 + tests/utdfn4ep.test.ts | 15 ++++ 5 files changed, 97 insertions(+) create mode 100644 src/fn/utdfn4ep.ts create mode 100644 tests/__snapshots__/utdfn4ep_default.snap.svg create mode 100644 tests/__snapshots__/utdfn4ep_overrides.snap.svg create mode 100644 tests/utdfn4ep.test.ts diff --git a/src/fn/index.ts b/src/fn/index.ts index a697f502..97c76794 100644 --- a/src/fn/index.ts +++ b/src/fn/index.ts @@ -17,6 +17,7 @@ export { sot886 } from "./sot886" export { sot23 } from "./sot23" export { sot25 } from "./sot25" export { dfn } from "./dfn" +export { utdfn4ep } from "./utdfn4ep" export { pinrow } from "./pinrow" export { sot563 } from "./sot563" export { ms012 } from "./ms012" diff --git a/src/fn/utdfn4ep.ts b/src/fn/utdfn4ep.ts new file mode 100644 index 00000000..63b2136e --- /dev/null +++ b/src/fn/utdfn4ep.ts @@ -0,0 +1,79 @@ +import type { AnyCircuitElement } from "circuit-json" +import { rectpad } from "src/helpers/rectpad" +import { z } from "zod" + +/** + * UTDFN-4-EP (1x1) footprint + * + * References (JLCPCB part pages): + * - Microchip MIC5366-1.8YMT-TZ (UTDFN-4-EP 1x1): https://jlcpcb.com/partdetail/MIC5366-1.8YMT-TZ/C621364 + * - Fitipower FP6182-28X7 (UTDFN-4-EP 1x1): https://jlcpcb.com/partdetail/FP6182-28X7/C498349 + * Recommended land pattern per Microchip datasheet: + * - https://ww1.microchip.com/downloads/en/DeviceDoc/MIC5366-1.8YMT-TZ-DS20005619G.pdf (page 11) + */ +export const utdfn4ep_def = z.object({ + + origin: z.string().optional(), + + norefdes: z.boolean().optional(), + + faceup: z.boolean().optional(), + + pad_w: z.number().optional(), + pad_h: z.number().optional(), + ep_w: z.number().optional(), + ep_h: z.number().optional(), + inset: z.number().optional(), +}) + +export const utdfn4ep = ( + raw_params: z.input | undefined, +): { circuitJson: AnyCircuitElement[]; parameters: any } => { + const parameters = utdfn4ep_def.parse(raw_params ?? {}) + + + const body_w = 1.0 + const body_h = 1.0 + + + const pad_w = parameters.pad_w ?? 0.40 + const pad_h = parameters.pad_h ?? 0.48 + const ep_w = parameters.ep_w ?? 0.47 + const ep_h = parameters.ep_h ?? 0.22 + const inset = parameters.inset ?? 0.05 + + const half_body_w = body_w / 2 + const half_body_h = body_h / 2 + + const pads: AnyCircuitElement[] = [] + + // Bottom-left (pin 1) + const bl_x = - (half_body_w - pad_w / 2 - inset) + const bl_y = - (half_body_h - pad_h / 2 - inset) + pads.push(rectpad(1, bl_x, bl_y, pad_w, pad_h)) + + // Bottom-right (pin 2) + const br_x = + (half_body_w - pad_w / 2 - inset) + const br_y = - (half_body_h - pad_h / 2 - inset) + pads.push(rectpad(2, br_x, br_y, pad_w, pad_h)) + + // Top-right (pin 3) + const tr_x = + (half_body_w - pad_w / 2 - inset) + const tr_y = + (half_body_h - pad_h / 2 - inset) + pads.push(rectpad(3, tr_x, tr_y, pad_w, pad_h)) + + // Top-left (pin 4) + const tl_x = - (half_body_w - pad_w / 2 - inset) + const tl_y = + (half_body_h - pad_h / 2 - inset) + pads.push(rectpad(4, tl_x, tl_y, pad_w, pad_h)) + + // Central exposed pad (EP) - use pad id '5' to denote EP + pads.push(rectpad(5, 0, 0, ep_w, ep_h)) + + return { + circuitJson: pads as AnyCircuitElement[], + parameters, + } +} + +export type Utdfn4epParams = z.input diff --git a/tests/__snapshots__/utdfn4ep_default.snap.svg b/tests/__snapshots__/utdfn4ep_default.snap.svg new file mode 100644 index 00000000..b40af734 --- /dev/null +++ b/tests/__snapshots__/utdfn4ep_default.snap.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/tests/__snapshots__/utdfn4ep_overrides.snap.svg b/tests/__snapshots__/utdfn4ep_overrides.snap.svg new file mode 100644 index 00000000..309e302c --- /dev/null +++ b/tests/__snapshots__/utdfn4ep_overrides.snap.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/tests/utdfn4ep.test.ts b/tests/utdfn4ep.test.ts new file mode 100644 index 00000000..73c90163 --- /dev/null +++ b/tests/utdfn4ep.test.ts @@ -0,0 +1,15 @@ +import { test, expect } from "bun:test" +import { convertCircuitJsonToPcbSvg } from "circuit-to-svg" +import { utdfn4ep } from "../src/fn/utdfn4ep" + +test("utdfn4ep_default", () => { + const { circuitJson } = utdfn4ep(undefined) + const svgContent = convertCircuitJsonToPcbSvg(circuitJson) + expect(svgContent).toMatchSvgSnapshot(import.meta.path, "utdfn4ep_default") +}) + +test("utdfn4ep_overrides", () => { + const { circuitJson } = utdfn4ep({ pad_w: 0.4, pad_h: 0.5, ep_w: 0.7, ep_h: 0.7 }) + const svgContent = convertCircuitJsonToPcbSvg(circuitJson) + expect(svgContent).toMatchSvgSnapshot(import.meta.path, "utdfn4ep_overrides") +}) From 938313468bdf0d96cf8df0618d1dad152cbf0ce2 Mon Sep 17 00:00:00 2001 From: Devesh36 <142524747+Devesh36@users.noreply.github.com> Date: Sat, 6 Dec 2025 22:09:12 +0530 Subject: [PATCH 2/2] Refactor utdfn4ep footprint definition and tests for improved readability --- src/fn/utdfn4ep.ts | 27 ++++++++++++--------------- tests/utdfn4ep.test.ts | 7 ++++++- 2 files changed, 18 insertions(+), 16 deletions(-) diff --git a/src/fn/utdfn4ep.ts b/src/fn/utdfn4ep.ts index 63b2136e..2691de67 100644 --- a/src/fn/utdfn4ep.ts +++ b/src/fn/utdfn4ep.ts @@ -12,13 +12,12 @@ import { z } from "zod" * - https://ww1.microchip.com/downloads/en/DeviceDoc/MIC5366-1.8YMT-TZ-DS20005619G.pdf (page 11) */ export const utdfn4ep_def = z.object({ - origin: z.string().optional(), - + norefdes: z.boolean().optional(), - + faceup: z.boolean().optional(), - + pad_w: z.number().optional(), pad_h: z.number().optional(), ep_w: z.number().optional(), @@ -31,12 +30,10 @@ export const utdfn4ep = ( ): { circuitJson: AnyCircuitElement[]; parameters: any } => { const parameters = utdfn4ep_def.parse(raw_params ?? {}) - const body_w = 1.0 const body_h = 1.0 - - const pad_w = parameters.pad_w ?? 0.40 + const pad_w = parameters.pad_w ?? 0.4 const pad_h = parameters.pad_h ?? 0.48 const ep_w = parameters.ep_w ?? 0.47 const ep_h = parameters.ep_h ?? 0.22 @@ -48,23 +45,23 @@ export const utdfn4ep = ( const pads: AnyCircuitElement[] = [] // Bottom-left (pin 1) - const bl_x = - (half_body_w - pad_w / 2 - inset) - const bl_y = - (half_body_h - pad_h / 2 - inset) + const bl_x = -(half_body_w - pad_w / 2 - inset) + const bl_y = -(half_body_h - pad_h / 2 - inset) pads.push(rectpad(1, bl_x, bl_y, pad_w, pad_h)) // Bottom-right (pin 2) - const br_x = + (half_body_w - pad_w / 2 - inset) - const br_y = - (half_body_h - pad_h / 2 - inset) + const br_x = +(half_body_w - pad_w / 2 - inset) + const br_y = -(half_body_h - pad_h / 2 - inset) pads.push(rectpad(2, br_x, br_y, pad_w, pad_h)) // Top-right (pin 3) - const tr_x = + (half_body_w - pad_w / 2 - inset) - const tr_y = + (half_body_h - pad_h / 2 - inset) + const tr_x = +(half_body_w - pad_w / 2 - inset) + const tr_y = +(half_body_h - pad_h / 2 - inset) pads.push(rectpad(3, tr_x, tr_y, pad_w, pad_h)) // Top-left (pin 4) - const tl_x = - (half_body_w - pad_w / 2 - inset) - const tl_y = + (half_body_h - pad_h / 2 - inset) + const tl_x = -(half_body_w - pad_w / 2 - inset) + const tl_y = +(half_body_h - pad_h / 2 - inset) pads.push(rectpad(4, tl_x, tl_y, pad_w, pad_h)) // Central exposed pad (EP) - use pad id '5' to denote EP diff --git a/tests/utdfn4ep.test.ts b/tests/utdfn4ep.test.ts index 73c90163..428e26ec 100644 --- a/tests/utdfn4ep.test.ts +++ b/tests/utdfn4ep.test.ts @@ -9,7 +9,12 @@ test("utdfn4ep_default", () => { }) test("utdfn4ep_overrides", () => { - const { circuitJson } = utdfn4ep({ pad_w: 0.4, pad_h: 0.5, ep_w: 0.7, ep_h: 0.7 }) + const { circuitJson } = utdfn4ep({ + pad_w: 0.4, + pad_h: 0.5, + ep_w: 0.7, + ep_h: 0.7, + }) const svgContent = convertCircuitJsonToPcbSvg(circuitJson) expect(svgContent).toMatchSvgSnapshot(import.meta.path, "utdfn4ep_overrides") })