velxio/frontend/src/components/analog-ui/ElectricalOverlay.tsx

225 lines
7.3 KiB
TypeScript
Raw Normal View History

feat: electrical simulation via ngspice-WASM (eecircuit-engine) Adds full SPICE-accurate electrical simulation to Velxio, behind a lazy- loaded ⚡ toolbar toggle. Arduino / ESP32 / RP2040 sketches now co-simulate with real analog behaviour: correct voltages on wires, real I–V curves on LEDs, working potentiometers, NTC thermistors read by analogRead(), PWM driving RC filters, transistors, op-amps, diodes, MOSFETs, etc. Engine: eecircuit-engine (ngspice compiled to WebAssembly). Main bundle stays at 2.4 MB; the 20 MB SPICE chunk only loads when the user activates electrical mode. Disabled at build time via VITE_ELECTRICAL_SIM=false. Frontend additions: - simulation/spice/: SpiceEngine wrapper + lazy entry, NetlistBuilder with UnionFind over wires, componentToSpice mapping (24 metadataIds incl. real part numbers: 2N2222, 2N3055, BC547, IRF540, 2N7000, 1N4148, 1N4007, 1N4733, LEDs, NTC, op-amp ideal), CircuitScheduler with debounced coalescing, AVRSpiceBridge for quasi-static co-simulation. - store/useElectricalStore: Zustand slice, feature-flag aware. - components/analog-ui/: ⚡ toolbar toggle + SVG voltage overlay. - components/components-instruments/: Voltmeter, Ammeter probes. - 62 tests (spice-*, netlist-builder, component-to-spice, instruments). Sandbox (test/test_circuit/): 47-test validation sandbox that proved the approach (hand-rolled MNA baseline + ngspice pipeline) before porting to the app. Kept as reference. Docs: docs/wiki/circuit-emulation-*.md (13 engineering pages covering architecture, solvers, components, AVR bridge, gotchas, performance, integration plan, API reference, appendix) + electrical-simulation- user-guide.md (end-user facing). Reference plan: test/test_circuit/plan/phase_8_velxio_implementation.md Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-15 19:11:54 +07:00
/**
* Floating SVG overlay that renders voltage labels at wire midpoints.
* SPICE is always active; this overlay is visible whenever a solve has
* landed. Reads voltages from `useElectricalStore.nodeVoltages` (updated
* by the scheduler) and maps wires to nets via `buildWireNetMap`.
feat: electrical simulation via ngspice-WASM (eecircuit-engine) Adds full SPICE-accurate electrical simulation to Velxio, behind a lazy- loaded ⚡ toolbar toggle. Arduino / ESP32 / RP2040 sketches now co-simulate with real analog behaviour: correct voltages on wires, real I–V curves on LEDs, working potentiometers, NTC thermistors read by analogRead(), PWM driving RC filters, transistors, op-amps, diodes, MOSFETs, etc. Engine: eecircuit-engine (ngspice compiled to WebAssembly). Main bundle stays at 2.4 MB; the 20 MB SPICE chunk only loads when the user activates electrical mode. Disabled at build time via VITE_ELECTRICAL_SIM=false. Frontend additions: - simulation/spice/: SpiceEngine wrapper + lazy entry, NetlistBuilder with UnionFind over wires, componentToSpice mapping (24 metadataIds incl. real part numbers: 2N2222, 2N3055, BC547, IRF540, 2N7000, 1N4148, 1N4007, 1N4733, LEDs, NTC, op-amp ideal), CircuitScheduler with debounced coalescing, AVRSpiceBridge for quasi-static co-simulation. - store/useElectricalStore: Zustand slice, feature-flag aware. - components/analog-ui/: ⚡ toolbar toggle + SVG voltage overlay. - components/components-instruments/: Voltmeter, Ammeter probes. - 62 tests (spice-*, netlist-builder, component-to-spice, instruments). Sandbox (test/test_circuit/): 47-test validation sandbox that proved the approach (hand-rolled MNA baseline + ngspice pipeline) before porting to the app. Kept as reference. Docs: docs/wiki/circuit-emulation-*.md (13 engineering pages covering architecture, solvers, components, AVR bridge, gotchas, performance, integration plan, API reference, appendix) + electrical-simulation- user-guide.md (end-user facing). Reference plan: test/test_circuit/plan/phase_8_velxio_implementation.md Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-15 19:11:54 +07:00
*
* For nets with AC content (detected via `.tran` `timeWaveforms`) labels
* show `~<RMS>` prefixed with a tilde to mark them as time-varying. A
* summary pill in the top-left advertises DC vs AC analysis mode.
*
feat: electrical simulation via ngspice-WASM (eecircuit-engine) Adds full SPICE-accurate electrical simulation to Velxio, behind a lazy- loaded ⚡ toolbar toggle. Arduino / ESP32 / RP2040 sketches now co-simulate with real analog behaviour: correct voltages on wires, real I–V curves on LEDs, working potentiometers, NTC thermistors read by analogRead(), PWM driving RC filters, transistors, op-amps, diodes, MOSFETs, etc. Engine: eecircuit-engine (ngspice compiled to WebAssembly). Main bundle stays at 2.4 MB; the 20 MB SPICE chunk only loads when the user activates electrical mode. Disabled at build time via VITE_ELECTRICAL_SIM=false. Frontend additions: - simulation/spice/: SpiceEngine wrapper + lazy entry, NetlistBuilder with UnionFind over wires, componentToSpice mapping (24 metadataIds incl. real part numbers: 2N2222, 2N3055, BC547, IRF540, 2N7000, 1N4148, 1N4007, 1N4733, LEDs, NTC, op-amp ideal), CircuitScheduler with debounced coalescing, AVRSpiceBridge for quasi-static co-simulation. - store/useElectricalStore: Zustand slice, feature-flag aware. - components/analog-ui/: ⚡ toolbar toggle + SVG voltage overlay. - components/components-instruments/: Voltmeter, Ammeter probes. - 62 tests (spice-*, netlist-builder, component-to-spice, instruments). Sandbox (test/test_circuit/): 47-test validation sandbox that proved the approach (hand-rolled MNA baseline + ngspice pipeline) before porting to the app. Kept as reference. Docs: docs/wiki/circuit-emulation-*.md (13 engineering pages covering architecture, solvers, components, AVR bridge, gotchas, performance, integration plan, API reference, appendix) + electrical-simulation- user-guide.md (end-user facing). Reference plan: test/test_circuit/plan/phase_8_velxio_implementation.md Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-15 19:11:54 +07:00
* This is a read-only, zero-interactivity layer — it sits ABOVE the wire
* layer but below the component layer so labels remain legible without
* blocking clicks.
feat(breadboard): hover-gated labels + full-footprint seating solver Three changes, all driven by a real project where a 4-digit 7-segment clock was unreadable and half its parts were not actually seated. Labels on hover only -------------------- Eight vertical resistors at 19 px pitch rendered eight 93 px "Resistor 220 Ω" labels on top of each other, hiding the parts and the breadboard holes; the SPICE overlay added ~40 more `0uV` pills. Both are now revealed on hover: hovering a part also lights up the voltages of every wire touching it. The label is hidden with OPACITY and stays in flow. pinPositionCalculator derives the rotation pivot from wrapper.offsetHeight, so taking it out of flow would move the pins of every rotated component in every saved project. Seat-on-drop ------------ The drag-time magnet only aligned the anchor pin and assumed the rest followed, which is how parts ended up HALF-seated: some pins in holes, the rest dead in the air. It looks mounted in a screenshot and silently breaks the circuit. On release we now re-solve properly — nearest position where EVERY pin is in a free hole, sliding past occupied columns — via the new solvePlacement/seatOnDrop. Geometry comes from the element's own pinInfo, so there is no part whitelist. Sub-pitch translation --------------------- solvePlacement first assigned pins to holes at half-pitch, then translates by the centroid of the residuals before judging fit. Pinning the anchor dead centre refused every off-lattice footprint: a diode spans 7.5 pitches, so one leg landed 4.8 px out. Shifted 2.4 px, BOTH legs sit inside tolerance — what bending the leads does on a real board. Measured over the catalog this takes seatable parts from 87 to 125 of 152; diodes, transistors, regulators, optocouplers and flip-flops are rescued with no artwork change. Staying under SEAT_TOLERANCE (< half pitch) keeps each pin's nearest hole unambiguous, so computeSeating resolves the same holes and the netlist is unaffected by the small offset. Also: refuse a placement that would put two of a part's own pins in one strip. A column strip — and far worse, a power rail — is a single net, so such a seating shorts the part to itself. Without it a 7-segment happily lays its pins across a rail. And deduplicate pin names before solving: calculatePinPosition resolves by name and returns the first match, so a board carrying GND x5 collided with itself and was refused outright. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-19 10:28:40 +07:00
*
* Labels are HOVER-GATED. Showing every net at once buried dense boards
* (a 4-digit 7-segment clock draws ~40 wires, so ~40 `0uV` pills covered
* the breadboard). A label is drawn only when the user hovers its wire,
* or hovers a component/board that wire lands on — so pointing at a part
* reveals every voltage around it at once. The summary pill always shows.
feat: electrical simulation via ngspice-WASM (eecircuit-engine) Adds full SPICE-accurate electrical simulation to Velxio, behind a lazy- loaded ⚡ toolbar toggle. Arduino / ESP32 / RP2040 sketches now co-simulate with real analog behaviour: correct voltages on wires, real I–V curves on LEDs, working potentiometers, NTC thermistors read by analogRead(), PWM driving RC filters, transistors, op-amps, diodes, MOSFETs, etc. Engine: eecircuit-engine (ngspice compiled to WebAssembly). Main bundle stays at 2.4 MB; the 20 MB SPICE chunk only loads when the user activates electrical mode. Disabled at build time via VITE_ELECTRICAL_SIM=false. Frontend additions: - simulation/spice/: SpiceEngine wrapper + lazy entry, NetlistBuilder with UnionFind over wires, componentToSpice mapping (24 metadataIds incl. real part numbers: 2N2222, 2N3055, BC547, IRF540, 2N7000, 1N4148, 1N4007, 1N4733, LEDs, NTC, op-amp ideal), CircuitScheduler with debounced coalescing, AVRSpiceBridge for quasi-static co-simulation. - store/useElectricalStore: Zustand slice, feature-flag aware. - components/analog-ui/: ⚡ toolbar toggle + SVG voltage overlay. - components/components-instruments/: Voltmeter, Ammeter probes. - 62 tests (spice-*, netlist-builder, component-to-spice, instruments). Sandbox (test/test_circuit/): 47-test validation sandbox that proved the approach (hand-rolled MNA baseline + ngspice pipeline) before porting to the app. Kept as reference. Docs: docs/wiki/circuit-emulation-*.md (13 engineering pages covering architecture, solvers, components, AVR bridge, gotchas, performance, integration plan, API reference, appendix) + electrical-simulation- user-guide.md (end-user facing). Reference plan: test/test_circuit/plan/phase_8_velxio_implementation.md Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-15 19:11:54 +07:00
*/
import { useMemo } from 'react';
import { useElectricalStore } from '../../store/useElectricalStore';
import { useSimulatorStore } from '../../store/useSimulatorStore';
import { buildWireNetMap } from '../../simulation/spice/NetlistBuilder';
import { BOARD_PIN_GROUPS } from '../../simulation/spice/boardPinGroups';
import { rms, isAC } from '../../simulation/spice/waveformStats';
feat: electrical simulation via ngspice-WASM (eecircuit-engine) Adds full SPICE-accurate electrical simulation to Velxio, behind a lazy- loaded ⚡ toolbar toggle. Arduino / ESP32 / RP2040 sketches now co-simulate with real analog behaviour: correct voltages on wires, real I–V curves on LEDs, working potentiometers, NTC thermistors read by analogRead(), PWM driving RC filters, transistors, op-amps, diodes, MOSFETs, etc. Engine: eecircuit-engine (ngspice compiled to WebAssembly). Main bundle stays at 2.4 MB; the 20 MB SPICE chunk only loads when the user activates electrical mode. Disabled at build time via VITE_ELECTRICAL_SIM=false. Frontend additions: - simulation/spice/: SpiceEngine wrapper + lazy entry, NetlistBuilder with UnionFind over wires, componentToSpice mapping (24 metadataIds incl. real part numbers: 2N2222, 2N3055, BC547, IRF540, 2N7000, 1N4148, 1N4007, 1N4733, LEDs, NTC, op-amp ideal), CircuitScheduler with debounced coalescing, AVRSpiceBridge for quasi-static co-simulation. - store/useElectricalStore: Zustand slice, feature-flag aware. - components/analog-ui/: ⚡ toolbar toggle + SVG voltage overlay. - components/components-instruments/: Voltmeter, Ammeter probes. - 62 tests (spice-*, netlist-builder, component-to-spice, instruments). Sandbox (test/test_circuit/): 47-test validation sandbox that proved the approach (hand-rolled MNA baseline + ngspice pipeline) before porting to the app. Kept as reference. Docs: docs/wiki/circuit-emulation-*.md (13 engineering pages covering architecture, solvers, components, AVR bridge, gotchas, performance, integration plan, API reference, appendix) + electrical-simulation- user-guide.md (end-user facing). Reference plan: test/test_circuit/plan/phase_8_velxio_implementation.md Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-15 19:11:54 +07:00
function formatV(v: number): string {
const abs = Math.abs(v);
if (abs < 1e-3) return `${(v * 1e6).toFixed(0)}uV`;
feat: electrical simulation via ngspice-WASM (eecircuit-engine) Adds full SPICE-accurate electrical simulation to Velxio, behind a lazy- loaded ⚡ toolbar toggle. Arduino / ESP32 / RP2040 sketches now co-simulate with real analog behaviour: correct voltages on wires, real I–V curves on LEDs, working potentiometers, NTC thermistors read by analogRead(), PWM driving RC filters, transistors, op-amps, diodes, MOSFETs, etc. Engine: eecircuit-engine (ngspice compiled to WebAssembly). Main bundle stays at 2.4 MB; the 20 MB SPICE chunk only loads when the user activates electrical mode. Disabled at build time via VITE_ELECTRICAL_SIM=false. Frontend additions: - simulation/spice/: SpiceEngine wrapper + lazy entry, NetlistBuilder with UnionFind over wires, componentToSpice mapping (24 metadataIds incl. real part numbers: 2N2222, 2N3055, BC547, IRF540, 2N7000, 1N4148, 1N4007, 1N4733, LEDs, NTC, op-amp ideal), CircuitScheduler with debounced coalescing, AVRSpiceBridge for quasi-static co-simulation. - store/useElectricalStore: Zustand slice, feature-flag aware. - components/analog-ui/: ⚡ toolbar toggle + SVG voltage overlay. - components/components-instruments/: Voltmeter, Ammeter probes. - 62 tests (spice-*, netlist-builder, component-to-spice, instruments). Sandbox (test/test_circuit/): 47-test validation sandbox that proved the approach (hand-rolled MNA baseline + ngspice pipeline) before porting to the app. Kept as reference. Docs: docs/wiki/circuit-emulation-*.md (13 engineering pages covering architecture, solvers, components, AVR bridge, gotchas, performance, integration plan, API reference, appendix) + electrical-simulation- user-guide.md (end-user facing). Reference plan: test/test_circuit/plan/phase_8_velxio_implementation.md Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-15 19:11:54 +07:00
if (abs < 1) return `${(v * 1e3).toFixed(1)}mV`;
if (abs < 100) return `${v.toFixed(2)}V`;
return `${v.toFixed(1)}V`;
}
feat(breadboard): hover-gated labels + full-footprint seating solver Three changes, all driven by a real project where a 4-digit 7-segment clock was unreadable and half its parts were not actually seated. Labels on hover only -------------------- Eight vertical resistors at 19 px pitch rendered eight 93 px "Resistor 220 Ω" labels on top of each other, hiding the parts and the breadboard holes; the SPICE overlay added ~40 more `0uV` pills. Both are now revealed on hover: hovering a part also lights up the voltages of every wire touching it. The label is hidden with OPACITY and stays in flow. pinPositionCalculator derives the rotation pivot from wrapper.offsetHeight, so taking it out of flow would move the pins of every rotated component in every saved project. Seat-on-drop ------------ The drag-time magnet only aligned the anchor pin and assumed the rest followed, which is how parts ended up HALF-seated: some pins in holes, the rest dead in the air. It looks mounted in a screenshot and silently breaks the circuit. On release we now re-solve properly — nearest position where EVERY pin is in a free hole, sliding past occupied columns — via the new solvePlacement/seatOnDrop. Geometry comes from the element's own pinInfo, so there is no part whitelist. Sub-pitch translation --------------------- solvePlacement first assigned pins to holes at half-pitch, then translates by the centroid of the residuals before judging fit. Pinning the anchor dead centre refused every off-lattice footprint: a diode spans 7.5 pitches, so one leg landed 4.8 px out. Shifted 2.4 px, BOTH legs sit inside tolerance — what bending the leads does on a real board. Measured over the catalog this takes seatable parts from 87 to 125 of 152; diodes, transistors, regulators, optocouplers and flip-flops are rescued with no artwork change. Staying under SEAT_TOLERANCE (< half pitch) keeps each pin's nearest hole unambiguous, so computeSeating resolves the same holes and the netlist is unaffected by the small offset. Also: refuse a placement that would put two of a part's own pins in one strip. A column strip — and far worse, a power rail — is a single net, so such a seating shorts the part to itself. Without it a 7-segment happily lays its pins across a rail. And deduplicate pin names before solving: calculatePinPosition resolves by name and returns the first match, so a board carrying GND x5 collided with itself and was refused outright. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-19 10:28:40 +07:00
interface ElectricalOverlayProps {
/** Wire currently under the cursor (canvas-level hit test). */
hoveredWireId?: string | null;
/** Component under the cursor — reveals every wire touching it. */
hoveredComponentId?: string | null;
/** Board under the cursor — same, for wires landing on board pins. */
hoveredBoardId?: string | null;
}
export function ElectricalOverlay({
hoveredWireId = null,
hoveredComponentId = null,
hoveredBoardId = null,
}: ElectricalOverlayProps = {}) {
feat: electrical simulation via ngspice-WASM (eecircuit-engine) Adds full SPICE-accurate electrical simulation to Velxio, behind a lazy- loaded ⚡ toolbar toggle. Arduino / ESP32 / RP2040 sketches now co-simulate with real analog behaviour: correct voltages on wires, real I–V curves on LEDs, working potentiometers, NTC thermistors read by analogRead(), PWM driving RC filters, transistors, op-amps, diodes, MOSFETs, etc. Engine: eecircuit-engine (ngspice compiled to WebAssembly). Main bundle stays at 2.4 MB; the 20 MB SPICE chunk only loads when the user activates electrical mode. Disabled at build time via VITE_ELECTRICAL_SIM=false. Frontend additions: - simulation/spice/: SpiceEngine wrapper + lazy entry, NetlistBuilder with UnionFind over wires, componentToSpice mapping (24 metadataIds incl. real part numbers: 2N2222, 2N3055, BC547, IRF540, 2N7000, 1N4148, 1N4007, 1N4733, LEDs, NTC, op-amp ideal), CircuitScheduler with debounced coalescing, AVRSpiceBridge for quasi-static co-simulation. - store/useElectricalStore: Zustand slice, feature-flag aware. - components/analog-ui/: ⚡ toolbar toggle + SVG voltage overlay. - components/components-instruments/: Voltmeter, Ammeter probes. - 62 tests (spice-*, netlist-builder, component-to-spice, instruments). Sandbox (test/test_circuit/): 47-test validation sandbox that proved the approach (hand-rolled MNA baseline + ngspice pipeline) before porting to the app. Kept as reference. Docs: docs/wiki/circuit-emulation-*.md (13 engineering pages covering architecture, solvers, components, AVR bridge, gotchas, performance, integration plan, API reference, appendix) + electrical-simulation- user-guide.md (end-user facing). Reference plan: test/test_circuit/plan/phase_8_velxio_implementation.md Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-15 19:11:54 +07:00
const nodeVoltages = useElectricalStore((s) => s.nodeVoltages);
const converged = useElectricalStore((s) => s.converged);
const error = useElectricalStore((s) => s.error);
const solveMs = useElectricalStore((s) => s.lastSolveMs);
const analysisMode = useElectricalStore((s) => s.analysisMode);
const timeWaveforms = useElectricalStore((s) => s.timeWaveforms);
feat: electrical simulation via ngspice-WASM (eecircuit-engine) Adds full SPICE-accurate electrical simulation to Velxio, behind a lazy- loaded ⚡ toolbar toggle. Arduino / ESP32 / RP2040 sketches now co-simulate with real analog behaviour: correct voltages on wires, real I–V curves on LEDs, working potentiometers, NTC thermistors read by analogRead(), PWM driving RC filters, transistors, op-amps, diodes, MOSFETs, etc. Engine: eecircuit-engine (ngspice compiled to WebAssembly). Main bundle stays at 2.4 MB; the 20 MB SPICE chunk only loads when the user activates electrical mode. Disabled at build time via VITE_ELECTRICAL_SIM=false. Frontend additions: - simulation/spice/: SpiceEngine wrapper + lazy entry, NetlistBuilder with UnionFind over wires, componentToSpice mapping (24 metadataIds incl. real part numbers: 2N2222, 2N3055, BC547, IRF540, 2N7000, 1N4148, 1N4007, 1N4733, LEDs, NTC, op-amp ideal), CircuitScheduler with debounced coalescing, AVRSpiceBridge for quasi-static co-simulation. - store/useElectricalStore: Zustand slice, feature-flag aware. - components/analog-ui/: ⚡ toolbar toggle + SVG voltage overlay. - components/components-instruments/: Voltmeter, Ammeter probes. - 62 tests (spice-*, netlist-builder, component-to-spice, instruments). Sandbox (test/test_circuit/): 47-test validation sandbox that proved the approach (hand-rolled MNA baseline + ngspice pipeline) before porting to the app. Kept as reference. Docs: docs/wiki/circuit-emulation-*.md (13 engineering pages covering architecture, solvers, components, AVR bridge, gotchas, performance, integration plan, API reference, appendix) + electrical-simulation- user-guide.md (end-user facing). Reference plan: test/test_circuit/plan/phase_8_velxio_implementation.md Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-15 19:11:54 +07:00
const wires = useSimulatorStore((s) => s.wires);
const components = useSimulatorStore((s) => s.components);
const boards = useSimulatorStore((s) => s.boards);
feat: electrical simulation via ngspice-WASM (eecircuit-engine) Adds full SPICE-accurate electrical simulation to Velxio, behind a lazy- loaded ⚡ toolbar toggle. Arduino / ESP32 / RP2040 sketches now co-simulate with real analog behaviour: correct voltages on wires, real I–V curves on LEDs, working potentiometers, NTC thermistors read by analogRead(), PWM driving RC filters, transistors, op-amps, diodes, MOSFETs, etc. Engine: eecircuit-engine (ngspice compiled to WebAssembly). Main bundle stays at 2.4 MB; the 20 MB SPICE chunk only loads when the user activates electrical mode. Disabled at build time via VITE_ELECTRICAL_SIM=false. Frontend additions: - simulation/spice/: SpiceEngine wrapper + lazy entry, NetlistBuilder with UnionFind over wires, componentToSpice mapping (24 metadataIds incl. real part numbers: 2N2222, 2N3055, BC547, IRF540, 2N7000, 1N4148, 1N4007, 1N4733, LEDs, NTC, op-amp ideal), CircuitScheduler with debounced coalescing, AVRSpiceBridge for quasi-static co-simulation. - store/useElectricalStore: Zustand slice, feature-flag aware. - components/analog-ui/: ⚡ toolbar toggle + SVG voltage overlay. - components/components-instruments/: Voltmeter, Ammeter probes. - 62 tests (spice-*, netlist-builder, component-to-spice, instruments). Sandbox (test/test_circuit/): 47-test validation sandbox that proved the approach (hand-rolled MNA baseline + ngspice pipeline) before porting to the app. Kept as reference. Docs: docs/wiki/circuit-emulation-*.md (13 engineering pages covering architecture, solvers, components, AVR bridge, gotchas, performance, integration plan, API reference, appendix) + electrical-simulation- user-guide.md (end-user facing). Reference plan: test/test_circuit/plan/phase_8_velxio_implementation.md Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-15 19:11:54 +07:00
const labels = useMemo(() => {
if (Object.keys(nodeVoltages).length === 0) return [];
const boardsForSpice = boards.map((b) => {
const pg = BOARD_PIN_GROUPS[b.boardKind] ?? BOARD_PIN_GROUPS.default;
return {
id: b.id,
vcc: pg.vcc,
groundPinNames: pg.gnd,
vccPinNames: pg.vcc_pins,
auxPinNames: pg.aux?.pins,
auxVolts: pg.aux?.volts,
pins: {},
};
});
const compsForSpice = components.map((c) => ({
id: c.id,
metadataId: c.metadataId,
properties: c.properties ?? {},
}));
const wiresForSpice = wires.map((w) => ({
id: w.id,
start: { componentId: w.start.componentId, pinName: w.start.pinName },
end: { componentId: w.end.componentId, pinName: w.end.pinName },
}));
const wireNetMap = buildWireNetMap({
components: compsForSpice,
wires: wiresForSpice,
boards: boardsForSpice,
});
return wires
.map((w) => {
const mx = (w.start.x + w.end.x) / 2;
const my = (w.start.y + w.end.y) / 2;
const netName = wireNetMap.get(w.id);
const samples = netName ? timeWaveforms?.nodes.get(netName) : undefined;
const ac = samples && samples.length > 0 && isAC(samples);
const displayV = ac ? rms(samples!) : netName ? nodeVoltages[netName] : undefined;
feat(breadboard): hover-gated labels + full-footprint seating solver Three changes, all driven by a real project where a 4-digit 7-segment clock was unreadable and half its parts were not actually seated. Labels on hover only -------------------- Eight vertical resistors at 19 px pitch rendered eight 93 px "Resistor 220 Ω" labels on top of each other, hiding the parts and the breadboard holes; the SPICE overlay added ~40 more `0uV` pills. Both are now revealed on hover: hovering a part also lights up the voltages of every wire touching it. The label is hidden with OPACITY and stays in flow. pinPositionCalculator derives the rotation pivot from wrapper.offsetHeight, so taking it out of flow would move the pins of every rotated component in every saved project. Seat-on-drop ------------ The drag-time magnet only aligned the anchor pin and assumed the rest followed, which is how parts ended up HALF-seated: some pins in holes, the rest dead in the air. It looks mounted in a screenshot and silently breaks the circuit. On release we now re-solve properly — nearest position where EVERY pin is in a free hole, sliding past occupied columns — via the new solvePlacement/seatOnDrop. Geometry comes from the element's own pinInfo, so there is no part whitelist. Sub-pitch translation --------------------- solvePlacement first assigned pins to holes at half-pitch, then translates by the centroid of the residuals before judging fit. Pinning the anchor dead centre refused every off-lattice footprint: a diode spans 7.5 pitches, so one leg landed 4.8 px out. Shifted 2.4 px, BOTH legs sit inside tolerance — what bending the leads does on a real board. Measured over the catalog this takes seatable parts from 87 to 125 of 152; diodes, transistors, regulators, optocouplers and flip-flops are rescued with no artwork change. Staying under SEAT_TOLERANCE (< half pitch) keeps each pin's nearest hole unambiguous, so computeSeating resolves the same holes and the netlist is unaffected by the small offset. Also: refuse a placement that would put two of a part's own pins in one strip. A column strip — and far worse, a power rail — is a single net, so such a seating shorts the part to itself. Without it a 7-segment happily lays its pins across a rail. And deduplicate pin names before solving: calculatePinPosition resolves by name and returns the first match, so a board carrying GND x5 collided with itself and was refused outright. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-19 10:28:40 +07:00
return {
id: w.id,
x: mx,
y: my,
v: displayV,
netName,
ac,
// Endpoint owners, so hovering a part can reveal its wires.
a: w.start.componentId,
b: w.end.componentId,
};
})
.filter((l) => l.v !== undefined && l.netName !== '0');
}, [wires, components, boards, nodeVoltages, timeWaveforms]);
feat(breadboard): hover-gated labels + full-footprint seating solver Three changes, all driven by a real project where a 4-digit 7-segment clock was unreadable and half its parts were not actually seated. Labels on hover only -------------------- Eight vertical resistors at 19 px pitch rendered eight 93 px "Resistor 220 Ω" labels on top of each other, hiding the parts and the breadboard holes; the SPICE overlay added ~40 more `0uV` pills. Both are now revealed on hover: hovering a part also lights up the voltages of every wire touching it. The label is hidden with OPACITY and stays in flow. pinPositionCalculator derives the rotation pivot from wrapper.offsetHeight, so taking it out of flow would move the pins of every rotated component in every saved project. Seat-on-drop ------------ The drag-time magnet only aligned the anchor pin and assumed the rest followed, which is how parts ended up HALF-seated: some pins in holes, the rest dead in the air. It looks mounted in a screenshot and silently breaks the circuit. On release we now re-solve properly — nearest position where EVERY pin is in a free hole, sliding past occupied columns — via the new solvePlacement/seatOnDrop. Geometry comes from the element's own pinInfo, so there is no part whitelist. Sub-pitch translation --------------------- solvePlacement first assigned pins to holes at half-pitch, then translates by the centroid of the residuals before judging fit. Pinning the anchor dead centre refused every off-lattice footprint: a diode spans 7.5 pitches, so one leg landed 4.8 px out. Shifted 2.4 px, BOTH legs sit inside tolerance — what bending the leads does on a real board. Measured over the catalog this takes seatable parts from 87 to 125 of 152; diodes, transistors, regulators, optocouplers and flip-flops are rescued with no artwork change. Staying under SEAT_TOLERANCE (< half pitch) keeps each pin's nearest hole unambiguous, so computeSeating resolves the same holes and the netlist is unaffected by the small offset. Also: refuse a placement that would put two of a part's own pins in one strip. A column strip — and far worse, a power rail — is a single net, so such a seating shorts the part to itself. Without it a 7-segment happily lays its pins across a rail. And deduplicate pin names before solving: calculatePinPosition resolves by name and returns the first match, so a board carrying GND x5 collided with itself and was refused outright. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-19 10:28:40 +07:00
// Hover gate kept in its own memo: the netlist rebuild above is expensive
// and must not re-run every time the cursor moves.
const visibleLabels = useMemo(() => {
if (!hoveredWireId && !hoveredComponentId && !hoveredBoardId) return [];
return labels.filter(
(l) =>
l.id === hoveredWireId ||
(hoveredComponentId !== null && (l.a === hoveredComponentId || l.b === hoveredComponentId)) ||
(hoveredBoardId !== null && (l.a === hoveredBoardId || l.b === hoveredBoardId)),
);
}, [labels, hoveredWireId, hoveredComponentId, hoveredBoardId]);
const modeBadge = analysisMode === 'tran' ? 'AC' : 'DC';
const badgeColor = analysisMode === 'tran' ? '#4dd0e1' : '#ffa500';
feat: electrical simulation via ngspice-WASM (eecircuit-engine) Adds full SPICE-accurate electrical simulation to Velxio, behind a lazy- loaded ⚡ toolbar toggle. Arduino / ESP32 / RP2040 sketches now co-simulate with real analog behaviour: correct voltages on wires, real I–V curves on LEDs, working potentiometers, NTC thermistors read by analogRead(), PWM driving RC filters, transistors, op-amps, diodes, MOSFETs, etc. Engine: eecircuit-engine (ngspice compiled to WebAssembly). Main bundle stays at 2.4 MB; the 20 MB SPICE chunk only loads when the user activates electrical mode. Disabled at build time via VITE_ELECTRICAL_SIM=false. Frontend additions: - simulation/spice/: SpiceEngine wrapper + lazy entry, NetlistBuilder with UnionFind over wires, componentToSpice mapping (24 metadataIds incl. real part numbers: 2N2222, 2N3055, BC547, IRF540, 2N7000, 1N4148, 1N4007, 1N4733, LEDs, NTC, op-amp ideal), CircuitScheduler with debounced coalescing, AVRSpiceBridge for quasi-static co-simulation. - store/useElectricalStore: Zustand slice, feature-flag aware. - components/analog-ui/: ⚡ toolbar toggle + SVG voltage overlay. - components/components-instruments/: Voltmeter, Ammeter probes. - 62 tests (spice-*, netlist-builder, component-to-spice, instruments). Sandbox (test/test_circuit/): 47-test validation sandbox that proved the approach (hand-rolled MNA baseline + ngspice pipeline) before porting to the app. Kept as reference. Docs: docs/wiki/circuit-emulation-*.md (13 engineering pages covering architecture, solvers, components, AVR bridge, gotchas, performance, integration plan, API reference, appendix) + electrical-simulation- user-guide.md (end-user facing). Reference plan: test/test_circuit/plan/phase_8_velxio_implementation.md Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-15 19:11:54 +07:00
const summaryLines: string[] = [];
if (error) summaryLines.push(`Warning: ${error}`);
else if (!converged) summaryLines.push('Warning: did not converge');
feat: electrical simulation via ngspice-WASM (eecircuit-engine) Adds full SPICE-accurate electrical simulation to Velxio, behind a lazy- loaded ⚡ toolbar toggle. Arduino / ESP32 / RP2040 sketches now co-simulate with real analog behaviour: correct voltages on wires, real I–V curves on LEDs, working potentiometers, NTC thermistors read by analogRead(), PWM driving RC filters, transistors, op-amps, diodes, MOSFETs, etc. Engine: eecircuit-engine (ngspice compiled to WebAssembly). Main bundle stays at 2.4 MB; the 20 MB SPICE chunk only loads when the user activates electrical mode. Disabled at build time via VITE_ELECTRICAL_SIM=false. Frontend additions: - simulation/spice/: SpiceEngine wrapper + lazy entry, NetlistBuilder with UnionFind over wires, componentToSpice mapping (24 metadataIds incl. real part numbers: 2N2222, 2N3055, BC547, IRF540, 2N7000, 1N4148, 1N4007, 1N4733, LEDs, NTC, op-amp ideal), CircuitScheduler with debounced coalescing, AVRSpiceBridge for quasi-static co-simulation. - store/useElectricalStore: Zustand slice, feature-flag aware. - components/analog-ui/: ⚡ toolbar toggle + SVG voltage overlay. - components/components-instruments/: Voltmeter, Ammeter probes. - 62 tests (spice-*, netlist-builder, component-to-spice, instruments). Sandbox (test/test_circuit/): 47-test validation sandbox that proved the approach (hand-rolled MNA baseline + ngspice pipeline) before porting to the app. Kept as reference. Docs: docs/wiki/circuit-emulation-*.md (13 engineering pages covering architecture, solvers, components, AVR bridge, gotchas, performance, integration plan, API reference, appendix) + electrical-simulation- user-guide.md (end-user facing). Reference plan: test/test_circuit/plan/phase_8_velxio_implementation.md Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-15 19:11:54 +07:00
else {
const n = Object.keys(nodeVoltages).length;
summaryLines.push(`${n} nets | ${solveMs.toFixed(0)} ms`);
feat: electrical simulation via ngspice-WASM (eecircuit-engine) Adds full SPICE-accurate electrical simulation to Velxio, behind a lazy- loaded ⚡ toolbar toggle. Arduino / ESP32 / RP2040 sketches now co-simulate with real analog behaviour: correct voltages on wires, real I–V curves on LEDs, working potentiometers, NTC thermistors read by analogRead(), PWM driving RC filters, transistors, op-amps, diodes, MOSFETs, etc. Engine: eecircuit-engine (ngspice compiled to WebAssembly). Main bundle stays at 2.4 MB; the 20 MB SPICE chunk only loads when the user activates electrical mode. Disabled at build time via VITE_ELECTRICAL_SIM=false. Frontend additions: - simulation/spice/: SpiceEngine wrapper + lazy entry, NetlistBuilder with UnionFind over wires, componentToSpice mapping (24 metadataIds incl. real part numbers: 2N2222, 2N3055, BC547, IRF540, 2N7000, 1N4148, 1N4007, 1N4733, LEDs, NTC, op-amp ideal), CircuitScheduler with debounced coalescing, AVRSpiceBridge for quasi-static co-simulation. - store/useElectricalStore: Zustand slice, feature-flag aware. - components/analog-ui/: ⚡ toolbar toggle + SVG voltage overlay. - components/components-instruments/: Voltmeter, Ammeter probes. - 62 tests (spice-*, netlist-builder, component-to-spice, instruments). Sandbox (test/test_circuit/): 47-test validation sandbox that proved the approach (hand-rolled MNA baseline + ngspice pipeline) before porting to the app. Kept as reference. Docs: docs/wiki/circuit-emulation-*.md (13 engineering pages covering architecture, solvers, components, AVR bridge, gotchas, performance, integration plan, API reference, appendix) + electrical-simulation- user-guide.md (end-user facing). Reference plan: test/test_circuit/plan/phase_8_velxio_implementation.md Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-15 19:11:54 +07:00
}
return (
<svg
style={{
position: 'absolute',
top: 0,
left: 0,
width: '100%',
height: '100%',
pointerEvents: 'none',
zIndex: 20,
}}
>
{/* Summary pill with AC/DC badge */}
feat: electrical simulation via ngspice-WASM (eecircuit-engine) Adds full SPICE-accurate electrical simulation to Velxio, behind a lazy- loaded ⚡ toolbar toggle. Arduino / ESP32 / RP2040 sketches now co-simulate with real analog behaviour: correct voltages on wires, real I–V curves on LEDs, working potentiometers, NTC thermistors read by analogRead(), PWM driving RC filters, transistors, op-amps, diodes, MOSFETs, etc. Engine: eecircuit-engine (ngspice compiled to WebAssembly). Main bundle stays at 2.4 MB; the 20 MB SPICE chunk only loads when the user activates electrical mode. Disabled at build time via VITE_ELECTRICAL_SIM=false. Frontend additions: - simulation/spice/: SpiceEngine wrapper + lazy entry, NetlistBuilder with UnionFind over wires, componentToSpice mapping (24 metadataIds incl. real part numbers: 2N2222, 2N3055, BC547, IRF540, 2N7000, 1N4148, 1N4007, 1N4733, LEDs, NTC, op-amp ideal), CircuitScheduler with debounced coalescing, AVRSpiceBridge for quasi-static co-simulation. - store/useElectricalStore: Zustand slice, feature-flag aware. - components/analog-ui/: ⚡ toolbar toggle + SVG voltage overlay. - components/components-instruments/: Voltmeter, Ammeter probes. - 62 tests (spice-*, netlist-builder, component-to-spice, instruments). Sandbox (test/test_circuit/): 47-test validation sandbox that proved the approach (hand-rolled MNA baseline + ngspice pipeline) before porting to the app. Kept as reference. Docs: docs/wiki/circuit-emulation-*.md (13 engineering pages covering architecture, solvers, components, AVR bridge, gotchas, performance, integration plan, API reference, appendix) + electrical-simulation- user-guide.md (end-user facing). Reference plan: test/test_circuit/plan/phase_8_velxio_implementation.md Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-15 19:11:54 +07:00
<g transform="translate(12, 12)">
<rect
x={0}
y={0}
rx={4}
ry={4}
width={250}
height={24}
feat: electrical simulation via ngspice-WASM (eecircuit-engine) Adds full SPICE-accurate electrical simulation to Velxio, behind a lazy- loaded ⚡ toolbar toggle. Arduino / ESP32 / RP2040 sketches now co-simulate with real analog behaviour: correct voltages on wires, real I–V curves on LEDs, working potentiometers, NTC thermistors read by analogRead(), PWM driving RC filters, transistors, op-amps, diodes, MOSFETs, etc. Engine: eecircuit-engine (ngspice compiled to WebAssembly). Main bundle stays at 2.4 MB; the 20 MB SPICE chunk only loads when the user activates electrical mode. Disabled at build time via VITE_ELECTRICAL_SIM=false. Frontend additions: - simulation/spice/: SpiceEngine wrapper + lazy entry, NetlistBuilder with UnionFind over wires, componentToSpice mapping (24 metadataIds incl. real part numbers: 2N2222, 2N3055, BC547, IRF540, 2N7000, 1N4148, 1N4007, 1N4733, LEDs, NTC, op-amp ideal), CircuitScheduler with debounced coalescing, AVRSpiceBridge for quasi-static co-simulation. - store/useElectricalStore: Zustand slice, feature-flag aware. - components/analog-ui/: ⚡ toolbar toggle + SVG voltage overlay. - components/components-instruments/: Voltmeter, Ammeter probes. - 62 tests (spice-*, netlist-builder, component-to-spice, instruments). Sandbox (test/test_circuit/): 47-test validation sandbox that proved the approach (hand-rolled MNA baseline + ngspice pipeline) before porting to the app. Kept as reference. Docs: docs/wiki/circuit-emulation-*.md (13 engineering pages covering architecture, solvers, components, AVR bridge, gotchas, performance, integration plan, API reference, appendix) + electrical-simulation- user-guide.md (end-user facing). Reference plan: test/test_circuit/plan/phase_8_velxio_implementation.md Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-15 19:11:54 +07:00
fill="rgba(26, 26, 26, 0.85)"
stroke={error ? '#ff6666' : badgeColor}
feat: electrical simulation via ngspice-WASM (eecircuit-engine) Adds full SPICE-accurate electrical simulation to Velxio, behind a lazy- loaded ⚡ toolbar toggle. Arduino / ESP32 / RP2040 sketches now co-simulate with real analog behaviour: correct voltages on wires, real I–V curves on LEDs, working potentiometers, NTC thermistors read by analogRead(), PWM driving RC filters, transistors, op-amps, diodes, MOSFETs, etc. Engine: eecircuit-engine (ngspice compiled to WebAssembly). Main bundle stays at 2.4 MB; the 20 MB SPICE chunk only loads when the user activates electrical mode. Disabled at build time via VITE_ELECTRICAL_SIM=false. Frontend additions: - simulation/spice/: SpiceEngine wrapper + lazy entry, NetlistBuilder with UnionFind over wires, componentToSpice mapping (24 metadataIds incl. real part numbers: 2N2222, 2N3055, BC547, IRF540, 2N7000, 1N4148, 1N4007, 1N4733, LEDs, NTC, op-amp ideal), CircuitScheduler with debounced coalescing, AVRSpiceBridge for quasi-static co-simulation. - store/useElectricalStore: Zustand slice, feature-flag aware. - components/analog-ui/: ⚡ toolbar toggle + SVG voltage overlay. - components/components-instruments/: Voltmeter, Ammeter probes. - 62 tests (spice-*, netlist-builder, component-to-spice, instruments). Sandbox (test/test_circuit/): 47-test validation sandbox that proved the approach (hand-rolled MNA baseline + ngspice pipeline) before porting to the app. Kept as reference. Docs: docs/wiki/circuit-emulation-*.md (13 engineering pages covering architecture, solvers, components, AVR bridge, gotchas, performance, integration plan, API reference, appendix) + electrical-simulation- user-guide.md (end-user facing). Reference plan: test/test_circuit/plan/phase_8_velxio_implementation.md Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-15 19:11:54 +07:00
/>
<rect
x={4}
y={4}
rx={2}
ry={2}
width={22}
height={16}
fill={badgeColor}
opacity={0.2}
stroke={badgeColor}
/>
<text
x={15}
y={16}
fontSize={10}
fill={badgeColor}
fontFamily="monospace"
textAnchor="middle"
fontWeight="bold"
>
{modeBadge}
</text>
<text
x={32}
y={17}
fontSize={11}
fill={error ? '#ff9999' : '#ffa500'}
fontFamily="monospace"
>
SPICE {summaryLines.join(' ')}
feat: electrical simulation via ngspice-WASM (eecircuit-engine) Adds full SPICE-accurate electrical simulation to Velxio, behind a lazy- loaded ⚡ toolbar toggle. Arduino / ESP32 / RP2040 sketches now co-simulate with real analog behaviour: correct voltages on wires, real I–V curves on LEDs, working potentiometers, NTC thermistors read by analogRead(), PWM driving RC filters, transistors, op-amps, diodes, MOSFETs, etc. Engine: eecircuit-engine (ngspice compiled to WebAssembly). Main bundle stays at 2.4 MB; the 20 MB SPICE chunk only loads when the user activates electrical mode. Disabled at build time via VITE_ELECTRICAL_SIM=false. Frontend additions: - simulation/spice/: SpiceEngine wrapper + lazy entry, NetlistBuilder with UnionFind over wires, componentToSpice mapping (24 metadataIds incl. real part numbers: 2N2222, 2N3055, BC547, IRF540, 2N7000, 1N4148, 1N4007, 1N4733, LEDs, NTC, op-amp ideal), CircuitScheduler with debounced coalescing, AVRSpiceBridge for quasi-static co-simulation. - store/useElectricalStore: Zustand slice, feature-flag aware. - components/analog-ui/: ⚡ toolbar toggle + SVG voltage overlay. - components/components-instruments/: Voltmeter, Ammeter probes. - 62 tests (spice-*, netlist-builder, component-to-spice, instruments). Sandbox (test/test_circuit/): 47-test validation sandbox that proved the approach (hand-rolled MNA baseline + ngspice pipeline) before porting to the app. Kept as reference. Docs: docs/wiki/circuit-emulation-*.md (13 engineering pages covering architecture, solvers, components, AVR bridge, gotchas, performance, integration plan, API reference, appendix) + electrical-simulation- user-guide.md (end-user facing). Reference plan: test/test_circuit/plan/phase_8_velxio_implementation.md Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-15 19:11:54 +07:00
</text>
</g>
feat(breadboard): hover-gated labels + full-footprint seating solver Three changes, all driven by a real project where a 4-digit 7-segment clock was unreadable and half its parts were not actually seated. Labels on hover only -------------------- Eight vertical resistors at 19 px pitch rendered eight 93 px "Resistor 220 Ω" labels on top of each other, hiding the parts and the breadboard holes; the SPICE overlay added ~40 more `0uV` pills. Both are now revealed on hover: hovering a part also lights up the voltages of every wire touching it. The label is hidden with OPACITY and stays in flow. pinPositionCalculator derives the rotation pivot from wrapper.offsetHeight, so taking it out of flow would move the pins of every rotated component in every saved project. Seat-on-drop ------------ The drag-time magnet only aligned the anchor pin and assumed the rest followed, which is how parts ended up HALF-seated: some pins in holes, the rest dead in the air. It looks mounted in a screenshot and silently breaks the circuit. On release we now re-solve properly — nearest position where EVERY pin is in a free hole, sliding past occupied columns — via the new solvePlacement/seatOnDrop. Geometry comes from the element's own pinInfo, so there is no part whitelist. Sub-pitch translation --------------------- solvePlacement first assigned pins to holes at half-pitch, then translates by the centroid of the residuals before judging fit. Pinning the anchor dead centre refused every off-lattice footprint: a diode spans 7.5 pitches, so one leg landed 4.8 px out. Shifted 2.4 px, BOTH legs sit inside tolerance — what bending the leads does on a real board. Measured over the catalog this takes seatable parts from 87 to 125 of 152; diodes, transistors, regulators, optocouplers and flip-flops are rescued with no artwork change. Staying under SEAT_TOLERANCE (< half pitch) keeps each pin's nearest hole unambiguous, so computeSeating resolves the same holes and the netlist is unaffected by the small offset. Also: refuse a placement that would put two of a part's own pins in one strip. A column strip — and far worse, a power rail — is a single net, so such a seating shorts the part to itself. Without it a 7-segment happily lays its pins across a rail. And deduplicate pin names before solving: calculatePinPosition resolves by name and returns the first match, so a board carrying GND x5 collided with itself and was refused outright. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-19 10:28:40 +07:00
{/* Per-wire voltage labels — only for what the cursor is on */}
{visibleLabels.map((l) => (
<g key={l.id} transform={`translate(${l.x}, ${l.y})`}>
<rect
x={-22}
y={-9}
rx={3}
ry={3}
width={44}
height={16}
fill="rgba(0, 0, 0, 0.75)"
stroke={l.ac ? '#4dd0e1' : 'none'}
strokeWidth={l.ac ? 0.5 : 0}
/>
<text
x={0}
y={4}
textAnchor="middle"
fontSize={10}
fontFamily="monospace"
fill={l.ac ? '#4dd0e1' : '#ffd700'}
>
{l.ac ? `~${formatV(l.v!)}` : formatV(l.v!)}
</text>
</g>
feat: electrical simulation via ngspice-WASM (eecircuit-engine) Adds full SPICE-accurate electrical simulation to Velxio, behind a lazy- loaded ⚡ toolbar toggle. Arduino / ESP32 / RP2040 sketches now co-simulate with real analog behaviour: correct voltages on wires, real I–V curves on LEDs, working potentiometers, NTC thermistors read by analogRead(), PWM driving RC filters, transistors, op-amps, diodes, MOSFETs, etc. Engine: eecircuit-engine (ngspice compiled to WebAssembly). Main bundle stays at 2.4 MB; the 20 MB SPICE chunk only loads when the user activates electrical mode. Disabled at build time via VITE_ELECTRICAL_SIM=false. Frontend additions: - simulation/spice/: SpiceEngine wrapper + lazy entry, NetlistBuilder with UnionFind over wires, componentToSpice mapping (24 metadataIds incl. real part numbers: 2N2222, 2N3055, BC547, IRF540, 2N7000, 1N4148, 1N4007, 1N4733, LEDs, NTC, op-amp ideal), CircuitScheduler with debounced coalescing, AVRSpiceBridge for quasi-static co-simulation. - store/useElectricalStore: Zustand slice, feature-flag aware. - components/analog-ui/: ⚡ toolbar toggle + SVG voltage overlay. - components/components-instruments/: Voltmeter, Ammeter probes. - 62 tests (spice-*, netlist-builder, component-to-spice, instruments). Sandbox (test/test_circuit/): 47-test validation sandbox that proved the approach (hand-rolled MNA baseline + ngspice pipeline) before porting to the app. Kept as reference. Docs: docs/wiki/circuit-emulation-*.md (13 engineering pages covering architecture, solvers, components, AVR bridge, gotchas, performance, integration plan, API reference, appendix) + electrical-simulation- user-guide.md (end-user facing). Reference plan: test/test_circuit/plan/phase_8_velxio_implementation.md Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-15 19:11:54 +07:00
))}
</svg>
);
}