Skip to content
Josh Blum edited this page Nov 21, 2017 · 4 revisions

SoapyMultiSDR - multi-device support

Use multiple SoapySDR supported devices under a single device wrapper.

Multi prefix to pass device arguments through the inception

Since SoapyMultiSDR is a bit of a meta-wrapper, it makes use of the prefix multi: (much like remote: for SoapyRemote) to pass arguments to the underlying drivers that would conflict with arguments we want to pass directly to SoapyMultiSDR. This is especially useful for the driver keyword which is used inside the factory lookup itself to filter out support modules. But MultiSDR supports any argument in general by simply stripping the prefix whenever its found.

For example, to simultaneously request the "multi" driver, and to request the underlying driver as rtlsdr use:

  • driver=multi,multi:driver=rtlsdr

Index format for specific device indexes

The example above would specify the rtlsdr driver for all internal devices. But that's not going to be sufficient for MultiSDR as it needs arguments to be specified for each device. Therefore MultiSDR also supports "indexing-format" for specifying a specific device in the list of devices. For example:

  • driver=multi,multi:driver=rtlsdr,serial[0]=00000001,serial[1]=00000002

SoapyMultiSDR can see there are two devices because it has two indexed keywords. And subsequently re-formats the internal device args to the format expected by the underlying SoapySDR device. The example above gets interpreted internally as:

  • Device 0 args: driver=rtlsdr,serial=00000001
  • Device 1 args: driver=rtlsdr,serial=00000002

Alternatively, one can also skip the multi: prefix and use the index format instead. Although this may seem redundant for homogeneous devices. Example again using indexes:

  • driver=multi,driver[0]=rtlsdr,driver[1]=rtlsdr,serial[0]=00000001,serial[1]=00000002

Mapping transforms for API calls

Once we have a MultiSDR device instance, we can make all of the regular SoapySDR API calls. But first, understand how named parameters and channels are transformed so that API calls can be mapped to a specific device and to specific channels on that device.

Channel index transforms

Channel mappings are very strait forward. The indexes grow sequentially for each device, so that the first indexes map to device 0, and the next indexes to the next device and so on. The API call getNumChannels() is critical here because it tells the channel logic how many channels are on each device, and subsequently effects the indexing. Take for example a MultiSDR of two devices where getNumChannels() == 2. Then the indexing would operate as follows:

  • setGain(dir, 0, dB) is transformed internally to device0->setGain(dir, 0, dB)
  • setGain(dir, 1, dB) is transformed internally to device0->setGain(dir, 1, dB)
  • setGain(dir, 2, dB) is transformed internally to device1->setGain(dir, 0, dB)
  • setGain(dir, 3, dB) is transformed internally to device1->setGain(dir, 1, dB)

Name parameter transforms

Global API calls with string named parameters (like readSensor) don't have a specific channel space which can be segmented for the multi-device, we must modify the string name itself. Therefore, the calls use the same index formatting once again to map parameters to a specific device. For example, if each underlying device had a sensor named foo, then the names presented as the multi device would be foo[0] and foo[1]:

  • readSensor("foo[0]") is transformed internally to device0->readSensor("foo")

Inception with SoapyRemote

Although it hurts to think about, the MultiSDR system is fully inceptive by supporting a SoapyMultiSDR made up of individual SoapyRemotes or a SoapyRemote that proxies for a local SoapyMultiSDR. Note that many of the arguments don't get prefixed because they don't really need to be mutated between layers since they are ignored in these layers:

Example Args for MultiSDR of remotes

driver=multi,multi:driver=remote,remote=host,remote:driver=rtlsdr,serial[0]=00000001,serial[1]=00000002

  • driver=multi specifies the multi support module
  • multi:driver=remote uses the remote support module for each internal device
  • remote=host specifies the remote host (could use index format if different hosts)
  • remote:driver=rtlsdr specifies the rtl driver on the remote node
  • serial[0]=00000001 specifies the specific device serial number

Args for SoapyRemote to proxy a MultiSDR

driver=remote,remote:driver=multi,remote=host,multi:driver=rtlsdr,serial[0]=00000001,serial[1]=00000002

  • driver=remote specifies the remote support module
  • remote:driver=multi specifies the multi driver on the remote end
  • remote=host specifies the remote host (could use index format if different hosts)
  • multi:driver=rtlsdr specifies the rtl driver on the remote node in the multi module
  • serial[0]=00000001 specifies the specific device serial number