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

Circuit json to dsn session conversion, DsnPcb to source_port, source_component, source_net etc. #24

Merged
merged 8 commits into from
Nov 18, 2024
Merged
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
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
Loading