@tscircuit/footprinter 0.0.8 → 0.0.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/src/fn/soic.ts +82 -0
- package/src/footprinter.ts +11 -2
- package/tests/res.test.ts +11 -0
- package/tests/soic.test.ts +10 -0
package/package.json
CHANGED
package/src/fn/soic.ts
ADDED
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import type { AnySoupElement } from "@tscircuit/soup"
|
|
2
|
+
import { platedhole } from "../helpers/platedhole"
|
|
3
|
+
import { z } from "zod"
|
|
4
|
+
import { length } from "@tscircuit/soup"
|
|
5
|
+
import type { NowDefined } from "../helpers/zod/now-defined"
|
|
6
|
+
|
|
7
|
+
const soic_def = z
|
|
8
|
+
.object({
|
|
9
|
+
soic: z.literal(true),
|
|
10
|
+
num_pins: z.number(),
|
|
11
|
+
w: length,
|
|
12
|
+
p: length.default(length.parse("1.27mm")),
|
|
13
|
+
id: length.optional(),
|
|
14
|
+
od: length.optional(),
|
|
15
|
+
})
|
|
16
|
+
.transform((v) => {
|
|
17
|
+
// Default inner diameter and outer diameter
|
|
18
|
+
if (!v.id && !v.od) {
|
|
19
|
+
v.id = length.parse("0.6mm")
|
|
20
|
+
v.od = length.parse("1.0mm")
|
|
21
|
+
} else if (!v.id) {
|
|
22
|
+
v.id = v.od! * (0.6 / 1.0)
|
|
23
|
+
} else if (!v.od) {
|
|
24
|
+
v.od = v.id! * (1.0 / 0.6)
|
|
25
|
+
}
|
|
26
|
+
return v as NowDefined<typeof v, "w" | "p" | "id" | "od">
|
|
27
|
+
})
|
|
28
|
+
|
|
29
|
+
export const getCcwSoicCoords = (
|
|
30
|
+
pinCount: number,
|
|
31
|
+
pn: number,
|
|
32
|
+
w: number,
|
|
33
|
+
p: number
|
|
34
|
+
) => {
|
|
35
|
+
/** pin height */
|
|
36
|
+
const ph = pinCount / 2
|
|
37
|
+
const isLeft = pn <= ph
|
|
38
|
+
|
|
39
|
+
/** Number of gaps between pins on each side, e.g. 4 pins = 3 spaces */
|
|
40
|
+
const leftPinGaps = ph - 1
|
|
41
|
+
|
|
42
|
+
/** gap size (pitch) */
|
|
43
|
+
const gs = p
|
|
44
|
+
|
|
45
|
+
const h = gs * leftPinGaps
|
|
46
|
+
|
|
47
|
+
if (isLeft) {
|
|
48
|
+
// The y position starts at h/2, then goes down by gap size
|
|
49
|
+
// for each pin
|
|
50
|
+
return { x: -w / 2, y: h / 2 - (pn - 1) * gs }
|
|
51
|
+
} else {
|
|
52
|
+
// The y position starts at -h/2, then goes up by gap size
|
|
53
|
+
return { x: w / 2, y: -h / 2 + (pn - ph - 1) * gs }
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Returns the plated holes for a SOIC package.
|
|
59
|
+
*/
|
|
60
|
+
export const soic = (raw_params: {
|
|
61
|
+
soic: true
|
|
62
|
+
num_pins: number
|
|
63
|
+
w: number
|
|
64
|
+
p?: number
|
|
65
|
+
id?: string | number
|
|
66
|
+
od?: string | number
|
|
67
|
+
}): AnySoupElement[] => {
|
|
68
|
+
const params = soic_def.parse(raw_params)
|
|
69
|
+
const platedHoles: AnySoupElement[] = []
|
|
70
|
+
for (let i = 0; i < params.num_pins; i++) {
|
|
71
|
+
const { x, y } = getCcwSoicCoords(
|
|
72
|
+
params.num_pins,
|
|
73
|
+
i + 1,
|
|
74
|
+
params.w,
|
|
75
|
+
params.p ?? 1.27
|
|
76
|
+
)
|
|
77
|
+
platedHoles.push(
|
|
78
|
+
platedhole(i + 1, x, y, params.id ?? "0.6mm", params.od ?? "1mm")
|
|
79
|
+
)
|
|
80
|
+
}
|
|
81
|
+
return platedHoles
|
|
82
|
+
}
|
package/src/footprinter.ts
CHANGED
|
@@ -4,6 +4,7 @@ import { cap } from "./fn/cap"
|
|
|
4
4
|
import { led } from "./fn/led"
|
|
5
5
|
import { res } from "./fn/res"
|
|
6
6
|
import { bga } from "./fn/bga"
|
|
7
|
+
import { soic } from "./fn/soic"
|
|
7
8
|
import type { AnySoupElement } from "@tscircuit/soup"
|
|
8
9
|
import { isNotNull } from "./helpers/is-not-null"
|
|
9
10
|
|
|
@@ -42,6 +43,7 @@ export type Footprinter = {
|
|
|
42
43
|
) => FootprinterParamsBuilder<
|
|
43
44
|
"grid" | "p" | "w" | "h" | "ball" | "pad" | "missing"
|
|
44
45
|
>
|
|
46
|
+
soic: (num_pins: number) => FootprinterParamsBuilder<"w" | "p" | "id" | "od">
|
|
45
47
|
params: () => any
|
|
46
48
|
soup: () => AnySoupElement[]
|
|
47
49
|
}
|
|
@@ -78,6 +80,7 @@ export const footprinter = (): Footprinter & { string: typeof string } => {
|
|
|
78
80
|
if ("led" in target) return () => led(target)
|
|
79
81
|
if ("res" in target) return () => res(target)
|
|
80
82
|
if ("bga" in target) return () => bga(target)
|
|
83
|
+
if ("soic" in target) return () => soic(target)
|
|
81
84
|
|
|
82
85
|
return () => {
|
|
83
86
|
// TODO improve error
|
|
@@ -91,9 +94,15 @@ export const footprinter = (): Footprinter & { string: typeof string } => {
|
|
|
91
94
|
return () => target
|
|
92
95
|
}
|
|
93
96
|
return (v: any) => {
|
|
94
|
-
if (
|
|
97
|
+
if (Object.keys(target).length === 0) {
|
|
95
98
|
target[prop] = true
|
|
96
|
-
|
|
99
|
+
if (prop === "res" || prop === "cap") {
|
|
100
|
+
if (v) {
|
|
101
|
+
target.imperial = v // res0402, cap0603 etc.
|
|
102
|
+
}
|
|
103
|
+
} else {
|
|
104
|
+
target.num_pins = parseFloat(v)
|
|
105
|
+
}
|
|
97
106
|
} else {
|
|
98
107
|
target[prop] = v ?? true
|
|
99
108
|
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import test from "ava"
|
|
2
|
+
import { getTestFixture } from "tests/fixtures/get-test-fixture"
|
|
3
|
+
import { su } from "@tscircuit/soup-util"
|
|
4
|
+
|
|
5
|
+
test("res_imperial0402", async (t) => {
|
|
6
|
+
const { fp } = await getTestFixture(t)
|
|
7
|
+
const soup = fp.string("res_imperial0402").soup()
|
|
8
|
+
|
|
9
|
+
t.is(su(soup).pcb_smtpad.list().length, 2)
|
|
10
|
+
t.is(su(soup).pcb_plated_hole.list().length, 0)
|
|
11
|
+
})
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import test from "ava"
|
|
2
|
+
import { getTestFixture } from "tests/fixtures/get-test-fixture"
|
|
3
|
+
import { su } from "@tscircuit/soup-util"
|
|
4
|
+
|
|
5
|
+
test("soic8_w5.3mm_p1.27mm", async (t) => {
|
|
6
|
+
const { fp } = await getTestFixture(t)
|
|
7
|
+
const soup = fp.string("soic8_w5.3mm_p1.27mm").soup()
|
|
8
|
+
|
|
9
|
+
t.is(su(soup).pcb_plated_hole.list().length, 8)
|
|
10
|
+
})
|