예제 #1
1
void get_rx_parameters(uhd::usrp::multi_usrp::sptr usrp, size_t mboard , std::ostream & os)
{
	using namespace std;
	namespace radio = uhd::usrp;
	size_t nchan = 0;

	// Get sub device specification
	os << std::endl << "********** RX Sub Device ***********" << std::endl;
	os << std::endl << "-----> Get Rx Subdevice" << std::endl;
	radio::subdev_spec_t rx_subdev = usrp->get_rx_subdev_spec(mboard);
	os << "RX Subdevice Specification:" << endl;
	os << rx_subdev.to_pp_string() << endl;
	
	os << std::endl << "-----> Get number of RX channels" << std::endl;
	size_t num_rx = usrp->get_rx_num_channels();
	os << "Number of RX channels:" << endl;
	os << num_rx << endl;
	
	os << std::endl << "-----> Get RX Subdevice Name" << std::endl;
	string rx_name = usrp->get_rx_subdev_name(nchan);
	os << "RX Subdevice Name:" << endl;
	os << rx_name << endl;

	os << std::endl << "********** RX Sample Rate ***********" << std::endl;
	os << std::endl << "-----> Get RX Rate" << std::endl;
	double rx_rate = usrp->get_rx_rate(nchan);
	os << "RX Rate:" << endl;
	os << rx_rate << endl;
	
	os << std::endl << "-----> Get RX Rate List" << std::endl;
	uhd::meta_range_t rx_rates = usrp->get_rx_rates(nchan);
	os << "RX Rate List:" << endl;
	os << "Start: " << rx_rates.start() << "   Stop: " << rx_rates.stop() << "   Step: " << rx_rates.step() << endl;
	os << rx_rates.to_pp_string() << endl;
	
	// RX FREQUENCIES
	
	os << std::endl << "********** RX Frequencies ***********" << std::endl;
	os << std::endl << "-----> Get RX Center Frequency" << std::endl;
	double rx_freq = usrp->get_rx_freq(nchan);
	os << "RX Freq:" << endl;
	os << rx_freq << endl;

	os << std::endl << "-----> Get RX Center Frequency Range" << std::endl;
	uhd::freq_range_t rx_freq_range = usrp->get_rx_freq_range(nchan);
	os << "RX Frequency Range:" << endl;
	os << "Start: " << rx_freq_range.start() << "   Stop: " << rx_freq_range.stop() << "   Step: " << rx_freq_range.step() << endl;
	os << rx_freq_range.to_pp_string() << endl;
	
	// RX Front end frequencies
	os << std::endl << "-----> Get RX RF Front End Center Frequency Range" << std::endl;
	try
	{
		os << "RX Front End Frequency Range:" << endl;
		uhd::freq_range_t rx_fe_freq_range = usrp->get_fe_rx_freq_range(nchan);
		os << "Start: " << rx_fe_freq_range.start() << "   Stop: " << rx_fe_freq_range.stop() << "   Step: " << rx_fe_freq_range.step() << endl;
		os << rx_fe_freq_range.to_pp_string() << endl;
	}
		catch (uhd::runtime_error &e)
	{
		os << " Exception occurred : " << e.code() << endl;
	}
	
	// RX GAIN
	
	os << std::endl << "********** RX Gain  ***********" << std::endl;
	
	// Total combined gain
	os << endl << "-----> Get RX Total Gain" << endl;
	os << "RX Total Gain: " ;	
	try
	{
		double rx_total_gain = usrp->get_rx_gain(nchan);
		os << rx_total_gain << endl;
	}
	catch(uhd::runtime_error &e)
	{
		os << "Exception code: " << e.code() << endl;
	}
	
	// List of all gain elements
	os << std::endl << "-----> Get RX gain names" << std::endl;
	std::vector<std::string> rx_gain_names = usrp->get_rx_gain_names(nchan);
	os << "Rx Gain Names: " << std::endl;
	for (int index =0; index < rx_gain_names.size(); index++)
	{
		// Name
		os << "\t" << rx_gain_names[index] << endl;
	}
	for (int index =0; index < rx_gain_names.size(); index++)
	{
		// Name
		os << "\t" << "Name: " << rx_gain_names[index] << "  Value: ";
		// Value
		try
		{
		double element_gain = usrp->get_rx_gain(rx_gain_names[index], nchan);
		os << element_gain << endl;
		}
		catch(uhd::runtime_error &e)
		{
			os << "Exception code while getting value: " << e.code() << endl;
		}
	}

	// Gain ranges for each of the gain elements
	os << std::endl << "-----> Get RX element gain ranges" << std::endl;
	for (int index =0; index < rx_gain_names.size(); index++)
	{
		// Name
		os << "\t" << "Name: " << rx_gain_names[index] << "  Value: ";
		// Value
		try
		{
		uhd::gain_range_t element_gain_range = usrp->get_rx_gain_range(rx_gain_names[index], nchan);
		os << "Start: " << element_gain_range.start() << " End: " << element_gain_range.stop() << " Step: " << element_gain_range.step() << endl;
		}
		catch(uhd::runtime_error &e)
		{
			os << "Exception code while getting value: " << e.code() << endl;
		}
	}

	// Total Gain range
	try
	{
		os << endl << "-----> Get RX Total Gain Range" << endl;
		uhd::gain_range_t rx_total_gain_range = usrp->get_rx_gain_range(nchan);
		os << "RX Total Gain Range: " ;
		os << "Start: " << rx_total_gain_range.start() << " End: " << rx_total_gain_range.stop() << " Step: " << rx_total_gain_range.step() << endl;
	}
	catch(uhd::runtime_error &e)
	{
		os << "Exception code: " << e.code() <<endl;
	}
	
	// ANTENNA FUNCTIONS
	
	os << std::endl << "********** RX ANTENNA ***********" << std::endl;
	// Current Rx Antenna
	os << std::endl << "-----> Get RX Antenna" << std::endl;
	string rx_antenna = usrp->get_rx_antenna(nchan);
	os << "RX Antenna: " ;
	os << rx_antenna << endl;

	// RX Antenna choices
	os << std::endl << "-----> Get Rx Antenna List" << std::endl;
	std::vector<std::string> rx_antennas = usrp->get_rx_antennas(nchan);
	os << "RX Antennas : " << std::endl;
	for (int index =0; index < rx_antennas.size(); index++)
		os << "\t" << rx_antennas[index] << std::endl;
		
		
	// RX BANDWIDTH FUNCTIONS

	os << std::endl << "********** RX BANDWIDTH ***********" << std::endl;
	// Current RX Bandwidth
	os << endl << "-----> Get RX Bandwidth" << endl;
	try
	{
		os << "RX Bandwidth " ;
		double rx_bandwidth = usrp->get_rx_bandwidth(nchan);
		os << rx_bandwidth << endl;
	}
	catch (uhd::runtime_error &e)
	{
		os << "Exception occured " << e.code() << endl;
	}
	
	// RX Bandwidth Range
	os << endl << "-----> Get RX Bandwidth Range" << endl;
	try
	{
		os << "RX Bandwidth Range: " ;
		uhd::gain_range_t rx_bandwidth_range = usrp->get_rx_bandwidth_range(nchan);
		os << "Start: " << rx_bandwidth_range .start() << " End: " << rx_bandwidth_range .stop() << " Step: " << rx_bandwidth_range .step() << endl;
	}
	catch(uhd::runtime_error &e)
	{
		os << "Exception code: " << e.code() <<endl;
	}
	
	// RX DBOARD INTERFACE OBJECT

	os << std::endl << "********** RX DBOARD INTERFACE ***********" << std::endl;
	// RX Dboard Interface
	os << endl << "-----> Get rx_dboard_iface()" << endl;
	try
	{
		os << "RX Dboard Interface " ;
		uhd::usrp::dboard_iface::sptr rx_dboard_iface = usrp->get_rx_dboard_iface(nchan);
		os << rx_dboard_iface << endl;
	}
	catch (uhd::runtime_error &e)
	{
		os << "Exception occured " << e.code() << endl;
	}
	
	// RX _SENSORS

	os << std::endl << "********** RX Sensors  ***********" << std::endl;

	// List of all available sensors
	os << std::endl << "-----> Get RX Sensors Name" << std::endl;
	std::vector<std::string> rx_sensor_names = usrp->get_rx_sensor_names(nchan);
	os << "Sensor Names: " << std::endl;
	for (int index =0; index < rx_sensor_names.size(); index++)
	{
		// Name
		os << "\t" << rx_sensor_names[index] << ":  ";
		// Value
		try
		{
			uhd::sensor_value_t rx_sensor_value = usrp->get_rx_sensor(rx_sensor_names[index], nchan);
			os << rx_sensor_value.to_pp_string()<< std::endl;
		}
		catch(uhd::runtime_error &e)
		{
			os << "Exception occured " << e.code() << endl;
		}
	}
	

}
예제 #2
0
/***********************************************************************
 * RX Hammer
 **********************************************************************/
