The BOX-3 touch gamebook had several blocking bugs that made the voiced+foley story packs unusable. This fixes them end to end. - Stack overflow on story start: gb_play_task kept a 2 KB buffer on its 4 KB stack and rebooted the board. Buffers are now static (the task is a singleton) and the stack is 6 KB. - No sound at all: the ES8311 codec was never initialised — main.c wrote raw I2S to a muted DAC. Output (and the mic) now go through the BSP esp_codec_dev (bsp_audio_codec_speaker/microphone_init, esp_codec_dev_write/read). The power amplifier (GPIO46) is also forced on and volume set to 100, as the es8311 pa_pin handling did not drive it in practice. - First passage silent: gb_play re-mounted the SD that the gamebook had already mounted; the failed second bsp_sdcard_mount tore down the VFS so the first fopen failed. Now we open the file first and only mount if that fails. A short silence lead-in also primes the codec/PA ramp. - No accents: the gamebook used ASCII-only lv_font_montserrat_14/24. Added custom Montserrat fonts (font_fr_14/24, Latin-1 + œŒŸ « » ’ …, uncompressed so they render without LV_USE_FONT_COMPRESSED). - Mic/voice streaming gated behind CONFIG_BOX3_VOICE_STREAMING (default off): as a gamebook the BOX-3 needs no mic, and the constant codec reads + bridge reconnects interfered with playback and flooded the log. plip_virtual + cmd_exec handle types switched from i2s_chan_handle_t to esp_codec_dev_handle_t accordingly.
Zacus BOX-3 Voice Pipeline
ESP-IDF firmware for ESP32-S3-BOX-3 — voice interface for Le Mystere du Professeur Zacus escape room.
Prerequisites
- ESP-IDF v5.2+ (with ESP32-S3 support)
- Python 3.8+ (for idf.py)
Build
# Set target
idf.py set-target esp32s3
# Configure (optional — defaults in sdkconfig.defaults)
idf.py menuconfig
# Build
idf.py build
# Flash (USB-C on BOX-3)
idf.py -p /dev/tty.usbmodem* flash monitor
Configuration
Use idf.py menuconfig > Zacus BOX-3 Voice Configuration:
| Option | Default | Description |
|---|---|---|
| WiFi SSID | zacus-net |
Network for voice bridge |
| WiFi Password | (empty) | WPA2 password |
| Voice Bridge URL | ws://192.168.4.1:8080/ws/voice |
mascarade WebSocket |
| Wake Word | hi esp |
WakeNet9 trigger phrase |
| Speaker Volume | 70 | 0-100 |
| Mic Gain | 80 | 0-100 |
Hardware
- Board: ESP32-S3-BOX-3 (16MB flash, 8MB PSRAM)
- Codec: ES8311 (I2C addr 0x18)
- Display: ILI9341 320x240
- Mic: onboard MEMS
- Speaker: onboard 1W with PA
Architecture
[Mic] -> I2S -> WakeNet -> Voice Capture -> WebSocket -> mascarade bridge
|
[Speaker] <- I2S <- TTS audio <------------- WebSocket -------+
|
hints engine <--+
Générateur de stimulus (QR + mélodie)
En plus du pipeline vocal, la BOX-3 sert de source de stimulus pour le master Freenove. Elle affiche un QR code (lu par la caméra du master) et joue une mélodie (entendue par le micro du master). Cela permet de tester les énigmes locales P1 (son) et P3 (QR) du master de bout en bout, sans QR imprimé ni instrument de musique.
Les routes sont enregistrées sur le serveur HTTP existant (scenario_server)
au démarrage, juste après l'init de l'écran et de l'UI (stimulus_init() puis
stimulus_register_routes() dans app_main).
POST /stim/qr
{"text": "zacus-qr-1"}
Affiche le texte en QR plein écran : un widget lv_qrcode de 160 px sur une
page LVGL dédiée, chargée au premier plan. Le rétroéclairage est atténué à
35 % pour réduire le halo de l'écran émissif et préserver le contraste pour la
caméra du master.
curl -X POST http://192.168.1.50/stim/qr \
-H 'Content-Type: application/json' \
-d '{"text":"zacus-qr-1"}'
# {"status":"ok","text":"zacus-qr-1"}
POST /stim/melody
{"notes": [60, 62, 64, 65], "ms": 400}
Joue la séquence de notes MIDI au haut-parleur. notes est un tableau
d'entiers 0-127 (60 = do central), ms est la durée par note en
millisecondes, bornée à 1-4000 (défaut 400). La séquence est jouée sur une
tâche worker dédiée, donc la réponse HTTP revient immédiatement. Maximum
32 notes ; les notes hors plage sont ignorées.
curl -X POST http://192.168.1.50/stim/melody \
-H 'Content-Type: application/json' \
-d '{"notes":[60,62,64,65,67],"ms":300}'
# {"status":"ok","notes":5}
Note de terrain
Le décodage par la caméra du master du QR affiché sur l'écran LCD n'est pas
fiable : le contraste émissif est insuffisant pour quirc, qui ne retrouve pas
les motifs de repérage (finder patterns) quelle que soit la résolution, même
écran atténué. La mélodie est le chemin de stimulus le plus robuste. Pour
P3, le QR imprimé reste recommandé ; le /stim/qr sert surtout au cadrage
et au débogage de la caméra.
Configuration Wi-Fi
Le générateur est joignable sur l'IP de la BOX-3 en mode station. Configurez le
réseau via idf.py menuconfig > Zacus BOX-3 Voice Configuration, ou
directement par CONFIG_ZACUS_WIFI_SSID / CONFIG_ZACUS_WIFI_PASSWORD.