Skip to content

About

Arduino Logic Analyzer API supporting the SUMP protocol (for sigrok, pulseview)

Topics

Resources

Stars

130 stars

Watchers

7 watching

Forks

Latest commit

 

History

77 Commits

Folders and files

Repository files navigation

A flexible Arduino SUMP Logic Analyzer Library

Recently, when I started to research the topic of Logic Analyzers, I found the incredible PulseView Project. However, I did not want to invest in additional hardware but just use one of my favorite microprocessors (ESP32, Raspberry Pico) as capturing device.

There are quite a few logic analyzer projects with a similar goal:

However all of them are geared for one specific architecture and therefore are not portable.

I wanted to come up with a better design and provide a simple Arduino C++ Library that implements the SUMP protocol and clearly separates the generic functionality from the processor specific in order to support an easy rollout to new architectures: The only common precondition is the Arduino API.

I am currently providing implementations for

  • AVR Processors (Uno/Nano and Mega 2560)
  • ESP32 (+ hardware-timed I2S DMA capture)
  • ESP32-S3 / ESP32-P4 (hardware-timed LCD_CAM DMA capture)
  • ESP8266
  • Raspberry Pi Pico / RP2040 / RP2350 (+ hardware-timed PIO DMA capture)

The Basic Arduino Sketch

The basic Arduino Sketch for the logic-analyzer is quite simple. We just need create a LogicAnalyzer and a Capture object. In the setup we call the begin method on the LogicAnalyzer object which provides all mandatory parameters. The provided implementation just uses the default values which are defined in the config. Finally we add the command handler in the loop():

#include "Arduino.h"
#include "logic_analyzer.h"

using namespace logic_analyzer;  

int pinStart=START_PIN;
int numberOfPins=PIN_COUNT;
LogicAnalyzer logicAnalyzer;
Capture capture(MAX_FREQ, MAX_FREQ_THRESHOLD);


void setup() {
    Serial.begin(SERIAL_SPEED);  
    Serial.setTimeout(SERIAL_TIMEOUT);
    logicAnalyzer.begin(Serial, &capture, MAX_CAPTURE_SIZE, pinStart, numberOfPins);
}

void loop() {
    if (Serial) logicAnalyzer.processCommand();
}

Adding Additional Functionality

Logging

You can activate the logging by assigning a Stream to the LogicAnalyzer object by calling logicAnalyzer.setLogger(). Use a different port than the one that is connected to PulseView - e.g. on an ESP32:

// setup logger
Serial1.begin(115200, SERIAL_8N1, 16, 17);
logicAnalyzer.setLogger(Serial1);

Using Events

An easy way to extend the functionality is by adding an event handler. The following acts on a status change event by activating the LED dependent on the actual status:

// Use Event handler to control the LED
void onEvent(Event event) {
    if (event == STATUS) {
        switch (logicAnalyzer.status()) {
            case ARMED:
                digitalWrite(LED_BUILTIN, HIGH);
                break;
            case STOPPED:
                digitalWrite(LED_BUILTIN, LOW);
                break;
        }
    }
}

and we can just activate it in setup() by calling:

pinMode(LED_BUILTIN, OUTPUT);
logicAnalyzer.setEventHandler(&onEvent);

Custom Capturing

I am providing a default implementation for the capturing with the Capture class. Its main goal is portability because it should work on all Arduino Boards. To come up with a dedicated improved capturing is easy. Just implement your own class:

class YourFastCapture : public AbstractCapture {
    public:
        /// Default Constructor
        YourFastCapture() : AbstractCapture(){
        }

        /// starts the capturing of the data
        virtual void capture(){
            /// your implementation
        }
};

The library already contains the following hardware-timed implementations:

None of them supports triggers yet.

Supporting new Architectures

In order to support a new architecture you need to implement a simple config file (guarded by an #ifdef for the architecture and included in config.h), that must contain the following information:

  • Defines for the processor specific (resource) settings (e.g. MAX_CAPTURE_SIZE, SERIAL_SPEED ...)
  • A typedef of the PinBitArray which defines the recorded data size
  • An implementation of the class PinReader which reads all pins in one shot (as a contiguous range starting at the start pin)

Here is the config_esp32.h.

Documentation

The complete generated class documentation can be found on Github.

Platform-specific details (supported GPIO ranges, hardware-timed capture backends, required wiring/board settings) are documented separately per processor:

Connecting to PulseView

  • Start the Arduino "logic-analyzer" Sketch
  • Start PulseView
  • Select "Connect to a Device":
    • Choose the Driver: Openbench Logic Sniffer & SUMP Compatibles
    • Choose the Interface: Select Serial Port with the Port to your Arduino Device and the baud rate defined by SERIAL_SPEED in the config_.h (921600 for ESP32, ESP8266 and Pico; 9600 for AVR)
    • Click on "Scan for Devices using driver above" button
    • Select the Device (e.g. "Arduino-ESP32" - the name is defined by DESCRIPTION in the config) and confirm with OK

You can also check the connection on the command line with sigrok-cli:

sigrok-cli --driver ols:conn=/dev/ttyUSB0:serialcomm=921600/8n1 --scan

Installation

You can download the library as zip and call include Library -> zip library. Or you can git clone this project into the Arduino libraries folder e.g. with

cd  ~/Documents/Arduino/libraries
git clone https://github.com/pschatzmann/logic-analyzer.git

Supported Boards

Processor Max Samples
ESP32 (+ ESP32-S3/P4) 65535
ESP8266 50000
AVR Processors (Nano) 500
Arduino Mega 2560 500
Raspberry Pico 65535

Please note, that SUMP supports only max 65535 samples. See the per-platform docs linked in the Documentation section above for max frequency, GPIO ranges, and available hardware-timed capture backends.

Summary

The basic implementation is only using a single core. While capturing is in process we do not support any cancellation triggered from PulseView. In order to support this, we would just need to extend the functionality in a specific sketch to run the capturing on one core and the command handling on the second core. And this is exactly the purpose of this library: to be able to build a custom optimized logic analyzer implementation with minimal effort!

Please check out the examples directory for some dedicated implementations. And if you come up with your own implementation, please share it with the community...

About

Arduino Logic Analyzer API supporting the SUMP protocol (for sigrok, pulseview)

Topics

Resources

Stars

130 stars

Watchers

7 watching

Forks

Releases

Packages

Contributors

Languages