Loading...
Searching...
No Matches
Multiple USRP configurations

# Introduction

Some USRP devices are capable of being grouped to form a single, virtual device. A single uhd::usrp::multi_usrp instantiation can control such a compound of devices.

Currently, the following devices support this capability:

- USRP2 / N2x0 Series
- X3x0 Series
- N3x0 Series
- X4x0 Series

Note that only USRPs of the same type can be combined.

# Setting up devices

A description of a multiple-USRP setup can be found on the respective device's manual pages.

Addressing of a compound of devices is done by listing multiple addresses, e.g.:

    addr0=192.168.10.2,addr1=192.168.20.2

# Channel and Device Numbering

Assume we have combined 2 X310 USRPs into a single multi_usrp using the address string given above, maybe using the following command:

uhd::device_addr_t args("addr0=192.168.10.2,addr1=192.168.20.2");
uhd::usrp::multi_usrp::sptr usrp = uhd::usrp::multi_usrp::make(args);
uhd::device_addr_t
Definition device_addr.hpp:39
uhd::usrp::multi_usrp::sptr
std::shared_ptr< multi_usrp > sptr
Definition multi_usrp.hpp:98
uhd::usrp::multi_usrp::make
static sptr make(const device_addr_t &dev_addr)

Some uhd::usrp::multi_usrp commands require passing a device index. This is simply the index in the address list, so say we want to check the master clock rate on both devices, this would be valid:

double mcr0 = usrp->get_master_clock_rate(0);
double mcr1 = usrp->get_master_clock_rate(1);

Some methods default to applying to all devices, so the following command would set the time on all devices to zero:

usrp->set_time_next_pps(uhd::time_spec_t(0));
uhd::time_spec_t
Definition time_spec.hpp:31

So, device indexes run from 0 to N-1 where N is the number of devices.

Channels are indexed in a similar way. Channel indexes run from 0 to M-1 where M is the total number of channels on all devices.

The number and order of channels per device depends on the subdev spec (see also Specifying the Subdevice). In the current example, assume all the X310 USRPs are using their standard configuration, and all have two daughterboards inside.

In this case channels 0 and 1 map to slot A and B of the first USRP, respectively. Channels 2 and 3 map to slots A and B of the second USRP, and so on.

However, by changing the subdev spec on individual devices, this can change. Say we have this unusual piece of code next:

usrp->set_rx_subdev_spec("A:0 B:0", 0);
usrp->set_rx_subdev_spec("A:0", 1);
usrp->set_rx_subdev_spec("B:0 A:0", 2);

The first device uses the default configuration. The second device artificially disables slot B, giving this USRP a single channel only. The third device uses both devices, but flips their order.

Now, there's a total of 5 channels, mapped as:

- Channel 0: Slot A of Device 0
- Channel 1: Slot B of Device 0
- Channel 2: Slot A of Device 1
- Channel 3: Slot A of Device 2
- Channel 4: Slot B of Device 2

While valid, this kind of configuration is not recommended unless heavily documented. It is usually simplest to call set_rx_subdev_spec() without a device index, which will set the same subdev spec on all devices. This assumes all devices have a similar daughterboard configuration

# MIMO Operation

When a multi-channel streamer is generated from a compound multi_usrp, and a streamer with multiple channels is generated, MIMO operations is automatically chosen. This means samples will be aligned between streams automatically.

In order for this to work, all devices must use a common time and frequency reference. This can be achieved in different ways, e.g. by daisy-chaining devices (for a small number of X-Series devices), using the MIMO cable (when only 2 N2x0 devices are used), or using a clock distribution system, e.g. an OctoClock. See Device Synchronization and the individual device manuals on more details on how to do this.