Commit Graph

21 Commits

Author SHA1 Message Date
David Montero Crespo 87101175ce fix(boards): an overlay board could never enter ESP-IDF mode
BOARD_SUPPORTS_ESPIDF is a literal set of OSS board kinds and it gates
both the toolbar's ESP-IDF option and setBoardLanguageMode, so no overlay
board could ever be switched into ESP-IDF: loadExample called
setBoardLanguageMode(id, 'espidf') for an `languageMode: 'espidf'` gallery
example, the guard returned early, and the example opened in Arduino mode
with the toolbar saying "Arduino C++". It stayed invisible because the
backend sniffs `app_main` and compiles those sketches as pure IDF anyway —
until a board with no Arduino FQBN at all hit it, and the run died in the
browser at "No FQBN for board kind" before any request left the page.

- ProBoardDef.supportsEspIdf registers the kind into BOARD_SUPPORTS_ESPIDF,
  the same way supportsMicroPython already did for MicroPython.
- ProBoardDef.espidfFqbn + BOARD_KIND_ESPIDF_FQBN + fqbnForLanguage give the
  IDF lane a target for a board whose Arduino FQBN is null (the ESP32-C5
  kits: no arduino-esp32 core supports the C5, and the backend refuses that
  target for Arduino on purpose, but idf.py builds it fine). Both compile
  sites resolve through it instead of reading BOARD_KIND_FQBN directly.
- The language select shows when EITHER alternative mode exists (the P4 is
  ESP-IDF but not MicroPython, so it had no select at all), hides options
  the board does not support, and hides Arduino for a board with no FQBN.
- addBoard no longer seeds an Arduino-less board into 'arduino', where it
  could never compile and the select would show a value it does not carry.

Regression test: overlay-espidf-mode.test.ts.
2026-08-24 06:11:24 +02:00
David Montero Crespo 0ef656849d fix(spice): every overlay board was solved as a 5 V Arduino
BOARD_PIN_GROUPS is keyed by the BoardKind union, so a board registered by the
overlay could never appear in it and fell through to `default` — 5 V, ground
pads named GND/GND.1/GND.2, supply pads named 5V/VCC. Every RP2350 and
ESP32-family pro board is a 3.3 V part whose supply pad is called 3V3, so the
netlist powered it from the wrong rail and did not recognise its supply pad at
all. Nothing errors; the numbers are simply wrong.

Caught on the Pimoroni Pico Plus 2 W: a potentiometer across 3V3 and GND read
2.50 V at half travel instead of 1.65 V, because the divider was solving
against a 5 V rail. The same 1.5x error was sitting under every LED current,
pull-up and divider on every pro board.

boardPinGroupFor() consults the pro registry before falling back, and a board
declares its pads through ProBoardDef.power. The OSS table is untouched, so no
existing board changes behaviour.

Found while wiring the ADC seam: enabling the SPICE analog path for a pro board
is what finally made the wrong rail visible.
2026-08-23 03:07:43 +02:00
David Montero Crespo f35805175c fix(spice): overlay boards were skipped before a single volt was injected
ADC_PIN_MAP and ADC_PIN_TO_GPIO are keyed by the BoardKind union. An overlay
board's kind is a runtime string that can never join that union, so
connectAnalogInputsToMcu hit `if (!adcPins) continue;` at all three sites for
every pro board: a divider, an LDR, an op-amp output wired to one solved
correctly in SPICE and then had nowhere to go. Parts that inject their own value
(a potentiometer, through partUtils) were unaffected, which is exactly what made
this easy to miss — analog looked like it worked.

A pro board now declares its pads through ProBoardDef.adcPins, and pad->GPIO
resolution consults its own pinToNumber first. Both fall back to the existing
tables untouched, so no OSS board changes behaviour.

The pad NAME matters, not the GPIO: on the Pimoroni Pico Plus 2 W the analog
pads are silked 26/27/28 and tied to GP40/41/42 through 1k, so the two disagree
by design.
2026-08-22 05:13:41 +02:00
David Montero Crespo 2b7c9b6fb6 feat(boards): let a board declare the RAM and flash it is physically fitted with
An overlay board was invisible to the build-options model: its kind is not in
the OSS family sets, so isEsp32Family() said no, the Board Options menu never
appeared, and every compile went out with board_options: null - the
conservative family default of CONFIG_SPIRAM=n.