void rx_hammer(uhd::usrp::multi_usrp::sptr usrp, const std::string &rx_cpu, const std::string &rx_otw){
    uhd::set_thread_priority_safe();

    //create a receive streamer
    uhd::stream_args_t stream_args(rx_cpu, rx_otw);
    for (size_t ch = 0; ch < usrp->get_num_mboards(); ch++) //linear channel mapping
        stream_args.channels.push_back(ch);
    uhd::rx_streamer::sptr rx_stream = usrp->get_rx_stream(stream_args);

    //print pre-test summary
    std::cout << boost::format(
        "Testing receive rate %f Msps"
    ) % (usrp->get_rx_rate()/1e6) << std::endl;

    //setup variables and allocate buffer
    uhd::rx_metadata_t md;
    const size_t max_samps_per_packet = rx_stream->get_max_num_samps();
    std::vector<char> buff(max_samps_per_packet*uhd::convert::get_bytes_per_item(rx_cpu));
    std::vector<void *> buffs;
    for (size_t ch = 0; ch < stream_args.channels.size(); ch++)
        buffs.push_back(&buff.front()); //same buffer for each channel
    bool had_an_overflow = false;
    uhd::time_spec_t last_time;
    const double rate = usrp->get_rx_rate();
    double timeout = 1;

    uhd::stream_cmd_t cmd(uhd::stream_cmd_t::STREAM_MODE_NUM_SAMPS_AND_DONE);
    cmd.time_spec = usrp->get_time_now() + uhd::time_spec_t(0.05);
    cmd.stream_now = (buffs.size() == 1);
    srand( time(NULL) );

    while (not boost::this_thread::interruption_requested()){
        cmd.num_samps = rand() % 100000;
        usrp->issue_stream_cmd(cmd);
        num_rx_samps += rx_stream->recv(buffs, max_samps_per_packet, md, timeout, true);

        //handle the error codes
        switch(md.error_code){
        case uhd::rx_metadata_t::ERROR_CODE_NONE:
            if (had_an_overflow){
                had_an_overflow = false;
                num_dropped_samps += boost::math::iround((md.time_spec - last_time).get_real_secs()*rate);
            }
            break;

        case uhd::rx_metadata_t::ERROR_CODE_OVERFLOW:
            had_an_overflow = true;
            last_time = md.time_spec;
            num_overflows++;
            break;

        default:
            std::cerr << "Error code: " << md.error_code << std::endl;
            std::cerr << "Unexpected error on recv, continuing..." << std::endl;
            break;
        }
    }
}
예제 #3
0
파일: UHDDevice.cpp 프로젝트: Djimmer/obts
int uhd_device::set_rates(double tx_rate, double rx_rate)
{
	double offset_limit = 1.0;
	double tx_offset, rx_offset;

	// B2XX is the only device where we set FPGA clocking
	if (dev_type == B2XX) {
		if (set_master_clk(B2XX_CLK_RT) < 0)
			return -1;
	}

	// Set sample rates
	try {
		usrp_dev->set_tx_rate(tx_rate);
		usrp_dev->set_rx_rate(rx_rate);
	} catch (const std::exception &ex) {
		LOG(ALERT) << "UHD rate setting failed";
		LOG(ALERT) << ex.what();
		return -1;
	}
	this->tx_rate = usrp_dev->get_tx_rate();
	this->rx_rate = usrp_dev->get_rx_rate();

	tx_offset = fabs(this->tx_rate - tx_rate);
	rx_offset = fabs(this->rx_rate - rx_rate);
	if ((tx_offset > offset_limit) || (rx_offset > offset_limit)) {
		LOG(ALERT) << "Actual sample rate differs from desired rate";
		LOG(ALERT) << "Tx/Rx (" << this->tx_rate << "/"
			   << this->rx_rate << ")";
		return -1;
	}

	return 0;
}
예제 #4
0
/***********************************************************************
 * Data capture routine
 **********************************************************************/
