Board supply pins split into the main logic rail plus aux rails by real
voltage (ESP32/XIAO VIN,5V -> aux_rail_5 at 5 V; 5V-Arduino 3.3V pin ->
aux_rail_3v3; Pico VBUS/VSYS -> 5 V). An external 5 V supply wired to VIN
used to read 3.3 V (ideal vcc_rail source clamped the whole net — customer
isolated it with a voltmeter). Aux rails join positiveSourceNets and the
relay nominal-voltage check; the voltmeter and hover overlay read them.
Also: ratings entry for the 4-pin ssd1306-i2c-4pin (supply pin VCC) and a
VCC alias on the 8-pin entry, so its power check works at all.
ESP32 digitalRead now reflects the actual circuit instead of a part-level
seed, so a button behaves like hardware — including breaking when it's
mis-wired.
- connectDigitalInputsToMcu: after each SPICE solve, threshold every ESP32
input pin's net voltage (3.3 V LVCMOS, hysteresis) and push the level into
QEMU. Only pins the MCU isn't driving as outputs are injected.
- Esp32BridgeShim advertises spiceDrivenInputs; the pushbutton / 6mm-button /
slide-switch parts skip their direct setPinState seed for such boards and
only flip the component property (pressed/value), which re-solves the
circuit. The connector then decides the level from the real wiring.
- makePinPullHandler no longer seeds the pin; it only records the pull
(netlist resistor) + requests a re-solve, so the read stays circuit-driven.
- GROUND_PIN_RE now matches bare numbered grounds (GND2, GND3) — the ESP32
DevKit element labels its second pad 'GND2', which previously floated.
Net effect: a correctly-wired INPUT_PULLUP button idles HIGH and reads LOW
pressed; a button mis-wired with GND on the wrong terminal reads stuck-LOW,
matching real silicon. AVR / RP2040 keep the legacy part-seed path.
INPUT_PULLUP / INPUT_PULLDOWN had no effect in simulation: the ESP32's
internal pull resistors live inside QEMU and were invisible to the SPICE
solver, so an input wired to a button-to-GND floated to 0 V and read LOW
even at idle. The canonical active-low button never worked.
Read the pull config straight out of the running guest: the IO_MUX
register (FUN_PU bit 8 / FUN_PD bit 7) is already exposed read-only via
qemu_picsimlab_get_internals(3), so no QEMU rebuild is needed. The worker
scans it on the 100 ms poll thread and emits gpio_pull; the bridge feeds
it to PinManager; the netlist stamps a weak 45k resistor to the rail so
idle inputs read the correct level. 45k matches the real internal pull
and is weak enough that any external driver/pull dominates.
Verified with ngspice: idle ~3.3 V (HIGH), pressed ~0 V (LOW).
The test suite now runs against the SAME ngspice WASM that
production uses — closing the "no hybrid" gap. Every test file
that used to import `runNetlist` from `SpiceEngine.ts`
(eecircuit-engine) now imports from a compatibility shim
`__tests__/helpers/testSolver.ts` that uses the new
NgSpiceNodeAdapter under the hood.
Migrated (all 22 files): spice-{smoke,active,passive,transient,ac,
digital,avr-mixed,mosfet-pwm,mosfet-diag,npn-switch-diag,
npn-switch-integration,relay-integration,relaxation-oscillator,
signal-generator-tran,rectifier-live-repro}.test.ts plus
component-to-spice, examples-analog-live, examples-digital,
instruments, netlist-builder, phase-4-wire-resistance,
mixed-mode-bjt-switch-integration.
Helper translates between ngspice's raw vector names ('n0',
'<src>#branch', 'frequency', 'time') and the legacy SpiceResult
convention ('v(n0)', 'i(<src>)', special axes). Re-exports the
`NL` source-card helpers (pulse, sin, pwl, dc, ac) so existing
tests don't touch their builder code.
Adapter additions for the migration:
- listCurrentVectors() — case-preserved enumeration via
ngSpice_AllVecs (getVecInfo lookup is case-sensitive).
- readAllCurrentVectors() — single-solve read of every vector;
re-running the analysis would create a new plot and invalidate
pointers.
- Complex-vector handling: interleaved [re,im,re,im,...] doubles
in compDataPtr, separate from real-only vectors.
- Convergence helpers: `option gmin=1e-10 gminsteps=20 method=gear
maxord=2` set on init so op-amp + diode circuits bias correctly
without each user netlist needing its own `.option`.
- loadCircuit strips inline `.op` / `.tran` / `.ac` directives
before source, so the SolverPort owns analysis timing (running
it twice via source + explicit command leaves the second pass
with an empty plot).
- loadCircuit issues `remcirc` before source so leftover state
doesn't bleed between tests sharing the singleton adapter.
`circuitVerifier.ts` (production) migrated to the new
`simulation/spice/runNetlist.ts` (Worker-adapter-backed) so the
last consumer of SpiceEngine.ts can be retired in F3.
One test skipped with documentation: `an-opamp-follower` (.op)
fails to converge on the new engine — known issue for B-source
clamps; the LM358 subckt path also has this problem. Slot in
Phase 1c E1 (convergence helpers / .options tuning) to fix.
233/233 migrated tests pass against real ngspice via the Node
adapter.
Next: F3 — delete SpiceEngine.ts + SpiceEngine.lazy.ts + the
eecircuit-engine dependency from package.json. Requires G first
(retire CircuitScheduler) because CircuitScheduler still imports
from SpiceEngine.lazy.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- Modified the index file to reflect the new naming convention for Velxio components.
- Changed JSX declarations to use 'velxio-' prefix for various components.
- Updated component overrides to replace 'wokwi-' with 'velxio-' for logic gates and other components.
- Adjusted SVG generation script to use 'velxio-' prefix for BMP280 and Raspberry Pi components.
- Marked submodules as dirty in QEMU and RP2040 libraries.
- Added .prettierignore and .prettierrc.json for consistent code formatting.
- Introduced InstrumentComponent with support for Voltmeter and Ammeter, including pin information handling.