Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
133 changes: 127 additions & 6 deletions src/fn/jst.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,24 @@ export const jst_def = base_def.extend({
pl: length.optional(),
w: length.optional(),
h: length.optional(),
mpx: length
.optional()
.describe("center-to-center distance between the SMD mounting pads"),
mpy: length
.optional()
.describe("mounting-pad row distance from the signal-pad row"),
mpw: length.optional().describe("SMD mounting pad width"),
mpl: length.optional().describe("SMD mounting pad length"),
mounttop: z
.boolean()
.optional()
.describe("place SMD mounting pads above the signal-pad row"),
smd: z
.boolean()
.optional()
.describe(
"Generic surface-mount JST-style connector with one signal row and two mounting pads.",
),
sh: z
.boolean()
.optional()
Expand Down Expand Up @@ -47,7 +65,7 @@ export const jst_def = base_def.extend({
export type jstDef = z.input<typeof jst_def>

// Variant type
type JstVariant = "ph" | "sh" | "zh"
type JstVariant = "ph" | "sh" | "smd" | "zh"

type Bounds = {
minX: number
Expand Down Expand Up @@ -100,6 +118,17 @@ const variantDefaults: Record<JstVariant, any> = {
w: length.parse("5.8mm"),
h: length.parse("7.8mm"),
},
smd: {
p: length.parse("2mm"),
id: 0,
pw: length.parse("1mm"),
pl: length.parse("3mm"),
mpw: length.parse("1.8mm"),
mpl: length.parse("3mm"),
mpy: length.parse("2.5mm"),
w: length.parse("8mm"),
h: length.parse("5mm"),
},
zh: {
p: length.parse("1.5mm"),
id: length.parse("0.73mm"),
Expand All @@ -111,6 +140,7 @@ const variantDefaults: Record<JstVariant, any> = {
}

function getVariant(params: jstDef): JstVariant {
if (params.smd) return "smd"
if (params.sh) return "sh"
if (params.ph) return "ph"
if (params.zh) return "zh"
Expand All @@ -124,13 +154,23 @@ function generatePads({
id,
pw,
pl,
mpx,
mpy,
mpw,
mpl,
mounttop,
}: {
variant: JstVariant
numPins: number
p: number
id: number
pw: number
pl: number
mpx: number
mpy: number
mpw: number
mpl: number
mounttop: boolean
}): {
pads: AnyCircuitElement[]
padBounds: Bounds
Expand All @@ -140,7 +180,33 @@ function generatePads({
const padBounds = createEmptyBounds()
let maxPadHalfY = 0

if (variant === "ph") {
if (variant === "smd") {
const startX = -((numPins - 1) / 2) * p
for (let i = 0; i < numPins; i++) {
const x = startX + i * p
pads.push(rectpad(i + 1, x, 0, pw, pl))
modifyBoundsToIncludeRect({
bounds: padBounds,
centerX: x,
centerY: 0,
width: pw,
height: pl,
})
}

const mountY = mpy === 0 ? 0 : (mounttop ? 1 : -1) * mpy
for (const [index, x] of [-mpx / 2, mpx / 2].entries()) {
pads.push(rectpad(numPins + index + 1, x, mountY, mpw, mpl))
modifyBoundsToIncludeRect({
bounds: padBounds,
centerX: x,
centerY: mountY,
width: mpw,
height: mpl,
})
}
maxPadHalfY = Math.max(pl / 2, mpl / 2)
} else if (variant === "ph") {
const startX = -((numPins - 1) / 2) * p
for (let i = 0; i < numPins; i++) {
const x = startX + i * p
Expand Down Expand Up @@ -244,7 +310,22 @@ function generateSilkscreenBody({
numPins?: number
p?: number
}): PcbSilkscreenPath {
if (variant === "ph") {
if (variant === "smd") {
return {
type: "pcb_silkscreen_path",
layer: "top",
pcb_component_id: "",
route: [
{ x: -w / 2, y: -h / 2 },
{ x: w / 2, y: -h / 2 },
{ x: w / 2, y: h / 2 },
{ x: -w / 2, y: h / 2 },
{ x: -w / 2, y: -h / 2 },
],
stroke_width: 0.1,
pcb_silkscreen_path_id: "",
}
} else if (variant === "ph") {
return {
type: "pcb_silkscreen_path",
layer: "top",
Expand Down Expand Up @@ -337,23 +418,53 @@ export const jst = (
)
}

const mpx = params.mpx ?? (numPins - 1) * p + 3.4
const mpy = params.mpy ?? defaults.mpy ?? 0
const mpw = params.mpw ?? defaults.mpw ?? 0
const mpl = params.mpl ?? defaults.mpl ?? 0
const mounttop = params.mounttop ?? false
const padGeometry = generatePads({
variant,
numPins,
p,
id,
pw,
pl,
mpx,
mpy,
mpw,
mpl,
mounttop,
})
const { pads, padBounds, maxPadHalfY } = padGeometry
const silkscreenWidth =
variant === "smd"
? Math.max(
w,
2 * Math.max(Math.abs(padBounds.minX), Math.abs(padBounds.maxX)) +
0.4,
)
: w
const silkscreenHeight =
variant === "smd"
? Math.max(
h,
2 * Math.max(Math.abs(padBounds.minY), Math.abs(padBounds.maxY)) +
0.4,
)
: h
const silkscreenBody = generateSilkscreenBody({
variant,
w,
h,
w: silkscreenWidth,
h: silkscreenHeight,
numPins,
p,
})
const silkscreenRefText: SilkscreenRef = silkscreenRef(0, h / 2 + 1, 0.5)
const silkscreenRefText: SilkscreenRef = silkscreenRef(
0,
silkscreenHeight / 2 + 1,
0.5,
)

const silkscreenXs = silkscreenBody.route.map((point) => point.x)
const silkscreenYs = silkscreenBody.route.map((point) => point.y)
Expand Down Expand Up @@ -409,7 +520,17 @@ export const jst = (
num_pins: numPins,
sh: variant === "sh",
ph: variant === "ph",
smd: variant === "smd",
zh: variant === "zh",
...(variant === "smd"
? {
mpx,
mpy,
mpw,
mpl,
mounttop,
}
: {}),
},
}
}
15 changes: 14 additions & 1 deletion src/footprinter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -258,7 +258,20 @@ export type Footprinter = {
minimelf: () => FootprinterParamsBuilder<"w" | "h" | "p" | "pw" | "pl">
melf: () => FootprinterParamsBuilder<"w" | "h" | "p" | "pw" | "pl">
jst: () => FootprinterParamsBuilder<
"w" | "h" | "p" | "id" | "pw" | "pl" | "ph" | "sh"
| "w"
| "h"
| "p"
| "id"
| "pw"
| "pl"
| "ph"
| "sh"
| "smd"
| "mpx"
| "mpy"
| "mpw"
| "mpl"
| "mounttop"
>
micromelf: () => FootprinterParamsBuilder<"w" | "h" | "p" | "pw" | "pl">
ms013: () => FootprinterParamsBuilder<"w" | "p">
Expand Down
1 change: 1 addition & 0 deletions tests/__snapshots__/jst.test.tsjst4_smd.snap.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
28 changes: 28 additions & 0 deletions tests/jst.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,34 @@ test("jst6_sh", () => {
expect(svgContent).toMatchSvgSnapshot(import.meta.path + "jst6_sh")
})

test("jst4_smd with mounting pads below the signal row", () => {
const definition =
"jst4_smd_p2mm_pw1mm_pl6mm_mpx10.698mm_mpy2.316mm_mpw1.8mm_mpl3.4mm"
const circuitJson = fp.string(definition).circuitJson()
const params = fp.string(definition).json() as any

expect(params.num_pins).toBe(4)
expect(params.smd).toBe(true)
expect(params.mounttop).toBe(false)
expect(convertCircuitJsonToPcbSvg(circuitJson)).toMatchSvgSnapshot(
import.meta.path + "jst4_smd",
)
})

test("jst5_smd_mounttop", () => {
const definition =
"jst5_smd_mounttop_p1.5mm_pw0.7mm_pl5mm_mpx10.1mm_mpy1.85mm_mpw1.5mm_mpl2.3mm"
const circuitJson = fp.string(definition).circuitJson()
const params = fp.string(definition).json() as any

expect(params.num_pins).toBe(5)
expect(params.smd).toBe(true)
expect(params.mounttop).toBe(true)
expect(convertCircuitJsonToPcbSvg(circuitJson)).toMatchSvgSnapshot(
import.meta.path + "jst5_smd_mounttop",
)
})
Comment on lines +34 to +60

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

A *.test.ts file may have AT MOST one test(...). This file already contained multiple tests before this PR, and two additional test(...) calls were added here (lines 34–46 and 48–60). Each test should be split into its own numbered file, e.g., jst4.test.ts, jst5.test.ts, etc., rather than accumulating all tests in a single jst.test.ts file.

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

Fix in Graphite


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


test("jst_sh6_is_invalid", () => {
expect(() => fp.string("jst_sh6").json()).toThrow()
})
Expand Down
Loading