Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remove Y Axis Flip in DSN PCB Conversion, Merge Dsn Session into Dsn PCB, Minor Refactoring, Lots of Debug statements, Include vias in DSN stringification, Improve Circuit Json to DSN PCB conversion for traces/vias #68

Merged
merged 13 commits into from
Dec 16, 2024
Merged
Original file line number Diff line number Diff line change
Expand Up @@ -8,17 +8,11 @@ export function convertCircuitJsonToDsnSession(
dsnPcb: DsnPcb,
circuitJson: AnyCircuitElement[],
): DsnSession {
// First convert to DSN PCB to reuse component/pad processing
// const dsnPcb = convertCircuitJsonToDsnJson(circuitJson)

// console.dir(dsnPcb, { depth: null })

const pcb_traces = su(circuitJson as any).pcb_trace.list()
const source_traces = su(circuitJson as any).source_trace.list()
const source_ports = su(circuitJson as any).source_port.list()
const nets = su(circuitJson as any).source_net.list()

// Only applies to the traces (components are not getting affected)
const transformMmToSesUnit = scale(10000)
const session: DsnSession = {
is_dsn_session: true,
Expand All @@ -31,54 +25,54 @@ export function convertCircuitJsonToDsnSession(
resolution: dsnPcb.resolution,
parser: dsnPcb.parser,
library_out: {
// TODO Just add vias here
padstacks: [],
},
network_out: {
nets: dsnPcb.network.nets
.map((net) => {
const source_net = nets.find((n) => n.name === net.name)
if (!source_net) return null
const pcb_traces_for_net = pcb_traces.filter((pcb_trace) => {
const source_trace = source_traces.find(
(st) => st.source_trace_id === pcb_trace.source_trace_id,
)
nets: pcb_traces.map((trace) => {
const source_trace = source_traces.find(
(st) => st.source_trace_id === trace.source_trace_id,
)
const source_net =
source_trace &&
nets.find((n) =>
source_trace.connected_source_net_ids.includes(n.source_net_id),
)
const net_name = source_net?.name || trace.source_trace_id

// TODO only supports single layer traces
const traceLayer =
"layer" in trace.route[0] && trace.route[0].layer === "bottom"
? "bottom"
: "top"

return source_trace?.connected_source_net_ids.includes(
source_net.source_net_id,
)
})
const traceWidth =
"width" in trace.route[0] ? trace.route[0].width : 0.16

return {
name: net.name,
wires: pcb_traces_for_net.flatMap((trace): Wire => {
// TODO whenever the pcb trace changes layers or changes width,
// we have to create a new wire
return {
path: {
layer: "F.Cu",
width: 0.1, // TODO get width
coordinates: trace.route
.filter(
(rp): rp is PcbTraceRoutePointWire =>
rp.route_type === "wire",
)
.map((rp) =>
// Circuit JSON space to the SES space
applyToPoint(transformMmToSesUnit, {
x: rp.x,
y: rp.y,
}),
)
.flatMap((trp) => [trp.x, trp.y]),
},
}
}),
}
})
.filter((net): net is { name: string; wires: Wire[] } =>
Boolean(net),
),
return {
name: net_name!,
wires: [
{
path: {
layer: traceLayer === "bottom" ? "B.Cu" : "F.Cu",
width: traceWidth * 1000,
coordinates: trace.route
.filter(
(rp): rp is PcbTraceRoutePointWire =>
rp.route_type === "wire",
)
.map((rp) =>
// Circuit JSON space to the SES space
applyToPoint(transformMmToSesUnit, {
x: rp.x,
y: rp.y,
}),
)
.flatMap((trp) => [trp.x, trp.y]),
},
},
],
}
}),
},
},
}
Expand Down
41 changes: 0 additions & 41 deletions lib/dsn-pcb/circuit-json-to-dsn-json/process-pcb-traces.ts

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import type { DsnPcb, Padstack } from "lib/dsn-pcb/types"

export function findOrCreateViaPadstack(
pcb: DsnPcb,
outerDiameter: number,
holeDiameter: number,
): string {
const viaName = `Via[0-1]_${outerDiameter}:${holeDiameter}_um`

// Check if padstack already exists
const existingPadstack = pcb.library.padstacks.find((p) => p.name === viaName)

if (existingPadstack) {
return viaName
}

// Create new padstack for via
const viaPadstack: Padstack = {
name: viaName,
attach: "off",
shapes: [
{
shapeType: "circle",
layer: "F.Cu",
diameter: outerDiameter,
},
{
shapeType: "circle",
layer: "B.Cu",
diameter: outerDiameter,
},
],
hole: {
shape: "circle",
diameter: holeDiameter,
},
}

pcb.library.padstacks.push(viaPadstack)
return viaName
}
155 changes: 155 additions & 0 deletions lib/dsn-pcb/circuit-json-to-dsn-json/process-pcb-traces/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,155 @@
import type {
AnyCircuitElement,
LayerRef,
PcbTrace,
PcbTraceRoutePoint,
} from "circuit-json"
import type { DsnPcb, DsnSession } from "../../types"
import Debug from "debug"
import { findOrCreateViaPadstack } from "./findOrCreateViaPadstack"

const debug = Debug("dsn-converter:process-pcb-traces")

const DEFAULT_VIA_DIAMETER = 600 // μm
const DEFAULT_VIA_HOLE = 300 // μm

interface Wire {
path: {
layer: string
width: number
coordinates: number[]
}
net: string
type: string
}

function createWire(opts: {
layer: LayerRef
widthMm: number
netName: string
}): Wire {
return {
path: {
layer: opts.layer === "top" ? "F.Cu" : "B.Cu",
width: opts.widthMm * 1000,
coordinates: [],
},
net: opts.netName,
type: "route",
}
}

export function processPcbTraces(
circuitElements: AnyCircuitElement[],
pcb: DsnPcb,
) {
for (const element of circuitElements) {
if (element.type === "pcb_trace") {
const pcbTrace = element
debug("PCB TRACE\n----------\n", pcbTrace)
const netName =
pcbTrace.source_trace_id || `Net-${pcb.network.nets.length + 1}`

let currentLayer = ""
let currentWire: Wire | null = null

// Process each point in the route
for (let i = 0; i < pcbTrace.route.length; i++) {
const point = pcbTrace.route[i] as PcbTraceRoutePoint
debug("POINT\n------\n", point)

if (point.route_type === "wire") {
// If layer changed or this is the first point, start a new wire
const hasLayerChanged = currentLayer && point.layer !== currentLayer
const isFirstPoint = !currentWire

if (isFirstPoint) {
// Start new wire on new layer
currentWire = createWire({
layer: point.layer,
widthMm: point.width,
netName,
})

pcb.wiring.wires.push(currentWire)
currentLayer = point.layer
}

if (currentWire && !hasLayerChanged) {
// Add coordinates to current wire
currentWire.path.coordinates.push(point.x * 1000)
currentWire.path.coordinates.push(point.y * 1000)
continue
}

if (hasLayerChanged) {
const prevPoint = pcbTrace.route[i - 1]
const viaPadstackName = findOrCreateViaPadstack(
pcb,
DEFAULT_VIA_DIAMETER,
DEFAULT_VIA_HOLE,
)

// Add via reference to structure if not already there
if (!pcb.structure.via) {
pcb.structure.via = viaPadstackName
}

// Create wire segment for via placement
pcb.wiring.wires.push({
path: {
layer: currentLayer === "top" ? "F.Cu" : "B.Cu",
width: DEFAULT_VIA_DIAMETER,
coordinates: [prevPoint.x * 1000, prevPoint.y * 1000],
},
net: netName,
type: "via",
})
}
continue
}

if (point.route_type === "via") {
debug("VIA\n----\n", point)

// End current wire
if (currentWire) {
currentWire.path.coordinates.push(point.x * 1000)
currentWire.path.coordinates.push(point.y * 1000)
currentWire = null
}

// Handle explicit via points
const viaPadstackName = findOrCreateViaPadstack(
pcb,
DEFAULT_VIA_DIAMETER,
DEFAULT_VIA_HOLE,
)

debug("VIA PADSTACK NAME:", viaPadstackName)

// Add via reference to structure if not already there
if (!pcb.structure.via) {
pcb.structure.via = viaPadstackName
}

// Create wire segment for via placement
pcb.wiring.wires.push({
path: {
layer: point.from_layer === "top" ? "F.Cu" : "B.Cu",
width: DEFAULT_VIA_DIAMETER,
coordinates: [point.x * 1000, point.y * 1000],
},
net: netName,
type: "via",
})
debug("WIRING", pcb.wiring)

currentLayer = point.to_layer
currentWire = null // Start fresh wire after via
}
}
}
}
debug("PCB WIRING AT END", pcb.wiring)
}
6 changes: 5 additions & 1 deletion lib/dsn-pcb/circuit-json-to-dsn-json/stringify-dsn-json.ts
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,11 @@ export const stringifyDsnJson = (dsnJson: DsnPcb): string => {
// Wiring section
result += `${indent}(wiring\n`
;(dsnJson.wiring?.wires ?? []).forEach((wire) => {
result += `${indent}${indent}(wire ${stringifyPath(wire.path, 3)}(net ${stringifyValue(wire.net)})(type ${wire.type}))\n`
if (wire.type === "via") {
result += `${indent}${indent}(via ${stringifyPath(wire.path, 3)}(net ${stringifyValue(wire.net)}))\n`
} else {
result += `${indent}${indent}(wire ${stringifyPath(wire.path, 3)}(net ${stringifyValue(wire.net)})(type ${wire.type}))\n`
}
})
result += `${indent})\n`

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { fromTriangles, scale, applyToPoint } from "transformation-matrix"
import type { AnyCircuitElement, PcbBoard } from "circuit-json"
import type { DsnPcb, DsnSession } from "../types"
import { convertPadstacksToSmtPads } from "./dsn-component-converters/convert-padstacks-to-smtpads"
import { convertWiresToPcbTraces } from "./dsn-component-converters/convert-wire-to-trace"
import { convertWiresToPcbTraces } from "./dsn-component-converters/convert-wires-to-traces"
import { pairs } from "lib/utils/pairs"
import { convertDsnPcbToCircuitJson } from "./convert-dsn-pcb-to-circuit-json"
import { convertDsnSessionToCircuitJson } from "./convert-dsn-session-to-circuit-json"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { fromTriangles, scale, applyToPoint } from "transformation-matrix"
import type { AnyCircuitElement, PcbBoard } from "circuit-json"
import type { DsnPcb } from "../types"
import { convertPadstacksToSmtPads } from "./dsn-component-converters/convert-padstacks-to-smtpads"
import { convertWiresToPcbTraces } from "./dsn-component-converters/convert-wire-to-trace"
import { convertWiresToPcbTraces } from "./dsn-component-converters/convert-wires-to-traces"
import { pairs } from "lib/utils/pairs"
import { convertNetsToSourceNetsAndTraces } from "./dsn-component-converters/convert-nets-to-source-nets-and-traces"
import { convertDsnPcbComponentsToSourceComponentsAndPorts } from "./dsn-component-converters/convert-dsn-pcb-components-to-source-components-and-ports"
Expand Down
Loading
Loading