@tscircuit/cli 0.1.1150 → 0.1.1151
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli/main.js +294 -167
- package/dist/lib/index.js +2 -2
- package/package.json +2 -2
package/dist/cli/main.js
CHANGED
|
@@ -98175,7 +98175,7 @@ var import_perfect_cli = __toESM2(require_dist2(), 1);
|
|
|
98175
98175
|
// lib/getVersion.ts
|
|
98176
98176
|
import { createRequire as createRequire2 } from "node:module";
|
|
98177
98177
|
// package.json
|
|
98178
|
-
var version = "0.1.
|
|
98178
|
+
var version = "0.1.1150";
|
|
98179
98179
|
var package_default = {
|
|
98180
98180
|
name: "@tscircuit/cli",
|
|
98181
98181
|
version,
|
|
@@ -98217,7 +98217,7 @@ var package_default = {
|
|
|
98217
98217
|
cosmiconfig: "^9.0.0",
|
|
98218
98218
|
debug: "^4.4.0",
|
|
98219
98219
|
delay: "^6.0.0",
|
|
98220
|
-
"dsn-converter": "
|
|
98220
|
+
"dsn-converter": "0.0.86",
|
|
98221
98221
|
easyeda: "^0.0.252",
|
|
98222
98222
|
"fuse.js": "^7.1.0",
|
|
98223
98223
|
"get-port": "^7.1.0",
|
|
@@ -242126,33 +242126,31 @@ import {
|
|
|
242126
242126
|
} from "circuit-to-svg";
|
|
242127
242127
|
|
|
242128
242128
|
// node_modules/dsn-converter/dist/index.js
|
|
242129
|
-
import { applyToPoint as applyToPoint21, scale as scale6 } from "transformation-matrix";
|
|
242130
242129
|
import { su as su7 } from "@tscircuit/soup-util";
|
|
242130
|
+
import { applyToPoint as applyToPoint21, scale as scale6 } from "transformation-matrix";
|
|
242131
242131
|
import { su as su23 } from "@tscircuit/soup-util";
|
|
242132
242132
|
import Debug4 from "debug";
|
|
242133
242133
|
import { su as su33 } from "@tscircuit/soup-util";
|
|
242134
242134
|
import { applyToPoint as applyToPoint22, scale as scale22 } from "transformation-matrix";
|
|
242135
242135
|
import { su as su42 } from "@tscircuit/soup-util";
|
|
242136
242136
|
import Debug22 from "debug";
|
|
242137
|
-
import {
|
|
242138
|
-
import {
|
|
242139
|
-
import { scale as scale42, applyToPoint as applyToPoint102 } from "transformation-matrix";
|
|
242140
|
-
import { applyToPoint as applyToPoint42 } from "transformation-matrix";
|
|
242137
|
+
import { scale as scale32, applyToPoint as applyToPoint92 } from "transformation-matrix";
|
|
242138
|
+
import { applyToPoint as applyToPoint32 } from "transformation-matrix";
|
|
242141
242139
|
import Debug32 from "debug";
|
|
242142
242140
|
import"transformation-matrix";
|
|
242141
|
+
import { applyToPoint as applyToPoint42 } from "transformation-matrix";
|
|
242143
242142
|
import { applyToPoint as applyToPoint52 } from "transformation-matrix";
|
|
242144
|
-
import { applyToPoint as applyToPoint62 } from "transformation-matrix";
|
|
242145
242143
|
import Debug42 from "debug";
|
|
242146
242144
|
import Debug6 from "debug";
|
|
242147
|
-
import { applyToPoint as
|
|
242145
|
+
import { applyToPoint as applyToPoint62 } from "transformation-matrix";
|
|
242148
242146
|
import Debug5 from "debug";
|
|
242149
|
-
import { applyToPoint as
|
|
242150
|
-
import { su as
|
|
242147
|
+
import { applyToPoint as applyToPoint82 } from "transformation-matrix";
|
|
242148
|
+
import { su as su5 } from "@tscircuit/soup-util";
|
|
242151
242149
|
import"transformation-matrix";
|
|
242150
|
+
import { su as su62 } from "@tscircuit/soup-util";
|
|
242152
242151
|
import Debug7 from "debug";
|
|
242153
|
-
import { applyToPoint as
|
|
242152
|
+
import { applyToPoint as applyToPoint112, scale as scale42 } from "transformation-matrix";
|
|
242154
242153
|
import"transformation-matrix";
|
|
242155
|
-
import { su as su72 } from "@tscircuit/soup-util";
|
|
242156
242154
|
import Debug10 from "debug";
|
|
242157
242155
|
import Debug8 from "debug";
|
|
242158
242156
|
import Debug9 from "debug";
|
|
@@ -242282,6 +242280,81 @@ function createRectangularPadstack(name, width, height, layer) {
|
|
|
242282
242280
|
attach: "off"
|
|
242283
242281
|
};
|
|
242284
242282
|
}
|
|
242283
|
+
function createCircularHoleRectangularPadstack(name, outerWidth, outerHeight, holeDiameter) {
|
|
242284
|
+
const halfWidth = outerWidth / 2;
|
|
242285
|
+
const halfHeight = outerHeight / 2;
|
|
242286
|
+
const rectPolygon = [
|
|
242287
|
+
-halfWidth,
|
|
242288
|
+
halfHeight,
|
|
242289
|
+
halfWidth,
|
|
242290
|
+
halfHeight,
|
|
242291
|
+
halfWidth,
|
|
242292
|
+
-halfHeight,
|
|
242293
|
+
-halfWidth,
|
|
242294
|
+
-halfHeight,
|
|
242295
|
+
-halfWidth,
|
|
242296
|
+
halfHeight
|
|
242297
|
+
];
|
|
242298
|
+
return {
|
|
242299
|
+
name,
|
|
242300
|
+
shapes: [
|
|
242301
|
+
{
|
|
242302
|
+
shapeType: "polygon",
|
|
242303
|
+
layer: "F.Cu",
|
|
242304
|
+
width: 0,
|
|
242305
|
+
coordinates: rectPolygon
|
|
242306
|
+
},
|
|
242307
|
+
{
|
|
242308
|
+
shapeType: "polygon",
|
|
242309
|
+
layer: "B.Cu",
|
|
242310
|
+
width: 0,
|
|
242311
|
+
coordinates: rectPolygon
|
|
242312
|
+
}
|
|
242313
|
+
],
|
|
242314
|
+
hole: {
|
|
242315
|
+
shape: "circle",
|
|
242316
|
+
diameter: holeDiameter
|
|
242317
|
+
},
|
|
242318
|
+
attach: "off"
|
|
242319
|
+
};
|
|
242320
|
+
}
|
|
242321
|
+
function createAndAddPadstackFromPcbSmtPad(pcb, pad2, processedPadstacks) {
|
|
242322
|
+
const isCircle = pad2.shape === "circle";
|
|
242323
|
+
const padstackParams = {
|
|
242324
|
+
shape: isCircle ? "circle" : "rect",
|
|
242325
|
+
outerDiameter: isCircle ? pad2.radius * 1000 * 2 : undefined,
|
|
242326
|
+
holeDiameter: isCircle ? pad2.radius * 1000 * 2 : undefined,
|
|
242327
|
+
width: isCircle ? undefined : pad2.width * 1000,
|
|
242328
|
+
height: isCircle ? undefined : pad2.height * 1000,
|
|
242329
|
+
layer: pad2.layer
|
|
242330
|
+
};
|
|
242331
|
+
const padstackName = getPadstackName(padstackParams);
|
|
242332
|
+
if (!processedPadstacks.has(padstackName)) {
|
|
242333
|
+
const padstack = isCircle ? createCircularPadstack(padstackName, padstackParams.outerDiameter, padstackParams.holeDiameter) : createRectangularPadstack(padstackName, padstackParams.width, padstackParams.height, pad2.layer);
|
|
242334
|
+
pcb.library.padstacks.push(padstack);
|
|
242335
|
+
processedPadstacks.add(padstackName);
|
|
242336
|
+
}
|
|
242337
|
+
return padstackName;
|
|
242338
|
+
}
|
|
242339
|
+
function createPinForImage(pad2, pcbComponent, sourcePort) {
|
|
242340
|
+
if (!sourcePort)
|
|
242341
|
+
return;
|
|
242342
|
+
const isCircle = pad2.shape === "circle";
|
|
242343
|
+
const padstackParams = {
|
|
242344
|
+
shape: isCircle ? "circle" : "rect",
|
|
242345
|
+
outerDiameter: isCircle ? pad2.radius * 1000 * 2 : undefined,
|
|
242346
|
+
holeDiameter: isCircle ? pad2.radius * 1000 * 2 : undefined,
|
|
242347
|
+
width: isCircle ? undefined : pad2.width * 1000,
|
|
242348
|
+
height: isCircle ? undefined : pad2.height * 1000,
|
|
242349
|
+
layer: pad2.layer
|
|
242350
|
+
};
|
|
242351
|
+
return {
|
|
242352
|
+
padstack_name: getPadstackName(padstackParams),
|
|
242353
|
+
pin_number: sourcePort.port_hints?.find((hint) => !Number.isNaN(Number(hint))) || 1,
|
|
242354
|
+
x: (pad2.x - pcbComponent.center.x) * 1000,
|
|
242355
|
+
y: (pad2.y - pcbComponent.center.y) * 1000
|
|
242356
|
+
};
|
|
242357
|
+
}
|
|
242285
242358
|
var transformMmToUm = scale6(1000);
|
|
242286
242359
|
function processComponentsAndPads(componentGroups, circuitElements, pcb) {
|
|
242287
242360
|
const processedPadstacks = /* @__PURE__ */ new Set;
|
|
@@ -242315,42 +242388,16 @@ function processComponentsAndPads(componentGroups, circuitElements, pcb) {
|
|
|
242315
242388
|
if (!componentGroup)
|
|
242316
242389
|
continue;
|
|
242317
242390
|
for (const pad2 of componentGroup.pcb_smtpads) {
|
|
242318
|
-
|
|
242319
|
-
const padstackName = getPadstackName({
|
|
242320
|
-
shape: "rect",
|
|
242321
|
-
width: pad2.width * 1000,
|
|
242322
|
-
height: pad2.height * 1000,
|
|
242323
|
-
layer: pad2.layer
|
|
242324
|
-
});
|
|
242325
|
-
if (!processedPadstacks.has(padstackName)) {
|
|
242326
|
-
const padWidthInUm = Math.round(pad2.width * 1000);
|
|
242327
|
-
const padHeightInUm = Math.round(pad2.height * 1000);
|
|
242328
|
-
const padstack = createRectangularPadstack(padstackName, padWidthInUm, padHeightInUm, pad2.layer);
|
|
242329
|
-
pcb.library.padstacks.push(padstack);
|
|
242330
|
-
processedPadstacks.add(padstackName);
|
|
242331
|
-
}
|
|
242332
|
-
}
|
|
242391
|
+
createAndAddPadstackFromPcbSmtPad(pcb, pad2, processedPadstacks);
|
|
242333
242392
|
}
|
|
242334
242393
|
const image = {
|
|
242335
242394
|
name: footprintName,
|
|
242336
242395
|
outlines: [],
|
|
242337
242396
|
pins: componentGroup.pcb_smtpads.map((pad2) => {
|
|
242338
242397
|
const pcbComponent = circuitElements.find((e4) => e4.type === "pcb_component" && e4.source_component_id === firstComponent.sourceComponent?.source_component_id);
|
|
242339
|
-
|
|
242340
|
-
|
|
242341
|
-
|
|
242342
|
-
return {
|
|
242343
|
-
padstack_name: getPadstackName({
|
|
242344
|
-
shape: "rect",
|
|
242345
|
-
width: pad2.width * 1000,
|
|
242346
|
-
height: pad2.height * 1000,
|
|
242347
|
-
layer: pad2.layer
|
|
242348
|
-
}),
|
|
242349
|
-
pin_number: sourcePort?.port_hints?.find((hint) => !Number.isNaN(Number(hint))) || 1,
|
|
242350
|
-
x: (pad2.x - pcbComponent.center.x) * 1000,
|
|
242351
|
-
y: (pad2.y - pcbComponent.center.y) * 1000
|
|
242352
|
-
};
|
|
242353
|
-
}
|
|
242398
|
+
const pcbPort = su7(circuitElements).pcb_port.list().find((e4) => e4.pcb_port_id === pad2.pcb_port_id);
|
|
242399
|
+
const sourcePort = su7(circuitElements).source_port.list().find((e4) => e4.source_port_id === pcbPort?.source_port_id);
|
|
242400
|
+
return createPinForImage(pad2, pcbComponent, sourcePort);
|
|
242354
242401
|
}).filter((pin) => pin !== undefined)
|
|
242355
242402
|
};
|
|
242356
242403
|
pcb.library.images.push(image);
|
|
@@ -242394,6 +242441,7 @@ function processNets(circuitElements, pcb) {
|
|
|
242394
242441
|
}
|
|
242395
242442
|
}
|
|
242396
242443
|
const netMap = /* @__PURE__ */ new Map;
|
|
242444
|
+
const netTraceWidthMap = /* @__PURE__ */ new Map;
|
|
242397
242445
|
for (const element of circuitElements) {
|
|
242398
242446
|
if (element.type === "source_trace" && element.connected_source_port_ids) {
|
|
242399
242447
|
const connectedPorts = element.connected_source_port_ids;
|
|
@@ -242410,6 +242458,10 @@ function processNets(circuitElements, pcb) {
|
|
|
242410
242458
|
netMap.get(netName)?.add(`${padInfo.componentName}-${padInfo.pinNumber}`);
|
|
242411
242459
|
}
|
|
242412
242460
|
}
|
|
242461
|
+
if ("min_trace_thickness" in element && element.min_trace_thickness) {
|
|
242462
|
+
const traceWidthMicrons = element.min_trace_thickness * 1000;
|
|
242463
|
+
netTraceWidthMap.set(netName, traceWidthMicrons);
|
|
242464
|
+
}
|
|
242413
242465
|
}
|
|
242414
242466
|
}
|
|
242415
242467
|
}
|
|
@@ -242429,6 +242481,13 @@ function processNets(circuitElements, pcb) {
|
|
|
242429
242481
|
const connectedTraces = circuitElements.filter((e4) => e4.type === "source_trace" && e4.connected_source_net_ids?.includes(element.source_net_id) && e4.connected_source_port_ids?.includes(sourcePortId));
|
|
242430
242482
|
if (connectedTraces.length > 0) {
|
|
242431
242483
|
isInSourceNet = true;
|
|
242484
|
+
for (const trace of connectedTraces) {
|
|
242485
|
+
if ("min_trace_thickness" in trace && trace.min_trace_thickness) {
|
|
242486
|
+
const traceWidthMicrons = trace.min_trace_thickness * 1000;
|
|
242487
|
+
netTraceWidthMap.set(`${element.name}_${element.source_net_id}`, traceWidthMicrons);
|
|
242488
|
+
break;
|
|
242489
|
+
}
|
|
242490
|
+
}
|
|
242432
242491
|
break;
|
|
242433
242492
|
}
|
|
242434
242493
|
}
|
|
@@ -242452,6 +242511,10 @@ function processNets(circuitElements, pcb) {
|
|
|
242452
242511
|
netMap.get(netName)?.add(`${padInfo.componentName}-${padInfo.pinNumber}`);
|
|
242453
242512
|
}
|
|
242454
242513
|
}
|
|
242514
|
+
if ("min_trace_thickness" in trace && trace.min_trace_thickness && !netTraceWidthMap.has(netName)) {
|
|
242515
|
+
const traceWidthMicrons = trace.min_trace_thickness * 1000;
|
|
242516
|
+
netTraceWidthMap.set(netName, traceWidthMicrons);
|
|
242517
|
+
}
|
|
242455
242518
|
}
|
|
242456
242519
|
}
|
|
242457
242520
|
}
|
|
@@ -242470,13 +242533,56 @@ function processNets(circuitElements, pcb) {
|
|
|
242470
242533
|
return 1;
|
|
242471
242534
|
return a2.localeCompare(b);
|
|
242472
242535
|
});
|
|
242536
|
+
const traceWidthClassMap = /* @__PURE__ */ new Map;
|
|
242537
|
+
const defaultTraceWidth = 200;
|
|
242538
|
+
traceWidthClassMap.set(defaultTraceWidth, "kicad_default");
|
|
242539
|
+
for (const [netName, traceWidth] of netTraceWidthMap.entries()) {
|
|
242540
|
+
if (traceWidth !== defaultTraceWidth && !traceWidthClassMap.has(traceWidth)) {
|
|
242541
|
+
const className = `trace_width_${traceWidth}um`;
|
|
242542
|
+
traceWidthClassMap.set(traceWidth, className);
|
|
242543
|
+
pcb.network.classes.push({
|
|
242544
|
+
name: className,
|
|
242545
|
+
description: `Trace width ${traceWidth}μm`,
|
|
242546
|
+
net_names: [],
|
|
242547
|
+
circuit: {
|
|
242548
|
+
use_via: "Via[0-1]_600:300_um"
|
|
242549
|
+
},
|
|
242550
|
+
rule: {
|
|
242551
|
+
clearances: [
|
|
242552
|
+
{
|
|
242553
|
+
value: 200,
|
|
242554
|
+
type: ""
|
|
242555
|
+
}
|
|
242556
|
+
],
|
|
242557
|
+
width: traceWidth
|
|
242558
|
+
}
|
|
242559
|
+
});
|
|
242560
|
+
}
|
|
242561
|
+
}
|
|
242562
|
+
const netsByClass = /* @__PURE__ */ new Map;
|
|
242473
242563
|
for (const netName of allNets) {
|
|
242564
|
+
const traceWidth = netTraceWidthMap.get(netName) || defaultTraceWidth;
|
|
242565
|
+
const className = traceWidthClassMap.get(traceWidth) || "kicad_default";
|
|
242566
|
+
if (!netsByClass.has(className)) {
|
|
242567
|
+
netsByClass.set(className, []);
|
|
242568
|
+
}
|
|
242569
|
+
netsByClass.get(className)?.push(netName);
|
|
242474
242570
|
pcb.network.nets.push({
|
|
242475
242571
|
name: netName,
|
|
242476
242572
|
pins: Array.from(netMap.get(netName) || []).map((pin) => pin.replace("pin", ""))
|
|
242477
242573
|
});
|
|
242478
242574
|
}
|
|
242479
|
-
|
|
242575
|
+
for (const [className, nets] of netsByClass.entries()) {
|
|
242576
|
+
const classIndex = pcb.network.classes.findIndex((c3) => c3.name === className);
|
|
242577
|
+
if (classIndex !== -1) {
|
|
242578
|
+
pcb.network.classes[classIndex].net_names = nets;
|
|
242579
|
+
}
|
|
242580
|
+
}
|
|
242581
|
+
for (const classObj of pcb.network.classes) {
|
|
242582
|
+
if (classObj.net_names.length === 0) {
|
|
242583
|
+
classObj.net_names = allNets;
|
|
242584
|
+
}
|
|
242585
|
+
}
|
|
242480
242586
|
}
|
|
242481
242587
|
function findOrCreateViaPadstack(pcb, outerDiameter, holeDiameter) {
|
|
242482
242588
|
const viaName = `Via[0-1]_${outerDiameter}:${holeDiameter}_um`;
|
|
@@ -242563,7 +242669,7 @@ function createWire(opts) {
|
|
|
242563
242669
|
return {
|
|
242564
242670
|
path: {
|
|
242565
242671
|
layer: opts.layer === "top" ? "F.Cu" : "B.Cu",
|
|
242566
|
-
width: opts.widthMm
|
|
242672
|
+
width: opts.widthMm,
|
|
242567
242673
|
coordinates: []
|
|
242568
242674
|
},
|
|
242569
242675
|
net: opts.netName,
|
|
@@ -242598,7 +242704,7 @@ function processPcbTraces(circuitElements, pcb) {
|
|
|
242598
242704
|
if (isFirstPoint) {
|
|
242599
242705
|
currentWire = createWire({
|
|
242600
242706
|
layer: point5.layer,
|
|
242601
|
-
widthMm: point5.width,
|
|
242707
|
+
widthMm: point5.width * CJ_TO_DSN_SCALE,
|
|
242602
242708
|
netName
|
|
242603
242709
|
});
|
|
242604
242710
|
dsnWrapper.addWire(currentWire);
|
|
@@ -242667,123 +242773,164 @@ function processPcbTraces(circuitElements, pcb) {
|
|
|
242667
242773
|
var transformMmToUm2 = scale22(1000);
|
|
242668
242774
|
function processPlatedHoles(componentGroups, circuitElements, pcb) {
|
|
242669
242775
|
const processedPadstacks = /* @__PURE__ */ new Set;
|
|
242670
|
-
|
|
242671
|
-
|
|
242672
|
-
|
|
242673
|
-
|
|
242674
|
-
continue;
|
|
242675
|
-
const pcbComponent = su42(circuitElements).pcb_component.list().find((e4) => e4.pcb_component_id === pcb_component_id);
|
|
242676
|
-
const sourceComponent = pcbComponent && su42(circuitElements).source_component.list().find((e4) => e4.source_component_id === pcbComponent.source_component_id);
|
|
242677
|
-
if (!pcbComponent)
|
|
242678
|
-
continue;
|
|
242679
|
-
const footprintName = getFootprintName(sourceComponent, pcbComponent);
|
|
242680
|
-
const componentName = sourceComponent.name || "Unknown";
|
|
242681
|
-
const circuitSpaceCoordinates = applyToPoint22(transformMmToUm2, pcbComponent.center);
|
|
242682
|
-
if (pcb_smtpads.length === 0) {
|
|
242683
|
-
if (!componentsByFootprint.has(footprintName)) {
|
|
242684
|
-
componentsByFootprint.set(footprintName, []);
|
|
242685
|
-
}
|
|
242686
|
-
componentsByFootprint.get(footprintName)?.push({
|
|
242687
|
-
componentName,
|
|
242688
|
-
coordinates: circuitSpaceCoordinates,
|
|
242689
|
-
rotation: pcbComponent?.rotation || 0,
|
|
242690
|
-
value: getComponentValue(sourceComponent),
|
|
242691
|
-
sourceComponent
|
|
242692
|
-
});
|
|
242693
|
-
}
|
|
242694
|
-
for (const hole of pcb_plated_holes) {
|
|
242695
|
-
if (hole.shape === "circle") {
|
|
242696
|
-
const padstackName = getPadstackName({
|
|
242776
|
+
function ensurePadstack(hole) {
|
|
242777
|
+
switch (hole.shape) {
|
|
242778
|
+
case "circle": {
|
|
242779
|
+
const name = getPadstackName({
|
|
242697
242780
|
shape: "circle",
|
|
242698
242781
|
holeDiameter: hole.hole_diameter * 1000,
|
|
242699
242782
|
outerDiameter: hole.outer_diameter * 1000,
|
|
242700
242783
|
layer: "all"
|
|
242701
242784
|
});
|
|
242702
|
-
if (!processedPadstacks.has(
|
|
242703
|
-
const
|
|
242704
|
-
pcb.library.padstacks.push(createCircularPadstack(
|
|
242705
|
-
processedPadstacks.add(
|
|
242785
|
+
if (!processedPadstacks.has(name)) {
|
|
242786
|
+
const d3 = Math.round(hole.outer_diameter * 1000);
|
|
242787
|
+
pcb.library.padstacks.push(createCircularPadstack(name, d3, d3));
|
|
242788
|
+
processedPadstacks.add(name);
|
|
242706
242789
|
}
|
|
242707
|
-
|
|
242708
|
-
|
|
242790
|
+
return name;
|
|
242791
|
+
}
|
|
242792
|
+
case "oval":
|
|
242793
|
+
case "pill": {
|
|
242794
|
+
const name = getPadstackName({
|
|
242709
242795
|
shape: hole.shape,
|
|
242710
242796
|
width: hole.hole_width * 1000,
|
|
242711
242797
|
height: hole.hole_height * 1000,
|
|
242712
242798
|
layer: "all"
|
|
242713
242799
|
});
|
|
242714
|
-
if (!processedPadstacks.has(
|
|
242715
|
-
const
|
|
242716
|
-
const
|
|
242717
|
-
const
|
|
242718
|
-
const
|
|
242719
|
-
pcb.library.padstacks.push(createOvalPadstack(
|
|
242720
|
-
processedPadstacks.add(
|
|
242800
|
+
if (!processedPadstacks.has(name)) {
|
|
242801
|
+
const iW = Math.round(hole.hole_width * 1000);
|
|
242802
|
+
const iH = Math.round(hole.hole_height * 1000);
|
|
242803
|
+
const oW = Math.round(hole.outer_width * 1000);
|
|
242804
|
+
const oH = Math.round(hole.outer_height * 1000);
|
|
242805
|
+
pcb.library.padstacks.push(createOvalPadstack(name, oW, oH, iW, iH));
|
|
242806
|
+
processedPadstacks.add(name);
|
|
242721
242807
|
}
|
|
242808
|
+
return name;
|
|
242722
242809
|
}
|
|
242810
|
+
case "circular_hole_with_rect_pad": {
|
|
242811
|
+
const name = getPadstackName({
|
|
242812
|
+
shape: "rect",
|
|
242813
|
+
width: hole.rect_pad_width * 1000,
|
|
242814
|
+
height: hole.rect_pad_height * 1000,
|
|
242815
|
+
layer: "all"
|
|
242816
|
+
});
|
|
242817
|
+
if (!processedPadstacks.has(name)) {
|
|
242818
|
+
const oW = Math.round(hole.rect_pad_width * 1000);
|
|
242819
|
+
const oH = Math.round(hole.rect_pad_height * 1000);
|
|
242820
|
+
const hD = Math.round(hole.hole_diameter * 1000);
|
|
242821
|
+
pcb.library.padstacks.push(createCircularHoleRectangularPadstack(name, oW, oH, hD));
|
|
242822
|
+
processedPadstacks.add(name);
|
|
242823
|
+
}
|
|
242824
|
+
return name;
|
|
242825
|
+
}
|
|
242826
|
+
default:
|
|
242827
|
+
throw new Error(`Unsupported plated-hole shape: ${hole.shape}`);
|
|
242828
|
+
}
|
|
242829
|
+
}
|
|
242830
|
+
function ensureImage(name) {
|
|
242831
|
+
let image = pcb.library.images.find((img) => img.name === name);
|
|
242832
|
+
if (!image) {
|
|
242833
|
+
image = { name, outlines: [], pins: [] };
|
|
242834
|
+
pcb.library.images.push(image);
|
|
242723
242835
|
}
|
|
242724
|
-
|
|
242725
|
-
|
|
242726
|
-
|
|
242727
|
-
|
|
242728
|
-
|
|
242729
|
-
|
|
242836
|
+
return image;
|
|
242837
|
+
}
|
|
242838
|
+
function createNextPinNumberGenerator(image) {
|
|
242839
|
+
let current2 = image.pins.reduce((max, p3) => {
|
|
242840
|
+
const n3 = Number(typeof p3.pin_number === "string" ? p3.pin_number.replace(/pin/i, "") : p3.pin_number);
|
|
242841
|
+
return Number.isNaN(n3) ? max : Math.max(max, n3);
|
|
242842
|
+
}, 0) + 1;
|
|
242843
|
+
return () => current2++;
|
|
242844
|
+
}
|
|
242845
|
+
function findNumericHint(port) {
|
|
242846
|
+
const hint = port?.port_hints?.find((h4) => !Number.isNaN(Number(h4)));
|
|
242847
|
+
return hint !== undefined ? Number(hint) : undefined;
|
|
242848
|
+
}
|
|
242849
|
+
const componentsByFootprint = /* @__PURE__ */ new Map;
|
|
242850
|
+
for (const group of componentGroups) {
|
|
242851
|
+
const { pcb_component_id, pcb_plated_holes, pcb_smtpads } = group;
|
|
242852
|
+
if (pcb_plated_holes.length === 0)
|
|
242853
|
+
continue;
|
|
242854
|
+
const pcbComponent = su42(circuitElements).pcb_component.list().find((e4) => e4.pcb_component_id === pcb_component_id);
|
|
242855
|
+
if (!pcbComponent)
|
|
242856
|
+
continue;
|
|
242857
|
+
const sourceComponent = su42(circuitElements).source_component.list().find((e4) => e4.source_component_id === pcbComponent.source_component_id);
|
|
242858
|
+
const footprintName = getFootprintName(sourceComponent, pcbComponent);
|
|
242859
|
+
const image = ensureImage(footprintName);
|
|
242860
|
+
const nextPinNumber = createNextPinNumberGenerator(image);
|
|
242861
|
+
for (const hole of pcb_plated_holes) {
|
|
242862
|
+
const padstackName = ensurePadstack(hole);
|
|
242863
|
+
const pcbPort = hole.pcb_port_id ? su42(circuitElements).pcb_port.list().find((e4) => e4.pcb_port_id === hole.pcb_port_id) : undefined;
|
|
242864
|
+
const sourcePort = pcbPort ? su42(circuitElements).source_port.list().find((e4) => e4.source_port_id === pcbPort.source_port_id) : undefined;
|
|
242865
|
+
const pinNumber = findNumericHint(sourcePort) ?? nextPinNumber();
|
|
242866
|
+
const pin = {
|
|
242867
|
+
padstack_name: padstackName,
|
|
242868
|
+
pin_number: pinNumber,
|
|
242869
|
+
x: (Number(hole.x.toFixed(3)) - pcbComponent.center.x) * 1000,
|
|
242870
|
+
y: (Number(hole.y.toFixed(3)) - pcbComponent.center.y) * 1000
|
|
242730
242871
|
};
|
|
242731
|
-
|
|
242872
|
+
const duplicate = image.pins.some((p3) => p3.x === pin.x && p3.y === pin.y && p3.padstack_name === pin.padstack_name);
|
|
242873
|
+
if (!duplicate)
|
|
242874
|
+
image.pins.push(pin);
|
|
242875
|
+
}
|
|
242876
|
+
if (pcb_smtpads.length === 0) {
|
|
242877
|
+
const key = footprintName;
|
|
242878
|
+
if (!componentsByFootprint.has(key))
|
|
242879
|
+
componentsByFootprint.set(key, []);
|
|
242880
|
+
componentsByFootprint.get(key).push({
|
|
242881
|
+
componentName: sourceComponent?.name || "Unknown",
|
|
242882
|
+
coordinates: applyToPoint22(transformMmToUm2, pcbComponent.center),
|
|
242883
|
+
rotation: pcbComponent.rotation || 0,
|
|
242884
|
+
value: getComponentValue(sourceComponent),
|
|
242885
|
+
sourceComponent
|
|
242886
|
+
});
|
|
242732
242887
|
}
|
|
242733
|
-
const platedHolePins = pcb_plated_holes.map((hole) => {
|
|
242734
|
-
const pcbPort = su42(circuitElements).pcb_port.list().find((e4) => e4.pcb_port_id === hole.pcb_port_id);
|
|
242735
|
-
const sourcePort = pcbPort && su42(circuitElements).source_port.list().find((e4) => e4.source_port_id === pcbPort.source_port_id);
|
|
242736
|
-
if (hole.shape === "circle") {
|
|
242737
|
-
const pin = {
|
|
242738
|
-
padstack_name: getPadstackName({
|
|
242739
|
-
shape: "circle",
|
|
242740
|
-
holeDiameter: hole.hole_diameter * 1000,
|
|
242741
|
-
outerDiameter: hole.outer_diameter * 1000,
|
|
242742
|
-
layer: "all"
|
|
242743
|
-
}),
|
|
242744
|
-
pin_number: sourcePort?.port_hints?.find((hint) => !Number.isNaN(Number(hint))) || 1,
|
|
242745
|
-
x: (Number(hole.x.toFixed(3)) - pcbComponent.center.x) * 1000,
|
|
242746
|
-
y: (Number(hole.y.toFixed(3)) - pcbComponent.center.y) * 1000
|
|
242747
|
-
};
|
|
242748
|
-
return !existingImage.pins.some((existingPin) => {
|
|
242749
|
-
const samePinNumber = existingPin.pin_number === pin.pin_number;
|
|
242750
|
-
const samePositionAndPadstack = existingPin.x === pin.x && existingPin.y === pin.y && existingPin.padstack_name === pin.padstack_name;
|
|
242751
|
-
return samePinNumber || samePositionAndPadstack;
|
|
242752
|
-
}) ? pin : undefined;
|
|
242753
|
-
} else if (hole.shape === "oval" || hole.shape === "pill") {
|
|
242754
|
-
const pin = {
|
|
242755
|
-
padstack_name: getPadstackName({
|
|
242756
|
-
shape: hole.shape,
|
|
242757
|
-
width: hole.hole_width * 1000,
|
|
242758
|
-
height: hole.hole_height * 1000,
|
|
242759
|
-
layer: "all"
|
|
242760
|
-
}),
|
|
242761
|
-
pin_number: sourcePort?.port_hints?.find((hint) => !Number.isNaN(Number(hint))) || 1,
|
|
242762
|
-
x: (Number(hole.x.toFixed(3)) - pcbComponent.center.x) * 1000,
|
|
242763
|
-
y: (Number(hole.y.toFixed(3)) - pcbComponent.center.y) * 1000
|
|
242764
|
-
};
|
|
242765
|
-
return !existingImage.pins.some((existingPin) => existingPin.x === pin.x && existingPin.y === pin.y && existingPin.padstack_name === pin.padstack_name) ? pin : undefined;
|
|
242766
|
-
}
|
|
242767
|
-
}).filter((pin) => pin !== undefined);
|
|
242768
|
-
existingImage.pins.push(...platedHolePins);
|
|
242769
242888
|
}
|
|
242770
|
-
for (const [
|
|
242771
|
-
|
|
242772
|
-
name:
|
|
242773
|
-
places:
|
|
242774
|
-
refdes: `${
|
|
242775
|
-
x:
|
|
242776
|
-
y:
|
|
242889
|
+
for (const [footprint, comps] of componentsByFootprint) {
|
|
242890
|
+
pcb.placement.components.push({
|
|
242891
|
+
name: footprint,
|
|
242892
|
+
places: comps.map((c3) => ({
|
|
242893
|
+
refdes: `${c3.componentName}_${c3.sourceComponent?.source_component_id}`,
|
|
242894
|
+
x: c3.coordinates.x,
|
|
242895
|
+
y: c3.coordinates.y,
|
|
242777
242896
|
side: "front",
|
|
242778
|
-
rotation:
|
|
242779
|
-
PN:
|
|
242897
|
+
rotation: c3.rotation % 90,
|
|
242898
|
+
PN: c3.value
|
|
242780
242899
|
}))
|
|
242781
|
-
};
|
|
242782
|
-
|
|
242900
|
+
});
|
|
242901
|
+
}
|
|
242902
|
+
}
|
|
242903
|
+
function generateLayers(numLayers) {
|
|
242904
|
+
const layers = [];
|
|
242905
|
+
layers.push({
|
|
242906
|
+
name: "F.Cu",
|
|
242907
|
+
type: "signal",
|
|
242908
|
+
property: {
|
|
242909
|
+
index: 0
|
|
242910
|
+
}
|
|
242911
|
+
});
|
|
242912
|
+
for (let i2 = 1;i2 < numLayers - 1; i2++) {
|
|
242913
|
+
layers.push({
|
|
242914
|
+
name: `In${i2}.Cu`,
|
|
242915
|
+
type: "signal",
|
|
242916
|
+
property: {
|
|
242917
|
+
index: i2
|
|
242918
|
+
}
|
|
242919
|
+
});
|
|
242783
242920
|
}
|
|
242921
|
+
layers.push({
|
|
242922
|
+
name: "B.Cu",
|
|
242923
|
+
type: "signal",
|
|
242924
|
+
property: {
|
|
242925
|
+
index: numLayers - 1
|
|
242926
|
+
}
|
|
242927
|
+
});
|
|
242928
|
+
return layers;
|
|
242784
242929
|
}
|
|
242785
|
-
function convertCircuitJsonToDsnJson(circuitElements) {
|
|
242930
|
+
function convertCircuitJsonToDsnJson(circuitElements, options = {}) {
|
|
242786
242931
|
const pcbBoard = circuitElements.find((element) => element.type === "pcb_board");
|
|
242932
|
+
const numLayers = pcbBoard?.num_layers ?? 2;
|
|
242933
|
+
const layers = generateLayers(numLayers);
|
|
242787
242934
|
const pcb = {
|
|
242788
242935
|
is_dsn_pcb: true,
|
|
242789
242936
|
filename: "",
|
|
@@ -242799,22 +242946,7 @@ function convertCircuitJsonToDsnJson(circuitElements) {
|
|
|
242799
242946
|
},
|
|
242800
242947
|
unit: "um",
|
|
242801
242948
|
structure: {
|
|
242802
|
-
layers
|
|
242803
|
-
{
|
|
242804
|
-
name: "F.Cu",
|
|
242805
|
-
type: "signal",
|
|
242806
|
-
property: {
|
|
242807
|
-
index: 0
|
|
242808
|
-
}
|
|
242809
|
-
},
|
|
242810
|
-
{
|
|
242811
|
-
name: "B.Cu",
|
|
242812
|
-
type: "signal",
|
|
242813
|
-
property: {
|
|
242814
|
-
index: 1
|
|
242815
|
-
}
|
|
242816
|
-
}
|
|
242817
|
-
],
|
|
242949
|
+
layers,
|
|
242818
242950
|
boundary: {
|
|
242819
242951
|
path: {
|
|
242820
242952
|
layer: "pcb",
|
|
@@ -242826,11 +242958,7 @@ function convertCircuitJsonToDsnJson(circuitElements) {
|
|
|
242826
242958
|
rule: {
|
|
242827
242959
|
clearances: [
|
|
242828
242960
|
{
|
|
242829
|
-
value:
|
|
242830
|
-
},
|
|
242831
|
-
{
|
|
242832
|
-
value: 200,
|
|
242833
|
-
type: "default_smd"
|
|
242961
|
+
value: options.traceClearance ?? 150
|
|
242834
242962
|
},
|
|
242835
242963
|
{
|
|
242836
242964
|
value: 50,
|
|
@@ -242877,11 +243005,10 @@ function convertCircuitJsonToDsnJson(circuitElements) {
|
|
|
242877
243005
|
rule: {
|
|
242878
243006
|
clearances: [
|
|
242879
243007
|
{
|
|
242880
|
-
value:
|
|
242881
|
-
type: ""
|
|
243008
|
+
value: options.traceClearance ?? 150
|
|
242882
243009
|
}
|
|
242883
243010
|
],
|
|
242884
|
-
width:
|
|
243011
|
+
width: 150
|
|
242885
243012
|
}
|
|
242886
243013
|
}
|
|
242887
243014
|
]
|
|
@@ -243125,8 +243252,8 @@ var stringifyDsnJson = (dsnJson) => {
|
|
|
243125
243252
|
`;
|
|
243126
243253
|
return result;
|
|
243127
243254
|
};
|
|
243128
|
-
var convertCircuitJsonToDsnString = (circuitJson) => {
|
|
243129
|
-
const dsnJson = convertCircuitJsonToDsnJson(circuitJson);
|
|
243255
|
+
var convertCircuitJsonToDsnString = (circuitJson, options = {}) => {
|
|
243256
|
+
const dsnJson = convertCircuitJsonToDsnJson(circuitJson, options);
|
|
243130
243257
|
return stringifyDsnJson(dsnJson);
|
|
243131
243258
|
};
|
|
243132
243259
|
var debug33 = Debug32("dsn-converter:convertPadstacksToSmtpads");
|
package/dist/lib/index.js
CHANGED
|
@@ -60445,7 +60445,7 @@ var getNodeHandler = (winterSpec, { port, middleware = [] }) => {
|
|
|
60445
60445
|
}));
|
|
60446
60446
|
};
|
|
60447
60447
|
// package.json
|
|
60448
|
-
var version = "0.1.
|
|
60448
|
+
var version = "0.1.1150";
|
|
60449
60449
|
var package_default = {
|
|
60450
60450
|
name: "@tscircuit/cli",
|
|
60451
60451
|
version,
|
|
@@ -60487,7 +60487,7 @@ var package_default = {
|
|
|
60487
60487
|
cosmiconfig: "^9.0.0",
|
|
60488
60488
|
debug: "^4.4.0",
|
|
60489
60489
|
delay: "^6.0.0",
|
|
60490
|
-
"dsn-converter": "
|
|
60490
|
+
"dsn-converter": "0.0.86",
|
|
60491
60491
|
easyeda: "^0.0.252",
|
|
60492
60492
|
"fuse.js": "^7.1.0",
|
|
60493
60493
|
"get-port": "^7.1.0",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tscircuit/cli",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.1151",
|
|
4
4
|
"main": "dist/cli/main.js",
|
|
5
5
|
"exports": {
|
|
6
6
|
".": "./dist/cli/main.js",
|
|
@@ -39,7 +39,7 @@
|
|
|
39
39
|
"cosmiconfig": "^9.0.0",
|
|
40
40
|
"debug": "^4.4.0",
|
|
41
41
|
"delay": "^6.0.0",
|
|
42
|
-
"dsn-converter": "
|
|
42
|
+
"dsn-converter": "0.0.86",
|
|
43
43
|
"easyeda": "^0.0.252",
|
|
44
44
|
"fuse.js": "^7.1.0",
|
|
45
45
|
"get-port": "^7.1.0",
|