Skip to content

Commit

Permalink
Merge pull request #24 from tscircuit/dsn-session-generation
Browse files Browse the repository at this point in the history
Circuit json to dsn session conversion, DsnPcb to source_port, source_component, source_net etc.
  • Loading branch information
seveibar authored Nov 18, 2024
2 parents 7d8fc38 + 5ce670b commit 5049d5a
Show file tree
Hide file tree
Showing 15 changed files with 480 additions and 35 deletions.
151 changes: 151 additions & 0 deletions docs/CIRCUIT_JSON_SOURCE_COMPONENT_OVERVIEW.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@
# Circuit JSON Specification: Source Component Overview

> Created at 2024-11-12T19:07:05.930Z
> Latest Version: https://github.com/tscircuit/circuit-json/blob/main/docs/SOURCE_COMPONENT_OVERVIEW.md
Any type below can be imported from `circuit-json`. Every type has a corresponding
snake_case version which is a zod type that can be used to parse unknown json,
for example `SourceComponent` has a `source_component.parse` function that you
can also import.

```ts
interface SourceSimpleChip {
type: "source_component"
ftype: "simple_chip"
source_component_id: string
name: string
manufacturer_part_number?: string
supplier_part_numbers?: Partial<Record<string, string[]>>
display_value?: string
}

interface SourceSimpleInductor {
type: "source_component"
ftype: "simple_inductor"
source_component_id: string
name: string
manufacturer_part_number?: string
supplier_part_numbers?: Partial<Record<string, string[]>>
display_value?: string
inductance: number
}

interface SourceLed {
type: "source_component"
ftype: "led"
source_component_id: string
name: string
manufacturer_part_number?: string
supplier_part_numbers?: Partial<Record<string, string[]>>
display_value?: string
}

interface SourceTrace {
type: "source_trace"
source_trace_id: string
connected_source_port_ids: string[]
connected_source_net_ids: string[]
subcircuit_connectivity_map_key?: string
}

interface SourceSimpleGround {
type: "source_component"
ftype: "simple_ground"
source_component_id: string
name: string
manufacturer_part_number?: string
supplier_part_numbers?: Partial<Record<string, string[]>>
display_value?: string
}

interface SourceSimpleResistor {
type: "source_component"
ftype: "simple_resistor"
source_component_id: string
name: string
manufacturer_part_number?: string
supplier_part_numbers?: Partial<Record<string, string[]>>
display_value?: string
resistance: number
}

interface SourceSimpleBattery {
type: "source_component"
ftype: "simple_battery"
source_component_id: string
name: string
manufacturer_part_number?: string
supplier_part_numbers?: Partial<Record<string, string[]>>
display_value?: string
capacity: number
}

interface SourceNet {
type: "source_net"
source_net_id: string
name: string
member_source_group_ids: string[]
is_power?: boolean
is_ground?: boolean
is_digital_signal?: boolean
is_analog_signal?: boolean
trace_width?: number
}

interface SourceSimpleDiode {
type: "source_component"
ftype: "simple_diode"
source_component_id: string
name: string
manufacturer_part_number?: string
supplier_part_numbers?: Partial<Record<string, string[]>>
display_value?: string
}

interface SourceGroup {
type: "source_group"
source_group_id: string
name?: string
}

interface SourcePort {
type: "source_port"
pin_number?: number
port_hints?: string[]
name: string
source_port_id: string
source_component_id: string
}

interface SourceSimplePowerSource {
type: "source_component"
ftype: "simple_power_source"
source_component_id: string
name: string
manufacturer_part_number?: string
supplier_part_numbers?: Partial<Record<string, string[]>>
display_value?: string
voltage: number
}

interface SourceSimpleCapacitor {
type: "source_component"
ftype: "simple_capacitor"
source_component_id: string
name: string
manufacturer_part_number?: string
supplier_part_numbers?: Partial<Record<string, string[]>>
display_value?: string
capacitance: number
}

interface SourceComponentBase {
type: "source_component"
ftype?: string
source_component_id: string
name: string
manufacturer_part_number?: string
supplier_part_numbers?: Partial<Record<string, string[]>>
display_value?: string
}
```
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
import type { AnyCircuitElement, PcbTraceRoutePointWire } from "circuit-json"
import type { DsnPcb, DsnSession, Wire } from "../types"
import { su } from "@tscircuit/soup-util"
import { convertCircuitJsonToDsnJson } from "./convert-circuit-json-to-dsn-json"
import { applyToPoint, scale } from "transformation-matrix"

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()

const transformMmToDsnUnit = scale(1000)
const session: DsnSession = {
is_dsn_session: true,
filename: dsnPcb.filename || "session",
placement: {
resolution: dsnPcb.resolution,
components: dsnPcb.placement.components,
},
routes: {
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,
)

return source_trace?.connected_source_net_ids.includes(
source_net.source_net_id,
)
})

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) =>
applyToPoint(transformMmToDsnUnit, {
x: rp.x,
y: rp.y,
}),
)
.flatMap((trp) => [trp.x, trp.y]),
},
}
}),
}
})
.filter((net): net is { name: string; wires: Wire[] } =>
Boolean(net),
),
},
},
}

return session
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,15 @@ import { fromTriangles, scale, applyToPoint } from "transformation-matrix"

import type { AnyCircuitElement, PcbBoard } from "circuit-json"
import type { DsnPcb, DsnSession } from "../types"
import { convertPadstacksToSmtPads } from "./convert-padstacks-to-smtpads"
import { convertWiresToPcbTraces } from "./convert-wire-to-trace"
import { convertPadstacksToSmtPads } from "./dsn-component-converters/convert-padstacks-to-smtpads"
import { convertWiresToPcbTraces } from "./dsn-component-converters/convert-wire-to-trace"
import { pairs } from "lib/utils/pairs"
import { convertDsnPcbToCircuitJson } from "./convert-dsn-pcb-to-circuit-json"
import { convertDsnSessionToCircuitJson } from "./convert-dsn-session-to-circuit-json"

/**
* @deprecated use convertDsnPcbToCircuitJson instead
*/
export function convertDsnJsonToCircuitJson(
dsnPcb: DsnPcb,
): AnyCircuitElement[] {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,20 @@ import { fromTriangles, scale, applyToPoint } from "transformation-matrix"

import type { AnyCircuitElement, PcbBoard } from "circuit-json"
import type { DsnPcb } from "../types"
import { convertPadstacksToSmtPads } from "./convert-padstacks-to-smtpads"
import { convertWiresToPcbTraces } from "./convert-wire-to-trace"
import { convertPadstacksToSmtPads } from "./dsn-component-converters/convert-padstacks-to-smtpads"
import { convertWiresToPcbTraces } from "./dsn-component-converters/convert-wire-to-trace"
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"
import { su } from "@tscircuit/soup-util"

export function convertDsnPcbToCircuitJson(
dsnPcb: DsnPcb,
): AnyCircuitElement[] {
const elements: AnyCircuitElement[] = []

// TODO use pcb.resolution.unit and pcb.resolution.value
const transformUmToMm = scale(1 / 1000)
const transformDsnUnitToMm = scale(1 / 1000)

// Add the board
// You must use the dsnPcb.boundary to get the center, width and height
Expand All @@ -31,12 +34,12 @@ export function convertDsnPcbToCircuitJson(
const minX = Math.min(...boundaryPath.map(([x]) => x))
const maxY = Math.max(...boundaryPath.map(([, y]) => y))
const minY = Math.min(...boundaryPath.map(([, y]) => y))
board.center = applyToPoint(transformUmToMm, {
board.center = applyToPoint(transformDsnUnitToMm, {
x: (maxX + minX) / 2,
y: (maxY + minY) / 2,
})
board.width = (maxX - minX) * transformUmToMm.a
board.height = (maxY - minY) * transformUmToMm.a
board.width = (maxX - minX) * transformDsnUnitToMm.a
board.height = (maxY - minY) * transformDsnUnitToMm.a
} else {
throw new Error(
`Couldn't read DSN boundary, add support for dsnPcb.structure.boundary["${Object.keys(dsnPcb.structure.boundary).join(",")}"]`,
Expand All @@ -46,18 +49,31 @@ export function convertDsnPcbToCircuitJson(
elements.push(board)

// Convert padstacks to SMT pads using the transformation matrix
elements.push(...convertPadstacksToSmtPads(dsnPcb, transformUmToMm))
elements.push(...convertPadstacksToSmtPads(dsnPcb, transformDsnUnitToMm))

// Convert wires to PCB traces using the transformation matrix
if (dsnPcb.wiring && dsnPcb.network) {
elements.push(
...convertWiresToPcbTraces(
dsnPcb.wiring,
dsnPcb.network,
transformUmToMm,
transformDsnUnitToMm,
),
)
}

elements.push(
...convertDsnPcbComponentsToSourceComponentsAndPorts({
dsnPcb,
transformDsnUnitToMm,
}),
)
elements.push(
...convertNetsToSourceNetsAndTraces({
dsnPcb,
source_ports: su(elements as any).source_port.list(),
}),
)

return elements
}
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { scale, applyToPoint } from "transformation-matrix"
import type { AnyCircuitElement, PcbBoard } from "circuit-json"
import type { DsnJson, DsnPcb, DsnSession } from "../types"
import { convertWiresToPcbTraces } from "./convert-wire-to-trace"
import { convertWiresToPcbTraces } from "./dsn-component-converters/convert-wire-to-trace"
import Debug from "debug"
import { convertDsnPcbToCircuitJson } from "./convert-dsn-pcb-to-circuit-json"
import { convertWiringPathToPcbTraces } from "./convert-wiring-path-to-pcb-traces"
import { convertWiringPathToPcbTraces } from "./dsn-component-converters/convert-wiring-path-to-pcb-traces"

const debug = Debug("dsn-converter")

Expand Down
Loading

0 comments on commit 5049d5a

Please sign in to comment.