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

Reply via email to