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
50 changes: 33 additions & 17 deletions lib/components/normal-components/Board/Board.ts
Original file line number Diff line number Diff line change
Expand Up @@ -252,6 +252,35 @@ export class Board
}
}

/**
* Via hole/pad diameters (mm) required by this board's design rules:
* minViaHoleDiameter/minViaPadDiameter, then the board's pcbStyle via size,
* then JLCPCB's minimums. These are recorded on pcb_board and are the
* default size for vias placed without an explicit or styled size.
*/
_getResolvedMinViaDiameters(): { holeDiameter: number; padDiameter: number } {
const subcircuitProps = this.getSubcircuit()._parsedProps
const pcbStyle = this.getInheritedMergedProperty("pcbStyle")
const styledViaDimensions = getViaDiameterDefaults(pcbStyle)
const configuredViaHoleDiameter =
subcircuitProps.minViaHoleDiameter ??
(pcbStyle?.viaHoleDiameter !== undefined
? styledViaDimensions.holeDiameter
: undefined)
return {
holeDiameter:
configuredViaHoleDiameter ?? jlcMinTolerances.min_via_hole_diameter!,
padDiameter:
subcircuitProps.minViaPadDiameter ??
(pcbStyle?.viaPadDiameter !== undefined
? styledViaDimensions.padDiameter
: configuredViaHoleDiameter !== undefined
? configuredViaHoleDiameter +
DEFAULT_VIA_PAD_DIAMETER_OVER_HOLE_DIAMETER_MM
: jlcMinTolerances.min_via_pad_diameter!),
}
}