That is wrong for a module that always ships PSRAM. The ESP32-S3-EYE carries
8 MB of octal PSRAM and esp_camera allocates its frame buffer with
MALLOC_CAP_SPIRAM, so its camera examples compiled cleanly and then died at run
time with 'cam_dma_config(509): frame buffer malloc failed' - a hardware fact
surfacing as a mysterious driver error.

Boards now declare defaultBoardOptions, sent when the project saved none of its
own. ONLY the declared keys are sent: the backend backfills the rest from its
own defaults, which are deliberately not the modal's (huge_app vs min_spiffs),
so a board that gains one declared knob does not silently get repartitioned.
Boards that declare nothing keep sending null and build bit-for-bit as before.

Also route the family predicates through the registry, so overlay ESP32 boards
finally get the Tools menu they were missing.
2026-08-20 19:48:24 +02:00
David Montero Crespo c4860d4f23 feat(boards): widen esp32Family with p4/c5 - loud failure on the absent QEMU path
The overlay's ESP32-P4 (and the coming C5) run ONLY on their in-browser
engines: neither chip has a QEMU machine anywhere. toQemuBoardType now
throws a clear error for those families instead of booting the wrong
machine and wedging on the first register.
2026-08-19 04:42:24 +02:00
David Montero Crespo 149fbee1e9 feat(boards): ESP-EYE ad card + declarative builtInCamera on ProBoardDef
Overlay boards with a camera now declare builtInCamera on their def (bool,
or { maxFrameBytes } for drivers with tight frame buffers) and the canvas
CameraToggle keys off it - the hardcoded esp32-cam / xiao-esp32s3-sense
kinds keep working unchanged.
2026-08-19 02:50:49 +02:00
David Montero Crespo 189ba355a9 feat(boards): a board can ship the code it opens with
The editor seeded a freshly placed board from its FAMILY: the Arduino
LED_BUILTIN blink, the Pico Pin(25) MicroPython blink, or the Raspberry
Pi RPi.GPIO script. None of those run on a board that has no such LED,
no RPi.GPIO and its own vendor library, so the first Run failed on a
board the user had not touched yet.

ProBoardDef gains defaultFiles (per language mode, plus 'python' for the
QEMU-Linux guests) and defaultLibraries; addBoard and setBoardLanguageMode
prefer the board's own seed over the family default, and the seeded
libraries land in the board's compile manifest.

Also fix the MicroPython family fallback: it recognised an ESP32 by
'esp32' appearing in the group id, so an overlay ESP32 whose kind carries
no such substring (m5stack-core, cardputer-adv) was seeded the Pico's
Pin(25) blink - a dead pin on both. It now consults the board's declared
esp32Family too.
2026-08-18 15:02:13 +02:00
David Montero Crespo c89b0a6f39 feat(registry): i2cPmic — a board declares its power-management IC
Board DATA like spiPanelId: the bridge that supports the declared type
instantiates the model at the given address and setBatteryVoltage drives it.
First consumer is the M5Stack Core's IP5306.
2026-08-12 21:01:54 +02:00
David Montero Crespo 730652bfef feat(registry): spiPanelId — a board declares its display's autodetect identity
Vendor autodetects read the panel's RDDID with the display's own CS and
reject or misdetect the board on the bus's idle 0xFF. The answer is board
DATA (which CS, which id byte), not bridge code, so it moves to the def:
the M5Stack Core is {14, 0xE3}, the Cardputer ADV {37, 0x85}. Bridges that
support the probe consume it generically.
2026-08-12 16:39:37 +02:00
David Montero Crespo 7a7c9f93f7 feat(simulator): tilt and battery controls for boards that carry an IMU or a gauge
The emulated BMI270 and battery gauge were faithful and inert: with nothing
driving them the IMU reported the board lying flat for the whole run and the
gauge reported the single voltage it was seeded with, so a sketch that reacts
to tilt or warns on low charge could not be exercised at all.

A Sensors popover on the canvas header supplies the missing half. Tilt is
entered as roll/pitch on a drag pad rather than three raw axes — what a user
means is "lean it left" — and gravity in the board's frame is that rotation
applied to (0, 0, 1) g, which is also why the vector stays at 1 g whatever the
attitude. Turning the board spins the gyro for as long as the drag lasts and
parks it back at zero shortly after, matching a real part: a held tilt reads no
rotation. Battery is a slider over the LiPo working range.

