Discussion and technical support related to USRP, UHD, RFNoC
View all threadsHi all,
I'm saving IQ-Samples from both Channels of an USRP B210 for Direction of Arrival Estimation with Music. My source Code is based on the rx_multi_samples.cpp example. For tests I connected a sine-generator with a splitter to both channels. With a pulse sine a verified that the measured data is time aligned. (picture abs_pulse_sine in appendix) But the problem is, that there is a phase offset between the two channels of more than 180 degree. (picture real_sine and phase_diff) This offset varies by retuning.
I don't understand where this phase offset come from, because the LO of both channels is in the same Chip and should be phase aligned. Is this a known problem of the B210? Or is there an error in my source code?
Regards,
Stefan Ereth
//
// Copyright 2011 Ettus Research LLC
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see http://www.gnu.org/licenses/.
//
#define use_short
#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 <iostream>
#include <fstream>
#include <complex>
namespace po = boost::program_options;
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,file,file0,file1;
double seconds_in_future, freq;
size_t total_num_samps;
double rate,gain,tx_gain;
std::ofstream outfile,outfile2;
//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")
("file", po::value<std::string>(&file)->default_value("measure0-1"), "name of the file to write binary samples to")
("secs", po::value<double>(&seconds_in_future)->default_value(1.0), "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<double>(&rate)->default_value(8e6), "rate of incoming samples")
("sync", po::value<std::string>(&sync)->default_value("b210"), "synchronization method: now, pps, mimo")
("freq", po::value<double>(&freq)->default_value(800e6), "RF center frequency in Hz")
("gain", po::value<double>(&gain), "gain for the RF chain")
("tx-gain", po::value<double>(&tx_gain), "gain for the TX in calibration Mode")
("subdev", po::value<std::string>(&subdev), "subdev spec (homogeneous across motherboards)")
("v", "specify to enable inner-loop verbose")
("calc","specify to enable transmitting and recording of calibration data")
("channels", po::value<std::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("v") == 1;
bool calibration = vm.count("calc") == 1;
/**************** RX Init *************************************************/
//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);
usrp->set_master_clock_rate(30e6); //less then 30.72e6 //Möglichkeit 1: Variable Clock-Rate
//always select the subdevice first, the channel mapping affects the other settings
if (vm.count("subdev")){
uhd::usrp::subdev_spec_t subdevClass = subdev;
std::cout << subdevClass.to_pp_string() << std::endl;
usrp->set_rx_subdev_spec(subdevClass); //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;
//set center Frequency
std::cout << boost::format("Setting RX Freq: %f MHz...") % (freq/1e6) << std::endl;
uhd::tune_request_t tune_request(freq);
for(size_t i=0;i<usrp->get_rx_num_channels();i++)
usrp->set_rx_freq(tune_request,i);
std::cout << boost::format("Actual RX Freq: %f MHz...") % (usrp->get_rx_freq(1)/1e6) << std::endl << std::endl;
//set the rf gain
if (vm.count("gain")){
for(size_t i=0;i<usrp->get_rx_num_channels();i++){
std::cout << boost::format("Setting RX Gain for Channel %d: %f dB...") % i % gain << std::endl;
usrp->set_rx_gain(gain,i);
std::cout << boost::format("Actual RX Gain: %f dB...") % usrp->get_rx_gain() << std::endl << std::endl;
}
}
//open files to write
if(calibration) file+=".calc"; //Kalibrierdaten mit Endung .calc
else file+=".dat"; //Messdaten mit Endung.dat
file0 = file;
file1 = file;
file0 += "0";
file1 += "1";
outfile.open(file0.c_str(), std::ofstream::binary);
if(usrp->get_rx_num_channels()>1){
outfile2.open(file1.c_str(),std::ofstream::binary);
}
/**************** Recieve Start ******************************************/
//create a receive streamer
//linearly map channels (index0 = channel0, index1 = channel1, ...)
uhd::stream_args_t stream_args("sc16"); //complex short
//stream_args.channels = channel_nums;
for (size_t i = 0; i < usrp->get_rx_num_channels(); i++)
stream_args.channels.push_back(i);
uhd::rx_streamer::sptr rx_stream = usrp->get_rx_stream(stream_args);
//setup streaming
std::cout << std::endl;
std::cout << boost::format(
"Begin receiving of %u samples. Start in %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) + usrp->get_time_now();
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<short> > > buffs(
usrp->get_rx_num_channels(), std::vector<std::complex<short> >(samps_per_buff)
);
//create a vector of pointers to point to each of the channel buffers
std::vector<std::complex<short> *> 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 + 1; //timeout (delay before receive + padding)
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;
//Schreiben der gelesenen Werte in die Dateien
if(outfile.is_open())
outfile.write((const char *)&buffs[0].front(),num_rx_samps*sizeof(buffs[0].front()));
if(outfile2.is_open())
outfile2.write((const char *)&buffs[1].front(),num_rx_samps*sizeof(buffs[1][0]));
num_acc_samps += num_rx_samps;
}
if (num_acc_samps < total_num_samps) std::cerr << "Receive timeout before all samples received..." << std::endl;
/**************************** Recieve End *******************************************************/
if(outfile.is_open())
outfile.close();
if(outfile2.is_open())
outfile2.close();
//finished
std::cout << std::endl << "Done! Mine" << std::endl << std::endl;
return EXIT_SUCCESS;
}
On 05/02/2014 02:30 AM, Stefan Ereth via USRP-users wrote:
Hi all,
I'm saving IQ-Samples from both Channels of an USRP B210 for Direction of Arrival Estimation with Music. My source Code is based on the rx_multi_samples.cpp example. For tests I connected a sine-generator with a splitter to both channels. With a pulse sine a verified that the measured data is time aligned. (picture abs_pulse_sine in appendix) But the problem is, that there is a phase offset between the two channels of more than 180 degree. (picture real_sine and phase_diff) This offset varies by retuning.
I don't understand where this phase offset come from, because the LO of both channels is in the same Chip and should be phase aligned. Is this a known problem of the B210? Or is there an error in my source code?
Regards,
Stefan Ereth
//
// Copyright 2011 Ettus Research LLC
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, seehttp://www.gnu.org/licenses/.
//
#define use_short
#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<iostream>
#include<fstream>
#include<complex>
namespace po = boost::program_options;
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,file,file0,file1;
double seconds_in_future, freq;
size_t total_num_samps;
double rate,gain,tx_gain;
std::ofstream outfile,outfile2;
//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")
("file", po::value<std::string>(&file)->default_value("measure0-1"), "name of the file to write binary samples to")
("secs", po::value<double>(&seconds_in_future)->default_value(1.0), "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<double>(&rate)->default_value(8e6), "rate of incoming samples")
("sync", po::value<std::string>(&sync)->default_value("b210"), "synchronization method: now, pps, mimo")
("freq", po::value<double>(&freq)->default_value(800e6), "RF center frequency in Hz")
("gain", po::value<double>(&gain), "gain for the RF chain")
("tx-gain", po::value<double>(&tx_gain), "gain for the TX in calibration Mode")
("subdev", po::value<std::string>(&subdev), "subdev spec (homogeneous across motherboards)")
("v", "specify to enable inner-loop verbose")
("calc","specify to enable transmitting and recording of calibration data")
("channels", po::value<std::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("v") == 1;
bool calibration = vm.count("calc") == 1;
/**************** RX Init *************************************************/
//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);
usrp->set_master_clock_rate(30e6); //less then 30.72e6 //Möglichkeit 1: Variable Clock-Rate
//always select the subdevice first, the channel mapping affects the other settings
if (vm.count("subdev")){
uhd::usrp::subdev_spec_t subdevClass = subdev;
std::cout<< subdevClass.to_pp_string()<< std::endl;
usrp->set_rx_subdev_spec(subdevClass); //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;
//set center Frequency
std::cout<< boost::format("Setting RX Freq: %f MHz...") % (freq/1e6)<< std::endl;
uhd::tune_request_t tune_request(freq);
for(size_t i=0;i<usrp->get_rx_num_channels();i++)
usrp->set_rx_freq(tune_request,i);
std::cout<< boost::format("Actual RX Freq: %f MHz...") % (usrp->get_rx_freq(1)/1e6)<< std::endl<< std::endl;
//set the rf gain
if (vm.count("gain")){
for(size_t i=0;i<usrp->get_rx_num_channels();i++){
std::cout<< boost::format("Setting RX Gain for Channel %d: %f dB...") % i % gain<< std::endl;
usrp->set_rx_gain(gain,i);
std::cout<< boost::format("Actual RX Gain: %f dB...") % usrp->get_rx_gain()<< std::endl<< std::endl;
}
}
//open files to write
if(calibration) file+=".calc"; //Kalibrierdaten mit Endung .calc
else file+=".dat"; //Messdaten mit Endung.dat
file0 = file;
file1 = file;
file0 += "0";
file1 += "1";
outfile.open(file0.c_str(), std::ofstream::binary);
if(usrp->get_rx_num_channels()>1){
outfile2.open(file1.c_str(),std::ofstream::binary);
}
/**************** Recieve Start ******************************************/
//create a receive streamer
//linearly map channels (index0 = channel0, index1 = channel1, ...)
uhd::stream_args_t stream_args("sc16"); //complex short
//stream_args.channels = channel_nums;
for (size_t i = 0; i< usrp->get_rx_num_channels(); i++)
stream_args.channels.push_back(i);
uhd::rx_streamer::sptr rx_stream = usrp->get_rx_stream(stream_args);
//setup streaming
std::cout<< std::endl;
std::cout<< boost::format(
"Begin receiving of %u samples. Start in %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) + usrp->get_time_now();
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<short> > > buffs(
usrp->get_rx_num_channels(), std::vector<std::complex<short> >(samps_per_buff)
);
//create a vector of pointers to point to each of the channel buffers
std::vector<std::complex<short> *> 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 + 1; //timeout (delay before receive + padding)
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;
//Schreiben der gelesenen Werte in die Dateien
if(outfile.is_open())
outfile.write((const char *)&buffs[0].front(),num_rx_samps*sizeof(buffs[0].front()));
if(outfile2.is_open())
outfile2.write((const char *)&buffs[1].front(),num_rx_samps*sizeof(buffs[1][0]));
num_acc_samps += num_rx_samps;
}
if (num_acc_samps< total_num_samps) std::cerr<< "Receive timeout before all samples received..."<< std::endl;
/**************************** Recieve End *******************************************************/
if(outfile.is_open())
outfile.close();
if(outfile2.is_open())
outfile2.close();
//finished
std::cout<< std::endl<< "Done! Mine"<< std::endl<< std::endl;
return EXIT_SUCCESS;
}
USRP-users mailing list
USRP-users@lists.ettus.com
http://lists.ettus.com/mailman/listinfo/usrp-users_lists.ettus.com
What are you passing in for the subdev argument?
What does
usrp->get_rx_num_channels()
Return in this example?
--
Marcus Leech
Principal Investigator
Shirleys Bay Radio Astronomy Consortium
http://www.sbrac.org
Hi Stefan,
Regarding your code, I noticed that it is streaming the 2 RX channels to file. I have also modified some Ettus examples to do this same task (see attached). It is based on rx_samples_to_file and benchmark_rate rather than rx_multi_samples. One reason I chose to modify the rx_samples_to_file example was that it included an LO Locked verification. Not sure if that could affect your results by not doing this check...
Regarding the phase offset, is it just a calibration issue? If you measure a phase offset with a ref signal and then later measure a real signal and apply the cal offset, does that fix your issue?
Rob Kossler
-----Original Message-----
From: USRP-users [mailto:usrp-users-bounces@lists.ettus.com] On Behalf Of Stefan Ereth via USRP-users
Sent: Friday, May 02, 2014 2:30 AM
To: usrp-users@lists.ettus.com
Subject: [USRP-users] Phase Offset between USRP-B210 Channels
Hi all,
I'm saving IQ-Samples from both Channels of an USRP B210 for Direction of Arrival Estimation with Music. My source Code is based on the rx_multi_samples.cpp example. For tests I connected a sine-generator with a splitter to both channels. With a pulse sine a verified that the measured data is time aligned. (picture abs_pulse_sine in appendix) But the problem is, that there is a phase offset between the two channels of more than 180 degree. (picture real_sine and phase_diff) This offset varies by retuning.
I don't understand where this phase offset come from, because the LO of both channels is in the same Chip and should be phase aligned. Is this a known problem of the B210? Or is there an error in my source code?
Regards,
Stefan Ereth
//
// Copyright 2011 Ettus Research LLC
//
// This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version.
//
// This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License // along with this program. If not, see http://www.gnu.org/licenses/.
//
#define use_short
#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 <iostream> #include <fstream> #include <complex>
namespace po = boost::program_options;
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,file,file0,file1;
double seconds_in_future, freq;
size_t total_num_samps;
double rate,gain,tx_gain;
std::ofstream outfile,outfile2;
//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")
("file", po::value<std::string>(&file)->default_value("measure0-1"), "name of the file to write binary samples to")
("secs", po::value<double>(&seconds_in_future)->default_value(1.0), "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<double>(&rate)->default_value(8e6), "rate of incoming samples")
("sync", po::value<std::string>(&sync)->default_value("b210"), "synchronization method: now, pps, mimo")
("freq", po::value<double>(&freq)->default_value(800e6), "RF center frequency in Hz")
("gain", po::value<double>(&gain), "gain for the RF chain")
("tx-gain", po::value<double>(&tx_gain), "gain for the TX in calibration Mode")
("subdev", po::value<std::string>(&subdev), "subdev spec (homogeneous across motherboards)")
("v", "specify to enable inner-loop verbose")
("calc","specify to enable transmitting and recording of calibration data")
("channels", po::value<std::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("v") == 1;
bool calibration = vm.count("calc") == 1;
/**************** RX Init *************************************************/
//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);
usrp->set_master_clock_rate(30e6); //less then 30.72e6 //Möglichkeit 1: Variable Clock-Rate
//always select the subdevice first, the channel mapping affects the other settings
if (vm.count("subdev")){
uhd::usrp::subdev_spec_t subdevClass = subdev;
std::cout << subdevClass.to_pp_string() << std::endl;
usrp->set_rx_subdev_spec(subdevClass); //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;
//set center Frequency
std::cout << boost::format("Setting RX Freq: %f MHz...") % (freq/1e6) << std::endl;
uhd::tune_request_t tune_request(freq);
for(size_t i=0;i<usrp->get_rx_num_channels();i++)
usrp->set_rx_freq(tune_request,i);
std::cout << boost::format("Actual RX Freq: %f MHz...") % (usrp->get_rx_freq(1)/1e6) << std::endl << std::endl;
//set the rf gain
if (vm.count("gain")){
for(size_t i=0;i<usrp->get_rx_num_channels();i++){
std::cout << boost::format("Setting RX Gain for Channel %d: %f dB...") % i % gain << std::endl;
usrp->set_rx_gain(gain,i);
std::cout << boost::format("Actual RX Gain: %f dB...") % usrp->get_rx_gain() << std::endl << std::endl;
}
}
//open files to write
if(calibration) file+=".calc"; //Kalibrierdaten mit Endung .calc
else file+=".dat"; //Messdaten mit Endung.dat
file0 = file;
file1 = file;
file0 += "0";
file1 += "1";
outfile.open(file0.c_str(), std::ofstream::binary);
if(usrp->get_rx_num_channels()>1){
outfile2.open(file1.c_str(),std::ofstream::binary);
}
/**************** Recieve Start ******************************************/
//create a receive streamer
//linearly map channels (index0 = channel0, index1 = channel1, ...)
uhd::stream_args_t stream_args("sc16"); //complex short
//stream_args.channels = channel_nums;
for (size_t i = 0; i < usrp->get_rx_num_channels(); i++)
stream_args.channels.push_back(i);
uhd::rx_streamer::sptr rx_stream = usrp->get_rx_stream(stream_args);
//setup streaming
std::cout << std::endl;
std::cout << boost::format(
"Begin receiving of %u samples. Start in %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) + usrp->get_time_now();
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<short> > > buffs(
usrp->get_rx_num_channels(), std::vector<std::complex<short> >(samps_per_buff)
);
//create a vector of pointers to point to each of the channel buffers
std::vector<std::complex<short> *> 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 + 1; //timeout (delay before receive + padding)
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;
//Schreiben der gelesenen Werte in die Dateien
if(outfile.is_open())
outfile.write((const char *)&buffs[0].front(),num_rx_samps*sizeof(buffs[0].front()));
if(outfile2.is_open())
outfile2.write((const char *)&buffs[1].front(),num_rx_samps*sizeof(buffs[1][0]));
num_acc_samps += num_rx_samps;
}
if (num_acc_samps < total_num_samps) std::cerr << "Receive timeout before all samples received..." << std::endl;
/**************************** Recieve End *******************************************************/
if(outfile.is_open())
outfile.close();
if(outfile2.is_open())
outfile2.close();
//finished
std::cout << std::endl << "Done! Mine" << std::endl << std::endl;
return EXIT_SUCCESS;
}
Stefan, make sure that you can the calibration procedure on the USRP. I
have no idea if this is what is affecting your experiment, but you should
do it before you start digging deeper.
Sivan
On Fri, May 2, 2014 at 9:30 AM, Stefan Ereth via USRP-users <
usrp-users@lists.ettus.com> wrote:
Hi all,
I'm saving IQ-Samples from both Channels of an USRP B210 for Direction of
Arrival Estimation with Music. My source Code is based on the
rx_multi_samples.cpp example. For tests I connected a sine-generator with a
splitter to both channels. With a pulse sine a verified that the measured
data is time aligned. (picture abs_pulse_sine in appendix) But the problem
is, that there is a phase offset between the two channels of more than 180
degree. (picture real_sine and phase_diff) This offset varies by retuning.
I don't understand where this phase offset come from, because the LO of
both channels is in the same Chip and should be phase aligned. Is this a
known problem of the B210? Or is there an error in my source code?
Regards,
Stefan Ereth
//
// Copyright 2011 Ettus Research LLC
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see http://www.gnu.org/licenses/.
//
#define use_short
#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 <iostream>
#include <fstream>
#include <complex>
namespace po = boost::program_options;
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,file,file0,file1;
double seconds_in_future, freq;
size_t total_num_samps;
double rate,gain,tx_gain;
std::ofstream outfile,outfile2;
//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")
("file",
po::valuestd::string(&file)->default_value("measure0-1"), "name of the
file to write binary samples to")
("secs",
po::value<double>(&seconds_in_future)->default_value(1.0), "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<double>(&rate)->default_value(8e6), "rate of
incoming samples")
("sync", po::valuestd::string(&sync)->default_value("b210"),
"synchronization method: now, pps, mimo")
("freq", po::value<double>(&freq)->default_value(800e6), "RF
center frequency in Hz")
("gain", po::value<double>(&gain), "gain for the RF chain")
("tx-gain", po::value<double>(&tx_gain), "gain for the TX in
calibration Mode")
("subdev", po::valuestd::string(&subdev), "subdev spec
(homogeneous across motherboards)")
("v", "specify to enable inner-loop verbose")
("calc","specify to enable transmitting and recording of
calibration data")
("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("v") == 1;
bool calibration = vm.count("calc") == 1;
/**************** RX Init
*************************************************/
//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);
usrp->set_master_clock_rate(30e6); //less then 30.72e6 //Möglichkeit
1: Variable Clock-Rate
//always select the subdevice first, the channel mapping affects the
other settings
if (vm.count("subdev")){
uhd::usrp::subdev_spec_t subdevClass = subdev;
std::cout << subdevClass.to_pp_string() << std::endl;
usrp->set_rx_subdev_spec(subdevClass); //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;
//set center Frequency
std::cout << boost::format("Setting RX Freq: %f MHz...") % (freq/1e6)
<< std::endl;
uhd::tune_request_t tune_request(freq);
for(size_t i=0;i<usrp->get_rx_num_channels();i++)
usrp->set_rx_freq(tune_request,i);
std::cout << boost::format("Actual RX Freq: %f MHz...") %
(usrp->get_rx_freq(1)/1e6) << std::endl << std::endl;
//set the rf gain
if (vm.count("gain")){
for(size_t i=0;i<usrp->get_rx_num_channels();i++){
std::cout << boost::format("Setting RX Gain for Channel %d: %f
dB...") % i % gain << std::endl;
usrp->set_rx_gain(gain,i);
std::cout << boost::format("Actual RX Gain: %f dB...") %
usrp->get_rx_gain() << std::endl << std::endl;
}
}
//open files to write
if(calibration) file+=".calc"; //Kalibrierdaten mit Endung .calc
else file+=".dat"; //Messdaten mit Endung.dat
file0 = file;
file1 = file;
file0 += "0";
file1 += "1";
outfile.open(file0.c_str(), std::ofstream::binary);
if(usrp->get_rx_num_channels()>1){
outfile2.open(file1.c_str(),std::ofstream::binary);
}
/**************** Recieve Start
******************************************/
//create a receive streamer
//linearly map channels (index0 = channel0, index1 = channel1, ...)
uhd::stream_args_t stream_args("sc16"); //complex short
//stream_args.channels = channel_nums;
for (size_t i = 0; i < usrp->get_rx_num_channels(); i++)
stream_args.channels.push_back(i);
uhd::rx_streamer::sptr rx_stream = usrp->get_rx_stream(stream_args);
//setup streaming
std::cout << std::endl;
std::cout << boost::format(
"Begin receiving of %u samples. Start in %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) +
usrp->get_time_now();
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<short> > > buffs(
usrp->get_rx_num_channels(), std::vector<std::complex<short>
(samps_per_buff)
);
//create a vector of pointers to point to each of the channel buffers
std::vector<std::complex<short> *> 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 + 1; //timeout (delay before
receive + padding)
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;
//Schreiben der gelesenen Werte in die Dateien
if(outfile.is_open())
outfile.write((const char
)&buffs[0].front(),num_rx_sampssizeof(buffs[0].front()));
if(outfile2.is_open())
outfile2.write((const char
)&buffs[1].front(),num_rx_sampssizeof(buffs[1][0]));
num_acc_samps += num_rx_samps;
}
if (num_acc_samps < total_num_samps) std::cerr << "Receive timeout
before all samples received..." << std::endl;
/**************************** Recieve End
*******************************************************/
if(outfile.is_open())
outfile.close();
if(outfile2.is_open())
outfile2.close();
//finished
std::cout << std::endl << "Done! Mine" << std::endl << std::endl;
return EXIT_SUCCESS;
}
USRP-users mailing list
USRP-users@lists.ettus.com
http://lists.ettus.com/mailman/listinfo/usrp-users_lists.ettus.com
On 05/04/2014 05:11 AM, Sivan Toledo via USRP-users wrote:
Stefan, make sure that you can the calibration procedure on the USRP.
I have no idea if this is what is affecting your experiment, but you
should do it before you start digging deeper.
Sivan
Have you confirmed that your splitter is 0deg across all the frequencies
you care about? Not all of them are.
I did the same experiment when the B210 first came out, with a Marconi
test set as the signal source, and saw uniform zero-degree (more or less)
phase offset between channels across a number of different
frequencies. I then switched splitters, and it was all over the place.
On Fri, May 2, 2014 at 9:30 AM, Stefan Ereth via USRP-users
<usrp-users@lists.ettus.com mailto:usrp-users@lists.ettus.com> wrote:
Hi all,
I'm saving IQ-Samples from both Channels of an USRP B210 for
Direction of Arrival Estimation with Music. My source Code is
based on the rx_multi_samples.cpp example. For tests I connected a
sine-generator with a splitter to both channels. With a pulse sine
a verified that the measured data is time aligned. (picture
abs_pulse_sine in appendix) But the problem is, that there is a
phase offset between the two channels of more than 180 degree.
(picture real_sine and phase_diff) This offset varies by retuning.
I don't understand where this phase offset come from, because the
LO of both channels is in the same Chip and should be phase
aligned. Is this a known problem of the B210? Or is there an error
in my source code?
Regards,
Stefan Ereth
//
// Copyright 2011 Ettus Research LLC
//
// This program is free software: you can redistribute it and/or
modify
// it under the terms of the GNU General Public License as
published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see
<http://www.gnu.org/licenses/>.
//
#define use_short
#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 <iostream>
#include <fstream>
#include <complex>
namespace po = boost::program_options;
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,file,file0,file1;
double seconds_in_future, freq;
size_t total_num_samps;
double rate,gain,tx_gain;
std::ofstream outfile,outfile2;
//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")
("file",
po::value<std::string>(&file)->default_value("measure0-1"), "name
of the file to write binary samples to")
("secs",
po::value<double>(&seconds_in_future)->default_value(1.0), "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<double>(&rate)->default_value(8e6),
"rate of incoming samples")
("sync",
po::value<std::string>(&sync)->default_value("b210"),
"synchronization method: now, pps, mimo")
("freq", po::value<double>(&freq)->default_value(800e6),
"RF center frequency in Hz")
("gain", po::value<double>(&gain), "gain for the RF chain")
("tx-gain", po::value<double>(&tx_gain), "gain for the TX
in calibration Mode")
("subdev", po::value<std::string>(&subdev), "subdev spec
(homogeneous across motherboards)")
("v", "specify to enable inner-loop verbose")
("calc","specify to enable transmitting and recording of
calibration data")
("channels",
po::value<std::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("v") == 1;
bool calibration = vm.count("calc") == 1;
/**************** RX Init
*************************************************/
//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);
usrp->set_master_clock_rate(30e6); //less then 30.72e6
//Möglichkeit 1: Variable Clock-Rate
//always select the subdevice first, the channel mapping
affects the other settings
if (vm.count("subdev")){
uhd::usrp::subdev_spec_t subdevClass = subdev;
std::cout << subdevClass.to_pp_string() << std::endl;
usrp->set_rx_subdev_spec(subdevClass); //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;
//set center Frequency
std::cout << boost::format("Setting RX Freq: %f MHz...") %
(freq/1e6) << std::endl;
uhd::tune_request_t tune_request(freq);
for(size_t i=0;i<usrp->get_rx_num_channels();i++)
usrp->set_rx_freq(tune_request,i);
std::cout << boost::format("Actual RX Freq: %f MHz...") %
(usrp->get_rx_freq(1)/1e6) << std::endl << std::endl;
//set the rf gain
if (vm.count("gain")){
for(size_t i=0;i<usrp->get_rx_num_channels();i++){
std::cout << boost::format("Setting RX Gain for
Channel %d: %f dB...") % i % gain << std::endl;
usrp->set_rx_gain(gain,i);
std::cout << boost::format("Actual RX Gain: %f dB...")
% usrp->get_rx_gain() << std::endl << std::endl;
}
}
//open files to write
if(calibration) file+=".calc"; //Kalibrierdaten mit Endung .calc
else file+=".dat"; //Messdaten mit Endung.dat
file0 = file;
file1 = file;
file0 += "0";
file1 += "1";
outfile.open(file0.c_str(), std::ofstream::binary);
if(usrp->get_rx_num_channels()>1){
outfile2.open(file1.c_str(),std::ofstream::binary);
}
/**************** Recieve Start
******************************************/
//create a receive streamer
//linearly map channels (index0 = channel0, index1 = channel1,
...)
uhd::stream_args_t stream_args("sc16"); //complex short
//stream_args.channels = channel_nums;
for (size_t i = 0; i < usrp->get_rx_num_channels(); i++)
stream_args.channels.push_back(i);
uhd::rx_streamer::sptr rx_stream =
usrp->get_rx_stream(stream_args);
//setup streaming
std::cout << std::endl;
std::cout << boost::format(
"Begin receiving of %u samples. Start in %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) +
usrp->get_time_now();
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<short> > > buffs(
usrp->get_rx_num_channels(),
std::vector<std::complex<short> >(samps_per_buff)
);
//create a vector of pointers to point to each of the channel
buffers
std::vector<std::complex<short> *> 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 + 1; //timeout (delay
before receive + padding)
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;
//Schreiben der gelesenen Werte in die Dateien
if(outfile.is_open())
outfile.write((const char
*)&buffs[0].front(),num_rx_samps*sizeof(buffs[0].front()));
if(outfile2.is_open())
outfile2.write((const char
*)&buffs[1].front(),num_rx_samps*sizeof(buffs[1][0]));
num_acc_samps += num_rx_samps;
}
if (num_acc_samps < total_num_samps) std::cerr << "Receive
timeout before all samples received..." << std::endl;
/**************************** Recieve End
*******************************************************/
if(outfile.is_open())
outfile.close();
if(outfile2.is_open())
outfile2.close();
//finished
std::cout << std::endl << "Done! Mine" << std::endl << std::endl;
return EXIT_SUCCESS;
}
_______________________________________________
USRP-users mailing list
USRP-users@lists.ettus.com <mailto:USRP-users@lists.ettus.com>
http://lists.ettus.com/mailman/listinfo/usrp-users_lists.ettus.com
USRP-users mailing list
USRP-users@lists.ettus.com
http://lists.ettus.com/mailman/listinfo/usrp-users_lists.ettus.com
--
Marcus Leech
Principal Investigator
Shirleys Bay Radio Astronomy Consortium
http://www.sbrac.org