mirror of
https://github.com/saymrwulf/uhd.git
synced 2026-05-16 21:10:10 +00:00
Add --ref option to specify mboard clock reference source
Add check for lock to mboard clock reference (where applicable)
Add check of daughterboard LO lock detect (where applicable)
181 lines
7.6 KiB
C++
181 lines
7.6 KiB
C++
//
|
|
// Copyright 2010-2011 Ettus Research LLC
|
|
//
|
|
// This program is free software: you can redistribute it and/or modify
|
|
// it under the terms of the GNU General Public License as published by
|
|
// the Free Software Foundation, either version 3 of the License, or
|
|
// (at your option) any later version.
|
|
//
|
|
// This program is distributed in the hope that it will be useful,
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
// GNU General Public License for more details.
|
|
//
|
|
// You should have received a copy of the GNU General Public License
|
|
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
//
|
|
|
|
#include <uhd/utils/thread_priority.hpp>
|
|
#include <uhd/utils/safe_main.hpp>
|
|
#include <uhd/usrp/multi_usrp.hpp>
|
|
#include <uhd/transport/udp_simple.hpp>
|
|
#include <uhd/exception.hpp>
|
|
#include <boost/program_options.hpp>
|
|
#include <boost/format.hpp>
|
|
#include <boost/thread.hpp>
|
|
#include <iostream>
|
|
#include <complex>
|
|
|
|
namespace po = boost::program_options;
|
|
|
|
int UHD_SAFE_MAIN(int argc, char *argv[]){
|
|
uhd::set_thread_priority_safe();
|
|
|
|
//variables to be set by po
|
|
std::string args, file, ant, subdev, ref;
|
|
size_t total_num_samps;
|
|
double rate, freq, gain, bw;
|
|
std::string addr, port;
|
|
|
|
//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")
|
|
("nsamps", po::value<size_t>(&total_num_samps)->default_value(1000), "total number of samples to receive")
|
|
("rate", po::value<double>(&rate)->default_value(100e6/16), "rate of incoming samples")
|
|
("freq", po::value<double>(&freq)->default_value(0), "rf center frequency in Hz")
|
|
("gain", po::value<double>(&gain)->default_value(0), "gain for the RF chain")
|
|
("ant", po::value<std::string>(&ant), "daughterboard antenna selection")
|
|
("subdev", po::value<std::string>(&subdev), "daughterboard subdevice specification")
|
|
("bw", po::value<double>(&bw), "daughterboard IF filter bandwidth in Hz")
|
|
("port", po::value<std::string>(&port)->default_value("7124"), "server udp port")
|
|
("addr", po::value<std::string>(&addr)->default_value("192.168.1.10"), "resolvable server address")
|
|
("ref", po::value<std::string>(&ref)->default_value("INTERNAL"), "waveform type (INTERNAL, EXTERNAL, MIMO)")
|
|
;
|
|
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 to UDP %s") % desc << std::endl;
|
|
return ~0;
|
|
}
|
|
|
|
//create a usrp device
|
|
std::cout << std::endl;
|
|
std::cout << boost::format("Creating the usrp device with: %s...") % args << std::endl;
|
|
uhd::usrp::multi_usrp::sptr usrp = uhd::usrp::multi_usrp::make(args);
|
|
std::cout << boost::format("Using Device: %s") % usrp->get_pp_string() << std::endl;
|
|
|
|
//Lock mboard clocks
|
|
if (ref == "MIMO") {
|
|
uhd::clock_config_t clock_config;
|
|
clock_config.ref_source = uhd::clock_config_t::REF_MIMO;
|
|
clock_config.pps_source = uhd::clock_config_t::PPS_MIMO;
|
|
usrp->set_clock_config(clock_config, 0);
|
|
}
|
|
else if (ref == "EXTERNAL") {
|
|
usrp->set_clock_config(uhd::clock_config_t::external(), 0);
|
|
}
|
|
else if (ref == "INTERNAL") {
|
|
usrp->set_clock_config(uhd::clock_config_t::internal(), 0);
|
|
}
|
|
|
|
//set the rx 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 the rx center frequency
|
|
std::cout << boost::format("Setting RX Freq: %f Mhz...") % (freq/1e6) << std::endl;
|
|
usrp->set_rx_freq(freq);
|
|
std::cout << boost::format("Actual RX Freq: %f Mhz...") % (usrp->get_rx_freq()/1e6) << std::endl << std::endl;
|
|
|
|
//set the rx 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
|
|
if (vm.count("bw")){
|
|
std::cout << boost::format("Setting RX Bandwidth: %f MHz...") % bw << std::endl;
|
|
usrp->set_rx_bandwidth(bw);
|
|
std::cout << boost::format("Actual RX Bandwidth: %f MHz...") % usrp->get_rx_bandwidth() << std::endl << std::endl;
|
|
}
|
|
|
|
//set the antenna
|
|
if (vm.count("ant")) usrp->set_rx_antenna(ant);
|
|
|
|
boost::this_thread::sleep(boost::posix_time::seconds(1)); //allow for some setup time
|
|
|
|
//Check Ref and LO Lock detect
|
|
std::vector<std::string> sensor_names;
|
|
sensor_names = usrp->get_rx_sensor_names(0);
|
|
if (std::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);
|
|
std::cout << boost::format("Checking RX: %s ...") % lo_locked.to_pp_string() << std::endl;
|
|
UHD_ASSERT_THROW(lo_locked.to_bool());
|
|
}
|
|
sensor_names = usrp->get_mboard_sensor_names(0);
|
|
if ((ref == "MIMO") and (std::find(sensor_names.begin(), sensor_names.end(), "mimo_locked") != sensor_names.end())) {
|
|
uhd::sensor_value_t mimo_locked = usrp->get_mboard_sensor("mimo_locked",0);
|
|
std::cout << boost::format("Checking RX: %s ...") % mimo_locked.to_pp_string() << std::endl;
|
|
UHD_ASSERT_THROW(mimo_locked.to_bool());
|
|
}
|
|
if ((ref == "EXTERNAL") and (std::find(sensor_names.begin(), sensor_names.end(), "ref_locked") != sensor_names.end())) {
|
|
uhd::sensor_value_t ref_locked = usrp->get_mboard_sensor("ref_locked",0);
|
|
std::cout << boost::format("Checking RX: %s ...") % ref_locked.to_pp_string() << std::endl;
|
|
UHD_ASSERT_THROW(ref_locked.to_bool());
|
|
}
|
|
|
|
//setup streaming
|
|
uhd::stream_cmd_t stream_cmd(uhd::stream_cmd_t::STREAM_MODE_NUM_SAMPS_AND_DONE);
|
|
stream_cmd.num_samps = total_num_samps;
|
|
stream_cmd.stream_now = true;
|
|
usrp->issue_stream_cmd(stream_cmd);
|
|
|
|
//loop until total number of samples reached
|
|
size_t num_acc_samps = 0; //number of accumulated samples
|
|
uhd::rx_metadata_t md;
|
|
std::vector<std::complex<float> > buff(usrp->get_device()->get_max_recv_samps_per_packet());
|
|
uhd::transport::udp_simple::sptr udp_xport = uhd::transport::udp_simple::make_connected(addr, port);
|
|
|
|
while(num_acc_samps < total_num_samps){
|
|
size_t num_rx_samps = usrp->get_device()->recv(
|
|
&buff.front(), buff.size(), md,
|
|
uhd::io_type_t::COMPLEX_FLOAT32,
|
|
uhd::device::RECV_MODE_ONE_PACKET
|
|
);
|
|
|
|
//handle the error codes
|
|
switch(md.error_code){
|
|
case uhd::rx_metadata_t::ERROR_CODE_NONE:
|
|
break;
|
|
|
|
case uhd::rx_metadata_t::ERROR_CODE_TIMEOUT:
|
|
if (num_acc_samps == 0) continue;
|
|
std::cout << boost::format(
|
|
"Got timeout before all samples received, possible packet loss, exiting loop..."
|
|
) << std::endl;
|
|
goto done_loop;
|
|
|
|
default:
|
|
std::cout << boost::format(
|
|
"Got error code 0x%x, exiting loop..."
|
|
) % md.error_code << std::endl;
|
|
goto done_loop;
|
|
}
|
|
|
|
//send complex single precision floating point samples over udp
|
|
udp_xport->send(boost::asio::buffer(buff, num_rx_samps));
|
|
|
|
num_acc_samps += num_rx_samps;
|
|
} done_loop:
|
|
|
|
//finished
|
|
std::cout << std::endl << "Done!" << std::endl << std::endl;
|
|
|
|
return 0;
|
|
}
|