@tscircuit/schematic-trace-solver 0.0.196 → 0.0.198

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.
Files changed (29) hide show
  1. package/dist/index.d.ts +5 -0
  2. package/dist/index.js +120 -7
  3. package/lib/solvers/NetLabelToTraceSolver/NetLabelToTraceSolver.ts +42 -1
  4. package/lib/solvers/NetLabelToTraceSolver/getSimpleElbowPath.ts +31 -0
  5. package/lib/solvers/RailNetLabelCornerPlacementSolver/RailNetLabelCornerPlacementSolver.ts +128 -2
  6. package/lib/solvers/RailNetLabelCornerPlacementSolver/types.ts +1 -0
  7. package/lib/solvers/SchematicTracePipelineSolver/SchematicTracePipelineSolver.ts +2 -0
  8. package/package.json +1 -1
  9. package/site/SchematicTracePipelineSolver/repro-am3352-sheet3-power-rails.page.tsx +7 -0
  10. package/site/bug-reports/bug-report-20260911T195723Z.page.tsx +4 -0
  11. package/site/bug-reports/enc-scl-hop.page.tsx +6 -0
  12. package/tests/assets/enc-scl-hop.json +185 -0
  13. package/tests/bug-reports/bug-report-20260707T134549Z/__snapshots__/bug-report-20260707T134549Z.snap.svg +13 -31
  14. package/tests/bug-reports/bug-report-20260901T064117Z/__snapshots__/bug-report-20260901T064117Z.snap.svg +25 -61
  15. package/tests/bug-reports/bug-report-20260911T195723Z/__snapshots__/bug-report-20260911T195723Z.snap.svg +559 -0
  16. package/tests/bug-reports/bug-report-20260911T195723Z/bug-report-20260911T195723Z.json +1792 -0
  17. package/tests/bug-reports/bug-report-20260911T195723Z/bug-report-20260911T195723Z.test.ts +35 -0
  18. package/tests/repros/__snapshots__/repro-am3352-sheet3-power-rails.snap.svg +187 -0
  19. package/tests/repros/__snapshots__/repro-mcp73831-charger-traces.snap.svg +5 -23
  20. package/tests/repros/__snapshots__/repro-normal-net-label-branch-from-junction.snap.svg +31 -31
  21. package/tests/repros/__snapshots__/repro-trellis-core-gnd-net-label-overlap.snap.svg +25 -61
  22. package/tests/repros/__snapshots__/rp2040-robot-controller-disconnected-gnd.snap.svg +12 -26
  23. package/tests/repros/assets/repro-am3352-sheet3-power-rails.input.json +698 -0
  24. package/tests/repros/repro-am3352-sheet3-power-rails.md +66 -0
  25. package/tests/repros/repro-am3352-sheet3-power-rails.test.ts +39 -0
  26. package/tests/repros/repro-normal-net-label-branch-from-junction.test.ts +13 -0
  27. package/tests/solvers/SchematicTracePipelineSolver/__snapshots__/enc-scl-hop.snap.svg +101 -0
  28. package/tests/solvers/SchematicTracePipelineSolver/__snapshots__/explicit-hop.snap.svg +101 -0
  29. package/tests/solvers/SchematicTracePipelineSolver/enc-scl-hop.test.ts +139 -0
@@ -0,0 +1,66 @@
1
+ # AM3352 sheet 3: connector power and ground rails
2
+
3
+ This is a reduced, runnable solver repro for the J_SD, J_SPI, J_I2C and J_USB0
4
+ section of **03-Interfaces — Storage, USB and cable interfaces** (sheet 3).
5
+ It records the baseline for future V3V3/GND label and trace improvements.
6
+ No solver implementation is changed.
7
+
8
+ ## Source and reduction
9
+
10
+ - Deployment: https://am3352-dev-board.vercel.app/#file=index.circuit.tsx
11
+ - Circuit JSON: https://am3352-dev-board.vercel.app/index/circuit.json
12
+ - User-supplied source link: https://github.com/tscircuit/am3352-dev-board
13
+ (returned 404 when this repro was made).
14
+ - Retrieved 2026-09-15. Circuit JSON SHA-256:
15
+ `a9216069870f58ab841446871ed9101d09aabe2eb7457d130e1285cc204006c3`.
16
+ - Solver baseline: `77c271b` (`@tscircuit/schematic-trace-solver` 0.0.197).
17
+
18
+ The fixture preserves the deployed component centers, sizes, all 36 port
19
+ positions and directions, eight component text obstacles, and 19 named nets.
20
+ Component/port IDs become readable `J_SD` / `J_SD.4` identifiers. Net membership
21
+ comes from source-port connectivity keys, not intersections in the screenshot.
22
+ V3V3 connects J_SD.4, J_SPI.2 and J_I2C.2; GND has 16 terminals, including shield
23
+ and mounting pins. USB0_VBUS remains a separate power net.
24
+
25
+ Other sheet components are omitted. Signals leaving this crop become named
26
+ one-pin nets. The fixture contains no pre-routed output or manually imposed
27
+ trace paths. All selected source connections are port-to-net connections, so
28
+ `directConnections` is empty.
29
+
30
+ This is reconstructed solver input, not a captured original solver invocation.
31
+ Label dimensions and text obstacles follow the current core conventions:
32
+ 0.42 rail height; net text width `0.12 * (length + 1)` at 0.18 font size;
33
+ 0.12 inline font size with proportionately smaller width; refdes clearance
34
+ 0.06 with 0.01 overlap into the component. `maxMspPairDistance: 2.4` uses the
35
+ current core default; the deployment does not expose its original setting.
36
+
37
+ ## What it reproduces
38
+
39
+ The baseline routes V3V3 from J_SD.4 down and across to J_I2C.2, and routes GND
40
+ from J_SPI.1 down to J_I2C.1. J_SPI.2 has its own V3V3 label. Ground pin banks
41
+ on the connectors form short buses. These are generated by the solver, not
42
+ hard-coded. The screenshot's external MMC0_DAT2/I2C0_SCL runs are intentionally
43
+ reduced to labeled stubs.
44
+
45
+ The standard snapshot includes both the solver debug view and the semantic
46
+ schematic renderer. Its diagnostic text boxes and generic label rendering are
47
+ not a pixel-for-pixel copy of the deployed site's rail symbols. Use the
48
+ pipeline debugger and stage artifacts to inspect actual placement geometry.
49
+
50
+ ## Run
51
+
52
+ ```sh
53
+ bun install
54
+ bun test tests/repros/repro-am3352-sheet3-power-rails.test.ts
55
+ bun run debug:pipeline tests/repros/assets/repro-am3352-sheet3-power-rails.input.json --svg
56
+ bunx tsc --noEmit
57
+ ```
58
+
59
+ For interactive investigation, run `bun start` and open
60
+ `SchematicTracePipelineSolver/repro-am3352-sheet3-power-rails` in Cosmos.
61
+
62
+ To intentionally update the baseline after an improvement:
63
+
64
+ ```sh
65
+ BUN_UPDATE_SNAPSHOTS=1 bun test tests/repros/repro-am3352-sheet3-power-rails.test.ts
66
+ ```
@@ -0,0 +1,39 @@
1
+ import { expect, test } from "bun:test"
2
+ import { SchematicTracePipelineSolver } from "lib/solvers/SchematicTracePipelineSolver/SchematicTracePipelineSolver"
3
+ import type { InputProblem } from "lib/types/InputProblem"
4
+ import "tests/fixtures/matcher"
5
+ import input from "./assets/repro-am3352-sheet3-power-rails.input.json"
6
+
7
+ // Reduced from the deployed AM3352 board, sheet 3 (03-Interfaces).
8
+ // See the companion .md for provenance and reconstruction details.
9
+ test("repro AM3352 sheet 3 connector power and ground rails", async () => {
10
+ const problem = structuredClone(input) as InputProblem
11
+ expect(problem.chips.map((chip) => chip.chipId).sort()).toEqual([
12
+ "J_I2C",
13
+ "J_SD",
14
+ "J_SPI",
15
+ "J_USB0",
16
+ ])
17
+ expect(
18
+ problem.netConnections.find((net) => net.netId === "V3V3")?.pinIds,
19
+ ).toEqual(["J_SD.4", "J_SPI.2", "J_I2C.2"])
20
+ expect(
21
+ problem.netConnections.find((net) => net.netId === "GND")?.pinIds,
22
+ ).toHaveLength(16)
23
+
24
+ const pinIds = problem.chips.flatMap((chip) =>
25
+ chip.pins.map((pin) => pin.pinId),
26
+ )
27
+ expect(new Set(pinIds).size).toBe(36)
28
+ expect(problem.netConnections.flatMap((net) => net.pinIds).sort()).toEqual(
29
+ pinIds.sort(),
30
+ )
31
+ expect(problem.availableNetLabelOrientations.V3V3).toEqual(["y+"])
32
+ expect(problem.availableNetLabelOrientations.GND).toEqual(["y-"])
33
+
34
+ const solver = new SchematicTracePipelineSolver(problem)
35
+ solver.solve()
36
+ expect(solver.solved).toBe(true)
37
+ expect(solver.failed).toBe(false)
38
+ await expect(solver).toMatchSolverSnapshot(import.meta.path)
39
+ })
@@ -69,5 +69,18 @@ test("repro: V3V3 net-label branch does not start at the R8 edge", () => {
69
69
  expect(
70
70
  solver.inlineNetLabelSolver!.getOutput().inlineNetLabelPlacements,
71
71
  ).toHaveLength(0)
72
+ const connector = solver.netLabelToTraceSolver!.outputTraces.find(
73
+ (trace) => trace.mspPairId === "available-net-orientation-1-V3V3",
74
+ )
75
+ expect(connector?.tracePath[0]).toEqual({ x: -6.5, y: -19 })
76
+ const hostTrace = solver.netLabelToTraceSolver!.outputTraces.find((trace) =>
77
+ trace.pinIds.includes("R8.pin2"),
78
+ )
79
+ const v3v3Label = solver.netLabelToTraceSolver!.outputNetLabelPlacements.find(
80
+ (label) => label.netId === "V3V3",
81
+ )
82
+ expect(hostTrace?.tracePath).toContainEqual(connector!.tracePath[0]!)
83
+ expect(connector?.tracePath.at(-1)).toEqual(v3v3Label?.anchorPoint)
84
+ expect(connector?.tracePath.at(-1)?.y).toBeCloseTo(-18.649)
72
85
  expect(solver).toMatchSolverSnapshot(import.meta.path)
73
86
  })