Gated per board by builtInImu / builtInBattery on the pro board def, the same
way the Mic toggle is gated, and each section renders only if its flag is set.

The microphone stream also learns to resample. The engine now tells the source
which rate the guest programmed, so a sketch recording at 8 kHz consumes two
captured samples per read instead of playing back at half speed.
2026-08-09 23:48:56 +02:00
David Montero Crespo e96dae794a feat(mic): stream the computer's microphone into boards with an on-board mic
New canvas-header Mic toggle, shown for boards whose ProBoardDef declares
builtInMicrophone (their bridge implements setMicrophoneSource). Capture
runs at the AudioContext's native rate, is decimated to 16 kHz and ring-
buffered (2 s, drop-oldest on overflow, silence on underflow - the engine
paces pulls in simulated cycles, up to 4x real time during boot boost).
No auto-start: with the toggle off the bridge's 440 Hz test tone keeps
mic sketches alive, so taking the user's microphone stays an explicit
click. The source is re-applied on every run start to survive bridge
rebuilds.
2026-08-04 15:57:17 +02:00
David Montero Crespo 31c722b593 feat(pi): salida de pantalla para las Pi + arreglo del guard de connect
Seam nuevo registerBoardBuiltins/getBoardBuiltins: una placa que el arbol
OSS ya dibuja (la familia Pi) puede recibir perifericos del overlay sin
registrar un ProBoardDef, que es lo que secuestraba el arte de la placa y
dejaba los cables en la esquina. El overlay lo usa para llevar los frames
del guest (cv2.imshow) al panel cableado en el canvas.

Arregla ademas el guard de connect() del bridge: comparaba readyState con
WebSocket.OPEN leido del global, asi que cuando esas constantes no estaban
`undefined === undefined` era cierto con socket a null y connect() volvia
sin abrir nada — el bridge se quedaba muerto. Ahora comprueba que el socket
exista y usa el valor numerico. Recupera los 12 tests de
multi-board-integration que esto habia roto.

El test del UART Pi->Uno pasa a comprobar el contrato vigente: por el cable
va onUartTx (el UART del header), no la consola del guest; y se anade el
caso que fija que la charla de arranque NO se filtra al vecino.
2026-07-30 01:09:04 +02:00
David Montero Crespo 8e1001740a fix(boards): el overlay ya no secuestra el dibujo de las Raspberry Pi
Dos fallos que salieron probando pi-to-arduino-led-control y
pi5-pir-motion-alarm.

1) BoardOnCanvas mira getProBoard() ANTES del switch OSS para decidir si
   dibuja un elemento del overlay. El overlay registraba un def minimo
   para las seis Pi solo para llevar una linea de setup del guest, y eso
   basto para cambiarles el render: en vez de la ilustracion
   Raspberry_Pi_3_illustration.svg salia la caja esquematica, con otras
   coordenadas de pines, y los cables quedaban colgando en la esquina.
   Ahora hay un registro aparte, registerGuestSetup(kind, linea), que
   lleva la cadena y nada mas; getGuestSetup() la resuelve dando
   prioridad al def del overlay si existe.

2) Las partes de entrada (PIR, botones, sensores) avisan con
   simulator.setPinState(pin, nivel). En una placa QEMU-Linux no hay
   simulador de MCU -- el CPU es el guest -- asi que la llamada acababa
   en la instancia AVR heredada y se perdia: pulsar el sensor no hacia
   nada. traceDetailed devuelve ahora tambien la placa a la que llega el
   pin, y si es de la familia Pi la parte recibe un simulador que empuja
   el nivel al bridge (gpio_in para el guest, el valor pin<N> que leen
   los shims del motor de navegador) y al PinManager de esa placa.
2026-07-29 07:34:01 +02:00
David Montero Crespo 330b9ed1b2 feat(pi-family): quietBoot — hide the shared rootfs' branded boot chatter
The generic arm64 image prints another product's banner/motd/login line
during boot, before guestSetup can re-brand the guest. Boards with
quietBoot show a neutral '[Velxio] Booting <label> (Linux guest)...'
progress line (dots every 4 s) while boot detection and the prompt-gated
upload still run underneath; the shell is revealed (already re-branded)
right before the auto-run command, so the user's first visible output is
their own program.
2026-07-28 21:07:21 +02:00
David Montero Crespo dd86020343 feat(pi-family): one-click run UX — autoRun + guestHome + clean serial mirror
- ProBoardDef.autoRun: after boot (+guestSetup) the VFS uploads itself
  and the command runs, so a single Run click boots, uploads and starts
  the user's script (same UX as compiled boards)
