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
21 changes: 21 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ sot23
qfn24_w6_h6_p0.8mm_thermalpad_startingpin(topside,rightpin)_ccw
qfn64_thermalpad6.3mmx6.3mm_thermalvias4x4_thermalviapitch1mm_thermalviaid0.3048mm_thermalviaod0.6096mm
axial_p0.2in
do219ad
sod323he
```

You can use these like so:
Expand Down Expand Up @@ -113,6 +115,25 @@ fp().sod123w().p("3.4mm").pw("0.95mm").cathodepin(1)
fp().sod123w().p("3.4mm").pw("0.95mm").anodepin(1)
```

### Explicit two-pad package identity

Two rectangular pads alone do not identify the component package. Use a named
standard-family footprint when downstream tools such as a 3D renderer need an
unambiguous package identity:

```ts
fp.string("do219ad")
fp.string("sod323he")
fp.string("dfn2_w1.6mm_pl0.6mm_pw0.6mm")
```

`do-219ad` and `sod-323he` are accepted aliases and normalize to the canonical
names above. DO-219AD and SOD-323HE assign pin 1 to the cathode at negative X
and pin 2 to the anode at positive X. Their land-pattern parameters (`p`, `pw`,
and `ph`) are independent from their validated mechanical parameters such as
`bodylength`, `bodywidth`, and `bodyheight`. A generic `smdpads2` footprint
remains generic and never selects one of these packages by pad dimensions.

### Rounded pads

Every footprint accepts a `rounded${radius}` modifier that applies the requested
Expand Down
59 changes: 52 additions & 7 deletions src/fn/dfn.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,42 @@ import type {
PcbSilkscreenPath,
} from "circuit-json"
import { length } from "circuit-json"
import { extendSoicDef, getCcwSoicCoords } from "./soic"
import { rectpad } from "src/helpers/rectpad"
import { pillpad } from "src/helpers/pillpad"
import { z } from "zod"
import { CORNERS } from "src/helpers/corner"
import { type SilkscreenRef, silkscreenRef } from "src/helpers/silkscreenRef"
import { function_call } from "src/helpers/zod/function-call"
import { createThermalPad } from "src/helpers/create-thermal-pad"
import { addThermalVias, thermalViaDef } from "src/helpers/create-thermal-vias"
import { pillpad } from "src/helpers/pillpad"
import { polygonpad } from "src/helpers/polygonpad"
import { rectpad } from "src/helpers/rectpad"
import { type SilkscreenRef, silkscreenRef } from "src/helpers/silkscreenRef"
import { function_call } from "src/helpers/zod/function-call"
import { z } from "zod"
import { extendSoicDef, getCcwSoicCoords } from "./soic"

export const dfn_def = extendSoicDef({}).and(thermalViaDef)
const positiveMechanicalLength = length.refine((value) => value > 0, {
message: "DFN mechanical dimension must be positive",
})
const nonnegativeMechanicalLength = length.refine((value) => value >= 0, {
message: "DFN mechanical dimension must be non-negative",
})

/** Optional physical-package dimensions for an explicitly named DFN model. */
export const dfn_mechanical_def = z.object({
bodywidth: positiveMechanicalLength.optional(),
bodylength: positiveMechanicalLength.optional(),
bodythickness: positiveMechanicalLength.optional(),
standoff: nonnegativeMechanicalLength.optional(),
terminalinset: nonnegativeMechanicalLength.optional(),
terminallength: positiveMechanicalLength.optional(),
terminalwidth: positiveMechanicalLength.optional(),
terminalpitch: positiveMechanicalLength.optional(),
terminalthickness: positiveMechanicalLength.optional(),
pin1terminalchamfer: nonnegativeMechanicalLength.optional(),
pin1markwidth: nonnegativeMechanicalLength.optional(),
})