static void capture_samples(
    uhd::usrp::multi_usrp::sptr usrp,
    uhd::rx_streamer::sptr rx_stream,
    std::vector<samp_type > &buff,
    const size_t nsamps_requested)
{
    buff.resize(nsamps_requested);
    uhd::rx_metadata_t md;

    // Right after the stream is started, there will be transient data.
    // That transient data is discarded and only "good" samples are returned.
    size_t nsamps_to_discard = size_t(usrp->get_rx_rate() * 0.001); // 1ms to be discarded
    std::vector<samp_type> discard_buff(nsamps_to_discard);

    uhd::stream_cmd_t stream_cmd(uhd::stream_cmd_t::STREAM_MODE_NUM_SAMPS_AND_DONE);
    stream_cmd.num_samps = buff.size() + nsamps_to_discard;
    stream_cmd.stream_now = true;
    usrp->issue_stream_cmd(stream_cmd);
    size_t num_rx_samps = 0;

    // Discard the transient samples.
    rx_stream->recv(&discard_buff.front(), discard_buff.size(), md);
    if (md.error_code != uhd::rx_metadata_t::ERROR_CODE_NONE)
    {
        throw std::runtime_error(str(boost::format(
            "Receiver error: %s"
        ) % md.strerror()));
    }

    // Now capture the data we want
    num_rx_samps = rx_stream->recv(&buff.front(), buff.size(), md);

    //validate the received data
    if (md.error_code != uhd::rx_metadata_t::ERROR_CODE_NONE)
    {
        throw std::runtime_error(str(boost::format(
            "Receiver error: %s"
        ) % md.strerror()));
    }

    //we can live if all the data didnt come in
    if (num_rx_samps > buff.size()/2)
    {
        buff.resize(num_rx_samps);
        return;
    }
    if (num_rx_samps != buff.size())
        throw std::runtime_error("did not get all the samples requested");
}
예제 #5
0
double uhd_device::set_rates(double rate)
{
	double actual_rt, actual_clk_rt;

#if !defined(MULTICHAN) & !defined(RESAMPLE)
	// Make sure we can set the master clock rate on this device
	actual_clk_rt = usrp_dev->get_master_clock_rate();
	if (actual_clk_rt > U1_DEFAULT_CLK_RT) {
		LOG(ALERT) << "Cannot set clock rate on this device";
		LOG(ALERT) << "Please compile with host resampling support";
		return -1.0;
	}

	// Set master clock rate
	usrp_dev->set_master_clock_rate(master_clk_rt);
	actual_clk_rt = usrp_dev->get_master_clock_rate();

	if (actual_clk_rt != master_clk_rt) {
		LOG(ALERT) << "Failed to set master clock rate";
		LOG(ALERT) << "Actual clock rate " << actual_clk_rt;
		return -1.0;
	}
#endif

	// Set sample rates
	usrp_dev->set_tx_rate(rate);
	usrp_dev->set_rx_rate(rate);
	actual_rt = usrp_dev->get_tx_rate();

	if (actual_rt != rate) {
		LOG(ALERT) << "Actual sample rate differs from desired rate";
		LOG(ALERT) << actual_rt << "Hz";
		return -1.0;
	}
	if (usrp_dev->get_rx_rate() != actual_rt) {
		LOG(ALERT) << "Transmit and receive sample rates do not match";
		return -1.0;
	}

	return actual_rt;
}
예제 #6
0
/***********************************************************************
 * Function to find optimal RX gain setting (for the current frequency)
 **********************************************************************/
