Skip to content
Thomas Wuillemin edited this page Apr 2, 2019 · 2 revisions

GO Binding for SoapySDR

This project is the binding of SoapySDR APIs to Go

SoapySDR Version

The latest version of the binding is based on the current development version of SoapySDR (~v0.7.2 / ~v0.8.0).

The binding versioning scheme is roughly following SoapySDR major and minor. However the patch number is specific to the binding. So, for example, with SoapySDR v0.7.2 you can use go-bindings v0.7.4.

Status

Almost all APIs of SoapySDR are accessible (see part exceptions nonetheless).

The original documentation has been adapted to Go and should be usable without issue.

The error management is modified to be more "Go-ish" than the original C API.

Limitations

As of now:

  • The supported stream types are CU8, CS8, CU16, CS16, CF32 and CF64. It should be fairly easy to add more if needed.
  • The DirectBufferAccess APIs are not binded

Usage

There are two main "objects" usable from Go:

  • SDRDevice which is a structure representing a device
  • SDRStream which is an interface for streams

Contrary to the original version, and to comply with Go typing, streams are also typed. So the data type they are handling can be clearly exposed. For example, one implementation of the Stream interface is the struct SDRStreamCU8. In this case, the read and write methods are based an uint8 array, greatly simplifying the client part.

Arrays for receiving data and flags MUST be allocated before calling read and write functions. Note that it is, for now, the responsibility of the caller to allocate the good size. When receiving separated measures for I and Q such as in CU8, CS8, CU16, CS16, if asked a single data, SoapySDR will return two measures. For example reading a a single CS8 data needs an array of 2 int8.

Build

As the binding is using cgo, for building it is necessary to have a SoapySDR development environment (libraries and include files).

Example

The main.go archive in the cmd presents a complete example for retrieving the properties and the reading of data.

A shorted version would be:

// The name of the device
args := map[string]string{
    "driver": "hackrf",
}

// Open the device
dev, err := device.Make(args)
if err != nil {
    log.Fatal(err)
}

// Open the stream and activate it for receiving CS8 data
stream, err := dev.SetupSDRStreamCS8(device.DirectionRX, []uint{0}, nil)
if err != nil {
    log.Fatal(fmt.Printf("SetupStream fail: error: %v\n", err))
}
if err := stream.Activate(0, 0, 0); err != nil {
    log.Fatal(fmt.Printf("Activate fail: error: %v\n", err))
}

// Prepare an array for receiving the data. As CS8 is returning 2 * bytes (for I and Q), by allocating
// 1024 bytes, only 512 samples can be read.
buffers := make([][]int8, 1)
buffers[0] = make([]int8, 1024)
flags := make([]int, 1)

// Read the data
timeNs, numElemsRead, err := stream.Read(buffers, 512, flags, 100000)
fmt.Printf("flags=%v, numElemsRead=%v, timeNs=%v, err=%v\n", flags, numElemsRead, timeNs, err)

// Close the stream
if err := stream.Deactivate(0, 0); err != nil {
    log.Fatal(fmt.Printf("Deactivate fail: error: %v\n", err))
}
if err := stream.Close(); err != nil {
    log.Fatal(fmt.Printf("Close fail: error: %v\n", err))
}

// Close the device
err = dev.Unmake()
if err != nil {
    log.Fatal(err)
}
Clone this wiki locally