Skip to content
Open
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
8 changes: 8 additions & 0 deletions src/fn/res.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { res0402Array4 } from "../helpers/res0402-array4"
import { res0603Array2 } from "../helpers/res0603-array2"
import { res0603Array4 } from "../helpers/res0603-array4"
import { res0606Array2 } from "../helpers/res0606-array2"
import { res0612Array4 } from "../helpers/res0612-array4"
import { res1206Array4 } from "../helpers/res1206-array4"

type ResArrayParams = PassiveDef & {
Expand Down Expand Up @@ -80,6 +81,13 @@ export const res = (
}
}

if (arrayCount === 4 && imperialBase === "0612") {
return {
circuitJson: res0612Array4(rawParameters),
parameters: rawParameters,
}
}

if (arrayCount === 4 && imperialBase === "1206") {
return {
circuitJson: res1206Array4(rawParameters),
Expand Down
45 changes: 33 additions & 12 deletions src/helpers/chipArray.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ export interface ChipArrayParams {
textbottom?: boolean
convex?: boolean
concave?: boolean
padHeights?: number[] // Optional: variable pad heights per position (overrides padHeight)
yPositions?: number[] // Optional: custom Y positions (overrides padPitch calculation)
}

/**
Expand All @@ -22,36 +24,54 @@ export interface ChipArrayParams {
* @returns Array of circuit elements (pads, silkscreen, pin1 marker, ref text)
*/
export const chipArray = (params: ChipArrayParams): AnyCircuitElement[] => {
const { padSpacing, padWidth, padHeight, padPitch, numRows, textbottom } =
params
const {
padSpacing,
padWidth,
padHeight,
padPitch,
numRows,
textbottom,
padHeights,
yPositions: customYPositions,
} = params

// Calculate Y positions for pads (centered around origin)
const yPositions: number[] = []
const halfRange = (numRows - 1) * (padPitch / 2)
for (let i = 0; i < numRows; i++) {
yPositions.push(halfRange - i * padPitch)
}
const yPositions: number[] =
customYPositions ??
(() => {
const positions: number[] = []
const halfRange = (numRows - 1) * (padPitch / 2)
for (let i = 0; i < numRows; i++) {
positions.push(halfRange - i * padPitch)
}
return positions
})()

const pads: AnyCircuitElement[] = []

// Left column: pins 1 to numRows
yPositions.forEach((y, index) => {
pads.push(rectpad(index + 1, -padSpacing / 2, y, padWidth, padHeight))
const height = padHeights?.[index] ?? padHeight
pads.push(rectpad(index + 1, -padSpacing / 2, y, padWidth, height))
})

// Right column: pins numRows+1 to 2*numRows (reverse order)
yPositions
.slice()
.reverse()
.forEach((y, index) => {
// For right column, reverse the padHeights array as well
const height = padHeights?.[yPositions.length - 1 - index] ?? padHeight
pads.push(
rectpad(index + numRows + 1, padSpacing / 2, y, padWidth, padHeight),
rectpad(index + numRows + 1, padSpacing / 2, y, padWidth, height),
)
})

// Calculate silkscreen boundaries - match KiCad style (two horizontal lines)
const top = Math.max(...yPositions) + padHeight / 2 + 0.4
const bottom = Math.min(...yPositions) - padHeight / 2 - 0.4
// Use max pad height for silkscreen calculations
const maxPadHeight = padHeights ? Math.max(...padHeights) : padHeight
const top = Math.max(...yPositions) + maxPadHeight / 2 + 0.4
const bottom = Math.min(...yPositions) - maxPadHeight / 2 - 0.4
const left = -padSpacing / 2 - padWidth / 2 - 0.4
const right = padSpacing / 2 + padWidth / 2 + 0.4

Expand Down Expand Up @@ -85,8 +105,9 @@ export const chipArray = (params: ChipArrayParams): AnyCircuitElement[] => {
const pin1X = -padSpacing / 2
const pin1Y = Math.max(...yPositions)
const pin1MarkerSize = 0.2
const pin1Height = padHeights?.[0] ?? padHeight
const pin1Left = pin1X - padWidth / 2 - 0.1
const pin1Top = pin1Y + padHeight / 2 + 0.1
const pin1Top = pin1Y + pin1Height / 2 + 0.1
const pin1Marker: PcbSilkscreenPath = {
type: "pcb_silkscreen_path",
layer: "top",
Expand Down
53 changes: 53 additions & 0 deletions src/helpers/res0612-array4.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import type { AnyCircuitElement } from "circuit-json"
import { chipArray } from "./chipArray"
import { z } from "zod"
import { base_def } from "./zod/base_def"
import mm from "@tscircuit/mm"

export const res0612Array4_def = base_def.extend({
pw: z.string().default("0.7mm"),
ph: z.string().default("0.64mm"),
p: z.string().default("0.847mm"),
textbottom: z.boolean().optional(),
convex: z.boolean().optional(),
concave: z.boolean().optional(),
})

export type Res0612Array4Params = z.input<typeof res0612Array4_def>

const padSpacing = 1.4 // Horizontal spacing between columns (KiCad: 1.4mm)

export const res0612Array4 = (
rawParams: Res0612Array4Params,
): AnyCircuitElement[] => {
const params = res0612Array4_def.parse(rawParams)

// Convert string values to numbers
const padWidth = mm(params.pw)
const padHeight = mm(params.ph)
const padPitch = mm(params.p)

// Check if using default parameters to match KiCad exactly
const isDefaultParams =
params.pw === "0.7mm" && params.ph === "0.64mm" && params.p === "0.847mm"

// KiCad exact values for R_Array_Convex_4x0612
// Y positions: [1.270, 0.400, -0.400, -1.270]
// Pad heights: [0.640, 0.500, 0.500, 0.640] for top to bottom
const kicadYPositions = [1.27, 0.4, -0.4, -1.27]
const kicadPadHeights = [0.64, 0.5, 0.5, 0.64]

return chipArray({
padSpacing,
padWidth,
padHeight,
padPitch,
numRows: 4,
textbottom: params.textbottom,
convex: params.convex,
concave: params.concave,
// Use KiCad exact values when default params, otherwise use calculated positions
yPositions: isDefaultParams ? kicadYPositions : undefined,
padHeights: isDefaultParams ? kicadPadHeights : undefined,
})
}
1 change: 1 addition & 0 deletions tests/__snapshots__/0612_x4_default.snap.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions tests/__snapshots__/0612_x4_p2.0.snap.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions tests/__snapshots__/0612_x4_ph1.4.snap.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions tests/__snapshots__/0612_x4_pw1.2.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