UHD_INLINE void set_optimal_rx_gain(
    uhd::usrp::multi_usrp::sptr usrp,
    uhd::rx_streamer::sptr rx_stream,
    double wave_freq = 0.0)
{
    const double gain_step = 3.0;
    const double gain_compression_threshold = gain_step * 0.5;
    const double actual_rx_rate = usrp->get_rx_rate();
    const double actual_tx_freq = usrp->get_tx_freq();
    const double actual_rx_freq = usrp->get_rx_freq();
    const double bb_tone_freq = actual_tx_freq - actual_rx_freq + wave_freq;
    const size_t nsamps = size_t(actual_rx_rate / default_fft_bin_size);

    std::vector<samp_type> buff(nsamps);
    uhd::gain_range_t rx_gain_range = usrp->get_rx_gain_range();
    double rx_gain = rx_gain_range.start() + gain_step;
    double curr_dbrms = 0.0;
    double prev_dbrms = 0.0;
    double delta = 0.0;

    // No sense in setting the gain where this is no gain range
    if (rx_gain_range.stop() - rx_gain_range.start() < gain_step)
        return;

    // The algorithm below cycles through the RX gain range
    // looking for the point where the signal begins to get
    // clipped and the gain begins to be compressed.  It does
    // this by looking for the gain setting where the increase
    // in the tone is less than the gain step by more than the
    // gain compression threshold (curr - prev < gain - threshold).

    // Initialize prev_dbrms value
    usrp->set_rx_gain(rx_gain);
    capture_samples(usrp, rx_stream, buff, nsamps);
    prev_dbrms = compute_tone_dbrms(buff, bb_tone_freq/actual_rx_rate);
    rx_gain += gain_step;

    // Find RX gain where signal begins to clip
    while (rx_gain <= rx_gain_range.stop())
    {
        usrp->set_rx_gain(rx_gain);
        capture_samples(usrp, rx_stream, buff, nsamps);
        curr_dbrms = compute_tone_dbrms(buff, bb_tone_freq/actual_rx_rate);
        delta = curr_dbrms - prev_dbrms;

        // check if the gain is compressed beyone the threshold
        if (delta < gain_step - gain_compression_threshold)
            break;  // if so, we are done

        prev_dbrms = curr_dbrms;
        rx_gain += gain_step;
    }

    // The rx_gain value at this point is the gain setting where clipping
    // occurs or the gain setting that is just beyond the gain range.
    // The gain is reduced by 2 steps to make sure it is within the range and
    // under the point where it is clipped with enough room to make adjustments.
    rx_gain -= 2 * gain_step;

    // Make sure the gain is within the range.
    rx_gain = rx_gain_range.clip(rx_gain);

    // Finally, set the gain.
    usrp->set_rx_gain(rx_gain);
}
예제 #7
0
/***********************************************************************
 * recv_to_file function
 **********************************************************************/
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 &file,
    size_t samps_per_buff,
    int num_requested_samples,
    double settling_time,
    std::vector<size_t> rx_channel_nums
){
    int num_total_samps = 0;
    //create a receive streamer
    uhd::stream_args_t stream_args(cpu_format,wire_format);
    stream_args.channels = rx_channel_nums;
    uhd::rx_streamer::sptr rx_stream = usrp->get_rx_stream(stream_args);

    // Prepare buffers for received samples and metadata
    uhd::rx_metadata_t md;
    std::vector <std::vector< samp_type > > buffs(
        rx_channel_nums.size(), std::vector< samp_type >(samps_per_buff)
    );
    //create a vector of pointers to point to each of the channel buffers
    std::vector<samp_type *> buff_ptrs;
    for (size_t i = 0; i < buffs.size(); i++) {
        buff_ptrs.push_back(&buffs[i].front());
    }

    // Create one ofstream object per channel
    // (use shared_ptr because ofstream is non-copyable)
    std::vector<boost::shared_ptr<std::ofstream> > outfiles;
    for (size_t i = 0; i < buffs.size(); i++) {
        const std::string this_filename = generate_out_filename(file, buffs.size(), i);
        outfiles.push_back(boost::shared_ptr<std::ofstream>(new std::ofstream(this_filename.c_str(), std::ofstream::binary)));
    }
    UHD_ASSERT_THROW(outfiles.size() == buffs.size());
    UHD_ASSERT_THROW(buffs.size() == rx_channel_nums.size());
    bool overflow_message = true;
    double timeout = settling_time + 0.1f; //expected settling time + padding for first recv

    //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 = num_requested_samples;
    stream_cmd.stream_now = false;
    stream_cmd.time_spec = uhd::time_spec_t(settling_time);
    rx_stream->issue_stream_cmd(stream_cmd);

    while(not stop_signal_called and (num_requested_samples > num_total_samps or num_requested_samples == 0)){
        size_t num_rx_samps = rx_stream->recv(buff_ptrs, samps_per_buff, md, timeout);
        timeout = 0.1f; //small timeout for subsequent recv

        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){
            throw std::runtime_error(str(boost::format(
                "Receiver error %s"
            ) % md.strerror()));
        }

        num_total_samps += num_rx_samps;

        for (size_t i = 0; i < outfiles.size(); i++) {
            outfiles[i]->write((const char*) buff_ptrs[i], num_rx_samps*sizeof(samp_type));
        }
    }

    // Shut down receiver
    stream_cmd.stream_mode = uhd::stream_cmd_t::STREAM_MODE_STOP_CONTINUOUS;
    rx_stream->issue_stream_cmd(stream_cmd);

    // Close files
    for (size_t i = 0; i < outfiles.size(); i++) {
        outfiles[i]->close();
    }
}
예제 #8
0
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 &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);
    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 = num_requested_samples;
    stream_cmd.stream_now = true;
    stream_cmd.time_spec = uhd::time_spec_t();
    rx_stream->issue_stream_cmd(stream_cmd);

    boost::system_time start = boost::get_system_time();
    unsigned long long ticks_requested = (long)(time_requested * (double)boost::posix_time::time_duration::ticks_per_second());
    boost::posix_time::time_duration ticks_diff;
    boost::system_time last_update = start;
    unsigned long long last_update_samps = 0;

    typedef std::map<size_t,size_t> SizeMap;
    SizeMap mapSizes;

    while(not stop_signal_called and (num_requested_samples != num_total_samps or num_requested_samples == 0)) {
        boost::system_time now = boost::get_system_time();

        size_t num_rx_samps = rx_stream->recv(&buff.front(), buff.size(), md, 3.0, enable_size_map);

        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;
            boost::posix_time::time_duration update_diff = now - last_update;
            if (update_diff.ticks() > boost::posix_time::time_duration::ticks_per_second()) {
                double t = (double)update_diff.ticks() / (double)boost::posix_time::time_duration::ticks_per_second();
                double r = (double)last_update_samps / t;
                std::cout << boost::format("\t%f Msps") % (r/1e6) << std::endl;
                last_update_samps = 0;
                last_update = now;
            }
        }

        ticks_diff = now - start;
        if (ticks_requested > 0){
            if ((unsigned long long)ticks_diff.ticks() > ticks_requested)
                break;
        }
    }

    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;

        double t = (double)ticks_diff.ticks() / (double)boost::posix_time::time_duration::ticks_per_second();
        std::cout << boost::format("Received %d samples in %f seconds") % num_total_samps % t << std::endl;
        double r = (double)num_total_samps / t;
        std::cout << boost::format("%f Msps") % (r/1e6) << 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;
        }
    }
}
예제 #9
0
int setupUSRP(  uhd::usrp::multi_usrp::sptr&  usrp,
                const float                   center_freq,
                const float                   sample_rate,
                const int                     rx_gain,
                const char*                   dev_addr)
{
  //Initialize the USRP to the specified address
  usrp = uhd::usrp::multi_usrp::make(string(dev_addr));
  //Define the clock reference
  usrp->set_clock_source(__USRP_CLK_SRC);

  //Output some useful information
  cout  << "Using the following USRP device: " << endl
        << usrp->get_pp_string() << endl;

  //Try setting the sample rate.  If the rate we get is not the same as the
  //requested rate, we will return with a warning to ensure the user is aware
  //of the actual sample rate
  usrp->set_rx_rate( sample_rate );

  if( usrp->get_rx_rate() != sample_rate )
  {
    ios_base::fmtflags originalFlags = cout.flags();
    cout.setf(ios_base::left,ios_base::floatfield);
    cout.precision(15);
    cout  << "WARNING! Requested rate = " << sample_rate << endl
          << "WARNING! Actual rate = " << usrp->get_rx_rate() << endl;
    cout.setf(originalFlags);
  }

  //Try setting the center frequency.  Like above, if we get a different
  //frequency than the one we're requesting, we will spit out a warning for the
  //user
  usrp->set_rx_freq( center_freq );

  if( usrp->get_rx_freq() != center_freq )
  {
    ios_base::fmtflags originalFlags = cout.flags();
    cout.setf(ios_base::left,ios_base::floatfield);
    cout.precision(15);
    cout  << "WARNING! Requested frequency = " << center_freq << endl
          << "WARNING! Actual frequency = " << usrp->get_rx_freq() << endl;
    cout.setf(originalFlags);
  }

  //Set the RX gain.  There really shouldn't be any problems here, but the user
  //might request something silly like 50dB of gain when the module can't
  //accomodate.  So we'll perform a similar check here.
  usrp->set_rx_gain( rx_gain );

  if( usrp->get_rx_gain() != rx_gain )
  {
    cout  << "WARNING! Requested gain = " << rx_gain << endl
          << "WARNING! Actual gain = " << usrp->get_rx_gain() << endl;
  }

  //Ensure the LO locked
  vector<string> sensor_names;
  sensor_names = usrp->get_rx_sensor_names(0);
  if( find(sensor_names.begin(), sensor_names.end(), "lo_locked")
      != sensor_names.end() )
  {
    uhd::sensor_value_t lo_locked = usrp->get_rx_sensor("lo_locked",0);
    cout  << "Checking RX: " << endl
          << lo_locked.to_pp_string() << endl;
    UHD_ASSERT_THROW(lo_locked.to_bool());      //We should probably catch this
  }

  return 1;
}
예제 #10
0
void transceive(
    uhd::usrp::multi_usrp::sptr usrp,
    uhd::tx_streamer::sptr tx_stream,
    uhd::rx_streamer::sptr rx_stream,
    unsigned int npulses,
    float pulse_time,
    //std::complex<int16_t>* txbuff,
    std::vector<std::complex<int16_t> >* txbuff0,
    std::vector<std::complex<int16_t> >* txbuff1,
    float tx_ontime,
    std::complex<int16_t>** outdata,
    size_t samps_per_pulse
){
    int debug = 0;
    if (debug){
        std::cout << "samps_per_pulse: " << samps_per_pulse << std::endl;
    }
    //create metadeta tags for transmit streams
    uhd::time_spec_t start_time = usrp->get_time_now() + 0.05;
    uhd::tx_metadata_t md;
    md.start_of_burst = true;
    md.end_of_burst = false;
    md.has_time_spec = true;
    md.time_spec = start_time;
    std::vector<std::complex<int16_t> *> vec_ptr;
    vec_ptr.resize(1);
    //vec_ptr[0] = &txbuff->front();
    
    usrp->set_gpio_attr("RXA","CTRL",0x0, TR_BIT); //GPIO mode
    usrp->set_gpio_attr("RXA","DDR",TR_BIT, TR_BIT); //Direction out
    
    //create metadata tags for receive stream
    uhd::rx_metadata_t rxmd;
    std::vector<std::complex<int16_t> > buff(samps_per_pulse,0);
    if (verbose) std::cout << "rx buff size: " << buff.size() << std::endl;
    if (verbose) std::cout << "tx buff size: " << txbuff0->size() << std::endl;
    uhd::stream_cmd_t stream_cmd = uhd::stream_cmd_t::STREAM_MODE_NUM_SAMPS_AND_DONE;
    stream_cmd.num_samps = npulses*samps_per_pulse;
    stream_cmd.stream_now = false;
    stream_cmd.time_spec = start_time + 22 / usrp->get_rx_rate(); //Digital hardware delay is 22 samples long.  Found by experiment.
    if (verbose) std::cout << "time spec: " << stream_cmd.time_spec.get_real_secs() << std::endl;
    
    //loop for every pulse in the sequence
    size_t spb;
    std::vector<std::complex<int16_t>* > rx_dptr;
    rx_dptr.resize(usrp->get_rx_num_channels());
    spb = tx_stream->get_max_num_samps();
    if (verbose) std::cout << "npulses: " << npulses << std::endl;
    boost::thread_group rx_threads;
    boost::thread_group tx_threads;
    for (int ipulse=0; ipulse<npulses; ipulse++){
        if (debug) std::cout << "pulse number: " << ipulse << std::endl;
        for (size_t ichan=0; ichan<usrp->get_rx_num_channels(); ichan++){
         rx_dptr[ichan] = ipulse*samps_per_pulse + outdata[ichan];
        }
        
        float timeout = 1.1;
        
        //usrp->set_command_time(start_time-50e-6,0);
        //usrp->set_gpio_attr("RXA","OUT",TR_BIT, TR_BIT);
        
        if (ipulse==0){
            if (verbose) std::cout << "time spec: " << stream_cmd.time_spec.get_real_secs() << std::endl;
            if (verbose) std::cout << "Issuing stream command to start collecting samples\n";
            usrp->issue_stream_cmd(stream_cmd);
        }
        
        //usrp->set_command_time(start_time+tx_ontime,0);
        //usrp->set_gpio_attr("RXA","OUT",0x0, TR_BIT);
        
        size_t acc_samps=0;
        if (ipulse%2 == 0) {
            vec_ptr[0] = &txbuff0->front();
        }
        if (ipulse%2 == 1) {
            vec_ptr[0] = &txbuff1->front();
        }
        
        if (ipulse != npulses-1) {
             tx_threads.create_thread(boost::bind(tx_worker,
                 txbuff0->size(), tx_stream, start_time, vec_ptr[0], 0));
        }
        if (ipulse == npulses-1) {
             tx_threads.create_thread(boost::bind(tx_worker,
                 txbuff0->size(), tx_stream, start_time, vec_ptr[0], 1));
        }
        
        rx_threads.join_all();
        rx_threads.create_thread(boost::bind(rx_worker,
         rx_stream, samps_per_pulse, rx_dptr));
        
        //for (int k=0; k<10; k++){
        // //std::cout << "raw data: " << outdata[0][i][k] << "\t" << outdata[1][i][k] << std::endl;
        // std::cout << "raw data: " << rx_dptr[0][k] << " " << rx_dptr[1][k] << std::endl;
        //}
        //for (int k=0; k<samps_per_pulse; k++)
        //    outdata[i][k] += buff[k];
        
        
        start_time += float(pulse_time);
    }
    tx_threads.join_all();
    rx_threads.join_all();
}
예제 #11
0
/***********************************************************************
 * recv_to_file function
 **********************************************************************/
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 &file,
    size_t samps_per_buff,
    int num_requested_samples,
    float settling_time,
    std::vector<size_t> rx_channel_nums
) {
    int num_total_samps = 0;
    //create a receive streamer
    uhd::stream_args_t stream_args(cpu_format,wire_format);
    stream_args.channels = rx_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(file.c_str(), std::ofstream::binary);
    bool overflow_message = true;
    float timeout = settling_time + 0.1; //expected settling time + padding for first recv

    //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 = num_requested_samples;
    stream_cmd.stream_now = false;
    stream_cmd.time_spec = uhd::time_spec_t(settling_time);
    rx_stream->issue_stream_cmd(stream_cmd);

    while(not stop_signal_called and (num_requested_samples != num_total_samps or num_requested_samples == 0)) {
        size_t num_rx_samps = rx_stream->recv(&buff.front(), buff.size(), md, timeout);
        timeout = 0.1; //small timeout for subsequent recv

        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) {
            throw std::runtime_error(str(boost::format(
                                             "Receiver error %s"
                                         ) % md.strerror()));
        }

        num_total_samps += num_rx_samps;

        outfile.write((const char*)&buff.front(), num_rx_samps*sizeof(samp_type));
    }

    outfile.close();
}
예제 #12
0
/***********************************************************************
 * Benchmark RX Rate
 **********************************************************************/
