Close

Adding SCPI support

A project log for T76 Instrument Core: Pro instruments on Pi Pico 2

A C++ framework for building real-time, pro-grade digital instruments on the RP2350 / Pi Pico 2 platform.

marco-tabiniMarco Tabini 11/03/2025 at 16:420 Comments

Support for SCPI is the last big feature remaining in this project (save for a lot of cleanup and then, of course, actually testing it in the field).

SCPI is a text-based interfacing standard that instrumentation devices use to communicate with each other. From a syntactical perspective, it's pretty simple: A device exposes a hierarchical set of commands that can be used to either interrogate the state of one or more systems, or to change it.

For example, a programmable power supply may expose a “MEASure” command hierarchy, with a “VOLTage” subsection. If you wanted to know the voltage on channel 1, you could then interrogate the device by sending a command that looks like this:

MEAS:VOLT:1

And the device might respond with something like

2.35

As you can see, commands can be declared with optional suffixes; thus, “MEASure” can be either specified as “MEAS” or “MEASURE” (but nothing in between).

The main challenge working with SCPI is that it is a very loose standard, and, as a result, it is unevenly implemented by different vendors.

Our implementation

In our case, we're going to provide an interpreter generator that allows us to define our own command hierarchy, and an interpreter that can be used at runtime to parse requests sent over USBTMC.

The system uses a set of tries to store the command hierarchy. This is an efficient mechanism that requires relatively little memory and allows for a very simple runtime implementation. The command hierarchy is specified in a YAML file and can be completely arbitrary, so long as it conforms to the SCPI standard.

At runtime, the interpreter accumulates input until it either recognizes a valid command or detects a syntax error. In the case of valid input, it then calls a user-defined handler that can perform the tasks associated with a command. 

The interpreter also parses all the parameters and validates them according their types; this makes writing handlers a bit easy, since you don't have to worry about checking for parameter count or making sure that, say, a number is malformed. Of course, you are still responsible for the semantic validation of data.

Integration

Adding the interpreter to an IC application is very simple. The SCPI library is already linked in the overall IC library; therefore, all you need to do is create a YAML file for your definitions, instantiate an interpreter, and override the _onUSBTMCDataReceived() in your application code.

For more information, check out the add-scpi branch, which is now merged into main.

Discussions