@@ -0,0 +1,101 @@
1
+ <svg width="1200" height="2016" viewBox="0 0 1200 2016" xmlns="http://www.w3.org/2000/svg" role="img" aria-label="Solver debug visualization on top and Circuit JSON schematic on the bottom">
2
+ <g transform="translate(0, 0) scale(1.875, 1.875) translate(0, 0)">
3
+ <rect width="100%" height="100%" fill="white"/><g><polyline data-points="6.1000000000000005,1.2000000000000002 6.1000000000000005,1.4000000000000004 5.9,1.4000000000000004 5.9,1.2000000000000002" data-type="line" data-label="" points="510.4607046070461,263.089430894309 510.4607046070461,247.91327913279133 495.28455284552854,247.91327913279133 495.28455284552854,263.089430894309" fill="none" stroke="purple" stroke-width="1px"/></g><g><polyline data-points="5.9,-1.2000000000000002 5.9,-1.4000000000000004 6.1000000000000005,-1.4000000000000004 6.1000000000000005,-1.2000000000000002" data-type="line" data-label="" points="495.28455284552854,445.20325203252037 495.28455284552854,460.379403794038 510.4607046070461,460.379403794038 510.4607046070461,445.20325203252037" fill="none" stroke="purple" stroke-width="1px"/></g><g><polyline data-points="0,2.1 0,2.3000000000000003 2,2.3000000000000003 2,2.1" data-type="line" data-label="" points="47.58807588075882,194.7967479674797 47.58807588075882,179.62059620596207 199.34959349593498,179.62059620596207 199.34959349593498,194.7967479674797" fill="none" stroke="purple" stroke-width="1px"/></g><g><polyline data-points="0,1.5 0,0.10000000000000009 4.72,0.10000000000000009" data-type="line" data-label="" points="47.58807588075882,240.32520325203257 47.58807588075882,346.55826558265585 405.74525745257455,346.55826558265585" fill="none" stroke="purple" stroke-width="1px"/></g><g><polyline data-points="2,1.5 2,-0.1 4.72,-0.1" data-type="line" data-label="" points="199.34959349593498,240.32520325203257 199.34959349593498,361.7344173441735 405.74525745257455,361.7344173441735" fill="none" stroke="purple" stroke-width="1px"/></g><g><polyline data-points="0,1.5 0,0.10000000000000009 4.72,0.10000000000000009" data-type="line" data-label="recovered from net labels: R_ENC_SDA.2 -&gt; U_ENCODER.6" points="47.58807588075882,240.32520325203257 47.58807588075882,346.55826558265585 405.74525745257455,346.55826558265585" fill="none" stroke="green" stroke-width="1px"/></g><g><polyline data-points="2,1.5 2,-0.1 4.72,-0.1" data-type="line" data-label="recovered from net labels: R_ENC_SCL.2 -&gt; U_ENCODER.7" points="199.34959349593498,240.32520325203257 199.34959349593498,361.7344173441735 405.74525745257455,361.7344173441735" fill="none" stroke="green" stroke-width="1px"/></g><g><rect data-type="rect" data-label="R_ENC_SDA" data-x="0" data-y="1.8" x="41.51761517615177" y="194.7967479674797" width="12.140921409214101" height="45.52845528455288" fill="hsl(222, 100%, 50%, 0.8)" stroke="black" stroke-width="0.013178571428571428"/></g><g><rect data-type="rect" data-label="R_ENC_SCL" data-x="2" data-y="1.8" x="193.27913279132792" y="194.7967479674797" width="12.140921409214116" height="45.52845528455288" fill="hsl(202, 100%, 50%, 0.8)" stroke="black" stroke-width="0.013178571428571428"/></g><g><rect data-type="rect" data-label="U_ENCODER" data-x="6" data-y="0" x="405.7452574525746" y="263.089430894309" width="194.25474254742545" height="182.1138211382114" fill="hsl(242, 100%, 50%, 0.8)" stroke="black" stroke-width="0.013178571428571428"/></g><g><rect data-type="rect" data-label="netId: V3V3
4
+ globalConnNetId: connectivity_net1" data-x="0" data-y="2.5250000000000004" x="40.000000000000014" y="145.47425474254743" width="15.176151761517616" height="34.14634146341464" fill="#ef444466" stroke="#ef4444" stroke-width="0.013178571428571428"/></g><g><rect data-type="rect" data-label="netId: V3V3
5
+ globalConnNetId: connectivity_net1" data-x="6.1000000000000005" data-y="1.6250000000000004" x="502.8726287262873" y="213.76693766937672" width="15.176151761517588" height="34.14634146341464" fill="#ef444466" stroke="#ef4444" stroke-width="0.013178571428571428"/></g><g><rect data-type="rect" data-label="netId: GND
6
+ globalConnNetId: connectivity_net3" data-x="5.9" data-y="-1.6250000000000004" x="487.6964769647698" y="460.379403794038" width="15.176151761517588" height="34.146341463414615" fill="#00000066" stroke="#000000" stroke-width="0.013178571428571428"/></g><g><circle data-type="point" data-label="R_ENC_SDA.1
7
+ y+" data-x="0" data-y="2.1" cx="47.58807588075882" cy="194.7967479674797" r="3" fill="hsl(256, 100%, 50%, 0.8)"/></g><g><circle data-type="point" data-label="R_ENC_SDA.2
8
+ y-" data-x="0" data-y="1.5" cx="47.58807588075882" cy="240.32520325203257" r="3" fill="hsl(256, 100%, 50%, 0.8)"/></g><g><circle data-type="point" data-label="R_ENC_SCL.1
9
+ y+" data-x="2" data-y="2.1" cx="199.34959349593498" cy="194.7967479674797" r="3" fill="hsl(120, 100%, 50%, 0.8)"/></g><g><circle data-type="point" data-label="R_ENC_SCL.2
10
+ y-" data-x="2" data-y="1.5" cx="199.34959349593498" cy="240.32520325203257" r="3" fill="hsl(120, 100%, 50%, 0.8)"/></g><g><circle data-type="point" data-label="SDA
11
+ x-" data-x="4.72" data-y="0.1" cx="405.74525745257455" cy="346.55826558265585" r="3" fill="hsl(32, 100%, 50%, 0.8)"/></g><g><circle data-type="point" data-label="SCL
12
+ x-" data-x="4.72" data-y="-0.1" cx="405.74525745257455" cy="361.7344173441735" r="3" fill="hsl(32, 100%, 50%, 0.8)"/></g><g><circle data-type="point" data-label="VDD5V
13
+ y+" data-x="5.9" data-y="1.2000000000000002" cx="495.28455284552854" cy="263.089430894309" r="3" fill="hsl(32, 100%, 50%, 0.8)"/></g><g><circle data-type="point" data-label="VDD3V3
14
+ y+" data-x="6.1000000000000005" data-y="1.2000000000000002" cx="510.4607046070461" cy="263.089430894309" r="3" fill="hsl(32, 100%, 50%, 0.8)"/></g><g><circle data-type="point" data-label="GND
15
+ y-" data-x="5.9" data-y="-1.2000000000000002" cx="495.28455284552854" cy="445.20325203252037" r="3" fill="hsl(32, 100%, 50%, 0.8)"/></g><g><circle data-type="point" data-label="DIR
16
+ y-" data-x="6.1000000000000005" data-y="-1.2000000000000002" cx="510.4607046070461" cy="445.20325203252037" r="3" fill="hsl(48, 100%, 50%, 0.8)"/></g><g><circle data-type="point" data-label="OUT
17
+ x+" data-x="7.28" data-y="0.1" cx="600" cy="346.55826558265585" r="3" fill="hsl(32, 100%, 50%, 0.8)"/></g><g><circle data-type="point" data-label="PGO
18
+ x+" data-x="7.28" data-y="-0.1" cx="600" cy="361.7344173441735" r="3" fill="hsl(32, 100%, 50%, 0.8)"/></g><g><circle data-type="point" data-label="anchorPoint
19
+ orientation: y+" data-x="0" data-y="2.3000000000000003" cx="47.58807588075882" cy="179.62059620596207" r="3" fill="hsl(40, 100%, 50%, 0.9)"/></g><g><circle data-type="point" data-label="anchorPoint
20
+ orientation: y+" data-x="6.1000000000000005" data-y="1.4000000000000004" cx="510.4607046070461" cy="247.91327913279133" r="3" fill="hsl(40, 100%, 50%, 0.9)"/></g><g><circle data-type="point" data-label="anchorPoint
21
+ orientation: y-" data-x="5.9" data-y="-1.4000000000000004" cx="495.28455284552854" cy="460.379403794038" r="3" fill="hsl(40, 100%, 50%, 0.9)"/></g><g id="crosshair" style="display: none"><line id="crosshair-h" y1="0" y2="640" stroke="#666" stroke-width="0.5"/><line id="crosshair-v" x1="0" x2="640" stroke="#666" stroke-width="0.5"/><text id="coordinates" font-family="monospace" font-size="12" fill="#666"></text></g><script><![CDATA[
22
+ document.currentScript.parentElement.addEventListener('mousemove', (e) => {
23
+ const svg = e.currentTarget;
24
+ const rect = svg.getBoundingClientRect();
25
+ const x = e.clientX - rect.left;
26
+ const y = e.clientY - rect.top;
27
+ const crosshair = svg.getElementById('crosshair');
28
+ const h = svg.getElementById('crosshair-h');
29
+ const v = svg.getElementById('crosshair-v');
30
+ const coords = svg.getElementById('coordinates');
31
+
32
+ crosshair.style.display = 'block';
33
+ h.setAttribute('x1', '0');
34
+ h.setAttribute('x2', '640');
35
+ h.setAttribute('y1', y);
36
+ h.setAttribute('y2', y);
37
+ v.setAttribute('x1', x);
38
+ v.setAttribute('x2', x);
39
+ v.setAttribute('y1', '0');
40
+ v.setAttribute('y2', '640');
41
+
42
+ // Calculate real coordinates using inverse transformation
43
+ const matrix = {"a":75.88075880758808,"c":0,"e":47.58807588075882,"b":0,"d":-75.88075880758808,"f":354.1463414634147};
44
+ // Manually invert and apply the affine transform
45
+ // Since we only use translate and scale, we can directly compute:
46
+ // x' = (x - tx) / sx
47
+ // y' = (y - ty) / sy
48
+ const sx = matrix.a;
49
+ const sy = matrix.d;
50
+ const tx = matrix.e;
51
+ const ty = matrix.f;
52
+ const realPoint = {
53
+ x: (x - tx) / sx,
54
+ y: (y - ty) / sy // Flip y back since we used negative scale
55
+ }
56
+
57
+ coords.textContent = `(${realPoint.x.toFixed(2)}, ${realPoint.y.toFixed(2)})`;
58
+ coords.setAttribute('x', (x + 5).toString());
59
+ coords.setAttribute('y', (y - 5).toString());
60
+ });
61
+ document.currentScript.parentElement.addEventListener('mouseleave', () => {
62
+ document.currentScript.parentElement.getElementById('crosshair').style.display = 'none';
63
+ });
64
+ ]]></script>
65
+ </g>
66
+ <g transform="translate(0, 1216)">
67
+ <style>
68
+ .boundary { fill: rgb(245, 241, 237); }
69
+ .schematic-boundary { fill: none; stroke: #fff; }
70
+ .component { fill: none; stroke: rgb(132, 0, 0); }
71
+ .chip { fill: rgb(255, 255, 194); stroke: rgb(132, 0, 0); }
72
+ .component-pin { fill: none; stroke: rgb(132, 0, 0); }
73
+ .text { font-family: sans-serif; fill: rgb(0, 150, 0); }
74
+ .pin-number { fill: rgb(169, 0, 0); }
75
+ .port-label { fill: rgb(0, 100, 100); }
76
+ .component-name { fill: rgb(0, 100, 100); }
77
+
78
+ </style><rect class="boundary" x="0" y="0" width="1200" height="800"/><g class="trace sch-trace" data-layer="base" data-circuit-json-type="schematic_trace" data-schematic-trace-id="schematic_trace_0__stack1"><path d="M 958.09739524318 301.07361268414 L 958.09739524318 273.89354473398 L 930.91732729302 273.89354473398 L 930.91732729302 301.07361268414" class="trace-invisible-hover-outline sch-trace-hitbox" stroke="rgb(0, 150, 0)" fill="none" stroke-width="21.744054360127997px" stroke-linecap="round" opacity="0" stroke-linejoin="round"/><path class="sch-trace-path" d="M 958.09739524318 301.07361268414 L 958.09739524318 273.89354473398 L 930.91732729302 273.89354473398 L 930.91732729302 301.07361268414" stroke="rgb(0, 150, 0)" fill="none" stroke-width="2.7180067950159996px" stroke-linecap="round" stroke-linejoin="round"/></g><g class="trace sch-trace" data-layer="base" data-circuit-json-type="schematic_trace" data-schematic-trace-id="schematic_trace_1__stack1"><path d="M 930.91732729302 627.23442808606 L 930.91732729302 654.41449603622 L 958.09739524318 654.41449603622 L 958.09739524318 627.23442808606" class="trace-invisible-hover-outline sch-trace-hitbox" stroke="rgb(0, 150, 0)" fill="none" stroke-width="21.744054360127997px" stroke-linecap="round" opacity="0" stroke-linejoin="round"/><path class="sch-trace-path" d="M 930.91732729302 627.23442808606 L 930.91732729302 654.41449603622 L 958.09739524318 654.41449603622 L 958.09739524318 627.23442808606" stroke="rgb(0, 150, 0)" fill="none" stroke-width="2.7180067950159996px" stroke-linecap="round" stroke-linejoin="round"/></g><g class="trace sch-trace" data-layer="base" data-circuit-json-type="schematic_trace" data-schematic-trace-id="schematic_trace_2__stack1"><path d="M 129.1053227633 178.76330690842002 L 129.1053227633 151.58323895825998 L 400.90600226489994 151.58323895825998 L 400.90600226489994 178.76330690842002" class="trace-invisible-hover-outline sch-trace-hitbox" stroke="rgb(0, 150, 0)" fill="none" stroke-width="21.744054360127997px" stroke-linecap="round" opacity="0" stroke-linejoin="round"/><path class="sch-trace-path" d="M 129.1053227633 178.76330690842002 L 129.1053227633 151.58323895825998 L 400.90600226489994 151.58323895825998 L 400.90600226489994 178.76330690842002" stroke="rgb(0, 150, 0)" fill="none" stroke-width="2.7180067950159996px" stroke-linecap="round" stroke-linejoin="round"/></g><g class="trace sch-trace" data-layer="base" data-circuit-json-type="schematic_trace" data-schematic-trace-id="schematic_trace_3__stack1"><path d="M 129.1053227633 260.3035107589 L 129.1053227633 450.56398641002 L 770.554926387076 450.56398641002" class="trace-invisible-hover-outline sch-trace-hitbox" stroke="rgb(0, 150, 0)" fill="none" stroke-width="21.744054360127997px" stroke-linecap="round" opacity="0" stroke-linejoin="round"/><path class="sch-trace-path" d="M 129.1053227633 260.3035107589 L 129.1053227633 450.56398641002 L 770.554926387076 450.56398641002" stroke="rgb(0, 150, 0)" fill="none" stroke-width="2.7180067950159996px" stroke-linecap="round" stroke-linejoin="round"/></g><g class="trace sch-trace" data-layer="base" data-circuit-json-type="schematic_trace" data-schematic-trace-id="schematic_trace_4__stack1"><path d="M 400.90600226489994 260.3035107589 L 400.90600226489994 477.74405436018003 L 770.554926387076 477.74405436018003" class="trace-invisible-hover-outline sch-trace-hitbox" stroke="rgb(0, 150, 0)" fill="none" stroke-width="21.744054360127997px" stroke-linecap="round" opacity="0" stroke-linejoin="round"/><path class="sch-trace-path" d="M 400.90600226489994 260.3035107589 L 400.90600226489994 477.74405436018003 L 770.554926387076 477.74405436018003" stroke="rgb(0, 150, 0)" fill="none" stroke-width="2.7180067950159996px" stroke-linecap="round" stroke-linejoin="round"/></g><g class="trace-overlays sch-trace-overlays" data-layer="overlay" data-circuit-json-type="schematic_trace" data-schematic-trace-id="schematic_trace_0__stack1"/><g class="trace-overlays sch-trace-overlays" data-layer="overlay" data-circuit-json-type="schematic_trace" data-schematic-trace-id="schematic_trace_1__stack1"/><g class="trace-overlays sch-trace-overlays" data-layer="overlay" data-circuit-json-type="schematic_trace" data-schematic-trace-id="schematic_trace_2__stack1"/><g class="trace-overlays sch-trace-overlays" data-layer="overlay" data-circuit-json-type="schematic_trace" data-schematic-trace-id="schematic_trace_3__stack1"/><g class="trace-overlays sch-trace-overlays" data-layer="overlay" data-circuit-json-type="schematic_trace" data-schematic-trace-id="schematic_trace_4__stack1"/><g class="sch-component" data-circuit-json-type="schematic_component" data-schematic-component-id="schematic_component_0__stack1"><rect class="component-overlay sch-component-overlay" x="118.236013590031" y="178.76330690842002" width="21.738618346537976" height="81.54020385048" fill="transparent"/><path class="sch-component-symbol-path" d="M 129.1053227633 178.76330690842002 L 129.1053227633 192.35605889029503" stroke="rgb(132, 0, 0)" fill="none" stroke-width="2.7180067950159996px" stroke-linecap="round"/><path class="sch-component-symbol-path" d="M 129.1053227633 246.710758777025 L 129.1053227633 260.3035107589" stroke="rgb(132, 0, 0)" fill="none" stroke-width="2.7180067950159996px" stroke-linecap="round"/><path class="sch-component-symbol-path" d="M 139.97463193656898 192.35605889029503 L 139.97463193656898 246.710758777025 L 118.236013590031 246.710758777025 L 118.236013590031 192.35605889029503 L 139.97463193656898 192.35605889029503" stroke="rgb(132, 0, 0)" fill="none" stroke-width="2.7180067950159996px" stroke-linecap="round"/><text class="sch-component-name sch-component-text" x="150.84937712342798" y="197.789354473532" stroke="rgb(245, 241, 237)" stroke-width="2.7180067950159996px" paint-order="stroke" fill="rgb(15, 15, 15)" font-family="sans-serif" text-anchor="start" dominant-baseline="middle" font-size="24.462061155143996px">R_ENC_SDA</text><text class="sch-component-text" x="150.84937712342798" y="241.27746319378804" fill="rgb(15, 15, 15)" font-family="sans-serif" text-anchor="start" dominant-baseline="middle" font-size="24.462061155143996px"></text></g><g class="sch-component" data-circuit-json-type="schematic_component" data-schematic-component-id="schematic_component_1__stack1"><rect class="component-overlay sch-component-overlay" x="390.036693091631" y="178.76330690842002" width="21.73861834653792" height="81.54020385048" fill="transparent"/><path class="sch-component-symbol-path" d="M 400.90600226489994 178.76330690842002 L 400.90600226489994 192.35605889029503" stroke="rgb(132, 0, 0)" fill="none" stroke-width="2.7180067950159996px" stroke-linecap="round"/><path class="sch-component-symbol-path" d="M 400.90600226489994 246.710758777025 L 400.90600226489994 260.3035107589" stroke="rgb(132, 0, 0)" fill="none" stroke-width="2.7180067950159996px" stroke-linecap="round"/><path class="sch-component-symbol-path" d="M 411.7753114381689 192.35605889029503 L 411.7753114381689 246.710758777025 L 390.036693091631 246.710758777025 L 390.036693091631 192.35605889029503 L 411.7753114381689 192.35605889029503" stroke="rgb(132, 0, 0)" fill="none" stroke-width="2.7180067950159996px" stroke-linecap="round"/><text class="sch-component-name sch-component-text" x="422.65005662502796" y="197.789354473532" stroke="rgb(245, 241, 237)" stroke-width="2.7180067950159996px" paint-order="stroke" fill="rgb(15, 15, 15)" font-family="sans-serif" text-anchor="start" dominant-baseline="middle" font-size="24.462061155143996px">R_ENC_SCL</text><text class="sch-component-text" x="422.65005662502796" y="241.27746319378804" fill="rgb(15, 15, 15)" font-family="sans-serif" text-anchor="start" dominant-baseline="middle" font-size="24.462061155143996px"></text></g><g class="sch-component" data-circuit-json-type="schematic_component" data-schematic-component-id="schematic_component_2__stack1"><rect class="component chip sch-component-body" x="824.9150622873959" y="355.43374858446" width="239.18459796140803" height="217.44054360128007" stroke-width="2.7180067950159996px" fill="rgb(255, 255, 194)" stroke="rgb(132, 0, 0)"/><rect class="component-overlay sch-component-overlay" x="824.9150622873959" y="355.43374858446" width="239.18459796140803" height="217.44054360128007" fill="transparent"/><text class="sch-text" x="944.5073612681" y="464.1540203851" fill="#0f172a" text-anchor="middle" dominant-baseline="middle" font-family="sans-serif" font-size="24.462061155143996px" transform="rotate(0, 944.5073612681, 464.1540203851)">U_ENCODER</text><line class="component-pin sch-component-pin sch-port-line" x1="824.9150622873959" y1="450.56398641002" x2="770.554926387076" y2="450.56398641002" stroke-width="2.7180067950159996px"/><g class="sch-port" data-schematic-port-id="source_port_2_0__stack1"><rect x="767.83691959206" y="447.845979615004" width="5.436013590031999" height="5.436013590031999" opacity="0"/></g><text class="pin-number sch-pin-number" x="797.734994337236" y="447.845979615004" style="font-family: sans-serif;" fill="rgb(169, 0, 0)" text-anchor="middle" dominant-baseline="auto" font-size="20.385050962619996px" transform="">6</text><text class="pin-number sch-pin-label" x="838.505096262476" y="450.56398641002" style="font-family: sans-serif;" fill="rgb(169, 0, 0)" text-anchor="start" dominant-baseline="middle" font-size="20.385050962619996px" transform="">SDA</text><line class="component-pin sch-component-pin sch-port-line" x1="824.9150622873959" y1="477.74405436018003" x2="770.554926387076" y2="477.74405436018003" stroke-width="2.7180067950159996px"/><g class="sch-port" data-schematic-port-id="source_port_2_1__stack1"><rect x="767.83691959206" y="475.02604756516405" width="5.436013590031999" height="5.436013590031999" opacity="0"/></g><text class="pin-number sch-pin-number" x="797.734994337236" y="475.026047565164" style="font-family: sans-serif;" fill="rgb(169, 0, 0)" text-anchor="middle" dominant-baseline="auto" font-size="20.385050962619996px" transform="">7</text><text class="pin-number sch-pin-label" x="838.505096262476" y="477.74405436018003" style="font-family: sans-serif;" fill="rgb(169, 0, 0)" text-anchor="start" dominant-baseline="middle" font-size="20.385050962619996px" transform="">SCL</text><line class="component-pin sch-component-pin sch-port-line" x1="930.91732729302" y1="355.43374858446" x2="930.91732729302" y2="301.07361268414" stroke-width="2.7180067950159996px"/><g class="sch-port" data-schematic-port-id="source_port_2_2__stack1"><rect x="928.199320498004" y="298.35560588912404" width="5.436013590031999" height="5.436013590031999" opacity="0"/></g><text class="pin-number sch-pin-number" x="928.199320498004" y="328.2536806343" style="font-family: sans-serif;" fill="rgb(169, 0, 0)" text-anchor="middle" dominant-baseline="auto" font-size="20.385050962619996px" transform="rotate(-90 928.199320498004 328.2536806343)">1</text><text class="pin-number sch-pin-label" x="930.91732729302" y="369.02378255954" style="font-family: sans-serif;" fill="rgb(169, 0, 0)" text-anchor="end" dominant-baseline="middle" font-size="20.385050962619996px" transform="rotate(-90 930.91732729302 369.02378255954)">VDD5V</text><line class="component-pin sch-component-pin sch-port-line" x1="958.09739524318" y1="355.43374858446" x2="958.09739524318" y2="301.07361268414" stroke-width="2.7180067950159996px"/><g class="sch-port" data-schematic-port-id="source_port_2_3__stack1"><rect x="955.379388448164" y="298.35560588912404" width="5.436013590031999" height="5.436013590031999" opacity="0"/></g><text class="pin-number sch-pin-number" x="955.379388448164" y="328.2536806343" style="font-family: sans-serif;" fill="rgb(169, 0, 0)" text-anchor="middle" dominant-baseline="auto" font-size="20.385050962619996px" transform="rotate(-90 955.379388448164 328.2536806343)">2</text><text class="pin-number sch-pin-label" x="958.09739524318" y="369.02378255954" style="font-family: sans-serif;" fill="rgb(169, 0, 0)" text-anchor="end" dominant-baseline="middle" font-size="20.385050962619996px" transform="rotate(-90 958.09739524318 369.02378255954)">VDD3V3</text><line class="component-pin sch-component-pin sch-port-line" x1="930.91732729302" y1="572.87429218574" x2="930.91732729302" y2="627.23442808606" stroke-width="2.7180067950159996px"/><g class="sch-port" data-schematic-port-id="source_port_2_4__stack1"><rect x="928.199320498004" y="624.516421291044" width="5.436013590031999" height="5.436013590031999" opacity="0"/></g><text class="pin-number sch-pin-number" x="928.199320498004" y="600.0543601359" style="font-family: sans-serif;" fill="rgb(169, 0, 0)" text-anchor="middle" dominant-baseline="auto" font-size="20.385050962619996px" transform="rotate(-90 928.199320498004 600.0543601359)">4</text><text class="pin-number sch-pin-label" x="930.91732729302" y="559.28425821066" style="font-family: sans-serif;" fill="rgb(169, 0, 0)" text-anchor="start" dominant-baseline="middle" font-size="20.385050962619996px" transform="rotate(-90 930.91732729302 559.28425821066)">GND</text><line class="component-pin sch-component-pin sch-port-line" x1="958.09739524318" y1="572.87429218574" x2="958.09739524318" y2="627.23442808606" stroke-width="2.7180067950159996px"/><g class="sch-port" data-schematic-port-id="source_port_2_5__stack1"><rect x="955.379388448164" y="624.516421291044" width="5.436013590031999" height="5.436013590031999" opacity="0"/></g><text class="pin-number sch-pin-number" x="955.379388448164" y="600.0543601359" style="font-family: sans-serif;" fill="rgb(169, 0, 0)" text-anchor="middle" dominant-baseline="auto" font-size="20.385050962619996px" transform="rotate(-90 955.379388448164 600.0543601359)">8</text><text class="pin-number sch-pin-label" x="958.09739524318" y="559.28425821066" style="font-family: sans-serif;" fill="rgb(169, 0, 0)" text-anchor="start" dominant-baseline="middle" font-size="20.385050962619996px" transform="rotate(-90 958.09739524318 559.28425821066)">DIR</text><line class="component-pin sch-component-pin sch-port-line" x1="1064.099660248804" y1="450.56398641002" x2="1115.741789354108" y2="450.56398641002" stroke-width="2.7180067950159996px"/><g class="sch-port" data-schematic-port-id="source_port_2_6__stack1"><circle class="component-pin sch-component-pin sch-port-terminal" cx="1118.4597961491238" cy="450.56398641002" r="2.7180067950159996" stroke-width="2.7180067950159996px"/><rect x="1115.7417893541078" y="447.845979615004" width="5.436013590031999" height="5.436013590031999" opacity="0"/></g><text class="pin-number sch-pin-number" x="1091.2797281989638" y="447.845979615004" style="font-family: sans-serif;" fill="rgb(169, 0, 0)" text-anchor="middle" dominant-baseline="auto" font-size="20.385050962619996px" transform="">3</text><text class="pin-number sch-pin-label" x="1050.5096262737238" y="450.56398641002" style="font-family: sans-serif;" fill="rgb(169, 0, 0)" text-anchor="end" dominant-baseline="middle" font-size="20.385050962619996px" transform="">OUT</text><line class="component-pin sch-component-pin sch-port-line" x1="1064.099660248804" y1="477.74405436018003" x2="1115.741789354108" y2="477.74405436018003" stroke-width="2.7180067950159996px"/><g class="sch-port" data-schematic-port-id="source_port_2_7__stack1"><circle class="component-pin sch-component-pin sch-port-terminal" cx="1118.4597961491238" cy="477.74405436018003" r="2.7180067950159996" stroke-width="2.7180067950159996px"/><rect x="1115.7417893541078" y="475.02604756516405" width="5.436013590031999" height="5.436013590031999" opacity="0"/></g><text class="pin-number sch-pin-number" x="1091.2797281989638" y="475.026047565164" style="font-family: sans-serif;" fill="rgb(169, 0, 0)" text-anchor="middle" dominant-baseline="auto" font-size="20.385050962619996px" transform="">5</text><text class="pin-number sch-pin-label" x="1050.5096262737238" y="477.74405436018003" style="font-family: sans-serif;" fill="rgb(169, 0, 0)" text-anchor="end" dominant-baseline="middle" font-size="20.385050962619996px" transform="">PGO</text></g><g class="schematic-port-hover sch-port-hover" data-schematic-port-id="source_port_0_0__stack1"><circle cx="129.1053227633" cy="178.76330690842002" r="5.436013590031999" fill="red" opacity="0"/></g><g class="schematic-port-hover sch-port-hover" data-schematic-port-id="source_port_0_1__stack1"><circle cx="129.1053227633" cy="260.3035107589" r="5.436013590031999" fill="red" opacity="0"/></g><g class="schematic-port-hover sch-port-hover" data-schematic-port-id="source_port_1_0__stack1"><circle cx="400.90600226489994" cy="178.76330690842002" r="5.436013590031999" fill="red" opacity="0"/></g><g class="schematic-port-hover sch-port-hover" data-schematic-port-id="source_port_1_1__stack1"><circle cx="400.90600226489994" cy="260.3035107589" r="5.436013590031999" fill="red" opacity="0"/></g><g class="schematic-port-hover sch-port-hover" data-schematic-port-id="source_port_2_0__stack1"><circle cx="770.554926387076" cy="450.56398641002" r="5.436013590031999" fill="red" opacity="0"/></g><g class="schematic-port-hover sch-port-hover" data-schematic-port-id="source_port_2_1__stack1"><circle cx="770.554926387076" cy="477.74405436018003" r="5.436013590031999" fill="red" opacity="0"/></g><g class="schematic-port-hover sch-port-hover" data-schematic-port-id="source_port_2_2__stack1"><circle cx="930.91732729302" cy="301.07361268414" r="5.436013590031999" fill="red" opacity="0"/></g><g class="schematic-port-hover sch-port-hover" data-schematic-port-id="source_port_2_3__stack1"><circle cx="958.09739524318" cy="301.07361268414" r="5.436013590031999" fill="red" opacity="0"/></g><g class="schematic-port-hover sch-port-hover" data-schematic-port-id="source_port_2_4__stack1"><circle cx="930.91732729302" cy="627.23442808606" r="5.436013590031999" fill="red" opacity="0"/></g><g class="schematic-port-hover sch-port-hover" data-schematic-port-id="source_port_2_5__stack1"><circle cx="958.09739524318" cy="627.23442808606" r="5.436013590031999" fill="red" opacity="0"/></g><g class="schematic-port-hover sch-port-hover" data-schematic-port-id="source_port_2_6__stack1"><circle cx="1118.4597961491238" cy="450.56398641002" r="5.436013590031999" fill="red" opacity="0"/></g><g class="schematic-port-hover sch-port-hover" data-schematic-port-id="source_port_2_7__stack1"><circle cx="1118.4597961491238" cy="477.74405436018003" r="5.436013590031999" fill="red" opacity="0"/></g><path class="net-label sch-net-label" data-circuit-json-type="schematic_net_label" data-schematic-net-label-id="schematic_net_label_0__stack1" d="
79
+ M 129.1053227633,151.58323895825998
80
+ L 115.51528878821999,144.24462061171678
81
+ L 115.51528878822,71.14835787108649
82
+ L 142.69535673837999,71.14835787108649
83
+ L 142.69535673837999,144.24462061171678
84
+ Z
85
+ " fill="rgba(255, 255, 255, 0.6)" stroke="rgb(132, 0, 0)" stroke-width="2.7180067950159996px"/><text class="net-label-text sch-net-label-text" data-circuit-json-type="schematic_net_label" data-schematic-net-label-id="schematic_net_label_0__stack1" x="129.1053227633" y="139.35220838068798" fill="rgb(132, 0, 0)" text-anchor="start" dominant-baseline="central" font-family="sans-serif" font-variant-numeric="tabular-nums" font-size="24.462061155143996px" transform="rotate(-90 129.1053227633 139.35220838068798)">V3V3</text><path class="net-label sch-net-label" data-circuit-json-type="schematic_net_label" data-schematic-net-label-id="schematic_net_label_1__stack1" d="
86
+ M 958.09739524318,273.89354473398
87
+ L 944.5073612681,266.5549263874368
88
+ L 944.5073612681,193.45866364680649
89
+ L 971.68742921826,193.45866364680649
90
+ L 971.68742921826,266.5549263874368
91
+ Z
92
+ " fill="rgba(255, 255, 255, 0.6)" stroke="rgb(132, 0, 0)" stroke-width="2.7180067950159996px"/><text class="net-label-text sch-net-label-text" data-circuit-json-type="schematic_net_label" data-schematic-net-label-id="schematic_net_label_1__stack1" x="958.09739524318" y="261.662514156408" fill="rgb(132, 0, 0)" text-anchor="start" dominant-baseline="central" font-family="sans-serif" font-variant-numeric="tabular-nums" font-size="24.462061155143996px" transform="rotate(-90 958.09739524318 261.662514156408)">V3V3</text><path class="net-label sch-net-label" data-circuit-json-type="schematic_net_label" data-schematic-net-label-id="schematic_net_label_2__stack1" d="
93
+ M 930.91732729302,654.41449603622
94
+ L 944.5073612681,661.7531143827632
95
+ L 944.5073612681,728.8516421290582
96
+ L 917.32729331794,728.8516421290582
97
+ L 917.32729331794,661.7531143827632
98
+ Z
99
+ " fill="rgba(255, 255, 255, 0.6)" stroke="rgb(132, 0, 0)" stroke-width="2.7180067950159996px"/><text class="net-label-text sch-net-label-text" data-circuit-json-type="schematic_net_label" data-schematic-net-label-id="schematic_net_label_2__stack1" x="930.91732729302" y="666.6455266137921" fill="rgb(132, 0, 0)" text-anchor="start" dominant-baseline="central" font-family="sans-serif" font-variant-numeric="tabular-nums" font-size="24.462061155143996px" transform="rotate(90 930.91732729302 666.6455266137921)">GND</text>
100
+ </g>
101
+ </svg>
@@ -0,0 +1,101 @@
1
+ <svg width="1200" height="2016" viewBox="0 0 1200 2016" xmlns="http://www.w3.org/2000/svg" role="img" aria-label="Solver debug visualization on top and Circuit JSON schematic on the bottom">
2
+ <g transform="translate(0, 0) scale(1.875, 1.875) translate(0, 0)">
3
+ <rect width="100%" height="100%" fill="white"/><g><polyline data-points="6.1000000000000005,1.2000000000000002 6.1000000000000005,1.4000000000000004 5.9,1.4000000000000004 5.9,1.2000000000000002" data-type="line" data-label="" points="510.4607046070461,263.089430894309 510.4607046070461,247.91327913279133 495.28455284552854,247.91327913279133 495.28455284552854,263.089430894309" fill="none" stroke="purple" stroke-width="1px"/></g><g><polyline data-points="5.9,-1.2000000000000002 5.9,-1.4000000000000004 6.1000000000000005,-1.4000000000000004 6.1000000000000005,-1.2000000000000002" data-type="line" data-label="" points="495.28455284552854,445.20325203252037 495.28455284552854,460.379403794038 510.4607046070461,460.379403794038 510.4607046070461,445.20325203252037" fill="none" stroke="purple" stroke-width="1px"/></g><g><polyline data-points="0,2.1 0,2.3000000000000003 2,2.3000000000000003 2,2.1" data-type="line" data-label="" points="47.58807588075882,194.7967479674797 47.58807588075882,179.62059620596207 199.34959349593498,179.62059620596207 199.34959349593498,194.7967479674797" fill="none" stroke="purple" stroke-width="1px"/></g><g><polyline data-points="0,1.5 0,0.10000000000000009 4.72,0.10000000000000009" data-type="line" data-label="" points="47.58807588075882,240.32520325203257 47.58807588075882,346.55826558265585 405.74525745257455,346.55826558265585" fill="none" stroke="purple" stroke-width="1px"/></g><g><polyline data-points="2,1.5 2,-0.10000000000000009 4.72,-0.10000000000000009" data-type="line" data-label="" points="199.34959349593498,240.32520325203257 199.34959349593498,361.7344173441735 405.74525745257455,361.7344173441735" fill="none" stroke="purple" stroke-width="1px"/></g><g><polyline data-points="0,1.5 0,0.10000000000000009 4.72,0.10000000000000009" data-type="line" data-label="recovered from net labels: R_ENC_SDA.2 -&gt; U_ENCODER.6" points="47.58807588075882,240.32520325203257 47.58807588075882,346.55826558265585 405.74525745257455,346.55826558265585" fill="none" stroke="green" stroke-width="1px"/></g><g><polyline data-points="2,1.5 2,-0.10000000000000009 4.72,-0.10000000000000009" data-type="line" data-label="recovered from net labels: R_ENC_SCL.2 -&gt; U_ENCODER.7" points="199.34959349593498,240.32520325203257 199.34959349593498,361.7344173441735 405.74525745257455,361.7344173441735" fill="none" stroke="green" stroke-width="1px"/></g><g><rect data-type="rect" data-label="R_ENC_SDA" data-x="0" data-y="1.8" x="41.51761517615177" y="194.7967479674797" width="12.140921409214101" height="45.52845528455288" fill="hsl(222, 100%, 50%, 0.8)" stroke="black" stroke-width="0.013178571428571428"/></g><g><rect data-type="rect" data-label="R_ENC_SCL" data-x="2" data-y="1.8" x="193.27913279132792" y="194.7967479674797" width="12.140921409214116" height="45.52845528455288" fill="hsl(202, 100%, 50%, 0.8)" stroke="black" stroke-width="0.013178571428571428"/></g><g><rect data-type="rect" data-label="U_ENCODER" data-x="6" data-y="0" x="405.7452574525746" y="263.089430894309" width="194.25474254742545" height="182.1138211382114" fill="hsl(242, 100%, 50%, 0.8)" stroke="black" stroke-width="0.013178571428571428"/></g><g><rect data-type="rect" data-label="netId: V3V3
4
+ globalConnNetId: connectivity_net1" data-x="0" data-y="2.5250000000000004" x="40.000000000000014" y="145.47425474254743" width="15.176151761517616" height="34.14634146341464" fill="#ef444466" stroke="#ef4444" stroke-width="0.013178571428571428"/></g><g><rect data-type="rect" data-label="netId: V3V3
5
+ globalConnNetId: connectivity_net1" data-x="6.1000000000000005" data-y="1.6250000000000004" x="502.8726287262873" y="213.76693766937672" width="15.176151761517588" height="34.14634146341464" fill="#ef444466" stroke="#ef4444" stroke-width="0.013178571428571428"/></g><g><rect data-type="rect" data-label="netId: GND
6
+ globalConnNetId: connectivity_net3" data-x="5.9" data-y="-1.6250000000000004" x="487.6964769647698" y="460.379403794038" width="15.176151761517588" height="34.146341463414615" fill="#00000066" stroke="#000000" stroke-width="0.013178571428571428"/></g><g><circle data-type="point" data-label="R_ENC_SDA.1
7
+ y+" data-x="0" data-y="2.1" cx="47.58807588075882" cy="194.7967479674797" r="3" fill="hsl(256, 100%, 50%, 0.8)"/></g><g><circle data-type="point" data-label="R_ENC_SDA.2
8
+ y-" data-x="0" data-y="1.5" cx="47.58807588075882" cy="240.32520325203257" r="3" fill="hsl(256, 100%, 50%, 0.8)"/></g><g><circle data-type="point" data-label="R_ENC_SCL.1
9
+ y+" data-x="2" data-y="2.1" cx="199.34959349593498" cy="194.7967479674797" r="3" fill="hsl(120, 100%, 50%, 0.8)"/></g><g><circle data-type="point" data-label="R_ENC_SCL.2
10
+ y-" data-x="2" data-y="1.5" cx="199.34959349593498" cy="240.32520325203257" r="3" fill="hsl(120, 100%, 50%, 0.8)"/></g><g><circle data-type="point" data-label="SDA
11
+ x-" data-x="4.72" data-y="0.1" cx="405.74525745257455" cy="346.55826558265585" r="3" fill="hsl(32, 100%, 50%, 0.8)"/></g><g><circle data-type="point" data-label="SCL
12
+ x-" data-x="4.72" data-y="-0.1" cx="405.74525745257455" cy="361.7344173441735" r="3" fill="hsl(32, 100%, 50%, 0.8)"/></g><g><circle data-type="point" data-label="VDD5V
13
+ y+" data-x="5.9" data-y="1.2000000000000002" cx="495.28455284552854" cy="263.089430894309" r="3" fill="hsl(32, 100%, 50%, 0.8)"/></g><g><circle data-type="point" data-label="VDD3V3
14
+ y+" data-x="6.1000000000000005" data-y="1.2000000000000002" cx="510.4607046070461" cy="263.089430894309" r="3" fill="hsl(32, 100%, 50%, 0.8)"/></g><g><circle data-type="point" data-label="GND
15
+ y-" data-x="5.9" data-y="-1.2000000000000002" cx="495.28455284552854" cy="445.20325203252037" r="3" fill="hsl(32, 100%, 50%, 0.8)"/></g><g><circle data-type="point" data-label="DIR
16
+ y-" data-x="6.1000000000000005" data-y="-1.2000000000000002" cx="510.4607046070461" cy="445.20325203252037" r="3" fill="hsl(48, 100%, 50%, 0.8)"/></g><g><circle data-type="point" data-label="OUT
17
+ x+" data-x="7.28" data-y="0.1" cx="600" cy="346.55826558265585" r="3" fill="hsl(32, 100%, 50%, 0.8)"/></g><g><circle data-type="point" data-label="PGO
18
+ x+" data-x="7.28" data-y="-0.1" cx="600" cy="361.7344173441735" r="3" fill="hsl(32, 100%, 50%, 0.8)"/></g><g><circle data-type="point" data-label="anchorPoint
19
+ orientation: y+" data-x="0" data-y="2.3000000000000003" cx="47.58807588075882" cy="179.62059620596207" r="3" fill="hsl(40, 100%, 50%, 0.9)"/></g><g><circle data-type="point" data-label="anchorPoint
20
+ orientation: y+" data-x="6.1000000000000005" data-y="1.4000000000000004" cx="510.4607046070461" cy="247.91327913279133" r="3" fill="hsl(40, 100%, 50%, 0.9)"/></g><g><circle data-type="point" data-label="anchorPoint
21
+ orientation: y-" data-x="5.9" data-y="-1.4000000000000004" cx="495.28455284552854" cy="460.379403794038" r="3" fill="hsl(40, 100%, 50%, 0.9)"/></g><g id="crosshair" style="display: none"><line id="crosshair-h" y1="0" y2="640" stroke="#666" stroke-width="0.5"/><line id="crosshair-v" x1="0" x2="640" stroke="#666" stroke-width="0.5"/><text id="coordinates" font-family="monospace" font-size="12" fill="#666"></text></g><script><![CDATA[
22
+ document.currentScript.parentElement.addEventListener('mousemove', (e) => {
23
+ const svg = e.currentTarget;
24
+ const rect = svg.getBoundingClientRect();
25
+ const x = e.clientX - rect.left;
26
+ const y = e.clientY - rect.top;
27
+ const crosshair = svg.getElementById('crosshair');
28
+ const h = svg.getElementById('crosshair-h');
29
+ const v = svg.getElementById('crosshair-v');
30
+ const coords = svg.getElementById('coordinates');
31
+
32
+ crosshair.style.display = 'block';
33
+ h.setAttribute('x1', '0');
34
+ h.setAttribute('x2', '640');
35
+ h.setAttribute('y1', y);
36
+ h.setAttribute('y2', y);
37
+ v.setAttribute('x1', x);
38
+ v.setAttribute('x2', x);
39
+ v.setAttribute('y1', '0');
40
+ v.setAttribute('y2', '640');
41
+
42
+ // Calculate real coordinates using inverse transformation
43
+ const matrix = {"a":75.88075880758808,"c":0,"e":47.58807588075882,"b":0,"d":-75.88075880758808,"f":354.1463414634147};
44
+ // Manually invert and apply the affine transform
45
+ // Since we only use translate and scale, we can directly compute:
46
+ // x' = (x - tx) / sx
47
+ // y' = (y - ty) / sy
48
+ const sx = matrix.a;
49
+ const sy = matrix.d;
50
+ const tx = matrix.e;
51
+ const ty = matrix.f;
52
+ const realPoint = {
53
+ x: (x - tx) / sx,
54
+ y: (y - ty) / sy // Flip y back since we used negative scale
55
+ }
56
+
57
+ coords.textContent = `(${realPoint.x.toFixed(2)}, ${realPoint.y.toFixed(2)})`;
58
+ coords.setAttribute('x', (x + 5).toString());
59
+ coords.setAttribute('y', (y - 5).toString());
60
+ });
61
+ document.currentScript.parentElement.addEventListener('mouseleave', () => {
62
+ document.currentScript.parentElement.getElementById('crosshair').style.display = 'none';
63
+ });
64
+ ]]></script>
65
+ </g>
66
+ <g transform="translate(0, 1216)">
67
+ <style>
68
+ .boundary { fill: rgb(245, 241, 237); }
69
+ .schematic-boundary { fill: none; stroke: #fff; }
70
+ .component { fill: none; stroke: rgb(132, 0, 0); }
71
+ .chip { fill: rgb(255, 255, 194); stroke: rgb(132, 0, 0); }
72
+ .component-pin { fill: none; stroke: rgb(132, 0, 0); }
73
+ .text { font-family: sans-serif; fill: rgb(0, 150, 0); }
74
+ .pin-number { fill: rgb(169, 0, 0); }
75
+ .port-label { fill: rgb(0, 100, 100); }
76
+ .component-name { fill: rgb(0, 100, 100); }
77
+
78
+ </style><rect class="boundary" x="0" y="0" width="1200" height="800"/><g class="trace sch-trace" data-layer="base" data-circuit-json-type="schematic_trace" data-schematic-trace-id="schematic_trace_0__stack1"><path d="M 958.09739524318 301.07361268414 L 958.09739524318 273.89354473398 L 930.91732729302 273.89354473398 L 930.91732729302 301.07361268414" class="trace-invisible-hover-outline sch-trace-hitbox" stroke="rgb(0, 150, 0)" fill="none" stroke-width="21.744054360127997px" stroke-linecap="round" opacity="0" stroke-linejoin="round"/><path class="sch-trace-path" d="M 958.09739524318 301.07361268414 L 958.09739524318 273.89354473398 L 930.91732729302 273.89354473398 L 930.91732729302 301.07361268414" stroke="rgb(0, 150, 0)" fill="none" stroke-width="2.7180067950159996px" stroke-linecap="round" stroke-linejoin="round"/></g><g class="trace sch-trace" data-layer="base" data-circuit-json-type="schematic_trace" data-schematic-trace-id="schematic_trace_1__stack1"><path d="M 930.91732729302 627.23442808606 L 930.91732729302 654.41449603622 L 958.09739524318 654.41449603622 L 958.09739524318 627.23442808606" class="trace-invisible-hover-outline sch-trace-hitbox" stroke="rgb(0, 150, 0)" fill="none" stroke-width="21.744054360127997px" stroke-linecap="round" opacity="0" stroke-linejoin="round"/><path class="sch-trace-path" d="M 930.91732729302 627.23442808606 L 930.91732729302 654.41449603622 L 958.09739524318 654.41449603622 L 958.09739524318 627.23442808606" stroke="rgb(0, 150, 0)" fill="none" stroke-width="2.7180067950159996px" stroke-linecap="round" stroke-linejoin="round"/></g><g class="trace sch-trace" data-layer="base" data-circuit-json-type="schematic_trace" data-schematic-trace-id="schematic_trace_2__stack1"><path d="M 129.1053227633 178.76330690842002 L 129.1053227633 151.58323895825998 L 400.90600226489994 151.58323895825998 L 400.90600226489994 178.76330690842002" class="trace-invisible-hover-outline sch-trace-hitbox" stroke="rgb(0, 150, 0)" fill="none" stroke-width="21.744054360127997px" stroke-linecap="round" opacity="0" stroke-linejoin="round"/><path class="sch-trace-path" d="M 129.1053227633 178.76330690842002 L 129.1053227633 151.58323895825998 L 400.90600226489994 151.58323895825998 L 400.90600226489994 178.76330690842002" stroke="rgb(0, 150, 0)" fill="none" stroke-width="2.7180067950159996px" stroke-linecap="round" stroke-linejoin="round"/></g><g class="trace sch-trace" data-layer="base" data-circuit-json-type="schematic_trace" data-schematic-trace-id="schematic_trace_3__stack1"><path d="M 129.1053227633 260.3035107589 L 129.1053227633 450.56398641002 L 770.554926387076 450.56398641002" class="trace-invisible-hover-outline sch-trace-hitbox" stroke="rgb(0, 150, 0)" fill="none" stroke-width="21.744054360127997px" stroke-linecap="round" opacity="0" stroke-linejoin="round"/><path class="sch-trace-path" d="M 129.1053227633 260.3035107589 L 129.1053227633 450.56398641002 L 770.554926387076 450.56398641002" stroke="rgb(0, 150, 0)" fill="none" stroke-width="2.7180067950159996px" stroke-linecap="round" stroke-linejoin="round"/></g><g class="trace sch-trace" data-layer="base" data-circuit-json-type="schematic_trace" data-schematic-trace-id="schematic_trace_4__stack1"><path d="M 400.90600226489994 260.3035107589 L 400.90600226489994 477.74405436018003 L 770.554926387076 477.74405436018003" class="trace-invisible-hover-outline sch-trace-hitbox" stroke="rgb(0, 150, 0)" fill="none" stroke-width="21.744054360127997px" stroke-linecap="round" opacity="0" stroke-linejoin="round"/><path class="sch-trace-path" d="M 400.90600226489994 260.3035107589 L 400.90600226489994 477.74405436018003 L 770.554926387076 477.74405436018003" stroke="rgb(0, 150, 0)" fill="none" stroke-width="2.7180067950159996px" stroke-linecap="round" stroke-linejoin="round"/></g><g class="trace-overlays sch-trace-overlays" data-layer="overlay" data-circuit-json-type="schematic_trace" data-schematic-trace-id="schematic_trace_0__stack1"/><g class="trace-overlays sch-trace-overlays" data-layer="overlay" data-circuit-json-type="schematic_trace" data-schematic-trace-id="schematic_trace_1__stack1"/><g class="trace-overlays sch-trace-overlays" data-layer="overlay" data-circuit-json-type="schematic_trace" data-schematic-trace-id="schematic_trace_2__stack1"/><g class="trace-overlays sch-trace-overlays" data-layer="overlay" data-circuit-json-type="schematic_trace" data-schematic-trace-id="schematic_trace_3__stack1"/><g class="trace-overlays sch-trace-overlays" data-layer="overlay" data-circuit-json-type="schematic_trace" data-schematic-trace-id="schematic_trace_4__stack1"/><g class="sch-component" data-circuit-json-type="schematic_component" data-schematic-component-id="schematic_component_0__stack1"><rect class="component-overlay sch-component-overlay" x="118.236013590031" y="178.76330690842002" width="21.738618346537976" height="81.54020385048" fill="transparent"/><path class="sch-component-symbol-path" d="M 129.1053227633 178.76330690842002 L 129.1053227633 192.35605889029503" stroke="rgb(132, 0, 0)" fill="none" stroke-width="2.7180067950159996px" stroke-linecap="round"/><path class="sch-component-symbol-path" d="M 129.1053227633 246.710758777025 L 129.1053227633 260.3035107589" stroke="rgb(132, 0, 0)" fill="none" stroke-width="2.7180067950159996px" stroke-linecap="round"/><path class="sch-component-symbol-path" d="M 139.97463193656898 192.35605889029503 L 139.97463193656898 246.710758777025 L 118.236013590031 246.710758777025 L 118.236013590031 192.35605889029503 L 139.97463193656898 192.35605889029503" stroke="rgb(132, 0, 0)" fill="none" stroke-width="2.7180067950159996px" stroke-linecap="round"/><text class="sch-component-name sch-component-text" x="150.84937712342798" y="197.789354473532" stroke="rgb(245, 241, 237)" stroke-width="2.7180067950159996px" paint-order="stroke" fill="rgb(15, 15, 15)" font-family="sans-serif" text-anchor="start" dominant-baseline="middle" font-size="24.462061155143996px">R_ENC_SDA</text><text class="sch-component-text" x="150.84937712342798" y="241.27746319378804" fill="rgb(15, 15, 15)" font-family="sans-serif" text-anchor="start" dominant-baseline="middle" font-size="24.462061155143996px"></text></g><g class="sch-component" data-circuit-json-type="schematic_component" data-schematic-component-id="schematic_component_1__stack1"><rect class="component-overlay sch-component-overlay" x="390.036693091631" y="178.76330690842002" width="21.73861834653792" height="81.54020385048" fill="transparent"/><path class="sch-component-symbol-path" d="M 400.90600226489994 178.76330690842002 L 400.90600226489994 192.35605889029503" stroke="rgb(132, 0, 0)" fill="none" stroke-width="2.7180067950159996px" stroke-linecap="round"/><path class="sch-component-symbol-path" d="M 400.90600226489994 246.710758777025 L 400.90600226489994 260.3035107589" stroke="rgb(132, 0, 0)" fill="none" stroke-width="2.7180067950159996px" stroke-linecap="round"/><path class="sch-component-symbol-path" d="M 411.7753114381689 192.35605889029503 L 411.7753114381689 246.710758777025 L 390.036693091631 246.710758777025 L 390.036693091631 192.35605889029503 L 411.7753114381689 192.35605889029503" stroke="rgb(132, 0, 0)" fill="none" stroke-width="2.7180067950159996px" stroke-linecap="round"/><text class="sch-component-name sch-component-text" x="422.65005662502796" y="197.789354473532" stroke="rgb(245, 241, 237)" stroke-width="2.7180067950159996px" paint-order="stroke" fill="rgb(15, 15, 15)" font-family="sans-serif" text-anchor="start" dominant-baseline="middle" font-size="24.462061155143996px">R_ENC_SCL</text><text class="sch-component-text" x="422.65005662502796" y="241.27746319378804" fill="rgb(15, 15, 15)" font-family="sans-serif" text-anchor="start" dominant-baseline="middle" font-size="24.462061155143996px"></text></g><g class="sch-component" data-circuit-json-type="schematic_component" data-schematic-component-id="schematic_component_2__stack1"><rect class="component chip sch-component-body" x="824.9150622873959" y="355.43374858446" width="239.18459796140803" height="217.44054360128007" stroke-width="2.7180067950159996px" fill="rgb(255, 255, 194)" stroke="rgb(132, 0, 0)"/><rect class="component-overlay sch-component-overlay" x="824.9150622873959" y="355.43374858446" width="239.18459796140803" height="217.44054360128007" fill="transparent"/><text class="sch-text" x="944.5073612681" y="464.1540203851" fill="#0f172a" text-anchor="middle" dominant-baseline="middle" font-family="sans-serif" font-size="24.462061155143996px" transform="rotate(0, 944.5073612681, 464.1540203851)">U_ENCODER</text><line class="component-pin sch-component-pin sch-port-line" x1="824.9150622873959" y1="450.56398641002" x2="770.554926387076" y2="450.56398641002" stroke-width="2.7180067950159996px"/><g class="sch-port" data-schematic-port-id="source_port_2_0__stack1"><rect x="767.83691959206" y="447.845979615004" width="5.436013590031999" height="5.436013590031999" opacity="0"/></g><text class="pin-number sch-pin-number" x="797.734994337236" y="447.845979615004" style="font-family: sans-serif;" fill="rgb(169, 0, 0)" text-anchor="middle" dominant-baseline="auto" font-size="20.385050962619996px" transform="">6</text><text class="pin-number sch-pin-label" x="838.505096262476" y="450.56398641002" style="font-family: sans-serif;" fill="rgb(169, 0, 0)" text-anchor="start" dominant-baseline="middle" font-size="20.385050962619996px" transform="">SDA</text><line class="component-pin sch-component-pin sch-port-line" x1="824.9150622873959" y1="477.74405436018003" x2="770.554926387076" y2="477.74405436018003" stroke-width="2.7180067950159996px"/><g class="sch-port" data-schematic-port-id="source_port_2_1__stack1"><rect x="767.83691959206" y="475.02604756516405" width="5.436013590031999" height="5.436013590031999" opacity="0"/></g><text class="pin-number sch-pin-number" x="797.734994337236" y="475.026047565164" style="font-family: sans-serif;" fill="rgb(169, 0, 0)" text-anchor="middle" dominant-baseline="auto" font-size="20.385050962619996px" transform="">7</text><text class="pin-number sch-pin-label" x="838.505096262476" y="477.74405436018003" style="font-family: sans-serif;" fill="rgb(169, 0, 0)" text-anchor="start" dominant-baseline="middle" font-size="20.385050962619996px" transform="">SCL</text><line class="component-pin sch-component-pin sch-port-line" x1="930.91732729302" y1="355.43374858446" x2="930.91732729302" y2="301.07361268414" stroke-width="2.7180067950159996px"/><g class="sch-port" data-schematic-port-id="source_port_2_2__stack1"><rect x="928.199320498004" y="298.35560588912404" width="5.436013590031999" height="5.436013590031999" opacity="0"/></g><text class="pin-number sch-pin-number" x="928.199320498004" y="328.2536806343" style="font-family: sans-serif;" fill="rgb(169, 0, 0)" text-anchor="middle" dominant-baseline="auto" font-size="20.385050962619996px" transform="rotate(-90 928.199320498004 328.2536806343)">1</text><text class="pin-number sch-pin-label" x="930.91732729302" y="369.02378255954" style="font-family: sans-serif;" fill="rgb(169, 0, 0)" text-anchor="end" dominant-baseline="middle" font-size="20.385050962619996px" transform="rotate(-90 930.91732729302 369.02378255954)">VDD5V</text><line class="component-pin sch-component-pin sch-port-line" x1="958.09739524318" y1="355.43374858446" x2="958.09739524318" y2="301.07361268414" stroke-width="2.7180067950159996px"/><g class="sch-port" data-schematic-port-id="source_port_2_3__stack1"><rect x="955.379388448164" y="298.35560588912404" width="5.436013590031999" height="5.436013590031999" opacity="0"/></g><text class="pin-number sch-pin-number" x="955.379388448164" y="328.2536806343" style="font-family: sans-serif;" fill="rgb(169, 0, 0)" text-anchor="middle" dominant-baseline="auto" font-size="20.385050962619996px" transform="rotate(-90 955.379388448164 328.2536806343)">2</text><text class="pin-number sch-pin-label" x="958.09739524318" y="369.02378255954" style="font-family: sans-serif;" fill="rgb(169, 0, 0)" text-anchor="end" dominant-baseline="middle" font-size="20.385050962619996px" transform="rotate(-90 958.09739524318 369.02378255954)">VDD3V3</text><line class="component-pin sch-component-pin sch-port-line" x1="930.91732729302" y1="572.87429218574" x2="930.91732729302" y2="627.23442808606" stroke-width="2.7180067950159996px"/><g class="sch-port" data-schematic-port-id="source_port_2_4__stack1"><rect x="928.199320498004" y="624.516421291044" width="5.436013590031999" height="5.436013590031999" opacity="0"/></g><text class="pin-number sch-pin-number" x="928.199320498004" y="600.0543601359" style="font-family: sans-serif;" fill="rgb(169, 0, 0)" text-anchor="middle" dominant-baseline="auto" font-size="20.385050962619996px" transform="rotate(-90 928.199320498004 600.0543601359)">4</text><text class="pin-number sch-pin-label" x="930.91732729302" y="559.28425821066" style="font-family: sans-serif;" fill="rgb(169, 0, 0)" text-anchor="start" dominant-baseline="middle" font-size="20.385050962619996px" transform="rotate(-90 930.91732729302 559.28425821066)">GND</text><line class="component-pin sch-component-pin sch-port-line" x1="958.09739524318" y1="572.87429218574" x2="958.09739524318" y2="627.23442808606" stroke-width="2.7180067950159996px"/><g class="sch-port" data-schematic-port-id="source_port_2_5__stack1"><rect x="955.379388448164" y="624.516421291044" width="5.436013590031999" height="5.436013590031999" opacity="0"/></g><text class="pin-number sch-pin-number" x="955.379388448164" y="600.0543601359" style="font-family: sans-serif;" fill="rgb(169, 0, 0)" text-anchor="middle" dominant-baseline="auto" font-size="20.385050962619996px" transform="rotate(-90 955.379388448164 600.0543601359)">8</text><text class="pin-number sch-pin-label" x="958.09739524318" y="559.28425821066" style="font-family: sans-serif;" fill="rgb(169, 0, 0)" text-anchor="start" dominant-baseline="middle" font-size="20.385050962619996px" transform="rotate(-90 958.09739524318 559.28425821066)">DIR</text><line class="component-pin sch-component-pin sch-port-line" x1="1064.099660248804" y1="450.56398641002" x2="1115.741789354108" y2="450.56398641002" stroke-width="2.7180067950159996px"/><g class="sch-port" data-schematic-port-id="source_port_2_6__stack1"><circle class="component-pin sch-component-pin sch-port-terminal" cx="1118.4597961491238" cy="450.56398641002" r="2.7180067950159996" stroke-width="2.7180067950159996px"/><rect x="1115.7417893541078" y="447.845979615004" width="5.436013590031999" height="5.436013590031999" opacity="0"/></g><text class="pin-number sch-pin-number" x="1091.2797281989638" y="447.845979615004" style="font-family: sans-serif;" fill="rgb(169, 0, 0)" text-anchor="middle" dominant-baseline="auto" font-size="20.385050962619996px" transform="">3</text><text class="pin-number sch-pin-label" x="1050.5096262737238" y="450.56398641002" style="font-family: sans-serif;" fill="rgb(169, 0, 0)" text-anchor="end" dominant-baseline="middle" font-size="20.385050962619996px" transform="">OUT</text><line class="component-pin sch-component-pin sch-port-line" x1="1064.099660248804" y1="477.74405436018003" x2="1115.741789354108" y2="477.74405436018003" stroke-width="2.7180067950159996px"/><g class="sch-port" data-schematic-port-id="source_port_2_7__stack1"><circle class="component-pin sch-component-pin sch-port-terminal" cx="1118.4597961491238" cy="477.74405436018003" r="2.7180067950159996" stroke-width="2.7180067950159996px"/><rect x="1115.7417893541078" y="475.02604756516405" width="5.436013590031999" height="5.436013590031999" opacity="0"/></g><text class="pin-number sch-pin-number" x="1091.2797281989638" y="475.026047565164" style="font-family: sans-serif;" fill="rgb(169, 0, 0)" text-anchor="middle" dominant-baseline="auto" font-size="20.385050962619996px" transform="">5</text><text class="pin-number sch-pin-label" x="1050.5096262737238" y="477.74405436018003" style="font-family: sans-serif;" fill="rgb(169, 0, 0)" text-anchor="end" dominant-baseline="middle" font-size="20.385050962619996px" transform="">PGO</text></g><g class="schematic-port-hover sch-port-hover" data-schematic-port-id="source_port_0_0__stack1"><circle cx="129.1053227633" cy="178.76330690842002" r="5.436013590031999" fill="red" opacity="0"/></g><g class="schematic-port-hover sch-port-hover" data-schematic-port-id="source_port_0_1__stack1"><circle cx="129.1053227633" cy="260.3035107589" r="5.436013590031999" fill="red" opacity="0"/></g><g class="schematic-port-hover sch-port-hover" data-schematic-port-id="source_port_1_0__stack1"><circle cx="400.90600226489994" cy="178.76330690842002" r="5.436013590031999" fill="red" opacity="0"/></g><g class="schematic-port-hover sch-port-hover" data-schematic-port-id="source_port_1_1__stack1"><circle cx="400.90600226489994" cy="260.3035107589" r="5.436013590031999" fill="red" opacity="0"/></g><g class="schematic-port-hover sch-port-hover" data-schematic-port-id="source_port_2_0__stack1"><circle cx="770.554926387076" cy="450.56398641002" r="5.436013590031999" fill="red" opacity="0"/></g><g class="schematic-port-hover sch-port-hover" data-schematic-port-id="source_port_2_1__stack1"><circle cx="770.554926387076" cy="477.74405436018003" r="5.436013590031999" fill="red" opacity="0"/></g><g class="schematic-port-hover sch-port-hover" data-schematic-port-id="source_port_2_2__stack1"><circle cx="930.91732729302" cy="301.07361268414" r="5.436013590031999" fill="red" opacity="0"/></g><g class="schematic-port-hover sch-port-hover" data-schematic-port-id="source_port_2_3__stack1"><circle cx="958.09739524318" cy="301.07361268414" r="5.436013590031999" fill="red" opacity="0"/></g><g class="schematic-port-hover sch-port-hover" data-schematic-port-id="source_port_2_4__stack1"><circle cx="930.91732729302" cy="627.23442808606" r="5.436013590031999" fill="red" opacity="0"/></g><g class="schematic-port-hover sch-port-hover" data-schematic-port-id="source_port_2_5__stack1"><circle cx="958.09739524318" cy="627.23442808606" r="5.436013590031999" fill="red" opacity="0"/></g><g class="schematic-port-hover sch-port-hover" data-schematic-port-id="source_port_2_6__stack1"><circle cx="1118.4597961491238" cy="450.56398641002" r="5.436013590031999" fill="red" opacity="0"/></g><g class="schematic-port-hover sch-port-hover" data-schematic-port-id="source_port_2_7__stack1"><circle cx="1118.4597961491238" cy="477.74405436018003" r="5.436013590031999" fill="red" opacity="0"/></g><path class="net-label sch-net-label" data-circuit-json-type="schematic_net_label" data-schematic-net-label-id="schematic_net_label_0__stack1" d="
79
+ M 129.1053227633,151.58323895825998
80
+ L 115.51528878821999,144.24462061171678
81
+ L 115.51528878822,71.14835787108649
82
+ L 142.69535673837999,71.14835787108649
83
+ L 142.69535673837999,144.24462061171678
84
+ Z
85
+ " fill="rgba(255, 255, 255, 0.6)" stroke="rgb(132, 0, 0)" stroke-width="2.7180067950159996px"/><text class="net-label-text sch-net-label-text" data-circuit-json-type="schematic_net_label" data-schematic-net-label-id="schematic_net_label_0__stack1" x="129.1053227633" y="139.35220838068798" fill="rgb(132, 0, 0)" text-anchor="start" dominant-baseline="central" font-family="sans-serif" font-variant-numeric="tabular-nums" font-size="24.462061155143996px" transform="rotate(-90 129.1053227633 139.35220838068798)">V3V3</text><path class="net-label sch-net-label" data-circuit-json-type="schematic_net_label" data-schematic-net-label-id="schematic_net_label_1__stack1" d="
86
+ M 958.09739524318,273.89354473398
87
+ L 944.5073612681,266.5549263874368
88
+ L 944.5073612681,193.45866364680649
89
+ L 971.68742921826,193.45866364680649
90
+ L 971.68742921826,266.5549263874368
91
+ Z
92
+ " fill="rgba(255, 255, 255, 0.6)" stroke="rgb(132, 0, 0)" stroke-width="2.7180067950159996px"/><text class="net-label-text sch-net-label-text" data-circuit-json-type="schematic_net_label" data-schematic-net-label-id="schematic_net_label_1__stack1" x="958.09739524318" y="261.662514156408" fill="rgb(132, 0, 0)" text-anchor="start" dominant-baseline="central" font-family="sans-serif" font-variant-numeric="tabular-nums" font-size="24.462061155143996px" transform="rotate(-90 958.09739524318 261.662514156408)">V3V3</text><path class="net-label sch-net-label" data-circuit-json-type="schematic_net_label" data-schematic-net-label-id="schematic_net_label_2__stack1" d="
93
+ M 930.91732729302,654.41449603622
94
+ L 944.5073612681,661.7531143827632
95
+ L 944.5073612681,728.8516421290582
96
+ L 917.32729331794,728.8516421290582
97
+ L 917.32729331794,661.7531143827632
98
+ Z
99
+ " fill="rgba(255, 255, 255, 0.6)" stroke="rgb(132, 0, 0)" stroke-width="2.7180067950159996px"/><text class="net-label-text sch-net-label-text" data-circuit-json-type="schematic_net_label" data-schematic-net-label-id="schematic_net_label_2__stack1" x="930.91732729302" y="666.6455266137921" fill="rgb(132, 0, 0)" text-anchor="start" dominant-baseline="central" font-family="sans-serif" font-variant-numeric="tabular-nums" font-size="24.462061155143996px" transform="rotate(90 930.91732729302 666.6455266137921)">GND</text>
100
+ </g>
101
+ </svg>
@@ -0,0 +1,139 @@
1
+ import { NetLabelToTraceSolver } from "lib/solvers/NetLabelToTraceSolver/NetLabelToTraceSolver"
2
+ import { expect, test } from "bun:test"
3
+ import { SchematicTracePipelineSolver } from "lib/index"
4
+ import { findPerpendicularPathCrossings } from "lib/solvers/TraceCleanupSolver/sub-solver/findIntersectionsWithObstacles"
5
+ import type { InputProblem } from "lib/types/InputProblem"
6
+ import input from "../../assets/enc-scl-hop.json"
7
+ import "tests/fixtures/matcher"
8
+
9
+ const sclPins = ["R_ENC_SCL.2", "U_ENCODER.7"]
10
+ const solve = (problem: InputProblem) => {
11
+ const solver = new SchematicTracePipelineSolver(problem, {
12
+ hideRatsNet: true,
13
+ })
14
+ solver.solve()
15
+ expect(solver.solved).toBe(true)
16
+ return solver
17
+ }
18
+ const hasSclTrace = (solver: SchematicTracePipelineSolver) =>
19
+ solver
20
+ .netLabelToTraceSolver!.getOutput()
21
+ .traces.some((trace) =>
22
+ sclPins.every((pinId) => trace.pinIds.includes(pinId)),
23
+ )
24
+
25
+ // Geometry reconstructed from the ENC_SCL screenshot, not an exported input.
26
+ // SDA is explicitly wired; SCL is connected through its named net.
27
+ test("ENC_SCL routes across SDA instead of becoming two endpoint labels", () => {
28
+ const solver = solve(input as unknown as InputProblem)
29
+ const output = solver.netLabelToTraceSolver!.getOutput()
30
+ expect(
31
+ output.traces.some((trace) =>
32
+ ["R_ENC_SDA.2", "U_ENCODER.6"].every((pinId) =>
33
+ trace.pinIds.includes(pinId),
34
+ ),
35
+ ),
36
+ ).toBe(true)
37
+ expect(hasSclTrace(solver)).toBe(true)
38
+ expect(
39
+ output.netLabelPlacements.filter(
40
+ (label) => label.netId === "ENC_SCL" && label.pinIds.length === 1,
41
+ ),
42
+ ).toHaveLength(0)
43
+ expect(solver).toMatchSolverSnapshot(import.meta.path)
44
+ })
45
+
46
+ test("ENC_SCL recovers exactly one interior crossing of SDA", () => {
47
+ const solver = solve(input as unknown as InputProblem)
48
+ const traces = solver.netLabelToTraceSolver!.getOutput().traces
49
+ const scl = traces.find((trace) =>
50
+ sclPins.every((pinId) => trace.pinIds.includes(pinId)),
51
+ )!
52
+ const sda = traces.find((trace) => trace.pinIds.includes("R_ENC_SDA.2"))!
53
+ expect(
54
+ findPerpendicularPathCrossings(scl.tracePath, sda.tracePath, {
55
+ includeTerminalSegments: true,
56
+ }),
57
+ ).toHaveLength(1)
58
+ })
59
+
60
+ test("ENC_SCL control: explicit wiring produces the available hop", () => {
61
+ const problem = structuredClone(input) as unknown as InputProblem
62
+ problem.directConnections.push({
63
+ pinIds: [sclPins[0]!, sclPins[1]!],
64
+ netId: "ENC_SCL",
65
+ })
66
+ const solver = solve(problem)
67
+ expect(hasSclTrace(solver)).toBe(true)
68
+ const output = solver.netLabelToTraceSolver!.getOutput()
69
+ const scl = output.traces.find((trace) =>
70
+ sclPins.every((pinId) => trace.pinIds.includes(pinId)),
71
+ )!
72
+ const sda = output.traces.find((trace) =>
73
+ trace.pinIds.includes("R_ENC_SDA.2"),
74
+ )!
75
+ expect(
76
+ findPerpendicularPathCrossings(scl.tracePath, sda.tracePath, {
77
+ includeTerminalSegments: true,
78
+ }),
79
+ ).toHaveLength(1)
80
+ expect(solver).toMatchSolverSnapshot(import.meta.path, "explicit-hop")
81
+ })
82
+
83
+ test("ENC_SCL keeps labels when its elbow is blocked by a component", () => {
84
+ const problem = structuredClone(input) as unknown as InputProblem
85
+ problem.chips.push({
86
+ chipId: "BLOCKER",
87
+ center: { x: 2, y: 0.7 },
88
+ width: 0.5,
89
+ height: 0.5,
90
+ pins: [],
91
+ })
92
+ expect(hasSclTrace(solve(problem))).toBe(false)
93
+ })
94
+
95
+ test("ENC_SCL keeps labels across schematic sections", () => {
96
+ const problem = structuredClone(input) as unknown as InputProblem
97
+ problem.chips.find((chip) => chip.chipId === "R_ENC_SCL")!.sectionId =
98
+ "pullups"
99
+ problem.chips.find((chip) => chip.chipId === "U_ENCODER")!.sectionId =
100
+ "encoder"
101
+ expect(hasSclTrace(solve(problem))).toBe(false)
102
+ })
103
+
104
+ // Test the recovery stage directly so earlier routing cannot remove the obstacle.
105
+ test("ENC_SCL keeps labels when its elbow would require two hops", () => {
106
+ const pipeline = solve(input as unknown as InputProblem)
107
+ const stageInput = pipeline.netLabelToTraceSolver!.getConstructorParams()[0]
108
+ const sda = pipeline
109
+ .netLabelToTraceSolver!.getOutput()
110
+ .traces.find((trace) => trace.pinIds.includes("R_ENC_SDA.2"))!
111
+ const secondCrossing = {
112
+ ...sda,
113
+ mspPairId: "second-crossing",
114
+ globalConnNetId: "other-net",
115
+ tracePath: [
116
+ { x: 0, y: 0.7 },
117
+ { x: 4.72, y: 0.7 },
118
+ ],
119
+ }
120
+ const solver = new NetLabelToTraceSolver({
121
+ ...stageInput,
122
+ traces: [...stageInput.traces, sda, secondCrossing],
123
+ netLabelPlacements: stageInput.netLabelPlacements.filter(
124
+ (label) => label.netId !== "ENC_SDA",
125
+ ),
126
+ })
127
+ solver.solve()
128
+ expect(
129
+ solver
130
+ .getOutput()
131
+ .netLabelPlacements.filter((label) => label.netId === "ENC_SCL"),
132
+ ).toHaveLength(2)
133
+ })
134
+
135
+ test("ground nets keep endpoint labels instead of elbow recovery", () => {
136
+ const problem = structuredClone(input) as unknown as InputProblem
137
+ problem.netConnections.find((net) => net.netId === "ENC_SCL")!.isGround = true
138
+ expect(hasSclTrace(solve(problem))).toBe(false)
139
+ })