void benchmark_rx_rate(
        uhd::usrp::multi_usrp::sptr usrp,
        const std::string &rx_cpu,
        uhd::rx_streamer::sptr rx_stream,
        bool random_nsamps,
        const boost::posix_time::ptime &start_time,
        std::atomic<bool>& burst_timer_elapsed
) {
    uhd::set_thread_priority_safe();

    //print pre-test summary
    std::cout << boost::format(
        "[%s] Testing receive rate %f Msps on %u channels"
    ) % NOW() % (usrp->get_rx_rate()/1e6) % rx_stream->get_num_channels() << std::endl;

    //setup variables and allocate buffer
    uhd::rx_metadata_t md;
    const size_t max_samps_per_packet = rx_stream->get_max_num_samps();
    std::vector<char> buff(max_samps_per_packet*uhd::convert::get_bytes_per_item(rx_cpu));
    std::vector<void *> buffs;
    for (size_t ch = 0; ch < rx_stream->get_num_channels(); ch++)
        buffs.push_back(&buff.front()); //same buffer for each channel
    bool had_an_overflow = false;
    uhd::time_spec_t last_time;
    const double rate = usrp->get_rx_rate();

    uhd::stream_cmd_t cmd(uhd::stream_cmd_t::STREAM_MODE_START_CONTINUOUS);
    cmd.time_spec = usrp->get_time_now() + uhd::time_spec_t(INIT_DELAY);
    cmd.stream_now = (buffs.size() == 1);
    rx_stream->issue_stream_cmd(cmd);

    const float burst_pkt_time =
        std::max<float>(0.100f, (2 * max_samps_per_packet/rate));
    float recv_timeout = burst_pkt_time + INIT_DELAY;

    bool stop_called = false;
    while (true) {
        //if (burst_timer_elapsed.load(boost::memory_order_relaxed) and not stop_called) {
        if (burst_timer_elapsed and not stop_called) {
            rx_stream->issue_stream_cmd(uhd::stream_cmd_t::STREAM_MODE_STOP_CONTINUOUS);
            stop_called = true;
        }
        if (random_nsamps) {
            cmd.num_samps = rand() % max_samps_per_packet;
            rx_stream->issue_stream_cmd(cmd);
        }
        try {
            num_rx_samps += rx_stream->recv(buffs, max_samps_per_packet, md, recv_timeout)*rx_stream->get_num_channels();
            recv_timeout = burst_pkt_time;
        }
        catch (uhd::io_error &e) {
            std::cerr << "[" << NOW() << "] Caught an IO exception. " << std::endl;
            std::cerr << e.what() << std::endl;
            return;
        }

        //handle the error codes
        switch(md.error_code){
        case uhd::rx_metadata_t::ERROR_CODE_NONE:
            if (had_an_overflow) {
                had_an_overflow = false;
                const long dropped_samps =
                    (md.time_spec - last_time).to_ticks(rate);
                if (dropped_samps < 0) {
                    std::cerr
                        << "[" << NOW() << "] Timestamp after overrun recovery "
                           "ahead of error timestamp! Unable to calculate "
                           "number of dropped samples."
                           "(Delta: " << dropped_samps << " ticks)\n";
                }
                num_dropped_samps += std::max<long>(1, dropped_samps);
            }
            if ((burst_timer_elapsed or stop_called) and md.end_of_burst) {
                return;
            }
            break;

        // ERROR_CODE_OVERFLOW can indicate overflow or sequence error
        case uhd::rx_metadata_t::ERROR_CODE_OVERFLOW:
            last_time = md.time_spec;
            had_an_overflow = true;
            // check out_of_sequence flag to see if it was a sequence error or overflow
            if (!md.out_of_sequence) {
                num_overruns++;
            } else {
                num_seqrx_errors++;
                std::cerr << "[" << NOW() << "] Detected Rx sequence error." << std::endl;
            }
            break;

        case uhd::rx_metadata_t::ERROR_CODE_LATE_COMMAND:
            std::cerr << "[" << NOW() << "] Receiver error: " << md.strerror() << ", restart streaming..."<< std::endl;
            num_late_commands++;
            // Radio core will be in the idle state. Issue stream command to restart streaming.
            cmd.time_spec = usrp->get_time_now() + uhd::time_spec_t(0.05);
            cmd.stream_now = (buffs.size() == 1);
            rx_stream->issue_stream_cmd(cmd);
            break;

        case uhd::rx_metadata_t::ERROR_CODE_TIMEOUT:
            if (burst_timer_elapsed) {
                return;
            }
            std::cerr << "[" << NOW() << "] Receiver error: " << md.strerror() << ", continuing..." << std::endl;
            num_timeouts_rx++;
            break;

            // Otherwise, it's an error
        default:
            std::cerr << "[" << NOW() << "] Receiver error: " << md.strerror() << std::endl;
            std::cerr << "[" << NOW() << "] Unexpected error on recv, continuing..." << std::endl;
            break;
        }
    }
}