Files
ESP32_ZACUS/box3_voice/main/plip_virtual.h
T
clement 43dc1478b1
CI / platformio (pull_request) Failing after 3m44s
CI / platformio (push) Failing after 3m34s
box3: fix gamebook audio, accents, and crashes
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.
2026-06-21 11:07:34 +02:00

64 lines
2.4 KiB
C

// plip_virtual — phone-less PLIP annex running on the ESP32-S3-BOX-3.
//
// Implements the PLIP REST contract (PLIP_FIRMWARE/src/network_task.cpp) on
// the box's existing HTTP server:
// POST /ring { "duration_ms": 4000 } → ring cadence on the BOX-3 speaker
// POST /stop → stop ringing
// POST /play → 501 (audio path is the WS TTS)
// GET /status → { off_hook, ringing, playing }
//
// The BOOT button is the virtual hook switch: a press during the ring picks
// up, a press while off-hook hangs up. Each transition is reported to the
// Zacus master (POST CONFIG_ZACUS_MASTER_URL/voice/hook {state, reason})
// exactly like the real PLIP's zacus_hook_client — the master cannot tell
// the two annexes apart.
#pragma once
#include <stdbool.h>
#include "esp_codec_dev.h"
#include "esp_err.h"
#include "esp_http_server.h"
#ifdef __cplusplus
extern "C" {
#endif
// Hook state, exposed for the on-screen phone UI (plip_ui).
typedef enum {
PLIP_HOOK_ON = 0, // idle, handset down
PLIP_HOOK_RINGING,
PLIP_HOOK_OFF, // picked up
} plip_hook_state_t;
// Register the REST handlers on `server` and keep `spk` for the ring tone.
// Call once after scenario_server_start(); the speaker channel must be
// enabled (speaker_init() in main.c).
esp_err_t plip_virtual_init(httpd_handle_t server, esp_codec_dev_handle_t spk);
// Forward a BOOT-button press. Returns true when the press was consumed as
// a hook transition (pickup/hangup) — the caller should then skip its own
// handling (voice-streaming toggle).
bool plip_virtual_button_press(void);
// Programmatic hook transitions (used by the touch UI). Both are no-ops
// when the state does not allow the transition.
void plip_virtual_pickup(void); // RINGING -> OFF (stops the ring)
void plip_virtual_hangup(void); // OFF -> ON
// Report a dialed number to the master (reason "dial:<number>" on the
// existing /voice/hook contract) and remember it for GET /status.
// Only meaningful while off-hook; ignored otherwise.
void plip_virtual_dial(const char *number);
// UI notification: called on every hook state change (from HTTP, button or
// touch context — the callback must do its own LVGL locking).
typedef void (*plip_state_cb_t)(plip_hook_state_t state);
void plip_virtual_register_state_cb(plip_state_cb_t cb);
plip_hook_state_t plip_virtual_state(void);
#ifdef __cplusplus
}
#endif