The screen was a bare <rect fill='#1A1A1A'>, so the part read as a
cut-out in the board rather than one integrated piece - which is what
the module actually is: the glass panel is bonded ON TOP of the PCB and
overhangs the 128x64 active area on every side.
Now drawn as a real panel: glass body with a lit stand-off bevel, the
active area inset within it (the canvas still lands exactly on it), the
flex tail running down to the driver, and a faint specular sheen so it
reads as a screen even while dark. Body 108 -> 118 px for the overhang.
ssd1306-render tests 9/9.
A wire endpoint naming a pin the board element does not expose silently
resolved to nothing and rendered anchored at the board corner. A full
audit (all gallery examples + every saved project on velxio.dev) found 15
examples and 28 user projects doing it — the same electrical pin spelled
differently per surface: GND.1 on the classic ESP32 (element exposes
GND/GND2), 3.3V vs 3V3, GND2 vs GND.2, D13 vs 13 vs GP13, A0-A2 vs
GP26-28 on the Pico, 36/39 vs VP/VN, bare 5V vs VBUS/VIN.
calculatePinPosition now tries those equivalences AFTER the exact match
and the two existing fallbacks miss (so no current resolution changes),
healing old saves, .vlx imports and agent-authored wires without a data
migration. The Pico element gains A0/A1/A2 alias pads on the ADC pins
(RX2/16 dual-entry precedent) and a GP25 pad at the onboard LED silk so
pico-blink-style wires have an anchor. The two examples that were
outright wrong (microsd-card-esp32 GND.1, pico-serial-echo TX) now use
the element's real pin names.
Netlist snapshots (166) untouched; verifier + builder suites green.
DS3231 (I2C 0x68):
- New velxio-ds3231 Web Component (4-pin module: GND/VCC/SDA/SCL) with
pinInfo per CLAUDE.md 6a; registered in elements-register + main.tsx.
- Catalog entry in scripts/component-overrides.json (_customComponents)
mirrored into components-metadata.json exactly as the generator emits it
(verified by cloning wokwi-elements and running generate:metadata: zero drift).
- The existing VirtualDS3231 device sim (DS1307-compatible time regs
0x00-0x06 + control 0x0E / status 0x0F / temperature 0x11-0x12 at 0.25 C
steps) is now user-reachable from the picker; the AVR/RP2040 attach path
gains live temperature updates via the SensorControlPanel (new ds3231
slider in sensorControlConfig).
GPS NEO-6M (UART talker, 9600 baud):
- New velxio-gps-neo6m Web Component (VCC/RX/TX/GND, pulsing PPS LED).
- New part sim GpsParts.ts: emits a valid GPGGA+GPRMC cycle per second
(correct XOR checksums, ddmm.mmmmm coords, UTC clock advancing 1 s/cycle)
with lat/lng/altitude/speed configurable via property dialog and live
via a new SensorControlPanel entry. Defaults: Madrid 40.4168 N 3.7038 W.
- Injection routes, chosen by classifying the wired board pin:
1) hardware UART RX -> new uniform sim.feedUart(uart, data) seam
(AVR USART0, RP2040 uart0/1 via rp2040js feedByte, ESP32 uart0/2 and
STM32 USART1/2 via their bridge shims); byte feed is paced in 8-byte
wall-clock chunks so 32-byte RX FIFOs never overflow;
2) any other digital pin on a cycle-accurate sim -> real 8N1 bit-banged
waveform via schedulePinChange, so SoftwareSerial decodes it;
3) feedUart rejection (e.g. Mega USART1-3, not modelled by avr8js)
degrades permanently to the bit-banged path.
- Interconnect already probed sim.feedUart; implementing it also upgrades
cross-board UART byte shortcuts for RP2040 uart1.
Tests: new gps-neo6m.test.ts (16 tests: NMEA builders, byte injection on
Uno RX0 / ESP32 RX2, Mega RX1 fallback, waveform decode back to $GPGGA,
live position updates, PPS pulse) + 3 new ds3231 AVR-path tests in
protocol-parts.test.ts. Full frontend suite: 2294 passed, 2 pre-existing
Galaksija Z80 timeouts that pass in isolation. npx tsc --noEmit clean.
Tres cosas que salieron al tirar del hilo de los pull-ups.
1) ESP32_ADC_PIN_MAP era la tabla del ESP32 CLASICO aplicada a toda la familia, y
fallaba de dos maneras:
- S3: sus pines ADC son GPIO1..20, ninguno esta en esa tabla, asi que la
busqueda devolvia undefined y el listener del potenciometro no llegaba a
engancharse. El mando no hacia nada.
- C3/C6: GPIO0 SI esta en la tabla clasica, como ADC2_CH1 -> canal 9. Pero en
esos chips GPIO0 es ADC1_CH0 y sus motores toman un indice de canal de ADC1
(0..4). El valor se empujaba al canal 9, fuera de rango, descartado en
silencio mientras el firmware leia el 0. Una respuesta equivocada en vez de
ninguna, que es peor.
adcPinMapFor(boardKind) devuelve la tabla del chip.
2) El ejemplo de las gafas OLED en MicroPython declaraba sus botones con Pin.IN a
secas. Van entre 3V3 y el pin, asi que sin pull-down el pin queda FLOTANDO con
el boton abierto. El propio ejemplo ya lo avisaba en un comentario ("Add
Pin.PULL_DOWN if the pin floats") — ahora lo hace. Es un fallo de hardware de
verdad, no un artefacto del emulador.
3) gallery-run-gate.audit.test.ts: EditorToolbar bloquea el Run cuando el
verificador de circuito saca errores, asi que un circuito invalido no es
cosmetico, es la diferencia entre un ejemplo que arranca y uno que parece
muerto. Y esos defectos se esconden hasta que el circuito resuelve DE PUNTA A
PUNTA: c3-button llevaba un LED de 506 mA que nadie veia porque sus cables
apuntaban a pines inexistentes.
El test reproduce la puerta del Run tal cual (mismo snapshot de peor caso,
mismo buildInputFromStore, mismo verifyCircuit, ngspice de verdad) sobre los
227 ejemplos. Encontro tres mas sin resistencia en serie —nano-button-led,
mega-led-chase y mega-serial-control, 17 LEDs en total— y ahora quedan 0.
A partir de aqui, un ejemplo nuevo con un LED colgado del GPIO salta en CI.
Adds `velxio-ssd1306-i2c-4pin`, a native 4-pin SSD1306 OLED module
(GND/VCC/SCL/SDA) — the cheap 0.96" I2C board most beginners actually have,
matching Wokwi's board-ssd1306. The 8-pin `wokwi-ssd1306` breakout stays; this
is the distinct 4-pin part (issue #215). Same SSD1306Core render pipeline
(imageData/redraw) so the display paints identically; I2C-only, address via the
i2cAddress property (default 0x3C). Styled after the existing 8-pin element
(blue PCB, dark screen, corner holes, star).
Ships four "SSD1306 OLED (4-pin I2C)" gallery examples wiring it over I2C on
Arduino Uno (A4/A5), ESP32 (21/22), Raspberry Pi Pico (GP4/GP5) and STM32 Blue
Pill (PB7/PB6).
The stepper-motor and biaxial-stepper parts only decoded a one-hot wave-drive coil sequence, so they never rotated under the common two-phase full-step / Stepper.h / AccelStepper drive that Wokwi's own examples use -- only the servo moved. Rewrote both decoders to track the net magnetic-field vector of the coils (atan2 of the H-bridge currents), so the rotor follows wave, two-phase full-step and half-step drive alike, whether driven directly from GPIO or through a driver's outputs.
Also adds an A4988 STEP/DIR stepper driver (parity with Wokwi's wokwi-a4988): velxio-a4988 element renders the real Pololu A4988 Fritzing breadboard SVG (public/components/a4988.svg); MotorDriverParts.ts finds the wired stepper via the netlist and advances it one (micro)step per STEP rising edge in the DIR direction (MS1-3 microstep + active-low ENABLE). Metadata in component-overrides.json. Three examples (Uno/ESP32/Pico) wire MCU STEP/DIR -> A4988 -> stepper, coil map aligned to Wokwi (1A->B+,1B->B-,2A->A+,2B->A-).
Verified in-browser: motor rotates on Arduino Uno (avr8js) and Raspberry Pi Pico (rp2040js). tsc --noEmit clean.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
useSimulatorStore eagerly imports STM32_LED from this module, so the
top-level `class extends HTMLElement` + customElements.define ran at import
time and threw "HTMLElement is not defined" under vitest's node environment,
breaking 20 test files that load the store. Guard the base class with a
dummy fallback and skip registration when customElements is absent; browser
behavior is unchanged.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Adds stm32-f4-discovery, stm32-olimex-h405, stm32-netduino-plus2, stm32-netduino2, stm32-blackpill-f401 and stm32-bluepill-f103cb, mapped to existing qemu-lcgamboa machines (netduinoplus2, olimex-stm32-h405, netduino2, stm32vldiscovery). A generic inline board renderer (no SVG) draws the Discovery/Olimex/Netduino boards from a header pin layout; the Pill variants reuse the Blue/Black Pill SVGs. Per-board onboard-LED pin and polarity via STM32_LED. One blink+serial example per board.
tsc --noEmit clean; all new FQBN pnum variants present in STM32 core 2.12.0; worker smoke tests pass for the new machines.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
STM32 emulation (open-core, runs via libqemu-arm in the backend worker):
- backend: stm32_lib_manager + stm32_worker (GPIO, USART, I2C/SPI device models
reusing the ESP32 slaves, live sensor updates), arduino_cli STM32 branch,
start_stm32 simulation route.
- frontend: Stm32Bridge + Stm32BluePill(/BlackPill) web components (Wokwi SVGs),
board kinds, Interconnect/boardPinMapping/boardProtocols wiring, example
projects (blink, serial, I2C BMP280/MPU6050/DS1307/SSD1306/weather, 7-seg,
RGB, button, switch, stepper, cross-board interconnect).
- Raspberry Pi 4/5 board elements + thumbnails.
Pro board gating (generic OSS->Pro seam; entitlement logic lives in the overlay):
- lib/proBoardGate.ts: isProBoardKind (STM32 + every QEMU Raspberry Pi),
installBoardGateImpl/boardGateDecision, triggerProUpgradePrompt.
- PRO badge on those boards in the component picker; gate at the picker add +
the run backstop (startBoard).
- backend/app/services/board_access.py: server-side enforcement seam for the
simulation WebSocket; STM32/Pi unavailable -> Pro-framed message.
- desktop: generic QemuDownloadPrompt + Stm32QemuPrompt (download-behind-license,
mirrors the ESP32 prompt).
- .gitignore: never ship libqemu-* binaries in the public image.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The BoardKind type and the QEMU backend already supported
raspberry-pi-4 (Cortex-A72) and raspberry-pi-5 (Cortex-A76) by reusing
the Pi 3 arm64 image set, but the frontend had no way to actually
select either: the board picker, the canvas renderer, the serial
monitor, the oscilloscope channel list, and the editor toolbar all
hard-coded "raspberry-pi-3" as the only Pi entry. ComponentRegistry
even registered Pi 4 / Pi 5 metadata pointing at the velxio-raspberry-pi-3
custom-element tag — a placeholder that meant both boards rendered as
a Pi 3 in the picker thumbnail and on the canvas.
Add dedicated boards top-to-bottom:
* `RaspberryPi4Element.ts` / `RaspberryPi5Element.ts` — Velxio-style
schematic SVG (authored from scratch, not traced). Pi 4 is the
green PCB with BCM2711 SoC, 4× USB-A, USB-C power, dual µHDMI;
Pi 5 is the darker green PCB with BCM2712 + RP1 southbridge,
2.5 GbE, USB-C 5V/5A, PCIe FFC connector, dedicated power
button. Both carry a small "velxio" mark in the corner.
* `pi40PinHeader.ts` — shared `buildPi40PinHeader()` helper that
returns the 40-pin BCM layout. Every Pi from the 1B+ onwards
uses the same physical pin positions and same BCM GPIO
assignment, so Pi 3 / Pi 4 / Pi 5 elements all consume this
helper and example wires drawn against one model transfer to
the others without re-routing.
* React wrappers `RaspberryPi4.tsx` / `RaspberryPi5.tsx` render the
custom elements at absolute positions (mirrors how
RaspberryPi3.tsx handles the Pi 3 illustration).
* Wire-up across the editor surface:
- BoardOnCanvas: BOARD_SIZE entry + switch case.
- BoardPickerModal: description, icon, kinds list.
- ComponentPickerModal: thumbnails now instantiate the dedicated
custom element (was velxio-raspberry-pi-3 fallback).
- SerialMonitor / EditorToolbar: pill labels, icons, colours.
- Oscilloscope: GPIO channel list (28 BCM pins).
- SimulatorCanvas: remote-boards filter for run/stop sync.
- SPICE boardPinGroups: same 5V / 3V3 / GND as Pi 3.
- boardPinToNumber: accepts physical pin numbers ("1"-"40"),
BCM names ("GPIO14") and power labels for any Pi 3/4/5 id.
- ComponentRegistry: dedicated tagNames + per-board thumbnails
(green for Pi 4, darker green for Pi 5).
* EditorToolbar's Pi 3 special cases (Linux/Python compile path,
Run/Stop routing) now use `isPiBoardKind()` so Pi 4 and Pi 5
inherit the same behaviour automatically, and any future Pi
family member (Zero / 1 / 2) lands in the right code paths the
moment its backend boots.
QEMU backend was already wired (qemu_manager.py:71/82 + manifest entry
'raspberry-pi-3-virt' shared across arm64 Pis), so this commit makes
both boards selectable end-to-end without any backend follow-up.
On the ESP32 DevKit V1 the silkscreen labels GPIO 16 / 17 as RX2 / TX2,
and Esp32Element.PINS_ESP32 only exposed the silkscreen names. Examples
that wire to numeric pin "16" or "17" (e.g. ledcAttach(16, 5000, 8) on
esp32-pwm-led-rgb) couldn't resolve those names — pinPositionCalculator
failed lookups, the wire endpoint fell back to (0,0)/(50,50) and the
LED component visually floated off the board, breaking the SPICE
netlist for the example.
Add "16" and "17" as aliases pointing to the same (134,143) / (134,131)
coordinates as RX2 / TX2 so both naming conventions resolve to the same
physical pin tip.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
ATtiny85 (AVRSimulator + collectPinStates + connectAnalogInputsToMcu + SimulatorCanvas + Attiny85Element + examples):
- Add attiny85AdcConfig with correct register addresses (ADMUX=0x27,
ADCSRA=0x26, ADCSRB=0x23, ADCL=0x24, ADCH=0x25, DIDR0=0x34, adcInterrupt=0x08).
Without this, analogRead() polled the wrong address forever and the
firmware hung on first ADC read.
- Add attiny85Timer0Config + instantiate AVRTimer so OVF fires at the
ATTinyCore-expected ~1.024 ms cadence. delay() advance is still blocked
on avr8js TIFR auto-clear semantics (separate upstream issue, see
ATTINY85_TIMER0_UPSTREAM_ISSUE.md in velxio-prod test plan).
- Map ATtiny85 ADC channels to PB-style pin names (PB5/PB2/PB4/PB3 -> 0..3)
in connectAnalogInputsToMcu so SPICE node voltages reach the right ADC
channel.
- Recognise /^PB\d+$/ in collectPinStates.pinNameToArduinoPin so wires
named "PB1" emit v_attiny85_pb1 V-source and the LED responds to MCU
writes. Previously every PB-wire returned -1 and SPICE saw no source.
- SimulatorCanvas: subscribe pin 1 (PB1) for the built-in LED on the
attiny85 board kind (Digispark convention), instead of falling through
to the pin-13 default.
- Attiny85Element: remove the hand-drawn "yellow LED" circle that was
floating above the chip. The bare DIP-8 has no on-board LED; examples
wire a real wokwi-led + resistor instead.
- examples.ts: add a real wokwi-led + 220 Ohm wokwi-resistor + wires to
attiny85-blink, and add missing series resistors to attiny85-button-led
and attiny85-ntc-sensor. attiny85-pwm-fade was already correct.
Custom-chip pipeline (CustomChipPart + simulatorBridges):
- Add a requestAnimationFrame loop that calls instance.tickTimers() every
frame in CustomChipPart. Chips that register vx_timer_create (e.g. an
i8080 stepping its core, or a sensor publishing samples) had timers
added to the queue but nothing fired them; tickTimers was dead code.
- Gate the ESP32 backend path with detectSimulatorKind(sim)==='esp32'.
The previous `typeof sim.registerSensor === 'function'` check matched
AVR and RP2040 simulators too (they expose registerSensor for I2C
sensor proxies), routing client-side chips to a non-existent ESP32
worker on those boards.
- Replace direct simulator.usart.writeByte calls in avrUartTx with a
JS-level FIFO + setTimeout(1ms) drainer. avr8js writeByte drops bytes
under burst load (a chip emitting print_string lost ~99% of bytes via
non-immediate, or kept only the last byte via immediate). The drainer
attempts one non-immediate write per tick and retries on RXC busy /
RXEN off. Added a guard for ATtiny85 (no USART -> would queue forever).
End-to-end verified: i8080-banner-streamer now prints the boot banner
followed by "uptime ticks: 0xNN" lines stepping every ~50 ms, executing
real Intel 8080 instructions inside the WASM chip.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
The hand-drawn SVGs in Bmp280Element.ts and Attiny85Element.ts were
functional but obviously amateur next to a real Fritzing-drawn part.
Both components now mount the equivalent Fritzing breadboard SVG as a
public static asset (`<image href>` in the shadow DOM SVG), with pin
coordinates remapped to the new artwork and pin-name labels overlaid
on top so the user can still read each connector at a glance.
frontend/public/component-svgs/bmp280.svg (new)
Verbatim copy of third-party/fritzing-parts/svg/core/breadboard/
bmp180_breadboard.svg. The Adafruit BMP180 breakout is the
mechanically identical Bosch predecessor — same I2C interface,
same 4-pin pinout. Pin labels lifted from the matching .fzp.
frontend/public/component-svgs/attiny85.svg (new)
Verbatim copy of the Fritzing ATtiny85 DIP-8 breadboard art.
Bmp280Element.ts
Width 80×100 px (Fritzing aspect 28.35:35.43 ≈ 0.8:1, exact uniform
scale of 2.822 px/mm). Pin coords for SDA / SCL / GND / VCC matched
to the connector centres in the source SVG. Pin labels overlaid on
top. Existing wired example (esp32-bmp280) re-routes automatically
because the wire system reads coords by pin name from pinInfo.
Attiny85Element.ts
Width 160×132 px (Fritzing aspect 28.801:23.768 ≈ 1.21:1, exact
uniform scale of 5.555 px/mm). The Fritzing layout puts pins on the
TOP and BOTTOM edges (4 each), not LEFT and RIGHT like the older
hand-drawn version. Pin coords land on clean numbers
(x ∈ {20, 60, 100, 140}, y ∈ {6, 126}). Built-in LED on PB1 stays
as an overlaid circle outside the chip body.
Wires in the existing attiny85-* examples re-route automatically by
pin name; external components positioned to the right of the chip
may need a manual nudge for clean routing — but they work.
frontend/src/components/simulator/BoardOnCanvas.tsx
attiny85: { w: 160, h: 100 } → { w: 160, h: 132 } to match the new
aspect ratio. Same width as before so the chip occupies the same
horizontal slot in existing example layouts.
scripts/component-overrides.json
BMP280 thumbnail updated to mirror the Fritzing colour scheme
(dark blue PCB, BMP180 silkscreen, four gold connector circles)
so picker and canvas feel consistent.
frontend/public/components-metadata.json
Regenerated.
docs/THIRD_PARTY.md
New "Fritzing parts library" section. Both new assets are listed
with their upstream paths plus the CC-BY-SA licence and link to
the parts repo. Future Fritzing copies must be added there too.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Resolves several install pain points reported by users (#108, #120) and
removes the obligatory upstream-clone step that confused contributors and
slowed down every Docker build.
Install fixes:
- nginx: server_name → catch-all default_server, drop Debian's stock site
so reverse-proxied users no longer get the "Welcome to nginx" page.
- entrypoint: auto-generate SECRET_KEY at first boot, persisted under
data/.secret_key. backend/.env is now optional in docker-compose.yml.
- backend: add greenlet>=3.0.0 (SQLAlchemy async dep that was missing on
some Python builds — caused uvicorn startup failures on WSL).
Wokwi libs come from npm:
- @wokwi/elements 1.9.2, avr8js 0.21.0, rp2040js 1.3.2 are pinned in
frontend/package.json. Vite aliases removed.
- Dockerfile.standalone no longer clones avr8js / rp2040js / wokwi-elements
/ wokwi-boards. Frontend stage is just COPY + npm install + build:docker.
- Board SVGs vendored under frontend/public/boards/ (10 deduped against
existing files, 2 truly new). third-party/wokwi-* clones become reference-
only credits — generate-component-metadata.ts skips gracefully when absent.
Production config split out:
- docker-compose.prod.yml, deploy/nginx.prod.conf, nginx-host-velxio*.conf,
update-third-party.bat removed. Production deployment lives in its own
repo: https://github.com/velxio/velxio-prod (host nginx + HTTPS + backups
+ pinned upstream commit).
Verified locally: 1161 frontend tests pass, build:docker completes clean.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The directory grew well beyond Wokwi-only contents: it now hosts
lcgamboa's QEMU fork (qemu-lcgamboa), Espressif's esp32-camera, the
ngspice WASM build, fritzing-parts, picowi, an alternative QEMU
(qemu-esp32), the 100_Days_100_IoT_Projects examples repo, and
Wokwi's own avr8js/rp2040js/wokwi-elements/wokwi-features/wokwi-boards.
"wokwi-libs" was misleading — half the contents have nothing to do
with Wokwi. "third-party/" is the standard convention for vendored
external dependencies.
Mechanical changes:
Path rename:
wokwi-libs/ → third-party/
update-wokwi-libs.bat → update-third-party.bat
docs/WOKWI_LIBS.md → docs/THIRD_PARTY.md
Submodule reconfiguration:
.gitmodules — 4 path= and section names updated
.git/modules/wokwi-libs/ → .git/modules/third-party/
each submodule's .git file rewired to ../../.git/modules/third-party/<name>
Reference updates (~80 files): vite.config.ts aliases, Dockerfile
COPY paths, GH Actions workflow steps, build_qemu_*.sh, all
docs/* and test/*/autosearch/* entries that mention the path,
package-lock.json file: dependencies, .gitignore patterns,
sitemap.xml + index.html SEO blurbs, scripts/generate-component-*,
.dockerignore, .idea/vcs.xml. Bulk replaced both `wokwi-libs/`
(path) and bare `wokwi-libs` (textual mentions in docs/comments).
Verified:
- npx tsc -b --noEmit produces no new errors related to these paths
- vite.config.ts aliases now point at ../third-party/avr8js etc.
- All 4 git submodules (avr8js, rp2040js, wokwi-elements,
wokwi-features) are linked under third-party/ with their
worktrees re-populated and config files referencing the new path
- `grep -r wokwi-libs` returns zero hits outside node_modules,
.vite, frontend/dist, third-party/ (upstream submodule contents),
*.pyc caches, and *.dll.pre-camera rollback binaries
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- Introduced EPaperPanels.ts to define configurations for various ePaper panels including dimensions, refresh rates, and controller details.
- Implemented SSD168xDecoder.ts to handle the decoding of SPI commands for the SSD168x family of ePaper displays.
- Created EPaperPart.ts to manage the simulation of ePaper panels, integrating with the existing simulator architecture and handling events.
- Added example sketches for 2.13", 2.9", 4.2", and 7.5" ePaper displays, demonstrating basic functionality and text rendering.
- Ensured compatibility with AVR, RP2040, and ESP32 platforms, with appropriate pin configurations for each.
- 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.
- Introduced RelayElements for SPDT relay representation.
- Added Resistor component for adjustable resistance in ohms.
- Created RiscVBoard component for visualizing a RISC-V chip.
- Implemented TransistorElements for BJT and MOSFET packages.
- Added Capacitor and CapacitorElectrolytic elements for capacitors.
- Introduced Inductor element for inductor representation.
- Updated index file to export new custom elements.