Skip to content
Open
Show file tree
Hide file tree
Changes from 3 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
1 change: 1 addition & 0 deletions index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,5 @@ export { checkSourceTracesHavePcbTraces } from "./lib/check-source-traces-have-p
export { checkPcbTracesOutOfBoard } from "./lib/check-trace-out-of-board/checkTraceOutOfBoard"
export { checkPcbComponentOverlap } from "./lib/check-pcb-components-overlap/checkPcbComponentOverlap"
export { checkPinMustBeConnected } from "./lib/check-pin-must-be-connected"
export { checkInvalidPinConnections } from "./lib/check-invalid-pin-connections"
export { runAllChecks } from "./lib/run-all-checks"
58 changes: 58 additions & 0 deletions lib/check-invalid-pin-connections.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import type { AnyCircuitElement } from "circuit-json"
import { getSourcePortConnectivityMapFromCircuitJson } from "circuit-json-to-connectivity-map"

export type InvalidPinConnectionError = {
type: "invalid_pin_connection_error"
invalid_pin_connection_error_id: string
error_type: "invalid_pin_connection_error"
message: string
source_port_ids: string[]
}

export function checkInvalidPinConnections(
circuitJson: AnyCircuitElement[],
): InvalidPinConnectionError[] {
const errors: InvalidPinConnectionError[] = []

// Get all source ports to easily look up their attributes
const sourcePorts = circuitJson.filter(
(el): el is Extract<AnyCircuitElement, { type: "source_port" }> =>
el.type === "source_port",
)
const portMap = new Map(sourcePorts.map((p) => [p.source_port_id, p]))

const connMap = getSourcePortConnectivityMapFromCircuitJson(circuitJson)

for (const [netId, connectedPortIds] of Object.entries(connMap.netMap)) {
let hasSda = false
let hasScl = false

const conflictingPortIds: string[] = []

for (const portId of connectedPortIds) {
const port = portMap.get(portId)
if (!port) continue

if (port.is_configured_for_i2c_sda) {
hasSda = true
conflictingPortIds.push(portId)
}
if (port.is_configured_for_i2c_scl) {
hasScl = true
conflictingPortIds.push(portId)
}
}

if (hasSda && hasScl) {
errors.push({
type: "invalid_pin_connection_error",
invalid_pin_connection_error_id: `invalid_pin_connection_error_${netId}`,
error_type: "invalid_pin_connection_error",
message: "I2C SDA and SCL pins are connected together",
source_port_ids: conflictingPortIds,
})
}
}

return errors
}
2 changes: 2 additions & 0 deletions lib/run-all-checks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { checkSourceTracesHavePcbTraces } from "./check-source-traces-have-pcb-t
import { checkPcbTracesOutOfBoard } from "./check-trace-out-of-board/checkTraceOutOfBoard"
import { checkPcbComponentOverlap } from "./check-pcb-components-overlap/checkPcbComponentOverlap"
import { checkPinMustBeConnected } from "./check-pin-must-be-connected"
import { checkInvalidPinConnections } from "./check-invalid-pin-connections"
import type { AnyCircuitElement } from "circuit-json"

export async function runAllChecks(circuitJson: AnyCircuitElement[]) {
Expand All @@ -24,5 +25,6 @@ export async function runAllChecks(circuitJson: AnyCircuitElement[]) {
...checkPcbTracesOutOfBoard(circuitJson),
...checkPcbComponentOverlap(circuitJson),
...checkPinMustBeConnected(circuitJson),
...checkInvalidPinConnections(circuitJson),
]
}
10 changes: 5 additions & 5 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,18 +19,18 @@
"@types/bun": "^1.2.8",
"@types/debug": "^4.1.12",
"bun-match-svg": "^0.0.11",
"circuit-json": "^0.0.386",
"circuit-to-svg": "^0.0.166",
"circuit-json": "^0.0.380",
"debug": "^4.3.5",
"tscircuit": "^0.0.525",
"zod": "^3.23.8",
"tsup": "^8.2.3"
"tsup": "^8.2.3",
"zod": "^3.23.8"
},
"peerDependencies": {
"@flatten-js/core": "*",
"circuit-json": "*",
"@tscircuit/math-utils": "*",
"circuit-json-to-connectivity-map": "*",
"@flatten-js/core": "*",
"typescript": "^5.5.3"
}
}
}
58 changes: 58 additions & 0 deletions tests/lib/check-invalid-pin-connections.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import { expect, test } from "bun:test"
import { checkInvalidPinConnections } from "../../lib/check-invalid-pin-connections"
import type { AnyCircuitElement } from "circuit-json"

test("checkInvalidPinConnections detects SDA connected to SCL", () => {
const circuitJson: AnyCircuitElement[] = [
{
type: "source_port",
source_port_id: "port_sda",
name: "SDA",
is_configured_for_i2c_sda: true,
},
{
type: "source_port",
source_port_id: "port_scl",
name: "SCL",
is_configured_for_i2c_scl: true,
},
{
type: "source_trace",
source_trace_id: "trace_1",
connected_source_port_ids: ["port_sda", "port_scl"],
connected_source_net_ids: [],
},
] as AnyCircuitElement[]

const errors = checkInvalidPinConnections(circuitJson)
expect(errors).toHaveLength(1)
expect(errors[0].message).toBe("I2C SDA and SCL pins are connected together")
expect(errors[0].source_port_ids).toContain("port_sda")
expect(errors[0].source_port_ids).toContain("port_scl")
})

test("checkInvalidPinConnections allows SDA connected to SDA", () => {
const circuitJson: AnyCircuitElement[] = [
{
type: "source_port",
source_port_id: "port_sda1",
name: "SDA1",
is_configured_for_i2c_sda: true,
},
{
type: "source_port",
source_port_id: "port_sda2",
name: "SDA2",
is_configured_for_i2c_sda: true,
},
{
type: "source_trace",
source_trace_id: "trace_1",
connected_source_port_ids: ["port_sda1", "port_sda2"],
connected_source_net_ids: [],
},
] as AnyCircuitElement[]

const errors = checkInvalidPinConnections(circuitJson)
expect(errors).toHaveLength(0)
})