---
name: test-xteink-firmware
description: "Build and interactively test Xteink ESP32-C3 firmware in the native emulator. Use when validating firmware UI, buttons, screenshots, serial output, SD behavior, or networking."
---

# Test Xteink Firmware

## Overview

Build firmware for an Xteink device, boot it in the native emulator, and validate behavior through serial logs, physical controls, screenshots, SD state, and network access.

Resolve script paths relative to this skill directory. `scripts/xteink-emu.sh` stores the qemu-xteink checkout location, builds native QEMU when missing, and runs the emulator. If its location is unset, run the `variable.sh --set` command printed by the wrapper after asking the user for the checkout path.

## Workflow

1. Inspect the firmware project and use its documented build command. Locate the resulting ESP32-C3 application binary; for PlatformIO this is commonly:

   ```sh
   pio run
   export XTEINK_FIRMWARE=.pio/build/default/firmware.bin
   export XTEINK_EMU_STATE=/tmp/xteink-firmware-$UID
   export XTEINK_EMU_SD=/tmp/xteink-firmware-$UID.img
   ```

2. Create a persistent FAT32 SD image once, unless the test requires a fresh card:

   ```sh
   truncate -s 64M "$XTEINK_EMU_SD"
   mkfs.fat -F 32 "$XTEINK_EMU_SD"
   ```

3. Start a clean emulator process while preserving SD contents:

   ```sh
   scripts/xteink-emu.sh stop --state-dir "$XTEINK_EMU_STATE" || true
   scripts/xteink-emu.sh start \
     --state-dir "$XTEINK_EMU_STATE" \
     --firmware "$XTEINK_FIRMWARE" \
     --sdcard "$XTEINK_EMU_SD"
   ```

   `start` simulates a two-second power-button hold for cold boot. Override `--power-hold-ms` when testing power behavior.

4. Observe serial behavior with either a persistent regex cursor or the raw log:

   ```sh
   scripts/xteink-emu.sh wait \
     --state-dir "$XTEINK_EMU_STATE" --timeout 30 --match 'pattern'
   tail -f "$XTEINK_EMU_STATE/serial.log"
   ```

5. Drive the physical controls:

   ```sh
   scripts/xteink-emu.sh button --state-dir "$XTEINK_EMU_STATE" bottom-2
   scripts/xteink-emu.sh button --state-dir "$XTEINK_EMU_STATE" power --down
   scripts/xteink-emu.sh button --state-dir "$XTEINK_EMU_STATE" power --up
   ```

   Available buttons are `left`, `right`, `bottom-1` through `bottom-4`, and `power`. Use the labels rendered by the current screen as the authoritative mapping. Allow the e-ink panel to refresh after state-changing input.

6. Capture and inspect the screen after meaningful transitions:

   ```sh
   scripts/xteink-emu.sh screenshot \
     --state-dir "$XTEINK_EMU_STATE" --output /tmp/xteink-screen.png
   ```

7. For network tests, connect the firmware to the single open Wi-Fi network named `qemu`, then validate the feature's observable result.

## Diagnose Failures

- Firmware serial output: `$XTEINK_EMU_STATE/serial.log`
- Emulator output: `$XTEINK_EMU_STATE/qemu.log`
- Assembled flash image: `$XTEINK_EMU_STATE/flash.bin`
- Resolve crash addresses against the exact ELF produced with the tested binary, using the project's RISC-V `addr2line` tool.
- Preserve the SD image when reproducing persistence bugs; replace it when testing first-boot behavior.

## Cleanup

```sh
scripts/xteink-emu.sh stop --state-dir "$XTEINK_EMU_STATE"
```
