Using the SDK

Do you love your Saleae analyzer, but need it to do something extra, or do something it already does, only differently?  You can do these things, and more, with the Saleae Logic SDKs.  This post is a brief introduction to the Saleae SDKs, providing an overview of the Saleae Scripting Socket API and Analyzer SDK, along with links to documentation, resources, and source code.  Future posts about the SDKs may go into more detail, however this should whet your appetite for Logic customization and control using Saleae SDKs.

Suppose you are designing an embedded system with a requirement to monitor communications, control, or data buses, detect particular activity, and take some action when it occurs.  You could do this in the lab with Logic by using the GUI to configure appropriate triggers, capture, and analyze the data yourself, however, an embedded system usually has to take care of itself, and we can’t afford to have a human in the loop in this hypothetical production system (a human would be much more expensive, and less reliable, than Logic and some code).  This is where Logic’s SDK support comes in.  Using the SDKs, we can configure and control Logic under program control without interacting with the GUI, to capture data when triggered, and then process our captured data with custom analyzers (plugins) for more refined detection capability; when our custom analyzer plugin confirms the event of interest has occurred, the controlling program can take appropriate action.

Scripting Socket API  & Analyzer SDK

Saleae provides SDK support for controlling Logic itself, and for implementing custom plugins for data analysis.  The SDK for controlling Logic is called the Scripting Socket API, and provides programmatic control of and access to the internal functions of Logic, bypassing Logic’s GUI.  The SDK for implementing Logic plugins is called the Analyzer SDK, it provides a framework for developing custom modules to analyze data captured by Logic, and is used by Saleae developers to craft Logic’s protocol analyzer plugins.

Scripting Socket API

The Saleae Scripting Socket API gives you remote control and access to Logic’s internal functions and data through command line scripting rvia a network socket.  


Saleae Logic Analyzers have a scriptable configuration, command, and control interface  via a network socket server, which enables you to programmatically operate Logic and export captured data via a TCP connection.  The scripting socket server is platform independent, consisting of a text-based protocol designed for sending commands to Logic and receiving responses from Logic.

Each command will return back with either an “ACK” or a “NAK” string when Logic executes the command.  If any error occurs, or if the command is unrecognized, the software will return “NAK”.  The scripting interface supports a few commands.  Some commands require arguments.  Arguments must be separated with the comma character: ‘,’.

