I tried using directly the UHD interface. I reused the code example from
https://raw.githubusercontent.com/EttusResearch/uhd/master/host/examples/rx_samples_to_file.cpp
, I just added
fprintf(f, "%11.9lf\n", md.time_spec.get_real_secs());
after reading each block of samples to simply store all timestamps in a
file.
It seems I'm getting the same behaviour as with the SoapySDR interface. At
28MS/s, for blocks of 1024 samples, each time I get an overrun, I see a
group of 3 blocks with incorrect timestamps, while I would expect to just
see one "jump" in time.
I put all my timestamps in Excel in the 1st column, computed the difference
between each row in the 2nd column, and I hid all the rows where the time
difference is the expected difference. I saw 3 overrun, and I get the
following 9 rows
[image: Timestamp.png]
#255420: we got an overrun, so it's normal to see a "jump" in time (we lost
samples)
#255421: we get a timestamp smaller than the previous one (always by 81285 or
81286ns)
#255422: expected time difference so the row is filtered
#255423: expected time difference so the row is filtered
#255424: big jump in time
We get the same pattern for the other 2 overruns.
I'm attaching the test program. I ran it with --duration 20 --rate 28e6
--freq 2450e6 --gain 50 --bw 28e6 --null --spb 1024
and I got
Creating the usrp device with: ...
[INFO] [UHD] Win32; Microsoft Visual C++ version 14.0; Boost_105900;
UHD_3.12.0.0-release
[INFO] [B200] Detected Device: B210
[INFO] [B200] Operating over USB 3.
[INFO] [B200] Initialize CODEC control...
[INFO] [B200] Initialize Radio control...
[INFO] [B200] Performing register loopback test...
[INFO] [B200] Register loopback test passed
[INFO] [B200] Performing register loopback test...
[INFO] [B200] Register loopback test passed
[INFO] [B200] Setting master clock rate selection to 'automatic'.
[INFO] [B200] Asking for clock rate 16.000000 MHz...
[INFO] [B200] Actually got clock rate 16.000000 MHz.
Using Device: Single USRP:
Device: B-Series Device
Mboard 0: B210
RX Channel: 0
RX DSP: 0
RX Dboard: A
RX Subdev: FE-RX2
RX Channel: 1
RX DSP: 1
RX Dboard: A
RX Subdev: FE-RX1
TX Channel: 0
TX DSP: 0
TX Dboard: A
TX Subdev: FE-TX2
TX Channel: 1
TX DSP: 1
TX Dboard: A
TX Subdev: FE-TX1
Setting RX Rate: 28.000000 Msps...
[INFO] [B200] Asking for clock rate 28.000000 MHz...
[INFO] [B200] Actually got clock rate 28.000000 MHz.
Actual RX Rate: 28.000000 Msps...
Setting RX Freq: 2450.000000 MHz...
Actual RX Freq: 2450.000000 MHz...
Setting RX Gain: 50.000000 dB...
Actual RX Gain: 50.000000 dB...
Setting RX Bandwidth: 28.000000 MHz...
Actual RX Bandwidth: 28.000000 MHz...
Waiting for "lo_locked": ++++++++++ locked.
Press Ctrl + C to stop streaming...
OGot an overflow indication. Please consider the following:
Your write medium must sustain a rate of 112.000000MB/s.
Dropped samples will not be written to the file.
Please modify this example for your purposes.
This message will not appear again.
OO
Done!
By the way, if I rerun the same program, I get an error. I guess things are
not properly closed? I'm getting
Waiting for "lo_locked": ++++++++++ locked.
Press Ctrl + C to stop streaming...
[NO TIME SPEC
ERROR] [
Done!
STREAMER] recv packet demuxer unexpected sid 0xffa30091
D[ERROR] [STREAMER] recv packet demuxer unexpected sid 0xff06fed1
Executing the program a 2nd time works though.
On Tue, Jul 24, 2018 at 10:14 AM Marcus D. Leech <mle...@ripnet.com> wrote:
> On 07/23/2018 10:04 PM, RizThon wrote:
>
> Hi Marcus,
>
> It's a B210. So you confirm this is strange, and is probably a problem on
> the Soapy part?
>
> I can try to write the same straight in UHD to see what I get.
>
> Thanks.
>
> Yes an overrun should result in an overrun indication, and a timestamp
> that is a "jump", but always in the positive direction.
>
>
>
> On Tue, Jul 24, 2018 at 10:00 AM Marcus D. Leech via USRP-users <
> usrp-users@lists.ettus.com> wrote:
>
>> On 07/23/2018 09:51 PM, RizThon via USRP-users wrote:
>>
>> Hi all,
>>
>> I have a question concerning the timestamps while getting an overrun.
>>
>> I'm sampling at 28MS/s and reading blocks of 1024 samples. So it takes 36571
>> to 36572ns to sample each block.
>>
>> I try to read x blocks, calling receive for each block. I get something
>> like
>>
>> block 93: correctly read 1024 samples, timestamp as expected (ie +36571ns
>> compared to block 92)
>> block 94: only received 364 samples, timestamp still as expected
>> block 95: overrun, timestamp is bigger than expected (+94286)
>> block 96: correctly read 1024 samples, but timestamp is lower than block
>> 95 (-81286)
>> block 97: correctly read 1024 samples, timestamp as expected
>> block 98: correctly read 1024 samples, timestamp as expected
>> block 99: correctly read 1024 samples, but timestamp is bigger than
>> expected (+2818750)
>>
>> The exact same pattern repeats itself from time to time
>> block n: receive fewer than expected samples
>> block n+1: overrun with timestamp jump
>> block n+2: get timestamp smaller by always 81285 or 81286
>> block n+3: ok
>> block n+4: ok
>> block n+5: big timestamp jump
>>
>> Can someone explain what is happening, and what the proper way to handle
>> overruns is?
>>
>> I'm using SoapySDR, so I don't know if it's specific to UHD or if there's
>> some bug in Soapy (I'm not seeing that behaviour with the same program
>> running a LimeSDR).
>>
>> Thanks.
>>
>>
>> What type of USRP is this from?
>>
>> There aren't too many people on this list who can help debug SOAPYSDR
>> stuff, so debugging it might require doing a "throw away" purely using
>> the UHD API, to see if the problem persists there.
>>
>>
>> _______________________________________________
>> USRP-users mailing list
>> USRP-users@lists.ettus.com
>> http://lists.ettus.com/mailman/listinfo/usrp-users_lists.ettus.com
>>
>
>
#include "stdafx.h"
//
// Copyright 2010-2011,2014 Ettus Research LLC
// Copyright 2018 Ettus Research, a National Instruments Company
//
// SPDX-License-Identifier: GPL-3.0-or-later
//
#include <uhd/types/tune_request.hpp>
#include <uhd/utils/thread.hpp>
#include <uhd/utils/safe_main.hpp>
#include <uhd/usrp/multi_usrp.hpp>
#include <uhd/exception.hpp>
#include <boost/program_options.hpp>
#include <boost/format.hpp>
#include <boost/lexical_cast.hpp>
#include <iostream>
#include <fstream>
#include <csignal>
#include <complex>
#include <thread>
#include <chrono>
namespace po = boost::program_options;
static bool stop_signal_called = false;
void sig_int_handler(int) { stop_signal_called = true; }
template<typename samp_type> void recv_to_file(
uhd::usrp::multi_usrp::sptr usrp,
const std::string &cpu_format,
const std::string &wire_format,
const std::string &channel,
const std::string &file,
size_t samps_per_buff,
unsigned long long num_requested_samples,
double time_requested = 0.0,
bool bw_summary = false,
bool stats = false,
bool null = false,
bool enable_size_map = false,
bool continue_on_bad_packet = false
) {
unsigned long long num_total_samps = 0;
//create a receive streamer
uhd::stream_args_t stream_args(cpu_format, wire_format);
std::vector<size_t> channel_nums;
channel_nums.push_back(boost::lexical_cast<size_t>(channel));
stream_args.channels = channel_nums;
uhd::rx_streamer::sptr rx_stream = usrp->get_rx_stream(stream_args);
uhd::rx_metadata_t md;
std::vector<samp_type> buff(samps_per_buff);
std::ofstream outfile;
if (not null)
outfile.open(file.c_str(), std::ofstream::binary);
bool overflow_message = true;
//setup streaming
uhd::stream_cmd_t stream_cmd((num_requested_samples == 0) ?
uhd::stream_cmd_t::STREAM_MODE_START_CONTINUOUS :
uhd::stream_cmd_t::STREAM_MODE_NUM_SAMPS_AND_DONE
);
stream_cmd.num_samps = size_t(num_requested_samples);
stream_cmd.stream_now = true;
stream_cmd.time_spec = uhd::time_spec_t();
rx_stream->issue_stream_cmd(stream_cmd);
typedef std::map<size_t, size_t> SizeMap;
SizeMap mapSizes;
const auto start_time = std::chrono::steady_clock::now();
const auto stop_time =
start_time
+ std::chrono::milliseconds(int64_t(1000 * time_requested));
// Track time and samps between updating the BW summary
auto last_update = start_time;
unsigned long long last_update_samps = 0;
FILE* f = nullptr;
while (fopen_s(&f, "AllTimestamps_UHD.txt", "wb") != 0) {
printf("File in use. Press a key to retry.\n");
getchar();
}
// Run this loop until either time expired (if a duration was given),
until
// the requested number of samples were collected (if such a number was
// given), or until Ctrl-C was pressed.
while (not stop_signal_called
and (num_requested_samples != num_total_samps
or num_requested_samples == 0)
and (time_requested == 0.0
or std::chrono::steady_clock::now() <= stop_time)
) {
const auto now = std::chrono::steady_clock::now();
size_t num_rx_samps =
rx_stream->recv(&buff.front(), buff.size(), md, 3.0,
enable_size_map);
if (!md.has_time_spec) {
std::cout << boost::format("NO TIME SPEC") << std::endl;
break;
}
fprintf(f, "%11.9lf\n", md.time_spec.get_real_secs());
if (md.error_code == uhd::rx_metadata_t::ERROR_CODE_TIMEOUT) {
std::cout << boost::format("Timeout while streaming")
<< std::endl;
break;
}
if (md.error_code == uhd::rx_metadata_t::ERROR_CODE_OVERFLOW) {
if (overflow_message) {
overflow_message = false;
std::cerr << boost::format(
"Got an overflow indication. Please
consider the following:\n"
" Your write medium must sustain a
rate of %fMB/s.\n"
" Dropped samples will not be written
to the file.\n"
" Please modify this example for your
purposes.\n"
" This message will not appear
again.\n"
) % (usrp->get_rx_rate() * sizeof(samp_type) /
1e6);
}
continue;
}
if (md.error_code != uhd::rx_metadata_t::ERROR_CODE_NONE) {
std::string error = str(boost::format("Receiver error:
%s") % md.strerror());
if (continue_on_bad_packet) {
std::cerr << error << std::endl;
continue;
}
else
throw std::runtime_error(error);
}
if (enable_size_map) {
SizeMap::iterator it = mapSizes.find(num_rx_samps);
if (it == mapSizes.end())
mapSizes[num_rx_samps] = 0;
mapSizes[num_rx_samps] += 1;
}
num_total_samps += num_rx_samps;
if (outfile.is_open()) {
outfile.write(
(const char*)&buff.front(),
num_rx_samps * sizeof(samp_type)
);
}
if (bw_summary) {
last_update_samps += num_rx_samps;
const auto time_since_last_update = now - last_update;
if (time_since_last_update > std::chrono::seconds(1)) {
const double time_since_last_update_s =
std::chrono::duration<double>(time_since_last_update).count();
const double rate =
double(last_update_samps) /
time_since_last_update_s;
std::cout << "\t" << (rate / 1e6) << " Msps" <<
std::endl;
last_update_samps = 0;
last_update = now;
}
}
}
const auto actual_stop_time = std::chrono::steady_clock::now();
fclose(f);
stream_cmd.stream_mode = uhd::stream_cmd_t::STREAM_MODE_STOP_CONTINUOUS;
rx_stream->issue_stream_cmd(stream_cmd);
if (outfile.is_open()) {
outfile.close();
}
if (stats) {
std::cout << std::endl;
const double actual_duration_seconds =
std::chrono::duration<float>(actual_stop_time -
start_time).count();
std::cout
<< boost::format("Received %d samples in %f seconds")
% num_total_samps
% actual_duration_seconds
<< std::endl;
const double rate = (double)num_total_samps /
actual_duration_seconds;
std::cout << (rate / 1e6) << " Msps" << std::endl;
if (enable_size_map) {
std::cout << std::endl;
std::cout << "Packet size map (bytes: count)" <<
std::endl;
for (SizeMap::iterator it = mapSizes.begin(); it !=
mapSizes.end(); it++)
std::cout << it->first << ":\t" << it->second
<< std::endl;
}
}
}
typedef std::function<uhd::sensor_value_t(const std::string&)> get_sensor_fn_t;
bool check_locked_sensor(
std::vector<std::string> sensor_names,
const char* sensor_name,
get_sensor_fn_t get_sensor_fn,
double setup_time
) {
if (std::find(sensor_names.begin(), sensor_names.end(), sensor_name) ==
sensor_names.end())
return false;
auto setup_timeout =
std::chrono::steady_clock::now()
+ std::chrono::milliseconds(int64_t(setup_time * 1000));
bool lock_detected = false;
std::cout << boost::format("Waiting for \"%s\": ") % sensor_name;
std::cout.flush();
while (true) {
if (lock_detected and
(std::chrono::steady_clock::now() > setup_timeout)) {
std::cout << " locked." << std::endl;
break;
}
if (get_sensor_fn(sensor_name).to_bool()) {
std::cout << "+";
std::cout.flush();
lock_detected = true;
}
else {
if (std::chrono::steady_clock::now() > setup_timeout) {
std::cout << std::endl;
throw std::runtime_error(str(
boost::format("timed out waiting for
consecutive locks on sensor \"%s\"")
% sensor_name
));
}
std::cout << "_";
std::cout.flush();
}
std::this_thread::sleep_for(std::chrono::milliseconds(100));
}
std::cout << std::endl;
return true;
}
int UHD_SAFE_MAIN(int argc, char *argv[]) {
uhd::set_thread_priority_safe();
//variables to be set by po
std::string args, file, type, ant, subdev, ref, wirefmt, channel;
size_t total_num_samps, spb;
double rate, freq, gain, bw, total_time, setup_time;
//setup the program options
po::options_description desc("Allowed options");
desc.add_options()
("help", "help message")
("args", po::value<std::string>(&args)->default_value(""),
"multi uhd device address args")
("file",
po::value<std::string>(&file)->default_value("usrp_samples.dat"), "name of the
file to write binary samples to")
("type", po::value<std::string>(&type)->default_value("short"),
"sample type: double, float, or short")
("nsamps",
po::value<size_t>(&total_num_samps)->default_value(0), "total number of samples
to receive")
("duration", po::value<double>(&total_time)->default_value(0),
"total number of seconds to receive")
("time", po::value<double>(&total_time), "(DEPRECATED) will go
away soon! Use --duration instead")
("spb", po::value<size_t>(&spb)->default_value(10000), "samples
per buffer")
("rate", po::value<double>(&rate)->default_value(1e6), "rate of
incoming samples")
("freq", po::value<double>(&freq)->default_value(0.0), "RF
center frequency in Hz")
("gain", po::value<double>(&gain), "gain for the RF chain")
("ant", po::value<std::string>(&ant), "antenna selection")
("subdev", po::value<std::string>(&subdev), "subdevice
specification")
("channel",
po::value<std::string>(&channel)->default_value("0"), "which channel to use")
("bw", po::value<double>(&bw), "analog frontend filter
bandwidth in Hz")
("ref",
po::value<std::string>(&ref)->default_value("internal"), "reference source
(internal, external, mimo)")
("wirefmt",
po::value<std::string>(&wirefmt)->default_value("sc16"), "wire format (sc8,
sc16 or s16)")
("setup", po::value<double>(&setup_time)->default_value(1.0),
"seconds of setup time")
("progress", "periodically display short-term bandwidth")
("stats", "show average bandwidth on exit")
("sizemap", "track packet size and display breakdown on exit")
("null", "run without writing to file")
("continue", "don't abort on a bad packet")
("skip-lo", "skip checking LO lock status")
("int-n", "tune USRP with integer-N tuning")
;
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 samples to file %s") % desc
<< std::endl;
std::cout
<< std::endl
<< "This application streams data from a single channel
of a USRP device to a file.\n"
<< std::endl;
return ~0;
}
bool bw_summary = vm.count("progress") > 0;
bool stats = vm.count("stats") > 0;
bool null = vm.count("null") > 0;
bool enable_size_map = vm.count("sizemap") > 0;
bool continue_on_bad_packet = vm.count("continue") > 0;
if (enable_size_map)
std::cout << "Packet size tracking enabled - will only recv one
packet at a time!" << std::endl;
//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);
//Lock mboard clocks
usrp->set_clock_source(ref);
//always select the subdevice first, the channel mapping affects the
other settings
if (vm.count("subdev")) usrp->set_rx_subdev_spec(subdev);
std::cout << boost::format("Using Device: %s") % usrp->get_pp_string()
<< std::endl;
//set the sample rate
if (rate <= 0.0) {
std::cerr << "Please specify a valid sample rate" << std::endl;
return ~0;
}
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 the center frequency
if (vm.count("freq")) { //with default of 0.0 this will always be true
std::cout << boost::format("Setting RX Freq: %f MHz...") %
(freq / 1e6) << std::endl;
uhd::tune_request_t tune_request(freq);
if (vm.count("int-n")) tune_request.args =
uhd::device_addr_t("mode_n=integer");
usrp->set_rx_freq(tune_request);
std::cout << boost::format("Actual RX Freq: %f MHz...") %
(usrp->get_rx_freq() / 1e6) << std::endl << std::endl;
}
//set the rf gain
if (vm.count("gain")) {
std::cout << boost::format("Setting RX Gain: %f dB...") % gain
<< std::endl;
usrp->set_rx_gain(gain);
std::cout << boost::format("Actual RX Gain: %f dB...") %
usrp->get_rx_gain() << std::endl << std::endl;
}
//set the IF filter bandwidth
if (vm.count("bw")) {
std::cout << boost::format("Setting RX Bandwidth: %f MHz...") %
(bw / 1e6) << std::endl;
usrp->set_rx_bandwidth(bw);
std::cout << boost::format("Actual RX Bandwidth: %f MHz...") %
(usrp->get_rx_bandwidth() / 1e6) << std::endl << std::endl;
}
//set the antenna
if (vm.count("ant")) usrp->set_rx_antenna(ant);
std::this_thread::sleep_for(
std::chrono::milliseconds(int64_t(1000 * setup_time))
);
//check Ref and LO Lock detect
if (not vm.count("skip-lo")) {
check_locked_sensor(
usrp->get_rx_sensor_names(0),
"lo_locked",
[usrp](const std::string& sensor_name) {
return usrp->get_rx_sensor(sensor_name);
},
setup_time
);
if (ref == "mimo") {
check_locked_sensor(
usrp->get_mboard_sensor_names(0),
"mimo_locked",
[usrp](const std::string& sensor_name) {
return usrp->get_mboard_sensor(sensor_name);
},
setup_time
);
}
if (ref == "external") {
check_locked_sensor(
usrp->get_mboard_sensor_names(0),
"ref_locked",
[usrp](const std::string& sensor_name) {
return usrp->get_mboard_sensor(sensor_name);
},
setup_time
);
}
}
if (total_num_samps == 0) {
std::signal(SIGINT, &sig_int_handler);
std::cout << "Press Ctrl + C to stop streaming..." << std::endl;
}
#define recv_to_file_args(format) \
(usrp, format, wirefmt, channel, file, spb, total_num_samps, total_time,
bw_summary, stats, null, enable_size_map, continue_on_bad_packet)
//recv to file
if (wirefmt == "s16") {
if (type == "double")
recv_to_file<double>recv_to_file_args("f64");
else if (type == "float")
recv_to_file<float>recv_to_file_args("f32");
else if (type == "short")
recv_to_file<short>recv_to_file_args("s16");
else throw std::runtime_error("Unknown type " + type);
}
else {
if (type == "double") recv_to_file<std::complex<double>
>recv_to_file_args("fc64");
else if (type == "float") recv_to_file<std::complex<float>
>recv_to_file_args("fc32");
else if (type == "short") recv_to_file<std::complex<short>
>recv_to_file_args("sc16");
else throw std::runtime_error("Unknown type " + type);
}
//finished
std::cout << std::endl << "Done!" << std::endl << std::endl;
return EXIT_SUCCESS;
}
#include <uhd/utils/thread.hpp>
#include <uhd/utils/safe_main.hpp>
#include <uhd/usrp/multi_usrp.hpp>
#include <uhd/exception.hpp>
#include <uhd/types/tune_request.hpp>
#include <uhd/types/stream_cmd.hpp>
#include <boost/program_options.hpp>
#include <boost/format.hpp>
#include <boost/thread.hpp>
#include <iostream>
int _UHD_SAFE_MAIN(int argc, char *argv[]) {
uhd::set_thread_priority_safe();
//std::string device_args("addr=192.168.10.2");
std::string device_args("type=b200");
std::string subdev("A:0");
std::string ant("TX/RX");
std::string ref("internal");
double rate(28e6);
double freq(2450e6);
double gain(50);
double bw(28e6);
//create a usrp device
std::cout << std::endl;
std::cout << boost::format("Creating the usrp device with: %s...") %
device_args << std::endl;
//uhd::usrp::multi_usrp::sptr usrp =
uhd::usrp::multi_usrp::make(device_args);
uhd::usrp::multi_usrp::sptr usrp =
uhd::usrp::multi_usrp::make((std::string)"");
// Lock mboard clocks
std::cout << boost::format("Lock mboard clocks: %f") % ref << std::endl;
usrp->set_clock_source(ref);
//always select the subdevice first, the channel mapping affects the
other settings
//std::cout << boost::format("subdev set to: %f") % subdev << std::endl;
//usrp->set_rx_subdev_spec(subdev);
std::cout << boost::format("Using Device: %s") % usrp->get_pp_string()
<< std::endl;
//set the sample rate
if (rate <= 0.0) {
std::cerr << "Please specify a valid sample rate" << std::endl;
return ~0;
}
// set sample rate
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 freq
std::cout << boost::format("Setting RX Freq: %f MHz...") % (freq / 1e6)
<< std::endl;
uhd::tune_request_t tune_request(freq);
usrp->set_rx_freq(tune_request);
std::cout << boost::format("Actual RX Freq: %f MHz...") %
(usrp->get_rx_freq() / 1e6) << std::endl << std::endl;
// set the rf gain
std::cout << boost::format("Setting RX Gain: %f dB...") % gain <<
std::endl;
usrp->set_rx_gain(gain);
std::cout << boost::format("Actual RX Gain: %f dB...") %
usrp->get_rx_gain() << std::endl << std::endl;
// set the IF filter bandwidth
std::cout << boost::format("Setting RX Bandwidth: %f MHz...") % (bw /
1e6) << std::endl;
usrp->set_rx_bandwidth(bw);
std::cout << boost::format("Actual RX Bandwidth: %f MHz...") %
(usrp->get_rx_bandwidth() / 1e6) << std::endl << std::endl;
// set the antenna
std::cout << boost::format("Setting RX Antenna: %s") % ant << std::endl;
usrp->set_rx_antenna(ant);
std::cout << boost::format("Actual RX Antenna: %s") %
usrp->get_rx_antenna() << std::endl << std::endl;
double setup_time = 2;
check_locked_sensor(
usrp->get_rx_sensor_names(0),
"lo_locked",
[usrp](const std::string& sensor_name) {
return usrp->get_rx_sensor(sensor_name);
},
setup_time
);
uhd::stream_args_t stream_args("fc32", "sc16");
uhd::rx_streamer::sptr rx_stream = usrp->get_rx_stream(stream_args);
uhd::stream_cmd_t
stream_cmd_start(uhd::stream_cmd_t::stream_mode_t::STREAM_MODE_START_CONTINUOUS);
stream_cmd_start.stream_now = true;
stream_cmd_start.time_spec = uhd::time_spec_t();
FILE* f = nullptr;
while (fopen_s(&f, "AllTimestamps_UHD.txt", "wb") != 0) {
printf("File in use. Press a key to retry.\n");
}
usrp->issue_stream_cmd(stream_cmd_start, 0);
const int receiveBufferSize = 1024;
const int expectedDuration = (int)ceil(receiveBufferSize * 1e9 /
(double)rate);
printf("Expected duration %d\n", expectedDuration);
uhd::rx_metadata_t md;
std::vector<float> buff(receiveBufferSize);
const int PacketsNumber = 1e3;
long long startTimestamp = 0;
long long previousTimestamp = 0;
long long timestampNs = 0;
for (int times = 1; times <= PacketsNumber; times++) {
size_t num_rx_samps = rx_stream->recv(&buff.front(),
buff.size(), md, 3.0, false);
timestampNs = (long long)md.time_spec.get_real_secs();
fprintf(f, "%lld\n", timestampNs);
fflush(f);
long long timeDiff = timestampNs - previousTimestamp -
expectedDuration;
if (timeDiff == -1)
timeDiff = 0;
if (md.error_code == uhd::rx_metadata_t::ERROR_CODE_TIMEOUT) {
printf("#%d Timeout while streaming\n", times);
}
else if (md.error_code ==
uhd::rx_metadata_t::ERROR_CODE_OVERFLOW) {
printf("#%d Overflow\n", times);
}
else if (md.error_code != uhd::rx_metadata_t::ERROR_CODE_NONE) {
printf("#%d Receiver error: %s\n", times,
md.strerror());
}
else if (num_rx_samps != receiveBufferSize) {
// Error while receiving, we didn't get the correct
number of samples:
// - positive number: we had an overrun (ie we didn't
read fast enough)
// - negative number: there's a bigger error
printf("#%d ReceiveSamples returned %d. Expected
timestamp difference %lld\n", times, num_rx_samps, timeDiff);
}
else if (times != 1 && timeDiff != 0) {
printf("#%d OOOPS %lld | %lld\n", times, timeDiff,
timestampNs);
}
if (times == 1) {
startTimestamp = timestampNs;
printf("#%d Start at %lld\n", times, timestampNs);
}
previousTimestamp = timestampNs;
}
uhd::stream_cmd_t
stream_cmd_stop(uhd::stream_cmd_t::stream_mode_t::STREAM_MODE_STOP_CONTINUOUS);
usrp->issue_stream_cmd(stream_cmd_stop, 0);
return EXIT_SUCCESS;
}
_______________________________________________
USRP-users mailing list
USRP-users@lists.ettus.com
http://lists.ettus.com/mailman/listinfo/usrp-users_lists.ettus.com