- ProBoardDef.guestHome: VFS home dir override ('/root' for guests that
  log in as root); those boards drop the historic hello.sh sample
- upload sequence extracted to utils/piUpload (shared by the VFS panel
  button and autoRun)
- serial monitor strips DEL/C0 control echoes (backspace showed tofu)
2026-07-28 16:28:02 +02:00
David Montero Crespo 55dd25eeba feat(pi-family): guestSetup seam + board-branded workspace texts
Overlay QEMU-Linux boards are not Raspberry Pis: ProBoardDef.guestSetup
lets a board send one shell line at the boot prompt (hostname/PS1/clear)
to de-brand the generic image, sent before piBooted flips so uploads
cannot interleave; the workspace start button and power-on title carry
the board's own label for non raspberry-pi kinds; the compile console
line uses the board label instead of 'Raspberry Pi 3B'.
2026-07-28 14:36:13 +02:00
David Montero Crespo 6babaf08e1 feat(seams): overlay-registered QEMU-Linux board kinds + backend profile registry
registerPiFamilyKind + ProBoardDef.piFamily route an overlay board through
the existing Raspberry Pi bridge path (WebSocket qemu, VFS panel, boot
terminal); register_pi_board_profile lets the overlay add the matching
PI_CONFIGS entry (cpu/image_set/...) at registration time.
2026-07-28 08:45:56 +02:00
David Montero Crespo 5beccf94a6 fix(picker): late overlay registration re-renders the picker — no more reload races
The @pro overlay import is dynamic, so board/component registration can land
AFTER the picker mounted and memoized its lists. allBoards had frozen deps —
if the picker rendered first, overlay boards (M5Stack Core, Cardputer,
Pimoroni, C6) vanished for the whole session while their ONLINE ads were
already hidden; the component grid + ONLINE component ads flipped between ad
cards and real entries depending on who won the reload race (different SVG,
ONLINE badge appearing and disappearing, wrong hover thumbnail).

proBoardRegistry and ComponentRegistry.mergeComponents now bump a version and
notify subscribers; the picker's allBoards / filteredComponents /
visibleComponentAds memos key off those via useSyncExternalStore — same
contract as proRoutes and registerProExamples.
2026-07-23 06:59:46 +02:00
David Montero Crespo 78f5f5ebc3 feat(proBoardRegistry): attachBuiltins — overlay-owned built-in peripheral wiring
Boards with built-in hardware (LCD on the element's own canvas, speaker,
on-board buttons/keyboard) need run-time wiring between the DOM element and
the board's simulator shim / ESP32 bridge. One generic SimulatorCanvas effect
now hands those handles to the overlay's attachBuiltins shortly after run
start and runs its cleanup on stop — no board names in the OSS tree.
2026-07-22 22:33:46 +02:00
David Montero Crespo a7c36f7a7b fix(proBoardRegistry): loadFirmware receives the store's compiled artifact as a string
compiledProgram is the base64/hex string the backend returned (what
RP2040Simulator.loadBinary consumes) — not raw bytes.
2026-07-22 21:22:40 +02:00
David Montero Crespo 32958640a3 feat(boards): runtime board-registration seam for private overlays
registerProBoards() lets a hosted overlay ship boards outside the OSS tree as
data-only definitions: registration patches the exported BoardKind maps
(labels / FQBN / MicroPython) so every existing read site keeps working, and
the sites a map can't cover consult the registry — canvas render (custom
element or overlay render fn), BOARD_SIZE, pin-name mapping, picker list +
descriptions + tag, ESP32 family routing, in-browser simulator construction
and firmware load (structural ProBoardSimulator contract, duck-typed PIO
attach/detach), built-in bridge sensors, and a CS-gated built-in microSD
(sdCsPin -> sd_card.cs_pin worker config). Esp32Bridge additionally gains the
esp32-c6 machine type + TX pin (public chip knowledge — the C6 compile path
already ships) and a generic sendKey() for built-in matrix keyboards.
registerProExamples() appends gallery examples at runtime; the board ONLINE
ads recompute at render so registration hides them. OSS behavior without an
overlay is unchanged — the registry is dead code, same as the other seams.
2026-07-22 21:21:21 +02:00