doInitialPcbBoardAutoSize(): void {
if (this.root?.pcbDisabled) return
if (!this.pcb_board_id) return
Expand Down Expand Up @@ -584,23 +613,10 @@ export class Board
}
}
const subcircuitProps = this.getSubcircuit()._parsedProps
const pcbStyle = this.getInheritedMergedProperty("pcbStyle")
const styledViaDimensions = getViaDiameterDefaults(pcbStyle)
const configuredViaHoleDiameter =
subcircuitProps.minViaHoleDiameter ??
(pcbStyle?.viaHoleDiameter !== undefined
? styledViaDimensions.holeDiameter
: undefined)
const resolvedMinViaHoleDiameter =
configuredViaHoleDiameter ?? jlcMinTolerances.min_via_hole_diameter
const resolvedMinViaPadDiameter =
subcircuitProps.minViaPadDiameter ??
(pcbStyle?.viaPadDiameter !== undefined
? styledViaDimensions.padDiameter
: configuredViaHoleDiameter !== undefined
? configuredViaHoleDiameter +
DEFAULT_VIA_PAD_DIAMETER_OVER_HOLE_DIAMETER_MM
: jlcMinTolerances.min_via_pad_diameter)
const {
holeDiameter: resolvedMinViaHoleDiameter,
padDiameter: resolvedMinViaPadDiameter,
} = this._getResolvedMinViaDiameters()
const pcb_board = db.pcb_board.insert({
source_board_id: this.source_board_id,
subcircuit_id: this.subcircuit_id ?? undefined,
Expand Down
1 change: 1 addition & 0 deletions lib/components/normal-components/Board/BoardI.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,6 @@ export interface BoardI {
_generatedStitchingViaIds?: Set<PcbVia["pcb_via_id"]>
allLayers: ReadonlyArray<LayerRef>
_getBoardCalcVariables(): Record<string, number>
_getResolvedMinViaDiameters?(): { holeDiameter: number; padDiameter: number }
pcb_board_id?: string | null
}
7 changes: 3 additions & 4 deletions lib/components/primitive-components/PcbTrace.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { type PcbTraceRoutePoint, pcb_trace_route_point } from "circuit-json"
import { applyToPoint } from "transformation-matrix"
import { z } from "zod"
import { getViaSpanLayers } from "lib/utils/getViaSpanLayers"
import { getViaDiameterDefaults } from "lib/utils/pcbStyle/getViaDiameterDefaults"
import { getViaDiameterDefaultsForComponent } from "lib/utils/pcbStyle/getViaDiameterDefaults"
import { PrimitiveComponent } from "../base-components/PrimitiveComponent"

export const pcbTraceProps = z.object({
Expand Down Expand Up @@ -87,9 +87,8 @@ export class PcbTrace extends PrimitiveComponent<typeof pcbTraceProps> {
})
this.pcb_trace_id = pcb_trace.pcb_trace_id

const { holeDiameter, padDiameter } = getViaDiameterDefaults(
this.getInheritedMergedProperty("pcbStyle"),
)
const { holeDiameter, padDiameter } =
getViaDiameterDefaultsForComponent(this)
for (const [routeIndex, point] of transformedRoute.entries()) {
if (point.route_type !== "via") continue
if (this._materializedRouteViaIndices.has(routeIndex)) continue
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import type { Port } from "../Port"
import type { Trace } from "./Trace"
import { applyToPoint, identity } from "transformation-matrix"
import { clipTraceEndAtPad } from "../../../utils/trace-clipping/clipTraceEndAtPad"
import { getViaDiameterDefaults } from "../../../utils/pcbStyle/getViaDiameterDefaults"
import { getViaDiameterDefaultsForComponent } from "../../../utils/pcbStyle/getViaDiameterDefaults"
import type { ManualPcbPathPoint } from "lib/utils/pcbTraceRouteToPcbPath"
import { TraceConnectionError } from "lib/errors"
import { getPcbSelectorErrorForTracePort } from "./getPcbSelectorErrorForTracePort"
Expand Down Expand Up @@ -188,8 +188,8 @@ export function Trace_doInitialPcbManualTraceRender(trace: Trace) {
subcircuit_id: subcircuit?.subcircuit_id ?? undefined,
pcb_group_id: trace.getGroup()?.pcb_group_id ?? undefined,
})
const pcbStyle = trace.getInheritedMergedProperty("pcbStyle")
const { holeDiameter, padDiameter } = getViaDiameterDefaults(pcbStyle)
const { holeDiameter, padDiameter } =
getViaDiameterDefaultsForComponent(trace)
for (let index = 0; index < transformedRoute.length; index++) {
const point = transformedRoute[index]
if (point.route_type === "via") {
Expand Down Expand Up @@ -485,8 +485,8 @@ export function Trace_doInitialPcbManualTraceRender(trace: Trace) {
const subcircuitConnectivityMapKey =
trace.subcircuit_connectivity_map_key ??
db.source_trace.get(trace.source_trace_id!)?.subcircuit_connectivity_map_key
const pcbStyle = trace.getInheritedMergedProperty("pcbStyle")
const { holeDiameter, padDiameter } = getViaDiameterDefaults(pcbStyle)
const { holeDiameter, padDiameter } =
getViaDiameterDefaultsForComponent(trace)
for (const point of route) {
if (point.route_type === "via") {
const fromLayer = point.from_layer as LayerRef
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ import {
import { getObstaclesFromCircuitJson } from "lib/utils/obstacles/getObstaclesFromCircuitJson"
import { pairs } from "lib/utils/pairs"
import { getRoutePointPosition } from "lib/utils/pcb-trace-route-point-utils"
import { getViaDiameterDefaults } from "lib/utils/pcbStyle/getViaDiameterDefaults"
import { getViaDiameterDefaultsForComponent } from "lib/utils/pcbStyle/getViaDiameterDefaults"
import { reversePcbTraceRoute } from "lib/utils/reverse-pcb-trace-route"
import { tryNow } from "lib/utils/try-now"
import type { Port } from "../Port"
Expand Down Expand Up @@ -510,8 +510,8 @@ export function Trace_doInitialPcbTraceRender(trace: Trace) {
const mergedRoute = mergeRoutes(routes)

const traceLength = getTraceLength(mergedRoute)
const pcbStyle = trace.getInheritedMergedProperty("pcbStyle")
const { holeDiameter, padDiameter } = getViaDiameterDefaults(pcbStyle)
const { holeDiameter, padDiameter } =
getViaDiameterDefaultsForComponent(trace)
const pcb_trace = db.pcb_trace.insert({
route: getCircuitJsonPcbTraceRoute(
mergedRoute as PcbTraceRoutePointWithSrjMetadata[],
Expand Down
6 changes: 3 additions & 3 deletions lib/components/primitive-components/Trace/render-pcb-paths.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import type { PcbPath } from "@tscircuit/props"
import type { LayerRef } from "circuit-json"
import { getViaSpanLayers } from "lib/utils/getViaSpanLayers"
import { getViaDiameterDefaults } from "../../../utils/pcbStyle/getViaDiameterDefaults"
import { getViaDiameterDefaultsForComponent } from "../../../utils/pcbStyle/getViaDiameterDefaults"
import type { Port } from "../Port"
import { getRouteForPcbPath } from "./get-route-for-pcb-path"
import { insertPcbPathViaContactErrors } from "./insert-pcb-path-via-contact-errors"
Expand Down Expand Up @@ -47,8 +47,8 @@ export const renderPcbPaths = ({
return
}

const pcbStyle = trace.getInheritedMergedProperty("pcbStyle")
const { holeDiameter, padDiameter } = getViaDiameterDefaults(pcbStyle)
const { holeDiameter, padDiameter } =
getViaDiameterDefaultsForComponent(trace)
const connectivityMapKey =
trace.subcircuit_connectivity_map_key ??
db.source_trace.get(trace.source_trace_id!)?.subcircuit_connectivity_map_key
Expand Down
33 changes: 10 additions & 23 deletions lib/components/primitive-components/Via.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { type PcbStyle, viaProps } from "@tscircuit/props"
import { viaProps } from "@tscircuit/props"
import type { LayerRef, PcbVia } from "circuit-json"
import { createNetsFromProps } from "lib/utils/components/createNetsFromProps"
import { getViaSpanLayers } from "lib/utils/getViaSpanLayers"
import { getViaDiameterDefaultsWithOverrides } from "lib/utils/pcbStyle/getViaDiameterDefaults"
import { getViaDiameterDefaultsForComponent } from "lib/utils/pcbStyle/getViaDiameterDefaults"
import { getViaTenting } from "lib/utils/getViaTenting"
import { z } from "zod"
import { PrimitiveComponent } from "../base-components/PrimitiveComponent"
Expand Down Expand Up @@ -36,21 +36,15 @@ export class Via extends PrimitiveComponent<typeof viaProps> {
return this._getLayers()
}

private _getResolvedViaDiameters(pcbStyle?: PcbStyle) {
return getViaDiameterDefaultsWithOverrides(
{
holeDiameter: this._parsedProps.holeDiameter,
padDiameter: this._parsedProps.outerDiameter,
},
pcbStyle,
)
private _getResolvedViaDiameters() {
return getViaDiameterDefaultsForComponent(this, {
holeDiameter: this._parsedProps.holeDiameter,
padDiameter: this._parsedProps.outerDiameter,
})
}

getPcbSize(): { width: number; height: number } {
const pcbStyle = this.getInheritedMergedProperty("pcbStyle") as
| PcbStyle
| undefined
const { padDiameter } = this._getResolvedViaDiameters(pcbStyle)
const { padDiameter } = this._getResolvedViaDiameters()
return { width: padDiameter, height: padDiameter }
}

Expand Down Expand Up @@ -158,10 +152,7 @@ export class Via extends PrimitiveComponent<typeof viaProps> {
doInitialPcbComponentRender(): void {
if (this.root?.pcbDisabled) return
const { db } = this.root!
const pcbStyle = this.getInheritedMergedProperty("pcbStyle") as
| PcbStyle
| undefined
const { padDiameter } = this._getResolvedViaDiameters(pcbStyle)
const { padDiameter } = this._getResolvedViaDiameters()
const position = this._getGlobalPcbPositionBeforeLayout()
const subcircuit = this.getSubcircuit()
const pcb_component = db.pcb_component.insert({
Expand Down Expand Up @@ -264,11 +255,7 @@ export class Via extends PrimitiveComponent<typeof viaProps> {
doInitialPcbPrimitiveRender(): void {
if (this.root?.pcbDisabled) return
const { db } = this.root!
const pcbStyle = this.getInheritedMergedProperty("pcbStyle") as
| PcbStyle
| undefined
const { holeDiameter, padDiameter } =
this._getResolvedViaDiameters(pcbStyle)
const { holeDiameter, padDiameter } = this._getResolvedViaDiameters()
const position = this._getGlobalPcbPositionBeforeLayout()
const subcircuit = this.getSubcircuit()
const connectedNetOrTrace = this._getConnectedNetOrTrace()
Expand Down
39 changes: 35 additions & 4 deletions lib/utils/pcbStyle/getViaDiameterDefaults.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import type { PcbStyle } from "@tscircuit/props"
import type { PrimitiveComponent } from "lib/components/base-components/PrimitiveComponent/PrimitiveComponent"

const DEFAULT_VIA_HOLE_DIAMETER = 0.2
const DEFAULT_VIA_PAD_DIAMETER = 0.3
Expand All @@ -13,26 +14,56 @@ const parseDistance = (
return Number.isFinite(parsed) ? parsed : fallback
}

export const getViaDiameterDefaults = (pcbStyle?: PcbStyle) => {
/** Via drill (hole) and copper pad diameters, in mm */
type ViaDiameters = { holeDiameter: number; padDiameter: number }

/**
* Default via size when a via doesn't specify one. A pcbStyle via size wins,
* then the board's resolved via minimums (so hand-placed vias match the vias
* the autorouter creates), then the global defaults.
*/
export const getViaDiameterDefaults = (
pcbStyle?: PcbStyle,
boardMinViaDiameters?: ViaDiameters,
): ViaDiameters => {
return {
holeDiameter: parseDistance(
pcbStyle?.viaHoleDiameter,
DEFAULT_VIA_HOLE_DIAMETER,
boardMinViaDiameters?.holeDiameter ?? DEFAULT_VIA_HOLE_DIAMETER,
),
padDiameter: parseDistance(
pcbStyle?.viaPadDiameter,
DEFAULT_VIA_PAD_DIAMETER,
boardMinViaDiameters?.padDiameter ?? DEFAULT_VIA_PAD_DIAMETER,
),
}
}

export const getViaDiameterDefaultsWithOverrides = (
overrides: { holeDiameter?: number; padDiameter?: number },
pcbStyle?: PcbStyle,
boardMinViaDiameters?: ViaDiameters,
) => {
const defaults = getViaDiameterDefaults(pcbStyle)
const defaults = getViaDiameterDefaults(pcbStyle, boardMinViaDiameters)
return {
holeDiameter: overrides.holeDiameter ?? defaults.holeDiameter,
padDiameter: overrides.padDiameter ?? defaults.padDiameter,
}
}

/**
* Default via size for a via created by `component` (a <via>, a trace's
* pcbPath, a <pcbtrace> route...), using its inherited pcbStyle and the
* minimums of the board it is on.
*/
export const getViaDiameterDefaultsForComponent = (
component: Pick<
PrimitiveComponent,
"getInheritedMergedProperty" | "_getBoard"
>,
overrides: { holeDiameter?: number; padDiameter?: number } = {},
) =>
getViaDiameterDefaultsWithOverrides(
overrides,
component.getInheritedMergedProperty("pcbStyle"),
component._getBoard()?._getResolvedMinViaDiameters?.(),
)
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.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
import { expect, test } from "bun:test"
import type { PcbTraceRoutePoint } from "circuit-json"
import { getTestFixture } from "tests/fixtures/get-test-fixture"

const explicitlySizedRoute = [
{ route_type: "wire", x: 4, y: 0, width: 0.15, layer: "top" },
{
route_type: "via",
x: 6,
y: 0,
from_layer: "top",
to_layer: "bottom",
hole_diameter: 0.45,
outer_diameter: 0.9,
},
{ route_type: "wire", x: 8, y: 0, width: 0.15, layer: "bottom" },
] satisfies PcbTraceRoutePoint[]

test("explicit and pcbStyle via sizes still win over the board's via minimums", async () => {
const { circuit } = getTestFixture()

circuit.add(
<board
width="20mm"
height="10mm"
minViaHoleDiameter={0.3}
minViaPadDiameter={0.6}
routingDisabled
>
<via
pcbX={-6}
pcbY={0}
fromLayer="top"
toLayer="bottom"
holeDiameter="0.4mm"
outerDiameter="0.8mm"
/>
<group pcbStyle={{ viaHoleDiameter: 0.35, viaPadDiameter: 0.7 }}>
<via pcbX={0} pcbY={0} fromLayer="top" toLayer="bottom" />
</group>
<pcbtrace route={explicitlySizedRoute} />
<pcbnotetext
pcbX={0}
pcbY={4}
fontSize={0.4}
text="board minVia 0.3/0.6mm keeps explicit and styled sizes"
/>
<pcbnotetext
pcbX={-6}
pcbY={-1.5}
fontSize={0.4}
text="explicit 0.4/0.8"
/>
<pcbnotetext
pcbX={0}
pcbY={-1.5}
fontSize={0.4}
text="pcbStyle 0.35/0.7"
/>
<pcbnotetext pcbX={6} pcbY={-1.5} fontSize={0.4} text="route 0.45/0.9" />
</board>,
)

await circuit.renderUntilSettled()

expect(
circuit.db.pcb_via
.list()
.map((via) => [via.hole_diameter, via.outer_diameter]),
).toEqual([
[0.4, 0.8],
[0.35, 0.7],
[0.45, 0.9],
])
expect(circuit).toMatchPcbSnapshot(import.meta.path)
})
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import { expect, test } from "bun:test"
import { getTestFixture } from "tests/fixtures/get-test-fixture"

test("a board with only minViaHoleDiameter sizes vias like its pcb_board minimums", async () => {
const { circuit } = getTestFixture()

circuit.add(
<board width="12mm" height="8mm" minViaHoleDiameter={0.3} routingDisabled>
<via pcbX={0} pcbY={0} fromLayer="top" toLayer="bottom" />
<pcbnotetext
pcbX={0}
pcbY={2.5}
fontSize={0.45}
text="minViaHoleDiameter 0.3mm: via 0.3mm drill / 0.45mm pad"
/>
</board>,
)

await circuit.renderUntilSettled()

const board = circuit.db.pcb_board.list()[0]
const [via] = circuit.db.pcb_via.list()
expect([via.hole_diameter, via.outer_diameter]).toEqual([
board.min_via_hole_diameter!,
board.min_via_pad_diameter!,
])
expect(circuit).toMatchPcbSnapshot(import.meta.path)
})
Loading
Loading