fix(esp32-ui): add bootable scaffold and align docs
This commit is contained in:
parent
ffbb1d9087
commit
8051c06756
4 changed files with 157 additions and 168 deletions
|
|
@ -7,10 +7,9 @@ description = "ZeroClaw ESP32 UI firmware with Slint - Graphical interface for A
|
||||||
authors = ["ZeroClaw Team"]
|
authors = ["ZeroClaw Team"]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
# ESP-IDF framework
|
anyhow = "1.0"
|
||||||
esp-idf-svc = "0.48"
|
esp-idf-svc = "0.48"
|
||||||
log = { version = "0.4", default-features = false }
|
log = { version = "0.4", default-features = false }
|
||||||
anyhow = "1.0"
|
|
||||||
|
|
||||||
# Slint UI - MCU optimized
|
# Slint UI - MCU optimized
|
||||||
slint = { version = "1.10", default-features = false, features = [
|
slint = { version = "1.10", default-features = false, features = [
|
||||||
|
|
@ -19,41 +18,13 @@ slint = { version = "1.10", default-features = false, features = [
|
||||||
"renderer-software",
|
"renderer-software",
|
||||||
] }
|
] }
|
||||||
|
|
||||||
# Display drivers
|
|
||||||
mipidsi = { version = "0.9", features = ["batch"] }
|
|
||||||
display-interface-spi = "0.5"
|
|
||||||
embedded-graphics = "0.8"
|
|
||||||
|
|
||||||
|
|
||||||
# Serialization for communication
|
|
||||||
serde = { version = "1.0", default-features = false, features = ["derive"] }
|
|
||||||
serde_json = { version = "1.0", default-features = false, features = ["alloc"] }
|
|
||||||
|
|
||||||
# Async support
|
|
||||||
embassy-sync = { version = "0.6", features = ["defmt"] }
|
|
||||||
embassy-futures = "0.1"
|
|
||||||
embassy-time = { version = "0.1", features = ["tick-hz-100", "defmt"] }
|
|
||||||
|
|
||||||
# WiFi networking
|
|
||||||
embedded-svc = "0.28"
|
|
||||||
|
|
||||||
# Capacitive touch driver (FT6X36)
|
|
||||||
ft6x36 = "0.2"
|
|
||||||
|
|
||||||
# I2C for touch controller
|
|
||||||
esp-idf-hal = "0.43"
|
|
||||||
|
|
||||||
# Utilities
|
|
||||||
heapless = "0.8"
|
|
||||||
nb = "1.1"
|
|
||||||
|
|
||||||
[build-dependencies]
|
[build-dependencies]
|
||||||
embuild = { version = "0.31", features = ["elf"] }
|
embuild = { version = "0.31", features = ["elf"] }
|
||||||
slint-build = "1.10"
|
slint-build = "1.10"
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = ["std", "display-st7789"]
|
default = ["std", "display-st7789"]
|
||||||
std = ["esp-idf-svc/std", "serde/std", "serde_json/std"]
|
std = ["esp-idf-svc/std"]
|
||||||
|
|
||||||
# Display selection (choose one)
|
# Display selection (choose one)
|
||||||
display-st7789 = [] # 320x240 or 135x240
|
display-st7789 = [] # 320x240 or 135x240
|
||||||
|
|
|
||||||
|
|
@ -1,193 +1,106 @@
|
||||||
# ZeroClaw ESP32 UI Firmware
|
# ZeroClaw ESP32 UI Firmware
|
||||||
|
|
||||||
Slint-based graphical interface for ZeroClaw AI assistant on ESP32.
|
Slint-based graphical UI firmware scaffold for ZeroClaw edge scenarios on ESP32.
|
||||||
|
|
||||||
|
## Scope of This Crate
|
||||||
|
|
||||||
|
This crate intentionally provides a **minimal, bootable UI scaffold**:
|
||||||
|
|
||||||
|
- Initializes ESP-IDF logging/runtime patches
|
||||||
|
- Compiles and runs a small Slint UI (`MainWindow`)
|
||||||
|
- Keeps display and touch feature flags available for incremental driver integration
|
||||||
|
|
||||||
|
What this crate **does not** do yet:
|
||||||
|
|
||||||
|
- No full chat runtime integration
|
||||||
|
- No production display/touch driver wiring in `src/main.rs`
|
||||||
|
- No Wi-Fi/BLE transport logic
|
||||||
|
|
||||||
## Features
|
## Features
|
||||||
|
|
||||||
- **Modern UI**: Declarative interface built with Slint UI framework
|
- **Slint UI scaffold** suitable for MCU-oriented iteration
|
||||||
- **Touch Support**: Compatible with resistive (XPT2046) and capacitive (FT6X36) touch panels
|
- **Display feature flags** for ST7789, ILI9341, SSD1306
|
||||||
- **Display Options**: Support for ST7789, ILI9341, and SSD1306 displays
|
- **Touch feature flags** for XPT2046 and FT6X36 integration planning
|
||||||
- **Connectivity**: WiFi and Bluetooth Low Energy support
|
- **ESP-IDF baseline** for embedded target builds
|
||||||
- **Memory Efficient**: Optimized for ESP32's limited RAM (~520KB)
|
|
||||||
|
|
||||||
## Hardware Requirements
|
|
||||||
|
|
||||||
### Recommended: ESP32-S3
|
|
||||||
- **SoC**: ESP32-S3 (Xtensa LX7 dual-core, 240MHz)
|
|
||||||
- **RAM**: 512KB SRAM + 8MB PSRAM (optional but recommended)
|
|
||||||
- **Display**: 2.8" 320x240 TFT LCD (ST7789 or ILI9341)
|
|
||||||
- **Touch**: XPT2046 resistive or FT6X36 capacitive
|
|
||||||
- **Storage**: 4MB+ Flash
|
|
||||||
|
|
||||||
### Alternative: ESP32-C3
|
|
||||||
- **SoC**: ESP32-C3 (RISC-V single-core, 160MHz)
|
|
||||||
- **RAM**: 400KB SRAM
|
|
||||||
- **Display**: 1.14" 135x240 TFT (ST7789)
|
|
||||||
- **Note**: Limited to simpler UI due to RAM constraints
|
|
||||||
|
|
||||||
## Project Structure
|
## Project Structure
|
||||||
|
|
||||||
```
|
```text
|
||||||
firmware/zeroclaw-esp32-ui/
|
firmware/zeroclaw-esp32-ui/
|
||||||
├── Cargo.toml # Rust dependencies
|
├── Cargo.toml # Rust package and feature flags
|
||||||
├── build.rs # Build script for Slint compilation
|
├── build.rs # Slint compilation hook
|
||||||
├── .cargo/
|
├── .cargo/
|
||||||
│ └── config.toml # Cross-compilation settings
|
│ └── config.toml # Cross-compilation defaults
|
||||||
├── ui/
|
├── ui/
|
||||||
│ └── main.slint # Slint UI definition
|
│ └── main.slint # Slint UI definition
|
||||||
└── src/
|
└── src/
|
||||||
└── main.rs # Application entry point
|
└── main.rs # Firmware entry point
|
||||||
```
|
```
|
||||||
|
|
||||||
## Prerequisites
|
## Prerequisites
|
||||||
|
|
||||||
1. **Rust toolchain with ESP32 support**:
|
1. **ESP Rust toolchain**
|
||||||
```bash
|
```bash
|
||||||
cargo install espup
|
cargo install espup
|
||||||
espup install
|
espup install
|
||||||
source ~/export-esp.sh
|
source ~/export-esp.sh
|
||||||
```
|
```
|
||||||
|
|
||||||
2. **Additional tools**:
|
2. **Flashing tools**
|
||||||
```bash
|
```bash
|
||||||
cargo install espflash cargo-espflash
|
cargo install espflash cargo-espflash
|
||||||
```
|
```
|
||||||
|
|
||||||
3. **Hardware setup**:
|
## Build and Flash
|
||||||
- Connect display to SPI pins (see pin configuration below)
|
|
||||||
- Ensure proper power supply (3.3V logic level)
|
|
||||||
|
|
||||||
## Pin Configuration
|
### Default target (ESP32-C3, from `.cargo/config.toml`)
|
||||||
|
|
||||||
Default pin mapping for ESP32-S3 with ST7789 display and FT6X36 capacitive touch:
|
|
||||||
|
|
||||||
### Display (SPI)
|
|
||||||
|
|
||||||
| Function | GPIO Pin | Description |
|
|
||||||
|----------|---------|-------------|
|
|
||||||
| SPI SCK | GPIO 6 | SPI Clock |
|
|
||||||
| SPI MOSI | GPIO 7 | SPI Data Out |
|
|
||||||
| SPI MISO | GPIO 8 | SPI Data In (optional) |
|
|
||||||
| SPI CS | GPIO 10 | Chip Select |
|
|
||||||
| DC | GPIO 4 | Data/Command |
|
|
||||||
| RST | GPIO 3 | Reset |
|
|
||||||
| Backlight| GPIO 5 | Display backlight |
|
|
||||||
|
|
||||||
### Touch Controller (I2C)
|
|
||||||
|
|
||||||
| Function | GPIO Pin | Description |
|
|
||||||
|----------|---------|-------------|
|
|
||||||
| I2C SDA | GPIO 1 | I2C Data |
|
|
||||||
| I2C SCL | GPIO 2 | I2C Clock |
|
|
||||||
| INT | GPIO 11 | Touch interrupt |
|
|
||||||
|
|
||||||
### Hardware Connections
|
|
||||||
|
|
||||||
```
|
|
||||||
ESP32-S3 ST7789 Display FT6X36 Touch
|
|
||||||
----------- --------------- -------------
|
|
||||||
GPIO 6 ──────────► SCK
|
|
||||||
GPIO 7 ──────────► MOSI
|
|
||||||
GPIO 10 ──────────► CS
|
|
||||||
GPIO 4 ──────────► DC
|
|
||||||
GPIO 3 ──────────► RST
|
|
||||||
GPIO 5 ──────────► BACKLIGHT (via resistor)
|
|
||||||
|
|
||||||
GPIO 1 ──────────► SDA
|
|
||||||
GPIO 2 ──────────► SCL
|
|
||||||
GPIO 11 ◄────────── INT
|
|
||||||
```
|
|
||||||
|
|
||||||
**Note**: Use 3.3V for power. ST7789 typically requires 3.3V logic level.
|
|
||||||
|
|
||||||
## Building
|
|
||||||
|
|
||||||
### Standard build for ESP32-S3:
|
|
||||||
```bash
|
```bash
|
||||||
cd firmware/zeroclaw-esp32-ui
|
cd firmware/zeroclaw-esp32-ui
|
||||||
cargo build --release
|
cargo build --release
|
||||||
```
|
|
||||||
|
|
||||||
### Flash to device:
|
|
||||||
```bash
|
|
||||||
cargo espflash flash --release --monitor
|
cargo espflash flash --release --monitor
|
||||||
```
|
```
|
||||||
|
|
||||||
### Build for ESP32-C3 (RISC-V):
|
### Build for ESP32-S3 (override target)
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
rustup target add riscv32imc-esp-espidf
|
cargo build --release --target xtensa-esp32s3-espidf
|
||||||
cargo build --release --target riscv32imc-esp-espidf
|
|
||||||
```
|
```
|
||||||
|
|
||||||
### Feature flags:
|
## Feature Flags
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# Use ILI9341 display instead of ST7789
|
# Switch display profile
|
||||||
cargo build --release --features display-ili9341
|
cargo build --release --features display-ili9341
|
||||||
|
|
||||||
# Enable WiFi support
|
# Enable planned touch profile
|
||||||
cargo build --release --features wifi
|
cargo build --release --features touch-ft6x36
|
||||||
|
|
||||||
# Enable touch support
|
|
||||||
cargo build --release --features touch-xpt2046
|
|
||||||
```
|
```
|
||||||
|
|
||||||
## UI Design
|
## UI Layout
|
||||||
|
|
||||||
The interface is defined in `ui/main.slint` with the following components:
|
The current `ui/main.slint` defines:
|
||||||
|
|
||||||
- **StatusBar**: Shows connection status and app title
|
- `StatusBar`
|
||||||
- **MessageList**: Displays conversation history
|
- `MessageList`
|
||||||
- **InputBar**: Text input with send button
|
- `InputBar`
|
||||||
- **MainWindow**: Root container with vertical layout
|
- `MainWindow`
|
||||||
|
|
||||||
### Customizing the UI
|
These components are placeholders to keep future hardware integration incremental and low-risk.
|
||||||
|
|
||||||
Edit `ui/main.slint` and rebuild:
|
## Next Integration Steps
|
||||||
```bash
|
|
||||||
cargo build --release
|
|
||||||
```
|
|
||||||
|
|
||||||
The build script automatically compiles Slint files.
|
1. Wire real display driver initialization in `src/main.rs`
|
||||||
|
2. Attach touch input events to Slint callbacks
|
||||||
## Memory Optimization
|
3. Connect UI state with ZeroClaw edge/runtime messaging
|
||||||
|
4. Add board-specific pin maps with explicit target profiles
|
||||||
For ESP32 (non-S3) with limited RAM:
|
|
||||||
|
|
||||||
1. Reduce display buffer size in `main.rs`:
|
|
||||||
```rust
|
|
||||||
const DISPLAY_WIDTH: usize = 240;
|
|
||||||
const DISPLAY_HEIGHT: usize = 135;
|
|
||||||
```
|
|
||||||
|
|
||||||
2. Use smaller font sizes in Slint UI
|
|
||||||
|
|
||||||
3. Enable release optimizations (already in Cargo.toml):
|
|
||||||
- `opt-level = "s"` (optimize for size)
|
|
||||||
- `lto = true` (link-time optimization)
|
|
||||||
|
|
||||||
## Troubleshooting
|
|
||||||
|
|
||||||
### Display shows garbage
|
|
||||||
- Check SPI connections and pin mapping
|
|
||||||
- Verify display orientation in `Builder::with_orientation()`
|
|
||||||
- Try different baud rates (26MHz is default)
|
|
||||||
|
|
||||||
### Out of memory
|
|
||||||
- Reduce Slint window size
|
|
||||||
- Disable unused features
|
|
||||||
- Consider ESP32-S3 with PSRAM
|
|
||||||
|
|
||||||
### Touch not working
|
|
||||||
- Verify touch controller is properly wired
|
|
||||||
- Check I2C/SPI address configuration
|
|
||||||
- Ensure interrupt pin is correctly connected
|
|
||||||
|
|
||||||
## License
|
## License
|
||||||
|
|
||||||
MIT - See root LICENSE file
|
MIT - See root `LICENSE`
|
||||||
|
|
||||||
## References
|
## References
|
||||||
|
|
||||||
- [Slint ESP32 Documentation](https://slint.dev/esp32)
|
- [Slint ESP32 Documentation](https://slint.dev/esp32)
|
||||||
- [ESP-IDF Rust Book](https://esp-rs.github.io/book/)
|
- [ESP-IDF Rust Book](https://esp-rs.github.io/book/)
|
||||||
- [ZeroClaw Hardware Design](../docs/hardware-peripherals-design.md)
|
- [ZeroClaw Hardware Design](../../docs/hardware-peripherals-design.md)
|
||||||
|
|
|
||||||
22
firmware/zeroclaw-esp32-ui/src/main.rs
Normal file
22
firmware/zeroclaw-esp32-ui/src/main.rs
Normal file
|
|
@ -0,0 +1,22 @@
|
||||||
|
//! ZeroClaw ESP32 UI firmware scaffold.
|
||||||
|
//!
|
||||||
|
//! This binary initializes ESP-IDF, boots a minimal Slint UI, and keeps
|
||||||
|
//! architecture boundaries explicit so hardware integrations can be added
|
||||||
|
//! incrementally.
|
||||||
|
|
||||||
|
use anyhow::Context;
|
||||||
|
use log::info;
|
||||||
|
|
||||||
|
slint::include_modules!();
|
||||||
|
|
||||||
|
fn main() -> anyhow::Result<()> {
|
||||||
|
esp_idf_svc::sys::link_patches();
|
||||||
|
esp_idf_svc::log::EspLogger::initialize_default();
|
||||||
|
|
||||||
|
info!("Starting ZeroClaw ESP32 UI scaffold");
|
||||||
|
|
||||||
|
let window = MainWindow::new().context("failed to create MainWindow")?;
|
||||||
|
window.run().context("MainWindow event loop failed")?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
83
firmware/zeroclaw-esp32-ui/ui/main.slint
Normal file
83
firmware/zeroclaw-esp32-ui/ui/main.slint
Normal file
|
|
@ -0,0 +1,83 @@
|
||||||
|
component StatusBar inherits Rectangle {
|
||||||
|
in property <string> title_text: "ZeroClaw ESP32 UI";
|
||||||
|
in property <string> status_text: "disconnected";
|
||||||
|
|
||||||
|
height: 32px;
|
||||||
|
background: #1f2937;
|
||||||
|
border-radius: 6px;
|
||||||
|
|
||||||
|
HorizontalLayout {
|
||||||
|
padding: 8px;
|
||||||
|
|
||||||
|
Text {
|
||||||
|
text: root.title_text;
|
||||||
|
color: #e5e7eb;
|
||||||
|
font-size: 14px;
|
||||||
|
vertical-alignment: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
Text {
|
||||||
|
text: root.status_text;
|
||||||
|
color: #93c5fd;
|
||||||
|
font-size: 12px;
|
||||||
|
horizontal-alignment: right;
|
||||||
|
vertical-alignment: center;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
component MessageList inherits Rectangle {
|
||||||
|
in property <string> message_text: "UI scaffold is running";
|
||||||
|
|
||||||
|
background: #0f172a;
|
||||||
|
border-radius: 6px;
|
||||||
|
border-color: #334155;
|
||||||
|
border-width: 1px;
|
||||||
|
|
||||||
|
Text {
|
||||||
|
text: root.message_text;
|
||||||
|
color: #cbd5e1;
|
||||||
|
horizontal-alignment: center;
|
||||||
|
vertical-alignment: center;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
component InputBar inherits Rectangle {
|
||||||
|
in property <string> hint_text: "Touch input integration pending";
|
||||||
|
|
||||||
|
height: 36px;
|
||||||
|
background: #1e293b;
|
||||||
|
border-radius: 6px;
|
||||||
|
|
||||||
|
Text {
|
||||||
|
text: root.hint_text;
|
||||||
|
color: #e2e8f0;
|
||||||
|
horizontal-alignment: center;
|
||||||
|
vertical-alignment: center;
|
||||||
|
font-size: 12px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export component MainWindow inherits Window {
|
||||||
|
width: 320px;
|
||||||
|
height: 240px;
|
||||||
|
background: #020617;
|
||||||
|
|
||||||
|
VerticalLayout {
|
||||||
|
padding: 10px;
|
||||||
|
spacing: 10px;
|
||||||
|
|
||||||
|
StatusBar {
|
||||||
|
title_text: "ZeroClaw Edge UI";
|
||||||
|
status_text: "booting";
|
||||||
|
}
|
||||||
|
|
||||||
|
MessageList {
|
||||||
|
message_text: "Display/touch drivers can be wired here";
|
||||||
|
}
|
||||||
|
|
||||||
|
InputBar {
|
||||||
|
hint_text: "Use touch-xpt2046 or touch-ft6x36 feature later";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue