# DeskLock A living-room visual/audio endpoint for **Tatlock**, the homelab butler. DeskLock gives Tatlock a face and a voice on a Waveshare round touch display: you talk to it, it listens, thinks, and answers — the first line of contact with the butler backend running on tower-of-joy. ## Hardware **Waveshare ESP32-P4-WIFI6-Touch-LCD-3.4C** | Component | Details | |-----------|---------| | SoC | ESP32-P4NRW32 — dual-core RISC-V @ 400 MHz + LP core | | Memory | 32 MB PSRAM (in-package), 32 MB NOR flash | | Display | 3.4" round IPS, 800×800, MIPI-DSI 2-lane, capacitive touch | | Radio | ESP32-C6-MINI-1 (Wi-Fi 6 + BLE 5) over SDIO via ESP-Hosted | | Audio in | Dual onboard microphones + ES7210 echo-cancellation ADC | | Audio out | ES8311 codec, PH2.0 2-pin speaker connector (8Ω 2W recommended) | | Flashing | USB-C (hold BOOT during reset for download mode) | The device is currently connected over USB-C directly to tower-of-joy, so build/flash happens on this server. ## Architecture ``` ┌──────────────────────┐ WebSocket: PCM audio + JSON events │ DeskLock device │◄───────────────────────────────────┐ │ (ESP32-P4) │ │ │ • LVGL face │ ┌──────────────────────────────┴───────────┐ │ • touch / wake word │ │ DeskLock Gateway (container, :8600) │ │ • mic capture + AEC │ │ thin orchestrator — no ML dependencies │ │ • TTS playback │ └───────┬──────────────────┬───────────────┘ └──────────────────────┘ │ │ OpenAI-format HTTP │ ▼ HTTP (LAN) │ ┌─────────────────────────────┐ ▼ │ Speaches (container, GPU) │ ┌────────────────────┐ │ • STT: faster-whisper │ │ Tatlock (butler) │ │ • TTS: Kokoro / Piper │ │ tatlock.schweitz. │ │ also usable by Open WebUI, │ │ internal :8000 │ │ Home Assistant, … │ └────────────────────┘ └─────────────────────────────┘ ``` Tatlock stays a text-only brain. The **gateway** orchestrates speech-to-text, chat, and text-to-speech; the **Speaches** container owns the actual STT/TTS models on the GPU, shared homelab-wide. The device firmware stays thin: audio transport, wake word, and face rendering only. Everything runs on the LAN — no cloud in the voice path. See [docs/architecture.md](docs/architecture.md) for the full design. ## Repository layout - `firmware/` — ESP-IDF (C, LVGL 9) application for the ESP32-P4 - `gateway/` — Python FastAPI voice gateway, deployed as a container on tower-of-joy - `sim/face/` — browser simulator of the face (design source of truth; serve with `python3 -m http.server` and open `index.html`, or use `?state=…&nochrome=1` for screenshots) - `docs/` — architecture and design notes ## Roadmap 1. ~~**Bring-up**~~ ✅ — display, touch, audio, 200 MHz PSRAM, cathedral gong 2. **Face + voice loop** (in hardware test) — full LVGL face (7 states, rain, orbit, power ladder), Wi-Fi, WebSocket, touch-to-talk 3. **Voice (touch-to-talk)** — tap to talk → gateway → Tatlock → spoken reply 4. **Wake word** — esp-sr WakeNet on-device, echo cancellation, barge-in 5. **Polish** — Tatlock-initiated notifications, presence, OTA updates ## References - [Waveshare wiki: ESP32-P4-WIFI6-Touch-LCD-3.4C](https://www.waveshare.com/wiki/ESP32-P4-WIFI6-Touch-LCD-3.4C) - [Official examples repo (waveshareteam/ESP32-P4-WIFI6-Touch-LCD-XC)](https://github.com/waveshareteam/ESP32-P4-WIFI6-Touch-LCD-XC) - [BSP component: waveshare/esp32_p4_wifi6_touch_lcd_xc](https://components.espressif.com/components/waveshare/esp32_p4_wifi6_touch_lcd_xc) - [Speaches — self-hosted OpenAI-compatible speech server](https://github.com/speaches-ai/speaches) - Tatlock backend: `/mnt/media/Projects/tatlock` — https://tatlock.schweitz.net