7.4 KiB
Multi-board support — Custom Chips
Validado el 2026-04-28. Fuente:
test/test_custom_chips_boards/(24 tests pytest: compile + sketch + GPIO bridge + I2C + UART + SPI E2E),test/test_chip_backend_runtime/(11 tests pytest: runtime aislado),test/test_custom_chips/(70 tests vitest sandbox).
Resumen ejecutivo
| Capa | Estado |
|---|---|
Compilación de chips (/api/compile-chip) |
✅ funciona — 11/11 chips de la galería pasan |
Compilación de sketches (/api/compile) |
✅ funciona en AVR (Uno/Nano/Mega), RP2040 Pi Pico, ESP32 |
| Runtime AVR (avr8js, browser) | ✅ GPIO+I2C+SPI+UART (sandbox 70/70) |
| Runtime ESP32 QEMU (lcgamboa, backend WASM-in-process) | ✅ GPIO + I2C + UART + SPI + pin_watch + timers (E2E con sketches reales) |
| Runtime RP2040 (rp2040js, browser) | ✅ GPIO + I2C + SPI + USART expuestos |
| Runtime ESP32-C3 (RV32IMC, browser) | ⚠️ Solo GPIO — peripherals stub |
| Runtime Raspberry Pi 3 (QEMU, backend) | ⚠️ Solo GPIO + Serial via WS |
| Runtime ATtiny85 (avr8js, browser) | ⚠️ Solo GPIO — chip no tiene TWI/SPI/USART |
Matriz detallada
| Board kind | Simulator class | pinManager | i2cBus | spi | usart | Custom chip funciona |
|---|---|---|---|---|---|---|
arduino-uno |
AVRSimulator |
✅ | ✅ | ✅ | ✅ | GPIO + I2C + SPI + UART |
arduino-nano |
AVRSimulator |
✅ | ✅ | ✅ | ✅ | GPIO + I2C + SPI + UART |
arduino-mega |
AVRSimulator |
✅ | ✅ | ✅ | ✅ | GPIO + I2C + SPI + UART |
attiny85 |
AVRSimulator |
✅ | ❌ | ❌ | ❌ | Solo GPIO |
raspberry-pi-pico |
RP2040Simulator |
✅ | ✅ | ✅ | ✅ | GPIO + I2C + SPI + UART |
pi-pico-w |
RP2040Simulator |
✅ | ✅ | ✅ | ✅ | GPIO + I2C + SPI + UART |
nano-rp2040 |
RP2040Simulator |
✅ | ✅ | ✅ | ✅ | GPIO + I2C + SPI + UART |
esp32 y variants |
Esp32Bridge (QEMU) |
✅ vía shim | ✅ backend WASM | ✅ backend WASM | ✅ backend WASM (UART0) | GPIO + I2C + SPI + UART + pin_watch + timers |
esp32-s3 |
Esp32Bridge |
✅ vía shim | ✅ backend WASM | ✅ backend WASM | ✅ backend WASM | GPIO + I2C + SPI + UART |
esp32-cam |
Esp32Bridge |
✅ vía shim | ✅ backend WASM | ✅ backend WASM | ✅ backend WASM | GPIO + I2C + SPI + UART |
esp32-c3 |
Esp32C3Simulator |
✅ | ❌ | ❌ | ❌ | Solo GPIO |
xiao-esp32-c3 |
Esp32C3Simulator |
✅ | ❌ | ❌ | ❌ | Solo GPIO |
arduino-nano-esp32 |
Esp32Bridge |
✅ vía shim | ✅ backend WASM | ✅ backend WASM | ✅ backend WASM | GPIO + I2C + SPI + UART |
raspberry-pi-3 |
RaspberryPi3Bridge (QEMU) |
✅ vía shim | ❌ | ❌ | ❌ | GPIO + Serial vía WS |
Componentes de display soportados
| Componente | AVR | RP2040 | ESP32 | Path |
|---|---|---|---|---|
wokwi-ssd1306 (I2C OLED) |
✅ | ✅ | ⚠️ I2C sink only (no canvas) | simulator.addI2CDevice (browser) |
wokwi-ili9341 (SPI TFT) |
✅ | ✅ | ❌ | spi.onByte (browser) |
wokwi-lcd2004 (parallel LCD) |
✅ | ✅ | ❌ | parallel pin monitor |
epaper-ssd168x (5 variants) |
✅ ≤2.13" | ✅ | ✅ | Browser decoder for AVR/RP2040; backend Ssd168xEpaperSlave for ESP32 — emits epaper_update WS events. See docs/wiki/epaper-emulation.md. |
Nota ESP32: el chip's .wasm corre en el proceso del worker QEMU (vía
wasmtime), así que todas las callbacks
(I2C / SPI / UART / pin_watch / timers) responden a QEMU sincrónicamente —
misma fidelidad que los slaves Python hardcodeados (MPU6050Slave, etc) y
sin round-trip por WebSocket. Ver
docs/wiki/custom-chips-esp32-backend-runtime.md
para la arquitectura completa, incluyendo el reference de op codes picsimlab.
Cómo se validó cada uno
AVR (Uno/Nano/Mega)
- 70 tests en
test/test_custom_chips/test/conavr8jsreal cargando.hexreal de un sketch Arduino (incluye el sketch I2Ci2c_eeprom_demo.inocompilado conarduino-cli). - Chip 24C01 contesta correctamente al
Wire.hdel sketch — full I2C E2E.
ESP32 (lcgamboa QEMU + backend WASM runtime)
test/test_custom_chips_boards/test_esp32_gpio_bridge.py(2 tests) — GPIO + serial round-trip básico, sin WASM.test/test_custom_chips_boards/test_esp32_chip_i2c.py(1 test) — sketch ESP32 conWire.h↔ chip 24C01 EEPROM. Valida pointer write, data write, pointer reset, read 4 bytes round-trip.test/test_custom_chips_boards/test_esp32_chip_uart.py(1 test) — sketch envía "Hello", chip ROT13 transforma byte a byte, sketch lee bytes transformados.test/test_custom_chips_boards/test_esp32_chip_spi.py(1 test) — sketch haceSPI.transfer(0xA5)+ RCLK pulse, chip 74HC595 latch a 8 GPIO outputs, sketch leeQ=10100101LSB-first. Valida la cadena completa: SPI byte → on_done → pin_watch en RCLK → vx_pin_write →qemu_picsimlab_set_pin→digitalRead.test/test_chip_backend_runtime/test_wasm_runtime.py(11 tests) — runtime Python aislado (sin QEMU): inverter, EEPROM 24C01 + pointer wrap, EEPROM 24LC256, GPIO output, UART ROT13, SPI shift register, timer plumbing, pin_watch edge.
Compilación multi-board
test_multi_board_sketch_compile.pycompila un blink simple en 5 boards representativos (Uno, Nano, Mega, Pi Pico, ESP32). Todos pasan en ~90 s.
Gaps documentados (follow-ups)
Alta prioridad
- ESP32-C3 — exponer USART/I2C/SPI MMIO. El simulator JS hoy hace stubs;
habría que rutear las MMIO regions a un bus equivalente al del AVR. Alternativa:
replicar el patrón ESP32 — el lcgamboa fork ya tiene
esp32c3_picsimlab.ccon los mismos hookspicsimlab_i2c_event/spi_event/uart_tx_eventy los eventos picsimlab tienen el mismo encoding, así que elWasmChipRuntimefunciona tal cual. Falta agregar el branchcustom-chipen el worker C3.
Baja prioridad
- ATtiny85 — añadir USI (peripheral 2-wire). Avr8js puede no soportarlo; validar primero.
- Raspberry Pi 3 — bridge a I2C real del kernel dentro del QEMU. Más complejo, depende del firmware.
- ESP32 framebuffer/display — chips con
vx_framebuffer_inithoy emitenchip_warning; falta forwardear pixel updates al canvas del frontend vía WebSocket (async, no en hot path). - ESP32
vx_pin_dac_write— hook aqemu_picsimlab_set_apin(~30 min).
Cómo correr la validación localmente
# 1. Backend (con lcgamboa lib disponible — ver paso 0 abajo si falta)
cd backend && uvicorn app.main:app --port 8765
# 2. Suite multi-board pytest
cd .. && VELXIO_BACKEND_URL=http://127.0.0.1:8765 \
python -m pytest test/test_custom_chips_boards/ -v
# 3. Sandbox AVR (browser-side via avr8js + Vitest)
cd test/test_custom_chips && npm test
Paso 0 — Cómo conseguir libqemu-xtensa.dll/.so en dev local
El Dockerfile.standalone la trae como parte del build. Si tenés un container
de Velxio corriendo:
# Windows / dev local
docker cp velxio-dev:/app/app/services/libqemu-xtensa.dll backend/app/services/
docker cp velxio-dev:/app/app/services/esp32-v3-rom.bin backend/app/services/
docker cp velxio-dev:/app/app/services/esp32-v3-rom-app.bin backend/app/services/
(Análogo en Linux con .so.) El backend la detecta en LIB_PATH y enruta
ESP32 a través de la C library en lugar del subprocess fallback.