From eb13ebbdae677e3a6fd1585ad5bd9c1bf5266b66 Mon Sep 17 00:00:00 2001 From: Sahil Gupta Date: Thu, 8 Jan 2026 13:38:20 +0530 Subject: [PATCH 1/6] add soj fp with parity test --- src/fn/index.ts | 1 + src/fn/soj.ts | 20 +++++++++++++++++++ .../soj40_w18.3mm_p1.27mm.snap.svg | 1 + .../soj44_parity._boolean_difference.snap.svg | 1 + .../__snapshots__/soj44_parity.snap.svg | 1 + tests/kicad-parity/soj_kicad_parity.test.ts | 18 +++++++++++++++++ tests/soj.test.ts | 12 +++++++++++ 7 files changed, 54 insertions(+) create mode 100644 src/fn/soj.ts create mode 100644 tests/__snapshots__/soj40_w18.3mm_p1.27mm.snap.svg create mode 100644 tests/kicad-parity/__snapshots__/soj44_parity._boolean_difference.snap.svg create mode 100644 tests/kicad-parity/__snapshots__/soj44_parity.snap.svg create mode 100644 tests/kicad-parity/soj_kicad_parity.test.ts create mode 100644 tests/soj.test.ts diff --git a/src/fn/index.ts b/src/fn/index.ts index 07668c12..e95c0b94 100644 --- a/src/fn/index.ts +++ b/src/fn/index.ts @@ -78,3 +78,4 @@ export { sot } from "./sot" export { sot343 } from "./sot343" export { m2host } from "./m2host" export { to92l } from "./to92l" +export { soj } from "./soj" diff --git a/src/fn/soj.ts b/src/fn/soj.ts new file mode 100644 index 00000000..f7771db1 --- /dev/null +++ b/src/fn/soj.ts @@ -0,0 +1,20 @@ +import type { AnySoupElement } from "circuit-json" +import { extendSoicDef, soicWithoutParsing } from "./soic" + +export const soj_def = extendSoicDef({ + legsoutside: false, + pw: "0.6mm", + pl: "2.1mm", +}) + +export const soj = ( + raw_params: any, +): { circuitJson: AnySoupElement[]; parameters: any } => { + const parameters = soj_def.parse(raw_params) + parameters.w += 1.8 + + return { + circuitJson: soicWithoutParsing(parameters), + parameters, + } +} diff --git a/tests/__snapshots__/soj40_w18.3mm_p1.27mm.snap.svg b/tests/__snapshots__/soj40_w18.3mm_p1.27mm.snap.svg new file mode 100644 index 00000000..5da5f3e7 --- /dev/null +++ b/tests/__snapshots__/soj40_w18.3mm_p1.27mm.snap.svg @@ -0,0 +1 @@ +{REF} \ No newline at end of file diff --git a/tests/kicad-parity/__snapshots__/soj44_parity._boolean_difference.snap.svg b/tests/kicad-parity/__snapshots__/soj44_parity._boolean_difference.snap.svg new file mode 100644 index 00000000..a5fdd34c --- /dev/null +++ b/tests/kicad-parity/__snapshots__/soj44_parity._boolean_difference.snap.svg @@ -0,0 +1 @@ +SOJ-44_10.16x28.575mm_P1.27mm - Alignment Analysis (Footprinter vs KiCad)soj44_w10.16mm_p1.27mmKiCad: SOJ-44_10.16x28.575mm_P1.27mmPerfect alignment = complete overlap \ No newline at end of file diff --git a/tests/kicad-parity/__snapshots__/soj44_parity.snap.svg b/tests/kicad-parity/__snapshots__/soj44_parity.snap.svg new file mode 100644 index 00000000..64c98315 --- /dev/null +++ b/tests/kicad-parity/__snapshots__/soj44_parity.snap.svg @@ -0,0 +1 @@ +{REF}Diff: 1.18% \ No newline at end of file diff --git a/tests/kicad-parity/soj_kicad_parity.test.ts b/tests/kicad-parity/soj_kicad_parity.test.ts new file mode 100644 index 00000000..ba80179c --- /dev/null +++ b/tests/kicad-parity/soj_kicad_parity.test.ts @@ -0,0 +1,18 @@ +import { expect, test } from "bun:test" +import { compareFootprinterVsKicad } from "../fixtures/compareFootprinterVsKicad" +import { convertCircuitJsonToPcbSvg } from "circuit-to-svg" + +test("parity/soj44", async () => { + const { combinedFootprintElements, booleanDifferenceSvg } = + await compareFootprinterVsKicad( + "soj44_w10.16mm_p1.27mm", + "Package_SO.pretty/SOJ-44_10.16x28.575mm_P1.27mm.circuit.json", + ) + + const svgContent = convertCircuitJsonToPcbSvg(combinedFootprintElements) + expect(svgContent).toMatchSvgSnapshot(import.meta.path, "soj44_parity") + expect(booleanDifferenceSvg).toMatchSvgSnapshot( + import.meta.path, + "soj44_parity._boolean_difference", + ) +}) diff --git a/tests/soj.test.ts b/tests/soj.test.ts new file mode 100644 index 00000000..586cc047 --- /dev/null +++ b/tests/soj.test.ts @@ -0,0 +1,12 @@ +import { test, expect } from "bun:test" +import { convertCircuitJsonToPcbSvg } from "circuit-to-svg" +import { fp } from "../src/footprinter" + +test("soj40_w18.3mm_p1.27mm", () => { + const soup = fp.string("soj40_w18.3mm_p1.27mm").circuitJson() + const svgContent = convertCircuitJsonToPcbSvg(soup) + expect(svgContent).toMatchSvgSnapshot( + import.meta.path, + "soj40_w18.3mm_p1.27mm", + ) +}) From 19ea7848a8b0a0c902279da7dbd46d509f90d511 Mon Sep 17 00:00:00 2001 From: Sahil Gupta Date: Tue, 13 Jan 2026 15:18:47 +0530 Subject: [PATCH 2/6] fix ref text size --- src/fn/soic.ts | 2 +- tests/__snapshots__/soj40_w18.3mm_p1.27mm.snap.svg | 2 +- tests/kicad-parity/__snapshots__/soj44_parity.snap.svg | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/fn/soic.ts b/src/fn/soic.ts index a324887b..06fa7386 100644 --- a/src/fn/soic.ts +++ b/src/fn/soic.ts @@ -135,7 +135,7 @@ export const soicWithoutParsing = (parameters: z.infer) => { const silkscreenRefText: SilkscreenRef = silkscreenRef( 0, sh / 2 + 0.4, - sh / 12, + Math.max(0.5, Math.min(0.7, sh / 12)), ) const silkscreenBorder: PcbSilkscreenPath = { type: "pcb_silkscreen_path", diff --git a/tests/__snapshots__/soj40_w18.3mm_p1.27mm.snap.svg b/tests/__snapshots__/soj40_w18.3mm_p1.27mm.snap.svg index 5da5f3e7..0994a3ea 100644 --- a/tests/__snapshots__/soj40_w18.3mm_p1.27mm.snap.svg +++ b/tests/__snapshots__/soj40_w18.3mm_p1.27mm.snap.svg @@ -1 +1 @@ -{REF} \ No newline at end of file +{REF} \ No newline at end of file diff --git a/tests/kicad-parity/__snapshots__/soj44_parity.snap.svg b/tests/kicad-parity/__snapshots__/soj44_parity.snap.svg index 64c98315..212a866c 100644 --- a/tests/kicad-parity/__snapshots__/soj44_parity.snap.svg +++ b/tests/kicad-parity/__snapshots__/soj44_parity.snap.svg @@ -1 +1 @@ -{REF}Diff: 1.18% \ No newline at end of file +{REF}Diff: 1.18% \ No newline at end of file From 63ea78c531a7e90981cd605b2f580f0e8e6174bf Mon Sep 17 00:00:00 2001 From: Sahil Gupta Date: Wed, 14 Jan 2026 11:24:38 +0530 Subject: [PATCH 3/6] fix tests --- src/fn/soic.ts | 10 +++++++++- src/fn/soj.ts | 6 ++++++ 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/src/fn/soic.ts b/src/fn/soic.ts index 06fa7386..e34ebebb 100644 --- a/src/fn/soic.ts +++ b/src/fn/soic.ts @@ -16,6 +16,7 @@ export const extendSoicDef = (newDefaults: { num_pins?: number legsoutside?: boolean pillpads?: boolean + ref_text_size?: number }) => base_def .extend({ @@ -33,9 +34,16 @@ export const extendSoicDef = (newDefaults: { .boolean() .optional() .default(newDefaults.pillpads ?? false), + ref_text_size: z.number().optional(), silkscreen_stroke_width: z.number().optional().default(0.1), }) .transform((v) => { + if ( + v.ref_text_size === undefined && + newDefaults.ref_text_size !== undefined + ) { + v.ref_text_size = newDefaults.ref_text_size + } // Default inner diameter and outer diameter if (!v.pw && !v.pl) { v.pw = length.parse("0.6mm") @@ -135,7 +143,7 @@ export const soicWithoutParsing = (parameters: z.infer) => { const silkscreenRefText: SilkscreenRef = silkscreenRef( 0, sh / 2 + 0.4, - Math.max(0.5, Math.min(0.7, sh / 12)), + parameters.ref_text_size ?? sh / 12, ) const silkscreenBorder: PcbSilkscreenPath = { type: "pcb_silkscreen_path", diff --git a/src/fn/soj.ts b/src/fn/soj.ts index f7771db1..365750b8 100644 --- a/src/fn/soj.ts +++ b/src/fn/soj.ts @@ -13,6 +13,12 @@ export const soj = ( const parameters = soj_def.parse(raw_params) parameters.w += 1.8 + const m = Math.min(1, parameters.p / 2) + const sh = + (parameters.num_pins / 2 - 1) * parameters.p + (parameters.pw ?? 0.6) + m + + parameters.ref_text_size = Math.max(0.5, Math.min(0.7, sh / 12)) + return { circuitJson: soicWithoutParsing(parameters), parameters, From 52ec000bd583a2dc2f20cad55abf81bc9ac7c93f Mon Sep 17 00:00:00 2001 From: Sahil Gupta Date: Wed, 14 Jan 2026 11:45:38 +0530 Subject: [PATCH 4/6] ref_text_size to reftextsize --- src/fn/soic.ts | 8 ++++---- src/fn/soj.ts | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/fn/soic.ts b/src/fn/soic.ts index e34ebebb..d61470d5 100644 --- a/src/fn/soic.ts +++ b/src/fn/soic.ts @@ -34,15 +34,15 @@ export const extendSoicDef = (newDefaults: { .boolean() .optional() .default(newDefaults.pillpads ?? false), - ref_text_size: z.number().optional(), + reftextsize: z.number().optional(), silkscreen_stroke_width: z.number().optional().default(0.1), }) .transform((v) => { if ( - v.ref_text_size === undefined && + v.reftextsize === undefined && newDefaults.ref_text_size !== undefined ) { - v.ref_text_size = newDefaults.ref_text_size + v.reftextsize = newDefaults.ref_text_size } // Default inner diameter and outer diameter if (!v.pw && !v.pl) { @@ -143,7 +143,7 @@ export const soicWithoutParsing = (parameters: z.infer) => { const silkscreenRefText: SilkscreenRef = silkscreenRef( 0, sh / 2 + 0.4, - parameters.ref_text_size ?? sh / 12, + parameters.reftextsize ?? sh / 12, ) const silkscreenBorder: PcbSilkscreenPath = { type: "pcb_silkscreen_path", diff --git a/src/fn/soj.ts b/src/fn/soj.ts index 365750b8..de7de9c2 100644 --- a/src/fn/soj.ts +++ b/src/fn/soj.ts @@ -17,7 +17,7 @@ export const soj = ( const sh = (parameters.num_pins / 2 - 1) * parameters.p + (parameters.pw ?? 0.6) + m - parameters.ref_text_size = Math.max(0.5, Math.min(0.7, sh / 12)) + parameters.reftextsize = Math.max(0.5, Math.min(0.7, sh / 12)) return { circuitJson: soicWithoutParsing(parameters), From 81f01c132cc8c1a96eb7a0f7fbf2778baed7495b Mon Sep 17 00:00:00 2001 From: Sahil Gupta Date: Wed, 14 Jan 2026 11:52:47 +0530 Subject: [PATCH 5/6] change in paramter --- src/fn/soic.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/fn/soic.ts b/src/fn/soic.ts index d61470d5..1e468e1e 100644 --- a/src/fn/soic.ts +++ b/src/fn/soic.ts @@ -16,7 +16,7 @@ export const extendSoicDef = (newDefaults: { num_pins?: number legsoutside?: boolean pillpads?: boolean - ref_text_size?: number + reftextsize?: number }) => base_def .extend({ @@ -40,9 +40,9 @@ export const extendSoicDef = (newDefaults: { .transform((v) => { if ( v.reftextsize === undefined && - newDefaults.ref_text_size !== undefined + newDefaults.reftextsize !== undefined ) { - v.reftextsize = newDefaults.ref_text_size + v.reftextsize = newDefaults.reftextsize } // Default inner diameter and outer diameter if (!v.pw && !v.pl) { From 2252d0f75485d2ac35d389ffd76ffaf4f83d467a Mon Sep 17 00:00:00 2001 From: Sahil Gupta Date: Thu, 15 Jan 2026 20:34:27 +0530 Subject: [PATCH 6/6] AnyCircuitElement instead soup --- src/fn/soj.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/fn/soj.ts b/src/fn/soj.ts index de7de9c2..db8793f9 100644 --- a/src/fn/soj.ts +++ b/src/fn/soj.ts @@ -1,4 +1,4 @@ -import type { AnySoupElement } from "circuit-json" +import type { AnyCircuitElement } from "circuit-json" import { extendSoicDef, soicWithoutParsing } from "./soic" export const soj_def = extendSoicDef({ @@ -9,7 +9,7 @@ export const soj_def = extendSoicDef({ export const soj = ( raw_params: any, -): { circuitJson: AnySoupElement[]; parameters: any } => { +): { circuitJson: AnyCircuitElement[]; parameters: any } => { const parameters = soj_def.parse(raw_params) parameters.w += 1.8