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

GO Binding for SoapySDR

This project is the binding of SoapySDR APIs to Go

SoapySDR Version

The current binding is based on the version v0.7.x of Soapy SDR. The binding is following SoapySDR major and minor. However the patch number is specific to the binding.

Status

Almost all APIs of Soapy SDR are accessible from. The main APIs not binded are the DirectBufferAccess APIs. As they are using array of void*, it is probably safer to not use them for now with the Go binding.

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

The error management is also more "Go-ish" than the original C API.

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.

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.

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, Soapy SDR 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