export const dfn_def = extendSoicDef({})
.and(thermalViaDef)
.and(dfn_mechanical_def)
export type DfnInput = z.input<typeof dfn_def> & {
/** Replace the four rectangular DFN pads with chamfered corner pads. */
cornerpads?: boolean
Expand Down Expand Up @@ -53,6 +77,27 @@ export const dfn = (
cornerpadcutlength,
missing: missingPositions,
}
if (
parameters.bodythickness !== undefined &&
parameters.standoff !== undefined &&
parameters.standoff >= parameters.bodythickness
) {
throw new Error("DFN standoff must be less than bodythickness")
}
if (
parameters.terminalthickness !== undefined &&
parameters.bodythickness !== undefined &&
parameters.terminalthickness > parameters.bodythickness
) {
throw new Error("DFN terminalthickness must not exceed bodythickness")
}
if (
parameters.pin1markwidth !== undefined &&
parameters.bodywidth !== undefined &&
parameters.pin1markwidth >= parameters.bodywidth / 2
) {
throw new Error("DFN pin1markwidth must be less than half bodywidth")
}
const nominalPinCount = parameters.num_pins
if (
missingPositions.some(
Expand Down
41 changes: 41 additions & 0 deletions src/fn/do219ad.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import type { AnyCircuitElement } from "circuit-json"
import type { z } from "zod"
import {
createStandardFlatLeadDiodeCircuitJson,
createStandardFlatLeadDiodeDef,
} from "../helpers/standard-flat-lead-diode"

/**
* JEDEC DO-219AD (MicroSMP), using nominal Vishay package dimensions.
* Dimensional reference: https://www.vishay.com/doc/?89019=
*/
export const do219ad_def = createStandardFlatLeadDiodeDef("do219ad", {
p: "1.84mm",
pw: "1.35mm",
ph: "0.95mm",
bodylength: "2.2mm",
bodywidth: "1.3mm",
bodyheight: "0.68mm",
leadspan: "2.5mm",
cathodelength: "1.3mm",
cathodewidth: "0.88mm",
anodelength: "0.65mm",
anodewidth: "0.65mm",
terminalthickness: "0.195mm",
standoff: "0.11mm",
taperinset: "0.05mm",
markingwidth: "0.23mm",
})

export const do219ad = (
rawParameters: z.input<typeof do219ad_def>,
): {
circuitJson: AnyCircuitElement[]
parameters: z.output<typeof do219ad_def>
} => {
const parameters = do219ad_def.parse(rawParameters)
return {
circuitJson: createStandardFlatLeadDiodeCircuitJson(parameters),
parameters,
}
}
2 changes: 2 additions & 0 deletions src/fn/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ export { sot886 } from "./sot886"
export { sot23 } from "./sot23"
export { sot25 } from "./sot25"
export { dfn } from "./dfn"
export { do219ad } from "./do219ad"
export { pinrow } from "./pinrow"
export { headermodule } from "./headermodule"
export { sot563 } from "./sot563"
Expand All @@ -46,6 +47,7 @@ export { sop8 } from "./sop8"
export { sod80 } from "./sod80"
export { sod123w } from "./sod123w"
export { sod323 } from "./sod323"
export { sod323he } from "./sod323he"
export { sod923 } from "./sod923"
export { sod882 } from "./sod882"
export { sod323f } from "./sod323f"
Expand Down
41 changes: 41 additions & 0 deletions src/fn/sod323he.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import type { AnyCircuitElement } from "circuit-json"
import type { z } from "zod"
import {
createStandardFlatLeadDiodeCircuitJson,
createStandardFlatLeadDiodeDef,
} from "../helpers/standard-flat-lead-diode"

/**
* JEITA SOD-323HE, using nominal ROHM package dimensions.
* Dimensional reference: https://www.rohm.com/products/diodes/fast-recovery-diodes/standard/rfu02vsm6s-product
*/
export const sod323he_def = createStandardFlatLeadDiodeDef("sod323he", {
p: "2.1001mm",
pw: "0.8mm",
ph: "1.1mm",
bodylength: "2mm",
bodywidth: "1.4mm",
bodyheight: "0.6mm",
leadspan: "2.5mm",
cathodelength: "0.55mm",
cathodewidth: "0.8mm",
anodelength: "0.55mm",
anodewidth: "0.8mm",
terminalthickness: "0.17mm",
standoff: "0.05mm",
taperinset: "0.15mm",
markingwidth: "0.2mm",
})

export const sod323he = (
rawParameters: z.input<typeof sod323he_def>,
): {
circuitJson: AnyCircuitElement[]
parameters: z.output<typeof sod323he_def>
} => {
const parameters = sod323he_def.parse(rawParameters)
return {
circuitJson: createStandardFlatLeadDiodeCircuitJson(parameters),
parameters,
}
}
53 changes: 52 additions & 1 deletion src/footprinter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -214,6 +214,36 @@ export type Footprinter = {
| "thermalviaod"
| "cornerpads"
| "cornerpadcutlength"
| "bodywidth"
| "bodylength"
| "bodythickness"
| "standoff"
| "terminalinset"
| "terminallength"
| "terminalwidth"
| "terminalpitch"
| "terminalthickness"
| "pin1terminalchamfer"
| "pin1markwidth"
>
do219ad: () => FootprinterParamsBuilder<
| "p"
| "pw"
| "ph"
| "cyw"
| "cyh"
| "bodylength"
| "bodywidth"
| "bodyheight"
| "leadspan"
| "cathodelength"
| "cathodewidth"
| "anodelength"
| "anodewidth"
| "terminalthickness"
| "standoff"
| "taperinset"
| "markingwidth"
>
pinrow: (
num_pins?: number,
Expand Down Expand Up @@ -376,6 +406,25 @@ export type Footprinter = {
electrolytic: () => FootprinterParamsBuilder<"d" | "p" | "id" | "od">
sod923: () => FootprinterParamsBuilder<"w" | "h" | "p" | "pl" | "pw">
sod323: () => FootprinterParamsBuilder<"w" | "h" | "p" | "pl" | "pw">
sod323he: () => FootprinterParamsBuilder<
| "p"
| "pw"
| "ph"
| "cyw"
| "cyh"
| "bodylength"
| "bodywidth"
| "bodyheight"
| "leadspan"
| "cathodelength"
| "cathodewidth"
| "anodelength"
| "anodewidth"
| "terminalthickness"
| "standoff"
| "taperinset"
| "markingwidth"
>
sod80: () => FootprinterParamsBuilder<"w" | "h" | "p" | "pl" | "pw">
sod882: () => FootprinterParamsBuilder<"w" | "h" | "p" | "pl" | "pw">
sod882d: () => FootprinterParamsBuilder<"w" | "h" | "p" | "pl" | "pw">
Expand Down Expand Up @@ -584,6 +633,8 @@ export type Footprinter = {
const normalizeDefinition = (def: string): string => {
return def
.trim()
.replace(/^do-219ad(?=_|$)/i, "do219ad")
.replace(/^sod-323he(?=_|$)/i, "sod323he")
.replace(/^pinheader(?=[\d_]|$)/i, "pinrow")
.replace(/^d2pak(\d+)(?=_|$)/i, "d2pak_$1")
.replace(/^to-252(?:-(\d+))?(?=_|$)/i, (_, pins) =>
Expand Down Expand Up @@ -632,7 +683,7 @@ export const string = (def: string): Footprinter => {
// parameter name. Require another value token after that name so a
// normal pitch such as p1mm is still parsed as p + 1mm.
const m = s.match(
/((?:p\d+[a-zA-Z]+(?=[\(\d\.\+\-\?]))|[a-zA-Z]+)([\(\d\.\+\-\?].*)?/,
/((?:(?:p\d+|pin1)[a-zA-Z]+(?=[\(\d\.\+\-\?]))|[a-zA-Z]+)([\(\d\.\+\-\?].*)?/,
)
if (!m) return null
const [, rawFn, v] = m
Expand Down
Loading
Loading