Replaces the truncated 4-5 param NPN/PNP/D models in componentToSpice.ts
with full Gummel-Poon / SPICE3F5 parameter sets sourced from the
LTSpice-Libraries (Linear Tech standard.bjt and standard.dio). Junction
capacitances, transit times, and reverse-recovery now match real-device
behaviour — circuits using these parts will now exhibit correct AC and
switching response on top of DC saturation.
Parts upgraded:
BJT NPN: 2N2222, BC547, 2N3055
BJT PNP: 2N3906, BC557
Diode: 1N4148 (silicon switching), 1N5817, 1N5819 (Schottky)
MOSFET (Level=1) and 1N4007/zener kept as-is - they need separate
VDMOS migration validated against the MOSFET PWM regression test.
Phase 2.0 of the mixed-mode simulator project. See
velxio-prod/project/sim-mixedmode/phase-02-device-models.md.
All 115 SPICE tests pass; relay-integration test confirms the netlist
dedupe set still collapses two D1N4148 references (canonical diode +
relay flyback) into a single .model line.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Adds the architecture pieces for mixed-mode coupling without yet
driving the SPICE engine. Components on a path that crosses an active
device (BJT, MOSFET, op-amp, diode, regulator, LED, relay) now route
through a new SPICE-resolved PinResolver variant; everything else
keeps the digital fast-path from Phase 0.
What ships:
- simulation/PinResolver.ts
* `isActiveDevice(metadataId)` predicate + `ACTIVE_DEVICE_PREFIXES`
list (BJTs, MOSFETs, op-amps, diodes, regulators, LED, relay).
* `DetailedPinTrace` / `DetailedPinTracer` types — the trace
function now reports whether it crossed an active device, on
top of the Arduino pin number.
* `createSpiceResolvedPinResolver()` — new factory; reads voltages
from a `SpiceVoltageSource` and threshold-converts to HIGH/LOW
with hysteresis (thresholdHigh != thresholdLow → Schmitt-like).
- simulation/spice/MixedModeScheduler.ts (new)
* Singleton orchestrator that holds the NgSpiceInteractive engine
and the SpiceVoltageSource subscription registry.
* `start()` / `stop()` / `dispose()` lifecycle.
* `subscribe()` + `getCurrentVoltage()` implement SpiceVoltageSource.
* `onMcuPinChange()` placeholder for the alter+tran event loop.
* Skeleton: subscribers register but never receive events yet.
Phase 1b continued will wire NgSpiceInteractive into the loop.
- components/DynamicComponent.tsx
* Trace function extended with `traceDetailed()` that tracks
whether the BFS crossed an active component.
* PinResolver factory branches: active-path → SPICE-resolved (uses
the scheduler), digital-only → existing default impl. Default
threshold = vcc/2 with no hysteresis; Phase 3 will replace with
per-logic-family Vil/Vih.
Phase 0 LED behavior intact (digital path). Phase 1b SPICE-resolved
path falls back to FLOATING until Phase 1b continued wires the engine.
Tests:
- pin-resolver-phase1b.test.ts (new) — 8/8 passing.
Covers isActiveDevice for every BJT/MOSFET/op-amp/diode/regulator
metadata id; SPICE-resolved resolver state reporting, threshold
conversion, hysteresis dead-band, unsubscribe.
- pin-resolver.test.ts (Phase 0) — 8/8 still passing (no regression).
- tsc --noEmit on the new files: clean.
No deploy in this commit — staged for end-of-session rebuild + push
per user preference.
Phase 1a of the mixed-mode simulator project. Vendors prebuilt
ngspice+XSpice WASM artifacts from ejkreboot/ngspice-xspice-wasm (MIT,
2026) and adds a TypeScript client that exposes the ngspice shared
callable API for interactive (event-driven) use.
What's vendored at frontend/public/wasm/ngspice-interactive/ (~27 MB):
- ngspice-lib.wasm (24 MB) — ngspice 33 + XSpice, MAIN_MODULE
- ngspice-lib.js (2.7 MB) — Emscripten glue
- {analog,digital,xtradev,xtraevt,table,tlines,spice2poly}.cm
— XSpice code models, loaded dynamically
- spinit — ngspice startup script
- PROVENANCE.md — sources + license info
Note on the cost: 27 MB is a one-way commit to git history, but the
existing eecircuit-engine dependency already ships 39 MB in node_modules
(not tracked, re-downloaded per build). Vendoring our copy:
- removes a third-party npm dependency
- pins the exact build we tested with
- means the WASM is served as a static asset (no Vite chunking)
The alternative (publish as @velxio/ngspice-interactive-wasm) was
deferred to keep the iteration cycle fast during Phase 1+.
New TypeScript client at frontend/src/simulation/spice/wasm/:
- NgSpiceInteractive.ts — Promise-based client class with
init / loadNetlist / command /
alter / readVec / reset / dispose
- ngspice-interactive-worker.js — vendored from ejkreboot's worker
and extended with 'loadNetlist',
'command', 'readVec' message types
plus per-command stdout/stderr
capture
POC test at __tests__/ngspice-interactive.test.ts (skipped in node env
because Worker isn't available; runs in a browser-mode test env):
- voltage divider .op → reads v(mid) ≈ 2.5V
- RC step → reads v(cap) time series, final ≈ 5V
- alter Vsrc → second .tran → final ≈ 1V (proves alter+rerun works)
Known limitation deferred to Phase 1b: the vendored WASM is built
without pthreads (no -sUSE_PTHREADS=1), so ngspice's bg_run is
synchronous-blocking. True mixed-mode event injection requires a
pthread-enabled rebuild (with SharedArrayBuffer + cross-origin
isolation). For Phase 1a we use the workaround: chained short-tran
invocations with `alter` between them. The new architecture is built
to swap in a real bg_halt/bg_resume implementation later without
changing component handlers — see NgSpiceInteractive.ts docstring.
Tests passing:
- pin-resolver (Phase 0): 8/8
- ngspice-interactive: 3 skipped (need browser env)
- tsc --noEmit on the new files: clean
- Implement HD44780Decoder for decoding I2C commands to HD44780-compatible LCDs.
- Add bmp280_bridge_reader.ino to read BMP280 chip_id and status registers via I2C.
- Create i2c_scanner_multi.ino to scan I2C addresses and report responding devices.
- Introduce lcd_i2c_hello.ino to demonstrate basic LCD functionality with I2C.
- Implement pcf8574_bidirectional.ino to test bidirectional communication with PCF8574.
- Add pico_i2c_master_reader.ino for reading BMP280 from a Raspberry Pi Pico.
- Create rtc_lcd_clock.ino to display time from a DS1307 RTC on an I2C LCD.
- 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.
- Implemented a script to inject passive-component preset variants into `scripts/component-overrides.json`, including resistors, capacitors, and inductors with custom names and thumbnails.
- Added a new custom element `<wokwi-capacitor-electrolytic>` representing a polarized aluminum-can capacitor with appropriate SVG representation.
- Updated metadata generation to accommodate new component names and thumbnails for better user experience in the component picker.
- Marked submodules `qemu-lcgamboa` and `rp2040js` as dirty to reflect local changes.
- Replaced syncStoreProperty function with emitPropertyChange to decouple parts from Zustand store.
- Updated relay component mapping to ensure proper handling of coil and contact states.
- Added new test cases for half-wave rectifier and relay-controlled LED to ensure correct functionality.
- Introduced InlineComponentSVGs for schematic-style icons of various components.
- Updated submodule references for qemu-lcgamboa, rp2040js, and wokwi-elements to indicate dirty state.
- Implement `ammeter-waveform.test.ts` to validate AC readings from a sine wave source.
- Create `capacitor-charge-transient.test.ts` to test the charging response of an RC circuit driven by a microcontroller pin.
- Introduce `esp32-rectifier-integration.test.ts` for testing rectifier behavior using QEMU and ESP32.
- Add helper functions in `esp32RectifierE2E.ts` for the rectifier test harness.
- Develop `voltmeter-waveform.test.ts` to ensure correct AC and DC readings from a sine wave source.
- Implement unit tests for waveform statistics in `waveform-stats.test.ts` to validate RMS, mean, peak, and interpolation functions.
- Create `waveformStats.ts` to provide statistical functions for time-domain waveform analysis.
- Implement `serial-batching.test.ts` to verify the behavior of `createSerialBatcher`, ensuring it coalesces multiple appends into a single flush, preserves byte order, and groups by board.
- Create `spice-rectifier-integration.test.ts` to test the end-to-end functionality of the Half-Wave Rectifier example, covering the entire simulation pipeline from input building to circuit solving.
- Add `spice-rectifier-live-repro.test.ts` to reproduce a live-app failure scenario, tracing through each layer of the simulation to identify potential failure points.
- Introduce `spice-signal-generator-tran.test.ts` to validate the behavior of the signal generator and ensure correct analysis type switching based on circuit components.
- Establish `serialBatcher.ts` to implement a batching mechanism for USART output, reducing the frequency of store updates and preventing React's maximum update depth error.
- Decoupled electrical simulation from the simulator store, ensuring SPICE is always active for accurate circuit analysis.
- Removed feature flag for electrical simulation, simplifying the state management.
- Preloaded SPICE engine at app start to eliminate latency during the first solve.
- Added comprehensive tests for MOSFET PWM LED behavior and NPN transistor switch functionality, ensuring correct current flow and response to pin states.
- Implemented diagnostics for floating input nodes in RC low-pass filter circuits, addressing singular matrix issues in SPICE simulations.
- Introduced active semiconductor metadata registry for better component management and simulation fidelity.
- Updated Vite configuration to force re-bundling of local wokwi-elements after component additions.
Electrical simulation is now active by default (mode='spice' instead of
'off') — users no longer need to toggle the mode on manually. The engine
lazy-loads on first solve, so there is no startup cost penalty.
Changes:
- useElectricalStore: default mode = 'spice' when ELECTRICAL_SIM_ENABLED
- subscribeToStore: ADC_PIN_MAP expanded to all 18 board types (Uno, Nano,
Mega with 16 ADC channels, ATtiny85, RP2040 GP26-29, ESP32/S3/C3 GPIO
ADCs). Voltages from SPICE solutions now inject into MCU ADC peripherals
for all boards.
- BasicParts LED: reads branchCurrents from useElectricalStore when SPICE
is active. Brightness = clamp(|I_led| / 20mA, 0, 1) instead of boolean.
Subscribes to store changes to update in real time.
- ElectricalOverlay: shows per-wire voltage labels (gold monospace on dark
pill) using buildWireNetMap() which replicates the NetlistBuilder's
Union-Find to map wireId -> netName -> nodeVoltage. Summary pill shows
net count + solve time.
- NetlistBuilder: new export buildWireNetMap() for lightweight wire-to-net
resolution without running ngspice.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Adds 44 SPICE mappers, 58 custom metadata entries, and 12 visual
Web Components covering logic gates, transistors, op-amps, regulators,
sources, electromechanical parts and integrated-circuit packaging.
Fase 9 — component catalog expansion
------------------------------------
- 7 logic gates (AND/OR/NAND/NOR/XOR/XNOR + NOT) as SPICE B-sources
- 8 multi-input gates (AND/OR/NAND/NOR with 3 and 4 inputs)
- 9 transistors: 5 BJTs (incl. PNP 2N3906/BC557) + 4 MOSFETs (incl.
P-channel IRF9540/FQP27P06). NMOS refactored from Level=3 W=0.1
(hangs ngspice) to Level=1 with sane W/L
- 5 op-amps: LM358, LM741, TL072, LM324 with per-chip saturation
rails + opamp-ideal
- 4 linear regulators (7805, 7812, 7905, LM317) with dropout
- 3 batteries (9V, AA, coin-cell) with realistic ESR
- Signal generator (sine / square / DC)
- 2 Schottky diodes (1N5817, 1N5819) + photodiode (lux-driven
current source)
Fase 10 — electromechanical + ICs
---------------------------------
- Relay (SPDT): coil + L + S-switch with native hysteresis +
flyback diode, inverted-control trick for the NC contact
- Optocouplers 4N25 and PC817 (LED + CCCS with CTR=0.5 / 1.0)
- 7 74HC ICs as DIP-14 packages emitting 4 or 6 B-sources per
component (first mapper pattern emitting multiple device cards)
- 3 flip-flops (D, T, JK) — digital-sim only (edge detection is
not representable in ngspice .op)
- L293D dual H-bridge motor driver
Infrastructure
--------------
- scripts/component-overrides.json gains a _customComponents[] array
that lets new Velxio-only parts survive metadata regeneration
(previously applyOverrides() could only patch wokwi-elements
components that had already been scanned)
- scripts/generate-component-metadata.ts injects custom entries
before the patch loop
- New ComponentCategory values: 'logic', 'analog', 'electromech'
- frontend/src/components/DynamicComponent.tsx PASSIVE tracing
extended from just ['resistor','resistor-us'] to 9 two-terminal
passives with per-part pin name maps
- New CI workflow test-circuit.yml runs the sandbox on push/PR
- frontend-tests.yml regenerates metadata and fails if committed
JSON is stale
- Documented 2 new ngspice gotchas in circuit-emulation-gotchas.md:
unicode in netlist titles silently hangs the parser, and
MOSFET Level=3 + W=0.1m causes .op to hang
- 164/164 sandbox tests passing in ~9 s (was 88 pre-fase-9)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>