velxio/test/autosearch/07_multi_board_support.md

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/ con avr8js real cargando .hex real de un sketch Arduino (incluye el sketch I2C i2c_eeprom_demo.ino compilado con arduino-cli).
  • Chip 24C01 contesta correctamente al Wire.h del 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 con Wire.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 hace SPI.transfer(0xA5) + RCLK pulse, chip 74HC595 latch a 8 GPIO outputs, sketch lee Q=10100101 LSB-first. Valida la cadena completa: SPI byte → on_done → pin_watch en RCLK → vx_pin_write → qemu_picsimlab_set_pindigitalRead.
  • 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.py compila un blink simple en 5 boards representativos (Uno, Nano, Mega, Pi Pico, ESP32). Todos pasan en ~90 s.

Gaps documentados (follow-ups)

Alta prioridad

  1. 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.c con los mismos hooks picsimlab_i2c_event/spi_event/uart_tx_event y los eventos picsimlab tienen el mismo encoding, así que el WasmChipRuntime funciona tal cual. Falta agregar el branch custom-chip en 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_init hoy emiten chip_warning; falta forwardear pixel updates al canvas del frontend vía WebSocket (async, no en hot path).
  • ESP32 vx_pin_dac_write — hook a qemu_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.