The scripting socket server will work with any tcp client, once enabled, however Saleae provides a Windows-only console application (with C# source) which will access and pass commands and responses to and from the software’s socket for you.  The automation tester ships pre-built with the Scripting Socket API as LogicAutomationController.exe and can be found in the (bin/Release directory).

Getting Started

The socket connection default is TCP port 10429.  To use the Scripting Socket API, enable the scripting interface in the software by opening the preferences dialog from the options menu, selecting the developer tab, and then check the box for “Enable scripting socket server.”  Save these changes.

Automation Tester Program

Start the Automation Tester Program (LogicAutomationController.exe  in the bin/Release directory) and it prompts you to enter the host ip address; you’ll probably want to just hit Enter to accept the default of ‘localhost’.  Next, you are prompted to provide the host port, hit Enter to accept the default of 10429/tcp (which is the default server port Logic will be listening on, because we did not change the server port when we enabled the scripting interface in the previous step).

The Automation Tester Program will try to connect to Logic and if successful will report

* Connected*
* Enter a string to xmit, q to exit.*

If there is an error connecting, check connections, firewalls, etc. and try again.  If connected, you can send commands, receive responses, get help, or start demo mode.

Hitting ‘h’ followed by Enter displays example commands:

Example scripts:
* set_sample_rate, 12000000, 6000000*
* set_num_samples, 1000000*
settrigger, high, negedge, low, none,
** capture
to_file, c:/test1.logicdata**

Enter a string to xmit, q to exit.

While the application is running, Socket commands can also be typed directly into the command prompt.  When creating automation scripts, it may be simpler to customize the source of the Automation Tester Program using the C# Functions as described in “Using the C# console app”, in Logic+Automation+Users+Guide.pdf..

Demo Mode

Typing ‘demo’ followed by Enter starts demo mode.  The software will run through a sequence of demonstration commands prompted by the enter key.  In Demo Mode the application calls the Demo() function within the SocketAPI class, shown below:

public void Demo()

StringHelper.WriteLine(“Demo Mode Initiated”);
SetActiveChannels(new int[] { 0, 1, 2, 3, 4 }, new int[] { 0, 1 });
List digitalchannels = new List();
List analog
channels = new List();
GetActiveChannels(digitalchannels, analogchannels);

//export captured data

List samplerates = GetAvailableSampleRates();
Trigger[] trigger = { Trigger.High, Trigger.Posedge, Trigger.High, Trigger.None, Trigger.High };
StringHelper.WriteLine(“Demo Complete”);


Using the C# App

The SocketAPI class, in the automation program, directly implements C# functions for controlling the software.

An instance of the SocketAPI class must be constructed in order to establish the socket connection. The constructor takes both the IP address and port number of the requested socket. The default values are set for localhost and the default software socket port.

SocketAPI( String hoststr = “”, int portinput = 10429 )


this.port = portinput; = host
Socket = new TcpClient(host, port);
Stream = Socket.GetStream();


The functions may then be called from the created object:

SAPI = new SocketAPI(host, port);

Functions and commands can be broken down into several categories.  In this brief introduction we will describe one socket command and the corresponding function from each category listed in Logic+Automation+Users+Guide.pdf; for complete coverage, please review the Users Guide.

Software PreCapture

The command to get available sample rates is in the PreCapture category.

Socket Command

Socket Command: getallsample_rates

This command returns all the available sample rate combinations for the current performance level and channel combination.

Example: getallsample_rates
Response( ${digital sample rate), ${analog sample rate} ):
5000000, 1250000
10000000, 625000

C# Function

List GetAvailableSampleRates()

This function returns a list of all the sample rates available for the current
performance option and channel combination.

struct SampleRate

public int AnalogSampleRate;
public int DigitalSampleRate;


Device/Channel Selection

When preparing to capture you may want to confirm the connected devices, and the Get Connected Devices command can help.

Socket Command

Socket Command: getconnecteddevices
This command will return a list of the devices currently connected to the computer.  The connected device will have the return parameter ACTIVE at the end of the line.

1, Demo Logic, LOGICDEVICE, 0x19b2
2, My Logic 16, LOGIC16

C# Function

ConnectedDevices[] GetConnectedDevices()

The function returns an array of ConnectedDevices structs. The structs contains the type of device, the name, the device id, the index of the device and whether or not the device is currently active.

struct ConnectedDevices

String type;
String name;
int deviceid;
int index;
bool is


Capture Data

When ready to capture, we’ll need to issue the Capture command.

Socket Command

Socket Command: capture

This command starts a capture. It will return NAK if an error occurs.


C# Function

void Capture()

The function takes no parameters.



After capture you may want to Save the data.

Socket Command

Socket Command: savetofile
This command saves the results of the current tab to a specified file. (Write permission required)
savetofile, C:\temp.logicdata

C# Function

void SaveToFile(String file)
The function takes a string with the file name to save to.

Analysis and Export

In the next section we will introduce the Analyzer SDK; for now, we will use the Get Analyzers command to find out what analyzers are installed.

Socket Command

Socket Command: get_analyzers

This function will return a list of analyzers currently attached to the capture, along with indexes so you can access them later.

Return Value:
SPI, 0
I2C, 1
SPI, 2

Please note that each line is separated by the ‘\n’ character.

C# Function

Analyzer[] GetAnalyzers()
The function returns an array of Strings, each containing the name and index of the analyzer.

struct Analyzer

String type;
int index;


Analyzer[] Analyzers = GetAnalyzers()

Analyzer SDK

The Saleae Analyzer SDK lets you make your own custom protocol analyzers.  The Analyzer SDK and documentation are available at .  After unpacking the archive, look in the documentation folder for Saleae Analyzer SDK.pdf.

Getting Started

The Analyzer SDK User Guide tells you how to set up your build environment, compile, and debug your Analyzer SDK Project in your choice of Windows, Mac, or Linux, with support for C++.  A sample analyzer source project is provided and used as an example throughout the User Guide.  The sample builds and runs out of the box.

Writing the Code for Your Analyzer Plugin

There are 4 c++ files and 4 header files that you will implement to create your analyzer.  The procedure in the User Guide describes how to build a working analyzer from the sample, and you will be modifying that code to suit your needs.  The User Guide explains customizing the sample code in detail; these are just excerpts, to get you started. Note, you may need to take a look at some of the other Analyzer SDK articles on the help center to get up and running. Depending on what version of the Saleae software you are using, or which OS could require different steps. Please check the analyzer SDK help center article for details.

Conceptually, the analyzer can be broken into 4 main parts – the 4 c++ files.

First, you’ll work on the AnalyzerSettings-derived class. You’ll define the settings your analyzer needs, and create interfaces that’ll allow the Logic software to display a GUI for the settings. You’ll also implement serialization for these settings so they can be saved and recalled from disk.

Next you implement the SimulationDataGenerator class. Here you’ll generate simulated data that can be later to test your analyzer, or provide an example of what your analyzer expects.

Third you’ll create your AnalyzerResults-derived class. This class translates saved results into text for a variety of uses. Here you’ll start thinking about the format your results will be saved in. You probably will revisit your this file after implementing your Analyzer.

Lastly, you’ll implement your Analyzer-derived class. The main thing you’ll do here is translate data streams into results, based on your protocol.

Analyzer Settings

After setting up your analyzer project, and renaming the source files to match your project, the first step is to implement/modify your analyzer’s AnalyzerSettings-derived class.  In this file, you provide a declaration for your uniquely-named, (e.g. {YourName}AnalyzerSettings class). This class must inherit from AnalyzerSettings, and should include the AnalyzerSettings.h header file.  The User Guide describes in detail how to flesh out the class including defining User-modifiable settings such as Bit rate and Bits per transfer, providing an interface object for each settings variable, writing the constructor and destructor, and completing the remainder of the necessary interfaces.


The next step after creating your uniquely-named, (e.g. {YourName}AnalyzerSettings) files, is to create your SimulationDataGenerator.  Your SimulationDataGenerator class provides simulated data so that you can test your analyzer against controlled, predictable waveforms.  Generally you should make the simulated data match the user settings, so you can easily test under a variety of expected conditions. In addition, simulated data gives end users an example of what to expect when using your analyzer, as well as examples of what the waveforms should look like.  That said, fully implementing simulated data is not absolutely required to make an analyzer.  Besides the constructor and destructor, there are only two required functions, and two required variables.  Other functions and variables can be added, to help implement your simulated data. The User Guide provides details using SimpleSerialSimulationDataGenerator.h as an example starting point.

AnalyzerResults-derived class

After creating your SimulationDataGenerator class, working on your uniquely-named, (e.g. {YourName}AnalyzerResults) files is the next step. AnalyzerResults is what we use to transform our results into text for display and as well as exported files, etc.  In addition to the constructor and destructor, there are 5 functions we’ll need to implement: GenerateBubbleText, GenerateExportFile, GenerateFrameTabularText, GeneratePacketTabularText, and GenerateTransactionTabularText.  The User Guide provides detailed examples.

Analyzer-derived class

Your Analyzer-derived class is the heart of the analyzer. It’s here were we analyze the bits coming in – in real time – and generate analyzer results. Other than a few other housekeeping things, that’s it. Let’s get started with your uniquely-named, (e.g. {YourName}Analyzer.h).

In addition to the constructor and destructor, here are the functions you’ll need to implement:

virtual void WorkerThread();

virtual U32 GenerateSimulationData( U64 newestsamplerequested, U32 samplerate, SimulationChannelDescriptor** simulationchannels );

virtual U32 GetMinimumSampleRateHz();

virtual const char* GetAnalyzerName() const;

virtual bool NeedsRerun();

extern “C” ANALYZEREXPORT const char* _cdecl GetAnalyzerName();

extern “C” ANALYZEREXPORT Analyzer* _cdecl CreateAnalyzer( );

extern “C” ANALYZEREXPORT void _cdecl DestroyAnalyzer( Analyzer* analyzer );

You’ll also need these member variables:

std::autoptr< {YourName}AnalyzerSettings > mSettings;
ptr< {YourName}AnalyzerResults > mResults;
{YourName}SimulationDataGenerator mSimulationDataGenerator;
bool mSimulationInitilized;

You’ll also need one AnalyzerChannelData raw pointer for each input. For SerialAnalyzer, for example, we need

AnalyzerChannelData* mSerial;

As you develop your analyzer, you’ll add additional member variables and helper functions depending on your analysis needs.

The User Guide describes in detail how to complete the implementation of your uniquely-named Analyzer, (e.g. {YourName}Analyzer.cpp).


This post introduced the Saleae Scripting Socket API and Analyzer SDK, with links to resources including documentation and code.  Watch the for updates, and look for future posts digging deeper into the SDKs.  If you have a cool custom device application or analysis plugin you’d like to share, please let us know!