# Two USRPs with MIMO cable - rx\_multi\_samples

**URL:** <https://www.ruby-forum.com/t/two-usrps-with-mimo-cable-rx-multi-samples/232459>\
**Category:** GNU Radio\
**Created:** [October 10, 2014, 9:22am UTC](https://www.ruby-forum.com/t/two-usrps-with-mimo-cable-rx-multi-samples/232459 "2014-10-10T09:22:16Z")\
**Posts on this page:** 1\
**Page:** 1

<div class="post-metadata">

**Author:** ![addis\_a](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/a/c4cdca/32.png) [@addis\_a](https://www.ruby-forum.com/u/addis_a)\
**Post date:** [October 10, 2014, 9:22am UTC](https://www.ruby-forum.com/t/two-usrps-with-mimo-cable-rx-multi-samples/232459/1 "2014-10-10T09:22:16Z")

</div>

Dear all

I’m trying to get samples from two USRP2s connected via MIMO cable and  
the Gigabit ethernet cable is connected with the PC with only one USRP2.  
What I couldn’t figure out is only one of the USRP2s getting the samples  
and the other is not. I am testing this by using one of the examples  
from the uhd i.e. rx\_multi\_samples.cpp. The code is executed from the  
terminal as  
$ ./rx\_multi\_samples --args=“addr0=192.168.10.2, addr1=192.168.10.3”  
–sync=mimo.  
If anyone has any suggestion I really appreciate it.

#include \<uhd/utils/thread\_priority.hpp\>  
#include \<uhd/utils/safe\_main.hpp\>  
#include \<uhd/usrp/multi\_usrp.hpp\>  
#include \<boost/program\_options.hpp\>  
#include \<boost/format.hpp\>  
#include \<boost/thread.hpp\>  
#include \<boost/lexical\_cast.hpp\>  
#include \<boost/algorithm/string.hpp\>  
#include   
#include

namespace po = boost::program\_options;  
using namespace std;

int UHD\_SAFE\_MAIN(int argc, char \*argv[]){  
uhd::set\_thread\_priority\_safe();

```
//variables to be set by po
std::string args, sync, subdev, channel_list;
double seconds_in_future;
size_t total_num_samps;
double rate;

//setup the program options
po::options_description desc("Allowed options");
desc.add_options()
    ("help", "help message")
    ("args", po::value<std::string>(&args)->default_value(""),

```

“single uhd device address args”)  
(“secs”,  
po::value(&seconds\_in\_future)-\>default\_value(1.5), “number of  
seconds in the future to receive”)  
(“nsamps”,  
po::value\<size\_t\>(&total\_num\_samps)-\>default\_value(10000), “total number  
of samples to receive”)  
(“rate”, po::value(&rate)-\>default\_value(100e6/16),  
“rate of incoming samples”)  
(“sync”, po::valuestd::string(&sync)-\>default\_value(“now”),  
“synchronization method: now, pps, mimo”)  
(“subdev”, po::valuestd::string(&subdev), “subdev spec  
(homogeneous across motherboards)”)  
(“dilv”, “specify to disable inner-loop verbose”)  
(“channels”,  
po::valuestd::string(&channel\_list)-\>default\_value(“0”), “which  
channel(s) to use (specify “0”, “1”, “0,1”, etc)”)  
;  
po::variables\_map vm;  
po::store(po::parse\_command\_line(argc, argv, desc), vm);  
po::notify(vm);

```
//print the help message
if (vm.count("help")){
    std::cout << boost::format("UHD RX Multi Samples %s") % desc <<

```

std::endl;  
std::cout \<\<  
" This is a demonstration of how to receive aligned data from  
multiple channels.\n"  
" This example can receive from multiple DSPs, multiple  
motherboards, or both.\n"  
" The MIMO cable or PPS can be used to synchronize the  
configuration. See --sync\n"  
“\n”  
" Specify --subdev to select multiple channels per  
motherboard.\n"  
" Ex: --subdev=“0:A 0:B” to get 2 channels on a Basic  
RX.\n"  
“\n”  
" Specify --args to select multiple motherboards in a  
configuration.\n"  
" Ex: --args=“addr0=192.168.10.2, addr1=192.168.10.3”\n"  
\<\< std::endl;  
return ~0;  
}

```
bool verbose = vm.count("dilv") == 0;

//create a usrp device
std::cout << std::endl;
std::cout << boost::format("Creating the usrp device with: %s...") %

```

args \<\< std::endl;  
uhd::usrp::multi\_usrp::sptr usrp =  
uhd::usrp::multi\_usrp::make(args);

```
//always select the subdevice first, the channel mapping affects the

```

other settings  
if (vm.count(“subdev”)) usrp-\>set\_rx\_subdev\_spec(subdev); //sets  
across all mboards  
if (vm.count(“subdev1”)) usrp-\>set\_rx\_subdev\_spec(subdev1); //sets  
across all mboards

```
std::cout << boost::format("Using Device: %s") %

```

usrp-\>get\_pp\_string() \<\< std::endl;

```
//set the rx sample rate (sets across all channels)
std::cout << boost::format("Setting RX Rate: %f Msps...") %

```

(rate/1e6) \<\< std::endl;  
usrp-\>set\_rx\_rate(rate);  
std::cout \<\< boost::format(“Actual RX Rate: %f Msps…”) %  
(usrp-\>get\_rx\_rate()/1e6) \<\< std::endl \<\< std::endl;

```
std::cout << boost::format("Setting device timestamp to 0...") <<

```

std::endl;  
if (sync == “now”){  
//This is not a true time lock, the devices will be off by a few  
RTT.  
//Rather, this is just to allow for demonstration of the code  
below.  
usrp-\>set\_time\_now(uhd::time\_spec\_t(0.0));  
}  
else if (sync == “pps”){  
usrp-\>set\_time\_source(“external”);  
usrp-\>set\_time\_unknown\_pps(uhd::time\_spec\_t(0.0));  
boost::this\_thread::sleep(boost::posix\_time::seconds(1)); //wait  
for pps sync pulse  
}  
else if (sync == “mimo”){  
UHD\_ASSERT\_THROW(usrp-\>get\_num\_mboards() == 2);

```
    //make mboard 1 a slave over the MIMO Cable
    usrp->set_clock_source("mimo", 1);
    usrp->set_time_source("mimo", 1);

    //set time on the master (mboard 0)
    usrp->set_time_now(uhd::time_spec_t(0.0), 0);

    //sleep a bit while the slave locks its time to the master
    boost::this_thread::sleep(boost::posix_time::milliseconds(1000));
}

//detect which channels to use
std::vector<std::string> channel_strings;
std::vector<size_t> channel_nums;
boost::split(channel_strings, channel_list,

```

boost::is\_any\_of(""’,"));  
for(size\_t ch = 0; ch \< channel\_strings.size(); ch++){  
size\_t chan = boost::lexical\_cast(channel\_strings[ch]);  
if(chan \>= usrp-\>get\_rx\_num\_channels()){  
throw std::runtime\_error(“Invalid channel(s) specified.”);  
}  
else  
channel\_nums.push\_back(boost::lexical\_cast(channel\_strings[ch]));  
}

```
//create a receive streamer
//linearly map channels (index0 = channel0, index1 = channel1, ...)
uhd::stream_args_t stream_args("fc32"); //complex floats
stream_args.channels = channel_nums;
uhd::rx_streamer::sptr rx_stream = usrp->get_rx_stream(stream_args);

//setup streaming
std::cout << std::endl;
std::cout << boost::format(
    "Begin streaming %u samples, %f seconds in the future..."
) % total_num_samps % seconds_in_future << std::endl;
uhd::stream_cmd_t

```

stream\_cmd(uhd::stream\_cmd\_t::STREAM\_MODE\_NUM\_SAMPS\_AND\_DONE);  
stream\_cmd.num\_samps = total\_num\_samps;  
stream\_cmd.stream\_now = false;  
stream\_cmd.time\_spec = uhd::time\_spec\_t(seconds\_in\_future);  
rx\_stream-\>issue\_stream\_cmd(stream\_cmd); //tells all channels to  
stream

```
//meta-data will be filled in by recv()
uhd::rx_metadata_t md;

//allocate buffers to receive with samples (one buffer per channel)
const size_t samps_per_buff = rx_stream->get_max_num_samps();
std::vector<std::vector<std::complex<float> > > buffs(
    usrp->get_rx_num_channels(), std::vector<std::complex<float>

```

> (samps\_per\_buff)  
> );

```
//create a vector of pointers to point to each of the channel

```

buffers  
std::vector\<std::complex \*\> buff\_ptrs;  
for (size\_t i = 0; i \< buffs.size(); i++)  
buff\_ptrs.push\_back(&buffs[i].front());

```
//the first call to recv() will block this many seconds before

```

receiving  
double timeout = seconds\_in\_future + 0.1; //timeout (delay before  
receive + padding)

vector\<std::complex \>::iterator it1 = buffs[0].begin();  
vector\<std::complex \>::iterator it2 = buffs[1].begin();

```
size_t num_acc_samps = 0; //number of accumulated samples
while(num_acc_samps < total_num_samps){
    //receive a single packet
    size_t num_rx_samps = rx_stream->recv(
        buff_ptrs, samps_per_buff, md, timeout
    );

    //use a small timeout for subsequent packets
    timeout = 0.1;

    //handle the error code
    if (md.error_code == uhd::rx_metadata_t::ERROR_CODE_TIMEOUT)

```

break;  
if (md.error\_code != uhd::rx\_metadata\_t::ERROR\_CODE\_NONE){  
throw std::runtime\_error(str(boost::format(  
“Receiver error %s”  
) % md.strerror()));  
}

```
    if(verbose) std::cout << boost::format(
        " Received packet: %u samples, %u full secs, %f

```

frac secs"  
) % num\_rx\_samps % md.time\_spec.get\_full\_secs() %  
md.time\_spec.get\_frac\_secs() \<\< std::endl;

```
num_acc_samps += num_rx_samps;
for (size_t i = 0; i < 363; i++)
{
  cout << "

```

buffs[1].front()\<\<\<\<\<\<\<\<\<\<\<\<\<\<\<\<\<\<\<\<\<" \<\< it2[i] \<\< endl;  
cout \<\< “buffs[0].front()\>\>\>\>\>\>\>\>\>\>\>\>\>\>\>\>\>\>\>\>\>” \<\< it1[i] \<\< endl;  
}  
}

```
if (num_acc_samps < total_num_samps) std::cerr << "Receive timeout

```

before all samples received…" \<\< std::endl;  
//finished  
std::cout \<\< std::endl \<\< “Done!” \<\< std::endl \<\< std::endl;

```
return EXIT_SUCCESS;

```

}
