Skip to content

Commit 6108d45

Browse files
authored
Populate pin numbers on pads (#170)
* Populate pin numbers on pads * Update SVG snapshots * Add JST fixture and refresh snapshots for pin numbers * Add missing USB-C and SMA fixtures
1 parent d4fb451 commit 6108d45

18 files changed

+785
-45
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
kicad-footprints
2+
!tests/fixtures/kicad-footprints
23
node_modules
34
dist
45
test-output

src/convert-kicad-json-to-tscircuit-soup.ts

Lines changed: 69 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,17 @@ const isNinetyLike = (deg: number) => {
7171
return n === 90 || n === 270
7272
}
7373

74+
const normalizePortName = (name: string | number | undefined) => {
75+
if (name === undefined || name === null) return undefined
76+
return `${name}`
77+
}
78+
79+
const getPinNumber = (name: string | number | undefined) => {
80+
const normalized = normalizePortName(name)
81+
const parsed = normalized !== undefined ? Number(normalized) : NaN
82+
return Number.isFinite(parsed) ? parsed : undefined
83+
}
84+
7485
const debug = Debug("kicad-mod-converter")
7586

7687
export const convertKicadLayerToTscircuitLayer = (kicadLayer: string) => {
@@ -121,12 +132,27 @@ export const convertKicadJsonToTsCircuitSoup = async (
121132

122133
// Collect all unique port names from pads and holes
123134
const portNames = new Set<string>()
135+
const portNameToPinNumber = new Map<string, number>()
124136
for (const pad of pads) {
125-
if (pad.name) portNames.add(pad.name)
137+
const portName = normalizePortName(pad.name)
138+
if (portName) {
139+
portNames.add(portName)
140+
const pinNumber = getPinNumber(pad.name)
141+
if (pinNumber !== undefined) {
142+
portNameToPinNumber.set(portName, pinNumber)
143+
}
144+
}
126145
}
127146
if (holes) {
128147
for (const hole of holes) {
129-
if (hole.name) portNames.add(hole.name)
148+
const portName = normalizePortName(hole.name)
149+
if (portName) {
150+
portNames.add(portName)
151+
const pinNumber = getPinNumber(hole.name)
152+
if (pinNumber !== undefined) {
153+
portNameToPinNumber.set(portName, pinNumber)
154+
}
155+
}
130156
}
131157
}
132158

@@ -142,6 +168,7 @@ export const convertKicadJsonToTsCircuitSoup = async (
142168
source_component_id: "source_component_0",
143169
name: portName,
144170
port_hints: [portName],
171+
pin_number: portNameToPinNumber.get(portName),
145172
})
146173
circuitJson.push({
147174
type: "schematic_port",
@@ -192,7 +219,7 @@ export const convertKicadJsonToTsCircuitSoup = async (
192219
let y = 0
193220
let layers: string[] = ["top", "bottom"]
194221

195-
const pad = pads.find((p) => p.name === portName)
222+
const pad = pads.find((p) => normalizePortName(p.name) === portName)
196223
if (pad) {
197224
x = pad.at[0]
198225
y = -pad.at[1]
@@ -202,7 +229,7 @@ export const convertKicadJsonToTsCircuitSoup = async (
202229
.filter(Boolean) as string[])
203230
: ["top", "bottom"]
204231
} else if (holes) {
205-
const hole = holes.find((h) => h.name === portName)
232+
const hole = holes.find((h) => normalizePortName(h.name) === portName)
206233
if (hole) {
207234
x = hole.at[0]
208235
y = -hole.at[1]
@@ -229,12 +256,15 @@ export const convertKicadJsonToTsCircuitSoup = async (
229256
let platedHoleId = 0
230257
let holeId = 0
231258
for (const pad of pads) {
259+
const portName = normalizePortName(pad.name)
260+
const pinNumber = portName ? portNameToPinNumber.get(portName) : undefined
261+
232262
if (pad.pad_type === "smd") {
233263
const rotation = getRotationDeg(pad.at)
234264
const width = isNinetyLike(rotation) ? pad.size[1] : pad.size[0]
235265
const height = isNinetyLike(rotation) ? pad.size[0] : pad.size[1]
236-
const pcb_port_id = pad.name
237-
? portNameToPcbPortId.get(pad.name)
266+
const pcb_port_id = portName
267+
? portNameToPcbPortId.get(portName)
238268
: undefined
239269
circuitJson.push({
240270
type: "pcb_smtpad",
@@ -246,8 +276,9 @@ export const convertKicadJsonToTsCircuitSoup = async (
246276
height,
247277
layer: convertKicadLayerToTscircuitLayer(pad.layers?.[0] ?? "F.Cu")!,
248278
pcb_component_id,
249-
port_hints: [pad.name],
279+
port_hints: portName ? [portName] : [],
250280
pcb_port_id,
281+
pin_number: pinNumber,
251282
} as any)
252283
} else if (pad.pad_type === "thru_hole") {
253284
if (pad.pad_shape === "rect") {
@@ -257,8 +288,8 @@ export const convertKicadJsonToTsCircuitSoup = async (
257288
const offX = pad.drill?.offset?.[0] ?? 0
258289
const offY = pad.drill?.offset?.[1] ?? 0
259290
const rotOff = rotatePoint(offX, offY, rotation)
260-
const pcb_port_id = pad.name
261-
? portNameToPcbPortId.get(pad.name)
291+
const pcb_port_id = portName
292+
? portNameToPcbPortId.get(portName)
262293
: undefined
263294
circuitJson.push({
264295
type: "pcb_plated_hole",
@@ -276,12 +307,13 @@ export const convertKicadJsonToTsCircuitSoup = async (
276307
rect_pad_height: height,
277308
layers: ["top", "bottom"],
278309
pcb_component_id,
279-
port_hints: [pad.name],
310+
port_hints: portName ? [portName] : [],
280311
pcb_port_id,
312+
pin_number: pinNumber,
281313
} as any)
282314
} else if (pad.pad_shape === "circle") {
283-
const pcb_port_id = pad.name
284-
? portNameToPcbPortId.get(pad.name)
315+
const pcb_port_id = portName
316+
? portNameToPcbPortId.get(portName)
285317
: undefined
286318
circuitJson.push({
287319
type: "pcb_plated_hole",
@@ -293,12 +325,13 @@ export const convertKicadJsonToTsCircuitSoup = async (
293325
hole_diameter: pad.drill?.width!,
294326
layers: ["top", "bottom"],
295327
pcb_component_id,
296-
port_hints: [pad.name],
328+
port_hints: portName ? [portName] : [],
297329
pcb_port_id,
330+
pin_number: pinNumber,
298331
} as any)
299332
} else if (pad.pad_shape === "oval") {
300-
const pcb_port_id = pad.name
301-
? portNameToPcbPortId.get(pad.name)
333+
const pcb_port_id = portName
334+
? portNameToPcbPortId.get(portName)
302335
: undefined
303336
circuitJson.push({
304337
type: "pcb_plated_hole",
@@ -312,8 +345,9 @@ export const convertKicadJsonToTsCircuitSoup = async (
312345
hole_height: pad.drill?.height!,
313346
layers: ["top", "bottom"],
314347
pcb_component_id,
315-
port_hints: [pad.name],
348+
port_hints: portName ? [portName] : [],
316349
pcb_port_id,
350+
pin_number: pinNumber,
317351
} as any)
318352
}
319353
} else if (pad.pad_type === "np_thru_hole") {
@@ -330,6 +364,8 @@ export const convertKicadJsonToTsCircuitSoup = async (
330364

331365
if (holes) {
332366
for (const hole of holes) {
367+
const portName = normalizePortName(hole.name)
368+
const pinNumber = portName ? portNameToPinNumber.get(portName) : undefined
333369
const hasCuLayer = hole.layers?.some(
334370
(l) => l.endsWith(".Cu") || l === "*.Cu",
335371
)
@@ -358,8 +394,8 @@ export const convertKicadJsonToTsCircuitSoup = async (
358394
: 0
359395
if (hasCuLayer) {
360396
if (hole.pad_shape === "rect") {
361-
const pcb_port_id = hole.name
362-
? portNameToPcbPortId.get(hole.name)
397+
const pcb_port_id = portName
398+
? portNameToPcbPortId.get(portName)
363399
: undefined
364400
circuitJson.push({
365401
type: "pcb_plated_hole",
@@ -380,14 +416,15 @@ export const convertKicadJsonToTsCircuitSoup = async (
380416
? (hole.size?.width ?? outerDiameter)
381417
: (hole.size?.height ?? outerDiameter),
382418
rect_border_radius: rectBorderRadius,
383-
port_hints: [hole.name],
419+
port_hints: portName ? [portName] : [],
384420
layers: ["top", "bottom"],
385421
pcb_component_id,
386422
pcb_port_id,
423+
pin_number: pinNumber,
387424
} as any)
388425
} else if (hole.pad_shape === "oval") {
389-
const pcb_port_id = hole.name
390-
? portNameToPcbPortId.get(hole.name)
426+
const pcb_port_id = portName
427+
? portNameToPcbPortId.get(portName)
391428
: undefined
392429
circuitJson.push({
393430
type: "pcb_plated_hole",
@@ -407,14 +444,15 @@ export const convertKicadJsonToTsCircuitSoup = async (
407444
hole_height: isNinetyLike(rotation)
408445
? (hole.drill?.width ?? holeDiameter)
409446
: (hole.drill?.height ?? holeDiameter),
410-
port_hints: [hole.name],
447+
port_hints: portName ? [portName] : [],
411448
layers: ["top", "bottom"],
412449
pcb_component_id,
413450
pcb_port_id,
451+
pin_number: pinNumber,
414452
} as any)
415453
} else if (hole.pad_shape === "roundrect") {
416-
const pcb_port_id = hole.name
417-
? portNameToPcbPortId.get(hole.name)
454+
const pcb_port_id = portName
455+
? portNameToPcbPortId.get(portName)
418456
: undefined
419457
const offX = hole.drill?.offset?.[0] ?? 0
420458
const offY = hole.drill?.offset?.[1] ?? 0
@@ -439,14 +477,15 @@ export const convertKicadJsonToTsCircuitSoup = async (
439477
rect_pad_width: width,
440478
rect_pad_height: height,
441479
rect_border_radius: rectBorderRadius,
442-
port_hints: [hole.name],
480+
port_hints: portName ? [portName] : [],
443481
layers: ["top", "bottom"],
444482
pcb_component_id,
445483
pcb_port_id,
484+
pin_number: pinNumber,
446485
} as any)
447486
} else {
448-
const pcb_port_id = hole.name
449-
? portNameToPcbPortId.get(hole.name)
487+
const pcb_port_id = portName
488+
? portNameToPcbPortId.get(portName)
450489
: undefined
451490
circuitJson.push({
452491
type: "pcb_plated_hole",
@@ -456,11 +495,12 @@ export const convertKicadJsonToTsCircuitSoup = async (
456495
y,
457496
outer_diameter: outerDiameter,
458497
hole_diameter: holeDiameter,
459-
port_hints: [hole.name],
498+
port_hints: portName ? [portName] : [],
460499
layers: ["top", "bottom"],
461500
pcb_component_id,
462501
pcb_port_id,
463-
})
502+
pin_number: pinNumber,
503+
} as any)
464504
}
465505
} else {
466506
circuitJson.push({

0 commit comments

Comments
 (0)