PulseView & Sigrok Firmware
ESP32-S3 firmware that turns your board into a USB logic analyzer compatible with sigrok and PulseView. No dedicated hardware needed — just an ESP32-S3 you already have.
How it works
ESP32-S3 (SUMP firmware)
↓ USB cable (CDC serial)
Your computer
↓ PulseView (ols driver)
Waveform display, 131+ protocol decoders, export
The firmware implements the SUMP protocol over USB CDC. PulseView connects to it using the built-in Openbench Logic Sniffer (ols) driver — the same driver used for Arduino-based SUMP analyzers and the original OLS FPGA board. No custom sigrok driver needed.
Why ESP32-S3
ESP32-S3 is the best ESP32 variant for this. Two reasons:
1. USB. S3 has both USB Serial/JTAG (fixed-function serial port)
and USB-OTG (TinyUSB device stack). The MVP uses USB Serial/JTAG,
which appears as /dev/ttyACM* on Linux or COM* on Windows. Later
you can switch to USB-OTG for better throughput.
USB-OTG and USB Serial/JTAG share one PHY on ESP32-S3. You can’t use both at the same time. If you switch to OTG mode, the built-in USB flash/debug path stops working.
2. Sampling hardware. S3 has dedic_gpio — a dedicated GPIO
peripheral that reads 8 GPIOs in a single CPU cycle via the Xtensa
ee.get_gpio_in instruction. Combined with a tight polling loop
pinned to core 1, this achieves 10-80 MSa/s on 8 channels. S3 also
has RMT with GDMA for single-channel high-speed paths. C3 and C6
lack these — they only have a single I2S and fixed-function USB
Serial/JTAG, making them poor choices for a general-purpose logic
analyzer.
Note: The
LCD_CAMperipheral on ESP32-S3 is output-only at the ESP-IDF API level (v5.3+). There is no documented camera/DVP input API. The firmware usesdedic_gpioCPU polling instead, which is simpler and comfortably exceeds the 10 MSa/s target.
C3 / C6 comparison
| ESP32-S3 | ESP32-C3 | ESP32-C6 | |
|---|---|---|---|
| USB | Serial/JTAG + OTG | Serial/JTAG only | Serial/JTAG only |
| Parallel sampling | dedic_gpio (8ch) + RMT/GDMA | No | No |
| I2S | Multiple | 1 | 1 |
| Verdict | Best for LA | Limited — few channels, low speed | Same as C3 |
C3/C6 can work as simple SUMP devices for 1-2 channels at low speed, but don’t expect multi-channel general-purpose analysis from them.
What is sigrok
sigrok is an open-source signal analysis stack with four layers:
| Layer | Component | What it does |
|---|---|---|
| Hardware | Your device | Captures digital/analog signals |
| Driver + firmware | libsigrok | Talks to hardware, uploads firmware, reads samples |
| Protocol decoding | libsigrokdecode | Decodes captured bitstreams into protocols |
| Frontend | PulseView or sigrok-cli | Displays waveforms, annotations, exports |
sigrok supports 258+ devices (logic analyzers, oscilloscopes,
multimeters, power supplies). The firmware side ranges from open-source
fx2lafw (for Cypress FX2 devices) to vendor blobs that need
extraction.
What is SUMP
SUMP is the capture protocol between your device and the host. It’s a finite-depth capture model: the device arms, waits for a trigger, captures pre/post-trigger samples into a local buffer, then uploads everything to the host.
This matches how MCUs work — you have limited RAM, so you capture a fixed number of samples, then send them. It’s NOT a continuous streaming protocol.
PulseView and sigrok-cli connect using:
sigrok-cli --driver=ols:conn=/dev/ttyACM0
or in PulseView: device dropdown → Openbench Logic Sniffer → pick the serial port.
Protocol decoders
sigrok ships 131+ protocol decoders (Python, running in
libsigrokdecode). They can be stacked — lower decoders feed into
higher ones.
Common decoder chains:
| Wires → | Base decoder → | Upper decoder |
|---|---|---|
| SDA, SCL | I2C | 24xx EEPROM, EDID, HDCP |
| TX, RX | UART | Modbus RTU |
| TDI, TDO, TCK, TMS | JTAG | ARM ITM, EJTAG, STM32 |
| D+, D− | USB signalling | USB packet → USB request |
| CLK, MOSI, MISO, CS | SPI | SPI flash, SD card |
Also supported: CAN, I2S, 1-Wire, WS2812, infrared, FlexRay, USB PD,
S/PDIF, and many more. Each decoder is a Python module in
libsigrokdecode/decoders/. You can write your own.
Firmware architecture
The SUMP firmware has four layers:
┌─────────────────────────────┐
│ transport │
│ Receives SUMP commands, │
│ sends samples back. │
│ USB Serial/JTAG or CDC. │
├─────────────────────────────┤
│ capture │
│ Arms the sampler, waits │
│ for trigger, captures │
│ into the ring buffer. │
│ Uses dedic_gpio on core 1. │
├─────────────────────────────┤
│ buffer │
│ Ring buffer in SRAM for │
│ pre-trigger + post-trigger │
│ samples. │
├─────────────────────────────┤
│ upload │
│ Packs samples per SUMP │
│ spec and sends them over │
│ the transport. │
└─────────────────────────────┘
The capture layer is where the ESP32-S3’s hardware matters. The
dedic_gpio peripheral reads 8 GPIOs in one cycle, and a tight
unrolled loop on core 1 achieves 10-80 MSa/s depending on rate
limiting.
Build the firmware
The sigrok firmware is an ESP-IDF project. Build it through espctl:
1. Ask your AI assistant: "Build the sigrok firmware for esp32s3"
2. Or use the MCP Console at esphome.cloud/mcp/esp-idf
3. Or run: espctl build <project> --target esp32s3
The build produces a flash_bundle.tar.gz in the project’s build/
directory. The bundle contains manifest.json plus the bootloader,
partition table, and app binaries — everything espctl flash needs
in a single file. There is no separate fetch step; the bundle is
returned atomically in the same session as the build.
Flash
Flash the firmware over USB:
- From the browser: Use the Flash tab in the MCP Console or Browser Wizard.
- From the CLI:
espctl flash build/flash_bundle.tar.gz --port /dev/cu.usbmodem*
espctl flash uses the pure-Rust espflash
library under the hood — no Python esptool.py dependency. Do not
pip install esptool as a workaround if something goes wrong; file a
bug report under docs/espctl-flash-bugs-YYYY-MM-DD.md instead so the
real cause gets fixed.
After flashing, the ESP32-S3 re-enumerates as a USB CDC device. Your
OS should see a new serial port (/dev/ttyACM0 on Linux, COM3 on
Windows).
Two-USB-cable topology. On an ESP32-S3-DevKitC-1, the “UART” port (via the on-board USB-UART bridge) is what you flash and monitor through. The “USB” port (native USB-OTG straight to the S3 USB pins) is what sigrok-cli / PulseView talks to for SUMP data. For the full workflow — flash firmware, watch boot log, run
sigrok-cli --scanagainst the device — keep both cables plugged in.
Connect PulseView
- Open PulseView.
- Pick the driver: Device dropdown (top-left) → Openbench Logic Sniffer → pick your serial port.
- Set sample rate and sample count in the toolbar.
- Click Run (play button).
The ESP32-S3 arms, captures samples, and uploads them. PulseView displays the waveform.
Or from the command line:
sigrok-cli --driver=ols:conn=/dev/ttyACM0 \
--config samplerate=1M \
--samples 1000 \
--output-file capture.sr
Wiring
Connect the signal you want to capture to an ESP32-S3 GPIO pin. Connect ground between the ESP32-S3 and the target circuit.
Target circuit ESP32-S3
───────────── ────────
Signal pin ─────────────→ GPIO pin (input)
GND ─────────────→ GND
Voltage warning: ESP32-S3 GPIOs are 3.3V only. Do not connect 5V signals directly — use a level shifter or voltage divider.
Protocol decoding walkthrough
After capturing:
- Click + next to the channel list.
- Pick a decoder (UART, SPI, I2C, …).
- Map decoder channels to your GPIO pins.
- PulseView decodes and shows annotations on the waveform.
Decoders stack: add I2C, then add 24xx EEPROM on top of it. The EEPROM decoder reads the I2C decoder’s output and shows memory addresses and data values.
Best for
This firmware is a protocol analysis tool, not a Saleae/FX2/FPGA replacement. Best uses:
- Checking UART baud rates and framing
- Verifying SPI clock polarity and chip-select timing
- Debugging I2C address conflicts
- Decoding 1-Wire, WS2812, infrared timing
- Quick “is this bus alive?” checks
Limitations
- Sample rate: 10-80 MSa/s with
dedic_gpio(8 channels). Actual rate depends on loop unrolling and rate-limit settings. Not 100+ MHz like FPGA analyzers. - Buffer depth: Limited by ESP32-S3 SRAM (~32 KB default, up to 200 KB). SUMP is finite-depth, not streaming.
- Input only. Captures signals — doesn’t generate them.
- 3.3V logic only without external level shifting.
- USB PHY shared. If you use USB-OTG mode, you lose the built-in USB Serial/JTAG flash/debug path.
- macOS successive captures. On macOS, the kernel TTY driver
caches USB CDC data across port close/open. This causes the second
sigrok-clicapture to fail with “Invalid ID reply”. Workaround: power-cycle the device between captures. Linux does not have this issue.
See also
- MCP Console — build and flash from a browser.
- Tool Reference — the espctl build tools.
- sigrok.org — the sigrok project.
- PulseView — PulseView docs.
- SUMP protocol — SUMP compatible devices on sigrok wiki.
- Protocol decoders — full list of 131+ decoders.