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.
This commit is contained in:
David Montero Crespo 2026-08-19 02:50:49 +02:00
parent 9733047a9f
commit 149fbee1e9
3 changed files with 29 additions and 2 deletions

View File

@ -2731,15 +2731,22 @@ export const SimulatorCanvas = ({ headerSlot }: SimulatorCanvasProps = {}) => {
ESP32-CAM (OV2640 over I2S0 DVP) and the XIAO ESP32S3
Sense (OV2640-compatible over LCD_CAM). */}
{(activeBoard?.boardKind === 'esp32-cam' ||
activeBoard?.boardKind === 'xiao-esp32s3-sense') && (
activeBoard?.boardKind === 'xiao-esp32s3-sense' ||
(activeBoard &&
Boolean(getProBoard(activeBoard.boardKind)?.builtInCamera))) && (
<CameraToggle
boardId={activeBoard.id}
// The S3 esp32-camera build allocates width*height/5 bytes
// for a QVGA JPEG frame (15360) and stops copying at
// fb_size - one 1 KiB DMA half-buffer: frames must stay
// under ~14336 or the EOI marker is truncated (NO-EOI).
// Overlay boards declare their cap on builtInCamera.
maxFrameBytes={
activeBoard.boardKind === 'xiao-esp32s3-sense' ? 14000 : undefined
activeBoard.boardKind === 'xiao-esp32s3-sense'
? 14000
: ((cam) => (typeof cam === 'object' ? cam.maxFrameBytes : undefined))(
getProBoard(activeBoard.boardKind)?.builtInCamera,
)
}
/>
)}

View File

@ -47,6 +47,22 @@ export function isOnlineOnlyAdSuppressed(id: string): boolean {
}
export const ONLINE_ONLY_BOARD_ADS: OnlineOnlyBoardAd[] = [
{
id: 'esp-eye',
label: 'ESP-EYE',
description: 'Espressif AI vision devkit: ESP32 + OV2640 camera, I2S mic, face-recognition heritage — in-browser emulation',
thumbnailSvg:
'<svg width="72" height="72" viewBox="0 0 72 72" xmlns="http://www.w3.org/2000/svg">' +
'<rect x="20" y="4" width="32" height="64" rx="5" fill="#131316"/>' +
'<circle cx="36" cy="26" r="12" fill="#1c1c20" stroke="#33343a"/>' +
'<circle cx="36" cy="26" r="8" fill="#060608" stroke="#2f2f34"/>' +
'<circle cx="36" cy="26" r="3" fill="#101722"/>' +
'<rect x="30" y="42" width="12" height="10" fill="#d8b44a"/>' +
'<rect x="26" y="56" width="20" height="6" rx="1.5" fill="#b8bec6"/>' +
'<circle cx="47" cy="46" r="2.2" fill="#ff4030"/>' +
'<circle cx="25" cy="46" r="2.2" fill="#e8e8ea"/>' +
'</svg>',
},
{
id: 'esp32-c3-lcdkit',
label: 'ESP32-C3-LCDkit',

View File

@ -105,6 +105,10 @@ export interface ProBoardDef {
* setMicrophoneSource (I2S RX sample injection): shows the canvas-header
* Mic toggle that streams the computer's microphone into it. */
builtInMicrophone?: boolean;
/** The board carries a camera fed from the host webcam (CameraToggle in the
* canvas header; the bridge implements pushCameraFrame). An object form
* caps the injected JPEG size for drivers with tight frame buffers. */
builtInCamera?: boolean | { maxFrameBytes?: number };
/** Display-controller identity for panel autodetect probes. Vendor
* libraries (M5GFX and friends) identify a board by reading the panel's
* RDDID over SPI with the display's own chip-select — and reject the