-
Notifications
You must be signed in to change notification settings - Fork 8
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #16 from tscircuit/circuit-json-export
circuit json export
- Loading branch information
Showing
7 changed files
with
270 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,90 @@ | ||
import type { Command } from "commander" | ||
import { createCircuitWebWorker } from "@tscircuit/eval-webworker" | ||
import webWorkerBundleUrl from "@tscircuit/eval-webworker/blob-url" | ||
import { getVirtualFileSystemFromDirPath } from "make-vfs" | ||
import path from "node:path" | ||
import fs from "node:fs" | ||
|
||
const ALLOWED_FORMATS = [ | ||
"json", | ||
"circuit-json", | ||
"schematic-svg", | ||
"pcb-svg", | ||
"gerbers", | ||
"readable-netlist", | ||
"gltf", | ||
"specctra-dsn", | ||
] as const | ||
|
||
type Format = (typeof ALLOWED_FORMATS)[number] | ||
|
||
const OUTPUT_EXTENSIONS = { | ||
json: ".circuit.json", | ||
"circuit-json": ".circuit.json", | ||
"schematic-svg": "-schematic.svg", | ||
"pcb-svg": "-pcb.svg", | ||
gerbers: "-gerbers.zip", | ||
"readable-netlist": "-readable.netlist", | ||
gltf: ".gltf", | ||
"specctra-dsn": ".dsn", | ||
} | ||
|
||
export const registerExport = (program: Command) => { | ||
program | ||
.command("export") | ||
.description("Export tscircuit code to various formats") | ||
.argument("<file>", "Path to the snippet file") | ||
.option("-f, --format <format>", "Output format") | ||
.option("-o, --output <path>", "Output file path") | ||
.action(async (file, options) => { | ||
const { format = "circuit-json" } = options | ||
let { output } = options | ||
if (!ALLOWED_FORMATS.includes(format)) { | ||
throw new Error( | ||
`Invalid format: ${format}\nSupported formats: ${ALLOWED_FORMATS.join(",")}`, | ||
) | ||
} | ||
|
||
if (!output) { | ||
output = path.basename(file).replace(/\.[^.]+$/, "") | ||
} | ||
|
||
const worker = await createCircuitWebWorker({ | ||
webWorkerUrl: webWorkerBundleUrl, | ||
}) | ||
|
||
const projectDir = path.dirname(file) | ||
|
||
const relativeComponentPath = path.relative(projectDir, file) | ||
|
||
await worker.executeWithFsMap({ | ||
entrypoint: "entrypoint.tsx", | ||
fsMap: { | ||
...((await getVirtualFileSystemFromDirPath({ | ||
dirPath: projectDir, | ||
contentFormat: "string", | ||
})) as Record<string, string>), | ||
"entrypoint.tsx": ` | ||
import MyCircuit from "./${relativeComponentPath}" | ||
circuit.add(<MyCircuit />) | ||
`, | ||
}, | ||
}) | ||
|
||
await worker.renderUntilSettled() | ||
|
||
const circuitJson = await worker.getCircuitJson() | ||
|
||
const outputPath = path.join( | ||
projectDir, | ||
`${output}${OUTPUT_EXTENSIONS[format as Format]}`, | ||
) | ||
|
||
fs.writeFileSync(outputPath, JSON.stringify(circuitJson)) | ||
|
||
console.log(`Exported to ${outputPath}`) | ||
|
||
process.exit(0) | ||
}) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
File renamed without changes.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,174 @@ | ||
import { useHS91L02W2C01 } from "@tsci/seveibar.HS91L02W2C01" | ||
import manualEdits from "./manual-edits.json" | ||
import { WS2812B_2020 as LedWithIc } from "@tsci/seveibar.WS2812B_2020" | ||
import { usePICO_W } from "@tsci/seveibar.PICO_W" | ||
|
||
type Point = { x: number; y: number } | ||
|
||
type GridCellPositions = { | ||
index: number | ||
center: Point | ||
topLeft: Point | ||
bottomRight: Point | ||
} | ||
|
||
type GridOptions = { | ||
rows: number | ||
cols: number | ||
xSpacing?: number | ||
ySpacing?: number | ||
width?: number | ||
height?: number | ||
offsetX?: number | ||
offsetY?: number | ||
yDirection?: "cartesian" | "up-is-negative" | ||
} | ||
|
||
// ToDO import from tscircuit utils in the future | ||
function grid({ | ||
rows, | ||
cols, | ||
xSpacing, | ||
ySpacing, | ||
width, | ||
height, | ||
offsetX = 0, | ||
offsetY = 0, | ||
yDirection = "cartesian", | ||
}: GridOptions): GridCellPositions[] { | ||
// Calculate cell dimensions | ||
const cellWidth = width ? width / cols : (xSpacing ?? 1) | ||
const cellHeight = height ? height / rows : (ySpacing ?? 1) | ||
|
||
const cells: GridCellPositions[] = [] | ||
|
||
for (let row = 0; row < rows; row++) { | ||
for (let col = 0; col < cols; col++) { | ||
const index = row * cols + col | ||
|
||
// Calculate center position | ||
const centerX = offsetX + col * cellWidth + cellWidth / 2 | ||
const rawCenterY = offsetY + row * cellHeight + cellHeight / 2 | ||
|
||
// Adjust Y coordinate based on yDirection | ||
const centerY = | ||
yDirection === "cartesian" | ||
? offsetY + (rows - 1 - row) * cellHeight + cellHeight / 2 | ||
: rawCenterY | ||
|
||
cells.push({ | ||
row, | ||
col, | ||
index, | ||
center: { x: centerX, y: centerY }, | ||
topLeft: { | ||
x: centerX - cellWidth / 2, | ||
y: centerY + cellHeight / 2, | ||
}, | ||
bottomRight: { | ||
x: centerX + cellWidth / 2, | ||
y: centerY - cellHeight / 2, | ||
}, | ||
}) | ||
} | ||
} | ||
|
||
return cells | ||
} | ||
|
||
export default () => { | ||
const U1 = usePICO_W("U1") | ||
const U2 = useHS91L02W2C01("U2") | ||
return ( | ||
<board | ||
width="316mm" | ||
height="52mm" | ||
manualEdits={manualEdits} | ||
routingDisabled | ||
> | ||
<U1 pcbRotation="90deg" pcbX={-122 - 15} pcbY={0} /> | ||
<U2 | ||
GND="net.GND" | ||
VCC={"net.V5"} | ||
SDA={U1.GP26_ADC0_I2C1SDA} | ||
SCL={U1.GP27_ADC1_I2C1SCL} | ||
schX={-7} | ||
schY={0} | ||
pcbX={-122 + 5} | ||
pcbY={19} | ||
/> | ||
{grid({ | ||
cols: 53, | ||
rows: 7, | ||
xSpacing: 5, | ||
ySpacing: 5, | ||
offsetX: 3 - 122, | ||
offsetY: -32 / 2 - 7.5, | ||
}).map(({ center, index, row, col }) => { | ||
const ledName = `LED${index + 1}` | ||
const prevLedName = index > 0 ? `LED${index}` : null | ||
const capName = `C_${ledName}` | ||
const ledSchX = ((center.x / 2) * 8) / 5 + 2 + 101 | ||
const ledSchY = 5 + center.y / 1.5 | ||
return ( | ||
<> | ||
<LedWithIc | ||
schX={ledSchX} | ||
schY={ledSchY} | ||
name={ledName} | ||
pcbX={center.x} | ||
pcbY={center.y} | ||
/> | ||
<trace from={`.${ledName} .GND`} to="net.GND" /> | ||
<trace from={`.${ledName} .VDD`} to="net.V5" /> | ||
{prevLedName && ( | ||
<trace from={`.${prevLedName} .DO`} to={`.${ledName} .DI`} /> | ||
)} | ||
<capacitor | ||
name={capName} | ||
footprint="0402" | ||
capacitance="100nF" | ||
pcbX={center.x} | ||
pcbY={center.y - 2.2} | ||
pcbRotation="180deg" | ||
schX={ledSchX} | ||
schY={ledSchY - 1.1} | ||
schRotation="180deg" | ||
/> | ||
<trace from={`.${capName} .neg`} to="net.GND" /> | ||
<trace from={`.${capName} .pos`} to="net.V5" /> | ||
</> | ||
) | ||
})} | ||
|
||
<capacitor | ||
name="C1" | ||
capacitance="100uF" | ||
footprint="1206" | ||
schX={5} | ||
pcbX={-122} | ||
pcbRotation="90deg" | ||
schRotation="270deg" | ||
/> | ||
<trace from=".C1 .neg" to="net.GND" /> | ||
<trace from=".C1 .pos" to="net.V5" /> | ||
|
||
<trace from=".LED1 .DI" to={U1.GP11_SPI1TX_I2C1SCL} /> | ||
<trace from={U1.GND1} to="net.GND" /> | ||
<trace from={U1.GND2} to="net.GND" /> | ||
<trace from={U1.GND3} to="net.GND" /> | ||
<trace from={U1.GND4} to="net.GND" /> | ||
<trace from={U1.GND5} to="net.GND" /> | ||
<trace from={U1.GND6} to="net.GND" /> | ||
<trace from={U1.GND7} to="net.GND" /> | ||
|
||
<trace from={U1.VBUS} to="net.V5" /> | ||
<footprint> | ||
<hole pcbX={-32 - 122} pcbY={20} diameter="4.8mm" /> | ||
<hole pcbX={-32 - 122} pcbY={-20} diameter="4.8mm" /> | ||
<hole pcbX={32 + 122} pcbY={20} diameter="4.8mm" /> | ||
<hole pcbX={32 + 122} pcbY={-20} diameter="4.8mm" /> | ||
</footprint> | ||
</board> | ||
) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters