From ec451d811c335af672d7a8ffbcfd3d0a1a645b2b Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Mon, 14 Jun 2010 22:32:54 +0000 Subject: file option for rx timed samples, misc fixes --- host/examples/rx_timed_samples.cpp | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) (limited to 'host/examples') diff --git a/host/examples/rx_timed_samples.cpp b/host/examples/rx_timed_samples.cpp index 64da260d5..eb7ef7251 100644 --- a/host/examples/rx_timed_samples.cpp +++ b/host/examples/rx_timed_samples.cpp @@ -20,13 +20,14 @@ #include #include #include +#include #include namespace po = boost::program_options; int UHD_SAFE_MAIN(int argc, char *argv[]){ //variables to be set by po - std::string args; + std::string args, file_path; int seconds_in_future; size_t total_num_samps; double rx_rate, freq; @@ -40,6 +41,7 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){ ("nsamps", po::value(&total_num_samps)->default_value(1000), "total number of samples to receive") ("rxrate", po::value(&rx_rate)->default_value(100e6/16), "rate of incoming samples") ("freq", po::value(&freq)->default_value(0), "rf center frequency in Hz") + ("file", po::value(&file_path)->default_value(""), "write samps to output file") ; po::variables_map vm; po::store(po::parse_command_line(argc, argv, desc), vm); @@ -76,14 +78,20 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){ stream_cmd.time_spec = uhd::time_spec_t(seconds_in_future); sdev->issue_stream_cmd(stream_cmd); + std::ofstream outfile; + if(file_path != "") outfile.open (file_path.c_str(), std::ios::out | std::ios::binary); + + //setup recv buffer, io type, and metadata for recv + uhd::rx_metadata_t md; + uhd::io_type_t io_type(uhd::io_type_t::COMPLEX_INT16); + std::vector > recv_mem(dev->get_max_recv_samps_per_packet()); + boost::asio::mutable_buffer buff(boost::asio::buffer(recv_mem)); + //loop until total number of samples reached size_t num_acc_samps = 0; //number of accumulated samples while(num_acc_samps < total_num_samps){ - uhd::rx_metadata_t md; - std::vector > buff(dev->get_max_recv_samps_per_packet()); size_t num_rx_samps = dev->recv( - boost::asio::buffer(buff), - md, uhd::io_type_t::COMPLEX_FLOAT32, + buff, md, io_type, uhd::device::RECV_MODE_ONE_PACKET ); if (num_rx_samps == 0 and num_acc_samps > 0){ @@ -95,11 +103,14 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){ std::cout << boost::format("Got packet: %u samples, %u secs, %u nsecs") % num_rx_samps % md.time_spec.secs % md.time_spec.nsecs << std::endl; + if(file_path != "") outfile.write(boost::asio::buffer_cast(buff), num_rx_samps*io_type.size); + num_acc_samps += num_rx_samps; } //finished std::cout << std::endl << "Done!" << std::endl << std::endl; + if(file_path != "") outfile.close(); return 0; } -- cgit v1.2.3 From 6d43a4e83814c5c325caefb35eb1e07b415d8d37 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Mon, 14 Jun 2010 23:15:58 +0000 Subject: fix type, it was supposed to be complex float --- host/examples/rx_timed_samples.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'host/examples') diff --git a/host/examples/rx_timed_samples.cpp b/host/examples/rx_timed_samples.cpp index eb7ef7251..a7212eba3 100644 --- a/host/examples/rx_timed_samples.cpp +++ b/host/examples/rx_timed_samples.cpp @@ -83,7 +83,7 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){ //setup recv buffer, io type, and metadata for recv uhd::rx_metadata_t md; - uhd::io_type_t io_type(uhd::io_type_t::COMPLEX_INT16); + uhd::io_type_t io_type(uhd::io_type_t::COMPLEX_FLOAT32); std::vector > recv_mem(dev->get_max_recv_samps_per_packet()); boost::asio::mutable_buffer buff(boost::asio::buffer(recv_mem)); -- cgit v1.2.3 From d9b7d9f2f9c6ebe27b6cfd4085f4a5c524363a1f Mon Sep 17 00:00:00 2001 From: Philip Balister Date: Wed, 14 Jul 2010 22:16:52 +0000 Subject: Convert basic test programs to use shorts in the GPP to avoid using short to float code in uhd. --- host/examples/rx_timed_samples.cpp | 6 +++--- host/examples/tx_timed_samples.cpp | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) (limited to 'host/examples') diff --git a/host/examples/rx_timed_samples.cpp b/host/examples/rx_timed_samples.cpp index 3b9acbb2c..a72e1ec81 100644 --- a/host/examples/rx_timed_samples.cpp +++ b/host/examples/rx_timed_samples.cpp @@ -84,12 +84,12 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){ //loop until total number of samples reached size_t num_acc_samps = 0; //number of accumulated samples + uhd::rx_metadata_t md; + std::vector > buff(dev->get_max_recv_samps_per_packet()); while(num_acc_samps < total_num_samps){ - uhd::rx_metadata_t md; - std::vector > buff(dev->get_max_recv_samps_per_packet()); size_t num_rx_samps = dev->recv( &buff.front(), buff.size(), md, - uhd::io_type_t::COMPLEX_FLOAT32, + uhd::io_type_t::COMPLEX_INT16, uhd::device::RECV_MODE_ONE_PACKET ); diff --git a/host/examples/tx_timed_samples.cpp b/host/examples/tx_timed_samples.cpp index 5b72bd72f..ceae58a22 100644 --- a/host/examples/tx_timed_samples.cpp +++ b/host/examples/tx_timed_samples.cpp @@ -77,13 +77,13 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){ sdev->set_time_now(uhd::time_spec_t(0.0)); //allocate data to send - std::vector > buff(samps_per_packet, std::complex(ampl, ampl)); + std::vector > buff(samps_per_packet, std::complex(ampl, ampl)); + uhd::tx_metadata_t md; //send the data in multiple packets size_t num_packets = (total_num_samps+samps_per_packet-1)/samps_per_packet; for (size_t i = 0; i < num_packets; i++){ //setup the metadata flags and time spec - uhd::tx_metadata_t md; md.start_of_burst = true; //always SOB (good for continuous streaming) md.end_of_burst = (i == num_packets-1); //only last packet has EOB md.has_time_spec = (i == 0); //only first packet has time @@ -94,7 +94,7 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){ //send the entire packet (driver fragments internally) size_t num_tx_samps = dev->send( &buff.front(), samps_to_send, md, - uhd::io_type_t::COMPLEX_FLOAT32, + uhd::io_type_t::COMPLEX_INT16, uhd::device::SEND_MODE_FULL_BUFF ); if(verbose) std::cout << std::endl << boost::format("Sent %d samples") % num_tx_samps << std::endl; -- cgit v1.2.3 From 1b47702245f0c1f4dda3e0eff487bbe664d48855 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Tue, 17 Aug 2010 17:16:31 +0000 Subject: usrp-e: misc code tweaks --- host/examples/tx_timed_samples.cpp | 2 +- host/lib/usrp/usrp_e/clock_ctrl.cpp | 2 +- host/lib/usrp/usrp_e/codec_ctrl.cpp | 1 + 3 files changed, 3 insertions(+), 2 deletions(-) (limited to 'host/examples') diff --git a/host/examples/tx_timed_samples.cpp b/host/examples/tx_timed_samples.cpp index ceae58a22..aa22d3465 100644 --- a/host/examples/tx_timed_samples.cpp +++ b/host/examples/tx_timed_samples.cpp @@ -77,7 +77,7 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){ sdev->set_time_now(uhd::time_spec_t(0.0)); //allocate data to send - std::vector > buff(samps_per_packet, std::complex(ampl, ampl)); + std::vector > buff(samps_per_packet, std::complex(ampl, ampl)); uhd::tx_metadata_t md; //send the data in multiple packets diff --git a/host/lib/usrp/usrp_e/clock_ctrl.cpp b/host/lib/usrp/usrp_e/clock_ctrl.cpp index 22578a933..62807aec2 100644 --- a/host/lib/usrp/usrp_e/clock_ctrl.cpp +++ b/host/lib/usrp/usrp_e/clock_ctrl.cpp @@ -39,7 +39,7 @@ template static void set_clock_divider * Constants **********************************************************************/ static const bool enable_test_clock = false; -static const double ref_clock_doubler = 2; //enabled below +static const size_t ref_clock_doubler = 2; //enabled below static const double ref_clock_rate = 10e6 * ref_clock_doubler; static const size_t r_counter = 1; diff --git a/host/lib/usrp/usrp_e/codec_ctrl.cpp b/host/lib/usrp/usrp_e/codec_ctrl.cpp index 5322f94bd..2bdbc0f1c 100644 --- a/host/lib/usrp/usrp_e/codec_ctrl.cpp +++ b/host/lib/usrp/usrp_e/codec_ctrl.cpp @@ -97,6 +97,7 @@ usrp_e_codec_ctrl_impl::usrp_e_codec_ctrl_impl(usrp_e_iface::sptr iface){ _ad9862_regs.coarse_mod = ad9862_regs_t::COARSE_MOD_BYPASS; _ad9862_regs.dac_a_coarse_gain = 0x3; _ad9862_regs.dac_b_coarse_gain = 0x3; + _ad9862_regs.edges = ad9862_regs_t::EDGES_BOTH; //setup the dll _ad9862_regs.input_clk_ctrl = ad9862_regs_t::INPUT_CLK_CTRL_EXTERNAL; -- cgit v1.2.3 From 270fb931f11b23a0119a8fe836bbd712d9a50c60 Mon Sep 17 00:00:00 2001 From: Philip Balister Date: Tue, 17 Aug 2010 23:38:39 +0000 Subject: Merging my work back to usrp_e branch. --- host/examples/rx_to_file.cpp | 138 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 138 insertions(+) create mode 100644 host/examples/rx_to_file.cpp (limited to 'host/examples') diff --git a/host/examples/rx_to_file.cpp b/host/examples/rx_to_file.cpp new file mode 100644 index 000000000..cb8c42acc --- /dev/null +++ b/host/examples/rx_to_file.cpp @@ -0,0 +1,138 @@ +// +// Copyright 2010 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 . +// + +#include +#include +#include +#include +#include +#include +#include +#include + +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; + time_t seconds_in_future; + size_t total_num_samps; + double rx_rate, freq; + + //setup the program options + po::options_description desc("Allowed options"); + desc.add_options() + ("help", "help message") + ("args", po::value(&args)->default_value(""), "simple uhd device address args") + ("secs", po::value(&seconds_in_future)->default_value(3), "number of seconds in the future to receive") + ("nsamps", po::value(&total_num_samps)->default_value(1000), "total number of samples to receive") + ("rxrate", po::value(&rx_rate)->default_value(100e6/16), "rate of incoming samples") + ("freq", po::value(&freq)->default_value(0), "rf center frequency in Hz") + ("dilv", "specify to disable inner-loop verbose") + ; + 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 Timed Samples %s") % desc << std::endl; + return ~0; + } + + bool verbose = vm.count("dilv") == 0; + + //create a usrp device + std::cout << std::endl; + std::cout << boost::format("Creating the usrp device with: %s...") % args << std::endl; + uhd::usrp::simple_usrp::sptr sdev = uhd::usrp::simple_usrp::make(args); + uhd::device::sptr dev = sdev->get_device(); + std::cout << boost::format("Using Device: %s") % sdev->get_pp_string() << std::endl; + + //set properties on the device + std::cout << boost::format("Setting RX Rate: %f Msps...") % (rx_rate/1e6) << std::endl; + sdev->set_rx_rate(rx_rate); + std::cout << boost::format("Actual RX Rate: %f Msps...") % (sdev->get_rx_rate()/1e6) << std::endl; + std::cout << boost::format("Setting device timestamp to 0...") << std::endl; + sdev->set_rx_freq(freq); + sdev->set_time_now(uhd::time_spec_t(0.0)); + + sleep(1); + std::cout << "LO Locked = " << sdev->get_rx_lo_locked() << std::endl; + + //setup streaming + std::cout << std::endl; + std::cout << boost::format( + "Begin streaming %u samples, %d seconds in the future..." + ) % total_num_samps % seconds_in_future << std::endl; + uhd::stream_cmd_t stream_cmd(uhd::stream_cmd_t::STREAM_MODE_NUM_SAMPS_AND_DONE); + stream_cmd.num_samps = total_num_samps; + stream_cmd.stream_now = false; + stream_cmd.time_spec = uhd::time_spec_t(seconds_in_future); + sdev->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 > buff(dev->get_max_recv_samps_per_packet()); + std::ofstream outfile("out.dat", std::ofstream::binary); + + while(num_acc_samps < total_num_samps){ + size_t num_rx_samps = dev->recv( + &buff.front(), buff.size(), md, + uhd::io_type_t::COMPLEX_INT16, + 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; + } + + outfile.write((const char*)&buff[0], num_rx_samps * sizeof(std::complex)); + + if(verbose) std::cout << boost::format( + "Got packet: %u samples, %u full secs, %f frac secs" + ) % num_rx_samps % md.time_spec.get_full_secs() % md.time_spec.get_frac_secs() << std::endl; + + num_acc_samps += num_rx_samps; + } done_loop: + + outfile.close(); + + //finished + std::cout << std::endl << "Done!" << std::endl << std::endl; + + return 0; +} -- cgit v1.2.3 From 50b70be92442c05f8cebb63f51333dab2568ca71 Mon Sep 17 00:00:00 2001 From: Philip Balister Date: Wed, 18 Aug 2010 22:07:09 +0000 Subject: Build rx_to_file example. --- host/examples/CMakeLists.txt | 3 +++ 1 file changed, 3 insertions(+) (limited to 'host/examples') diff --git a/host/examples/CMakeLists.txt b/host/examples/CMakeLists.txt index 10a9a833a..70e74a9a8 100644 --- a/host/examples/CMakeLists.txt +++ b/host/examples/CMakeLists.txt @@ -25,6 +25,9 @@ TARGET_LINK_LIBRARIES(benchmark_rx_rate uhd) ADD_EXECUTABLE(rx_timed_samples rx_timed_samples.cpp) TARGET_LINK_LIBRARIES(rx_timed_samples uhd) +ADD_EXECUTABLE(rx_to_file rx_to_file.cpp) +TARGET_LINK_LIBRARIES(rx_to_file uhd) + ADD_EXECUTABLE(tx_timed_samples tx_timed_samples.cpp) TARGET_LINK_LIBRARIES(tx_timed_samples uhd) -- cgit v1.2.3 From b0a2f23bb66fce362b70117efe7b4e967e891c14 Mon Sep 17 00:00:00 2001 From: Philip Balister Date: Thu, 19 Aug 2010 16:25:03 +0000 Subject: Add program to transmit samples from a file. --- host/examples/CMakeLists.txt | 5 ++ host/examples/tx_from_file.cpp | 123 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 128 insertions(+) create mode 100644 host/examples/tx_from_file.cpp (limited to 'host/examples') diff --git a/host/examples/CMakeLists.txt b/host/examples/CMakeLists.txt index 70e74a9a8..cad01a7cc 100644 --- a/host/examples/CMakeLists.txt +++ b/host/examples/CMakeLists.txt @@ -31,10 +31,15 @@ TARGET_LINK_LIBRARIES(rx_to_file uhd) ADD_EXECUTABLE(tx_timed_samples tx_timed_samples.cpp) TARGET_LINK_LIBRARIES(tx_timed_samples uhd) +ADD_EXECUTABLE(tx_from_file tx_from_file.cpp) +TARGET_LINK_LIBRARIES(tx_from_file uhd) + INSTALL(TARGETS tx_continuous_samples benchmark_rx_rate rx_timed_samples tx_timed_samples + tx_from_file + rx_to_file RUNTIME DESTINATION ${PKG_DATA_DIR}/examples ) diff --git a/host/examples/tx_from_file.cpp b/host/examples/tx_from_file.cpp new file mode 100644 index 000000000..df6446c0c --- /dev/null +++ b/host/examples/tx_from_file.cpp @@ -0,0 +1,123 @@ +// +// Copyright 2010 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 . +// + +#include +#include +#include +#include +#include +#include +#include +#include + +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; + time_t seconds_in_future; + size_t total_num_samps; + size_t samps_per_packet; + double tx_rate, freq; + float ampl; + + //setup the program options + po::options_description desc("Allowed options"); + desc.add_options() + ("help", "help message") + ("args", po::value(&args)->default_value(""), "simple uhd device address args") + ("secs", po::value(&seconds_in_future)->default_value(3), "number of seconds in the future to transmit") + ("nsamps", po::value(&total_num_samps)->default_value(1000), "total number of samples to transmit") + ("txrate", po::value(&tx_rate)->default_value(100e6/16), "rate of outgoing samples") + ("freq", po::value(&freq)->default_value(0), "rf center frequency in Hz") + ("ampl", po::value(&l)->default_value(float(0.3)), "amplitude of each sample") + ("dilv", "specify to disable inner-loop verbose") + ; + 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 TX Timed Samples %s") % desc << std::endl; + return ~0; + } + + bool verbose = vm.count("dilv") == 0; + + //create a usrp device + std::cout << std::endl; + std::cout << boost::format("Creating the usrp device with: %s...") % args << std::endl; + uhd::usrp::simple_usrp::sptr sdev = uhd::usrp::simple_usrp::make(args); + uhd::device::sptr dev = sdev->get_device(); + std::cout << boost::format("Using Device: %s") % sdev->get_pp_string() << std::endl; + + //set properties on the device + std::cout << boost::format("Setting TX Rate: %f Msps...") % (tx_rate/1e6) << std::endl; + sdev->set_tx_rate(tx_rate); + std::cout << boost::format("Actual TX Rate: %f Msps...") % (sdev->get_tx_rate()/1e6) << std::endl; + std::cout << boost::format("Setting device timestamp to 0...") << std::endl; + sdev->set_tx_freq(freq); + sdev->set_time_now(uhd::time_spec_t(0.0)); + + sdev->set_tx_gain(0); + + //allocate data to send + std::vector > buff; + uhd::tx_metadata_t md; + + std::cout << "Read data to send from file: in.dat" << std::endl; + std::ifstream infile("in.dat", std::ifstream::binary); + while (!infile.eof()) { + std::complex c; + infile.read((char *)&c, sizeof(std::complex)); + if (!((c.real() == 0) && (c.imag() == 0))) { + buff.push_back(c); +//std::cout << "C = " << c << std::endl; + } + } + samps_per_packet = buff.size(); + infile.close(); + std::cout << "Number of samples in file: " << samps_per_packet << std::endl; + + //send the data in multiple packets + size_t num_packets = (total_num_samps+samps_per_packet-1)/samps_per_packet; + for (size_t i = 0; i < num_packets; i++){ + //setup the metadata flags and time spec + md.start_of_burst = true; //always SOB (good for continuous streaming) + md.end_of_burst = (i == num_packets-1); //only last packet has EOB + md.has_time_spec = (i == 0); //only first packet has time + md.time_spec = uhd::time_spec_t(seconds_in_future); + + size_t samps_to_send = std::min(total_num_samps - samps_per_packet*i, samps_per_packet); + + //send the entire packet (driver fragments internally) + size_t num_tx_samps = dev->send( + &buff.front(), samps_to_send, md, + uhd::io_type_t::COMPLEX_INT16, + uhd::device::SEND_MODE_FULL_BUFF + ); + if(verbose) std::cout << std::endl << boost::format("Sent %d samples") % num_tx_samps << std::endl; + } + + //finished + std::cout << std::endl << "Done!" << std::endl << std::endl; + + return 0; +} -- cgit v1.2.3 From 2ef82f57b815a9e53685617f1b779d4cbdf7fb31 Mon Sep 17 00:00:00 2001 From: Philip Balister Date: Thu, 19 Aug 2010 16:26:37 +0000 Subject: Add get setting to the rx_to_file program. --- host/examples/rx_to_file.cpp | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'host/examples') diff --git a/host/examples/rx_to_file.cpp b/host/examples/rx_to_file.cpp index cb8c42acc..79d3e9d8b 100644 --- a/host/examples/rx_to_file.cpp +++ b/host/examples/rx_to_file.cpp @@ -74,6 +74,10 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){ sdev->set_rx_freq(freq); sdev->set_time_now(uhd::time_spec_t(0.0)); + uhd::gain_range_t rx_gain = sdev->get_rx_gain_range(); + std::cout << "Setting RX Gain to: " << rx_gain.max << std::endl; + sdev->set_rx_gain(rx_gain.max); + sleep(1); std::cout << "LO Locked = " << sdev->get_rx_lo_locked() << std::endl; -- cgit v1.2.3 From f568f651c423fca8c9cf607655ea50ac4cfab524 Mon Sep 17 00:00:00 2001 From: Philip Balister Date: Thu, 19 Aug 2010 16:27:51 +0000 Subject: Add gain setting to tx_timed_samples program. --- host/examples/tx_timed_samples.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'host/examples') diff --git a/host/examples/tx_timed_samples.cpp b/host/examples/tx_timed_samples.cpp index aa22d3465..fa5bf4b2b 100644 --- a/host/examples/tx_timed_samples.cpp +++ b/host/examples/tx_timed_samples.cpp @@ -75,6 +75,7 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){ std::cout << boost::format("Setting device timestamp to 0...") << std::endl; sdev->set_tx_freq(freq); sdev->set_time_now(uhd::time_spec_t(0.0)); + sdev->set_tx_gain(0); //allocate data to send std::vector > buff(samps_per_packet, std::complex(ampl, ampl)); -- cgit v1.2.3 From 38722979512f0f6d57db9fd5e314b94cad1f188e Mon Sep 17 00:00:00 2001 From: Philip Balister Date: Thu, 19 Aug 2010 20:34:56 +0000 Subject: Add gain command line parameter. --- host/examples/tx_timed_samples.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'host/examples') diff --git a/host/examples/tx_timed_samples.cpp b/host/examples/tx_timed_samples.cpp index fa5bf4b2b..f7d7ea2ca 100644 --- a/host/examples/tx_timed_samples.cpp +++ b/host/examples/tx_timed_samples.cpp @@ -35,6 +35,7 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){ size_t samps_per_packet; double tx_rate, freq; float ampl; + float tx_gain; //setup the program options po::options_description desc("Allowed options"); @@ -47,6 +48,7 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){ ("txrate", po::value(&tx_rate)->default_value(100e6/16), "rate of outgoing samples") ("freq", po::value(&freq)->default_value(0), "rf center frequency in Hz") ("ampl", po::value(&l)->default_value(float(0.3)), "amplitude of each sample") + ("gain", po::value(&tx_gain)->default_value(float(0)), "TX Gain setting") ("dilv", "specify to disable inner-loop verbose") ; po::variables_map vm; @@ -75,7 +77,7 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){ std::cout << boost::format("Setting device timestamp to 0...") << std::endl; sdev->set_tx_freq(freq); sdev->set_time_now(uhd::time_spec_t(0.0)); - sdev->set_tx_gain(0); + sdev->set_tx_gain(tx_gain); //allocate data to send std::vector > buff(samps_per_packet, std::complex(ampl, ampl)); -- cgit v1.2.3 From d1a327862292d52d659b117aef28e37d9f60fb4b Mon Sep 17 00:00:00 2001 From: Philip Balister Date: Thu, 9 Sep 2010 19:30:02 -0400 Subject: Restore tx and rx timed smaple programs to the versions in master. They use floating point. --- host/examples/rx_timed_samples.cpp | 6 +++--- host/examples/tx_timed_samples.cpp | 9 +++------ 2 files changed, 6 insertions(+), 9 deletions(-) (limited to 'host/examples') diff --git a/host/examples/rx_timed_samples.cpp b/host/examples/rx_timed_samples.cpp index 5fbf8b6c5..4856f6779 100644 --- a/host/examples/rx_timed_samples.cpp +++ b/host/examples/rx_timed_samples.cpp @@ -85,12 +85,12 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){ //loop until total number of samples reached size_t num_acc_samps = 0; //number of accumulated samples - uhd::rx_metadata_t md; - std::vector > buff(dev->get_max_recv_samps_per_packet()); while(num_acc_samps < total_num_samps){ + uhd::rx_metadata_t md; + std::vector > buff(dev->get_max_recv_samps_per_packet()); size_t num_rx_samps = dev->recv( &buff.front(), buff.size(), md, - uhd::io_type_t::COMPLEX_INT16, + uhd::io_type_t::COMPLEX_FLOAT32, uhd::device::RECV_MODE_ONE_PACKET ); diff --git a/host/examples/tx_timed_samples.cpp b/host/examples/tx_timed_samples.cpp index f7d7ea2ca..5b72bd72f 100644 --- a/host/examples/tx_timed_samples.cpp +++ b/host/examples/tx_timed_samples.cpp @@ -35,7 +35,6 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){ size_t samps_per_packet; double tx_rate, freq; float ampl; - float tx_gain; //setup the program options po::options_description desc("Allowed options"); @@ -48,7 +47,6 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){ ("txrate", po::value(&tx_rate)->default_value(100e6/16), "rate of outgoing samples") ("freq", po::value(&freq)->default_value(0), "rf center frequency in Hz") ("ampl", po::value(&l)->default_value(float(0.3)), "amplitude of each sample") - ("gain", po::value(&tx_gain)->default_value(float(0)), "TX Gain setting") ("dilv", "specify to disable inner-loop verbose") ; po::variables_map vm; @@ -77,16 +75,15 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){ std::cout << boost::format("Setting device timestamp to 0...") << std::endl; sdev->set_tx_freq(freq); sdev->set_time_now(uhd::time_spec_t(0.0)); - sdev->set_tx_gain(tx_gain); //allocate data to send - std::vector > buff(samps_per_packet, std::complex(ampl, ampl)); - uhd::tx_metadata_t md; + std::vector > buff(samps_per_packet, std::complex(ampl, ampl)); //send the data in multiple packets size_t num_packets = (total_num_samps+samps_per_packet-1)/samps_per_packet; for (size_t i = 0; i < num_packets; i++){ //setup the metadata flags and time spec + uhd::tx_metadata_t md; md.start_of_burst = true; //always SOB (good for continuous streaming) md.end_of_burst = (i == num_packets-1); //only last packet has EOB md.has_time_spec = (i == 0); //only first packet has time @@ -97,7 +94,7 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){ //send the entire packet (driver fragments internally) size_t num_tx_samps = dev->send( &buff.front(), samps_to_send, md, - uhd::io_type_t::COMPLEX_INT16, + uhd::io_type_t::COMPLEX_FLOAT32, uhd::device::SEND_MODE_FULL_BUFF ); if(verbose) std::cout << std::endl << boost::format("Sent %d samples") % num_tx_samps << std::endl; -- cgit v1.2.3 From f9755b0ab33eb20abb5689893061f3b4039505fd Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Tue, 12 Oct 2010 10:55:07 -0700 Subject: uhd: test eob ack message, usrp2: remove rx drain on init with the promise of a reset register --- host/examples/test_async_messages.cpp | 32 ++++++++++++++++++++------------ host/lib/usrp/usrp2/io_impl.cpp | 2 -- host/lib/usrp/usrp2/mboard_impl.cpp | 5 ----- 3 files changed, 20 insertions(+), 19 deletions(-) (limited to 'host/examples') diff --git a/host/examples/test_async_messages.cpp b/host/examples/test_async_messages.cpp index e4a996ef5..fa39bcde6 100644 --- a/host/examples/test_async_messages.cpp +++ b/host/examples/test_async_messages.cpp @@ -27,13 +27,13 @@ namespace po = boost::program_options; /*! - * Test that no messages are received: + * Test the eob ack message: * Send a burst of many samples that will fragment internally. - * We expect to not get any async messages. + * We expect to get an eob ack async message. */ -void test_no_async_message(uhd::usrp::single_usrp::sptr sdev){ +void test_ack_async_message(uhd::usrp::single_usrp::sptr sdev){ uhd::device::sptr dev = sdev->get_device(); - std::cout << "Test no async message... " << std::flush; + std::cout << "Test eob ack message... " << std::flush; uhd::tx_metadata_t md; md.start_of_burst = true; @@ -50,19 +50,27 @@ void test_no_async_message(uhd::usrp::single_usrp::sptr sdev){ ); uhd::async_metadata_t async_md; - if (dev->recv_async_msg(async_md)){ + if (not dev->recv_async_msg(async_md)){ std::cout << boost::format( "failed:\n" - " Got unexpected event code 0x%x.\n" - ) % async_md.event_code << std::endl; - //clear the async messages - while (dev->recv_async_msg(async_md, 0)){}; + " Async message recv timed out.\n" + ) << std::endl; + return; } - else{ + + switch(async_md.event_code){ + case uhd::async_metadata_t::EVENT_CODE_EOB_ACK: std::cout << boost::format( "success:\n" - " Did not get an async message.\n" + " Got event code eob ack message.\n" ) << std::endl; + break; + + default: + std::cout << boost::format( + "failed:\n" + " Got unexpected event code 0x%x.\n" + ) % async_md.event_code << std::endl; } } @@ -195,7 +203,7 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){ //------------------------------------------------------------------ // begin asyc messages test //------------------------------------------------------------------ - test_no_async_message(sdev); + test_ack_async_message(sdev); test_underflow_message(sdev); test_time_error_message(sdev); diff --git a/host/lib/usrp/usrp2/io_impl.cpp b/host/lib/usrp/usrp2/io_impl.cpp index c9271cc8c..48ff7d509 100644 --- a/host/lib/usrp/usrp2/io_impl.cpp +++ b/host/lib/usrp/usrp2/io_impl.cpp @@ -249,8 +249,6 @@ void usrp2_impl::io_init(void){ }; std::memcpy(send_buff->cast(), &data, sizeof(data)); send_buff->commit(sizeof(data)); - //drain the recv buffers (may have junk) - while (data_transport->get_recv_buff(0).get()){}; } //the assumption is that all data transports should be identical diff --git a/host/lib/usrp/usrp2/mboard_impl.cpp b/host/lib/usrp/usrp2/mboard_impl.cpp index ddf147c8d..65066f125 100644 --- a/host/lib/usrp/usrp2/mboard_impl.cpp +++ b/host/lib/usrp/usrp2/mboard_impl.cpp @@ -70,11 +70,6 @@ usrp2_mboard_impl::usrp2_mboard_impl( _allowed_decim_and_interp_rates.push_back(i); } - //Issue a stop streaming command (in case it was left running). - //Since this command is issued before the networking is setup, - //most if not all junk packets will never make it to the socket. - this->issue_ddc_stream_cmd(stream_cmd_t::STREAM_MODE_STOP_CONTINUOUS); - //init the rx control registers _iface->poke32(U2_REG_RX_CTRL_NSAMPS_PER_PKT, _recv_samps_per_packet); _iface->poke32(U2_REG_RX_CTRL_NCHANNELS, 1); -- cgit v1.2.3 From 4dfb7b8cabef3097f822ac52f346cd6021cb35da Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Wed, 13 Oct 2010 11:59:35 -0700 Subject: usrp: test async messages app randomly runs tests --- host/examples/test_async_messages.cpp | 84 ++++++++++++++++++++++++++++------- 1 file changed, 67 insertions(+), 17 deletions(-) (limited to 'host/examples') diff --git a/host/examples/test_async_messages.cpp b/host/examples/test_async_messages.cpp index fa39bcde6..bdee7a504 100644 --- a/host/examples/test_async_messages.cpp +++ b/host/examples/test_async_messages.cpp @@ -19,8 +19,12 @@ #include #include #include +#include #include +#include +#include #include +#include #include #include @@ -31,7 +35,7 @@ namespace po = boost::program_options; * Send a burst of many samples that will fragment internally. * We expect to get an eob ack async message. */ -void test_ack_async_message(uhd::usrp::single_usrp::sptr sdev){ +bool test_eob_ack_message(uhd::usrp::single_usrp::sptr sdev){ uhd::device::sptr dev = sdev->get_device(); std::cout << "Test eob ack message... " << std::flush; @@ -55,7 +59,7 @@ void test_ack_async_message(uhd::usrp::single_usrp::sptr sdev){ "failed:\n" " Async message recv timed out.\n" ) << std::endl; - return; + return false; } switch(async_md.event_code){ @@ -64,13 +68,14 @@ void test_ack_async_message(uhd::usrp::single_usrp::sptr sdev){ "success:\n" " Got event code eob ack message.\n" ) << std::endl; - break; + return true; default: std::cout << boost::format( "failed:\n" " Got unexpected event code 0x%x.\n" ) % async_md.event_code << std::endl; + return false; } } @@ -79,7 +84,7 @@ void test_ack_async_message(uhd::usrp::single_usrp::sptr sdev){ * Send a start of burst packet with no following end of burst. * We expect to get an underflow(within a burst) async message. */ -void test_underflow_message(uhd::usrp::single_usrp::sptr sdev){ +bool test_underflow_message(uhd::usrp::single_usrp::sptr sdev){ uhd::device::sptr dev = sdev->get_device(); std::cout << "Test underflow message... " << std::flush; @@ -88,18 +93,21 @@ void test_underflow_message(uhd::usrp::single_usrp::sptr sdev){ md.end_of_burst = false; md.has_time_spec = false; - dev->send(NULL, 0, md, + std::vector > buff(1); //minimum 1 sample + + dev->send( + &buff.front(), buff.size(), md, uhd::io_type_t::COMPLEX_FLOAT32, uhd::device::SEND_MODE_FULL_BUFF ); uhd::async_metadata_t async_md; - if (not dev->recv_async_msg(async_md)){ + if (not dev->recv_async_msg(async_md, 1)){ std::cout << boost::format( "failed:\n" " Async message recv timed out.\n" ) << std::endl; - return; + return false; } switch(async_md.event_code){ @@ -108,13 +116,14 @@ void test_underflow_message(uhd::usrp::single_usrp::sptr sdev){ "success:\n" " Got event code underflow message.\n" ) << std::endl; - break; + return true; default: std::cout << boost::format( "failed:\n" " Got unexpected event code 0x%x.\n" ) % async_md.event_code << std::endl; + return false; } } @@ -123,7 +132,7 @@ void test_underflow_message(uhd::usrp::single_usrp::sptr sdev){ * Send a burst packet that occurs at a time in the past. * We expect to get a time error async message. */ -void test_time_error_message(uhd::usrp::single_usrp::sptr sdev){ +bool test_time_error_message(uhd::usrp::single_usrp::sptr sdev){ uhd::device::sptr dev = sdev->get_device(); std::cout << "Test time error message... " << std::flush; @@ -135,7 +144,10 @@ void test_time_error_message(uhd::usrp::single_usrp::sptr sdev){ sdev->set_time_now(uhd::time_spec_t(200.0)); //time at 200s - dev->send(NULL, 0, md, + std::vector > buff(1); //minimum 1 sample + + dev->send( + &buff.front(), buff.size(), md, uhd::io_type_t::COMPLEX_FLOAT32, uhd::device::SEND_MODE_FULL_BUFF ); @@ -146,7 +158,7 @@ void test_time_error_message(uhd::usrp::single_usrp::sptr sdev){ "failed:\n" " Async message recv timed out.\n" ) << std::endl; - return; + return false; } switch(async_md.event_code){ @@ -155,29 +167,38 @@ void test_time_error_message(uhd::usrp::single_usrp::sptr sdev){ "success:\n" " Got event code time error message.\n" ) << std::endl; - break; + return true; default: std::cout << boost::format( "failed:\n" " Got unexpected event code 0x%x.\n" ) % async_md.event_code << std::endl; + return false; } } +void flush_async_md(uhd::usrp::single_usrp::sptr sdev){ + uhd::device::sptr dev = sdev->get_device(); + uhd::async_metadata_t async_md; + while (dev->recv_async_msg(async_md, 1.0)){} +} + int UHD_SAFE_MAIN(int argc, char *argv[]){ uhd::set_thread_priority_safe(); //variables to be set by po std::string args; double rate; + size_t ntests; //setup the program options po::options_description desc("Allowed options"); desc.add_options() ("help", "help message") - ("args", po::value(&args)->default_value(""), "single uhd device address args") - ("rate", po::value(&rate)->default_value(1.5e6), "rate of outgoing samples") + ("args", po::value(&args)->default_value(""), "single uhd device address args") + ("rate", po::value(&rate)->default_value(1.5e6), "rate of outgoing samples") + ("ntests", po::value(&ntests)->default_value(10), "number of tests to run") ; po::variables_map vm; po::store(po::parse_command_line(argc, argv, desc), vm); @@ -203,9 +224,38 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){ //------------------------------------------------------------------ // begin asyc messages test //------------------------------------------------------------------ - test_ack_async_message(sdev); - test_underflow_message(sdev); - test_time_error_message(sdev); + static const uhd::dict > + tests = boost::assign::map_list_of + ("Test EOB ACK ", &test_eob_ack_message) + ("Test Underflow ", &test_underflow_message) + ("Test Time Error", &test_time_error_message) + ; + + //init result counts + uhd::dict failures, successes; + BOOST_FOREACH(const std::string &key, tests.keys()){ + failures[key] = 0; + successes[key] = 0; + } + + //run the tests, pick at random + for (size_t n = 0; n < ntests; n++){ + std::string key = tests.keys()[std::rand() % tests.size()]; + bool pass = tests[key](sdev); + flush_async_md(sdev); + + //store result + if (pass) successes[key]++; + else failures[key]++; + } + + //print the result summary + std::cout << std::endl << "Summary:" << std::endl << std::endl; + BOOST_FOREACH(const std::string &key, tests.keys()){ + std::cout << boost::format( + "%s -> %3d successes, %3d failures" + ) % key % successes[key] % failures[key] << std::endl; + } //finished std::cout << std::endl << "Done!" << std::endl << std::endl; -- cgit v1.2.3 From 71e1763332141603e9edba097fd19b00e9a76ab8 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Thu, 14 Oct 2010 16:51:47 -0700 Subject: uhd: removed 1 sample buffers in test async messages made a hack in the vrt handler to bump 0 sample requests up to 1 sample (until the hardware supports it) --- host/examples/test_async_messages.cpp | 8 ++------ host/lib/transport/vrt_packet_handler.hpp | 13 +++++++++++-- 2 files changed, 13 insertions(+), 8 deletions(-) (limited to 'host/examples') diff --git a/host/examples/test_async_messages.cpp b/host/examples/test_async_messages.cpp index bdee7a504..61db7ec04 100644 --- a/host/examples/test_async_messages.cpp +++ b/host/examples/test_async_messages.cpp @@ -93,10 +93,8 @@ bool test_underflow_message(uhd::usrp::single_usrp::sptr sdev){ md.end_of_burst = false; md.has_time_spec = false; - std::vector > buff(1); //minimum 1 sample - dev->send( - &buff.front(), buff.size(), md, + NULL, 0, md, uhd::io_type_t::COMPLEX_FLOAT32, uhd::device::SEND_MODE_FULL_BUFF ); @@ -144,10 +142,8 @@ bool test_time_error_message(uhd::usrp::single_usrp::sptr sdev){ sdev->set_time_now(uhd::time_spec_t(200.0)); //time at 200s - std::vector > buff(1); //minimum 1 sample - dev->send( - &buff.front(), buff.size(), md, + NULL, 0, md, uhd::io_type_t::COMPLEX_FLOAT32, uhd::device::SEND_MODE_FULL_BUFF ); diff --git a/host/lib/transport/vrt_packet_handler.hpp b/host/lib/transport/vrt_packet_handler.hpp index d5f03de0e..278bcfeaa 100644 --- a/host/lib/transport/vrt_packet_handler.hpp +++ b/host/lib/transport/vrt_packet_handler.hpp @@ -388,10 +388,19 @@ template UHD_INLINE T get_context_code( if_packet_info.sob = metadata.start_of_burst; if_packet_info.eob = metadata.end_of_burst; + //TODO remove this code when sample counts of zero are supported by hardware + std::vector buffs_(buffs); + size_t total_num_samps_(total_num_samps); + if (total_num_samps == 0){ + static const boost::uint64_t zeros = 0; //max size of a host sample + buffs_ = std::vector(buffs.size(), &zeros); + total_num_samps_ = 1; + } + return _send1( state, - buffs, 0, - std::min(total_num_samps, max_samples_per_packet), + buffs_, 0, + std::min(total_num_samps_, max_samples_per_packet), if_packet_info, io_type, otw_type, vrt_packer, -- cgit v1.2.3 From 3dc06cddaf0a0cf32f76be7077d1427ff4b71a7e Mon Sep 17 00:00:00 2001 From: Philip Balister Date: Thu, 14 Oct 2010 14:47:34 -0400 Subject: usrp-e: Add example that reads data from uhd and sends it over a udp socket. --- host/examples/CMakeLists.txt | 4 ++ host/examples/rx_to_udp.cpp | 167 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 171 insertions(+) create mode 100644 host/examples/rx_to_udp.cpp (limited to 'host/examples') diff --git a/host/examples/CMakeLists.txt b/host/examples/CMakeLists.txt index fb7777d42..3b36f3e71 100644 --- a/host/examples/CMakeLists.txt +++ b/host/examples/CMakeLists.txt @@ -25,6 +25,9 @@ TARGET_LINK_LIBRARIES(rx_timed_samples uhd) ADD_EXECUTABLE(rx_to_file rx_to_file.cpp) TARGET_LINK_LIBRARIES(rx_to_file uhd) +ADD_EXECUTABLE(rx_to_udp rx_to_udp.cpp) +TARGET_LINK_LIBRARIES(rx_to_udp uhd) + ADD_EXECUTABLE(test_async_messages test_async_messages.cpp) TARGET_LINK_LIBRARIES(test_async_messages uhd) @@ -48,6 +51,7 @@ INSTALL(TARGETS tx_timed_samples tx_from_file rx_to_file + rx_to_udp tx_waveforms RUNTIME DESTINATION ${PKG_DATA_DIR}/examples ) diff --git a/host/examples/rx_to_udp.cpp b/host/examples/rx_to_udp.cpp new file mode 100644 index 000000000..34b278599 --- /dev/null +++ b/host/examples/rx_to_udp.cpp @@ -0,0 +1,167 @@ +// +// Copyright 2010 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 . +// + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "sys/types.h" +#include "sys/socket.h" +#include "arpa/inet.h" + +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; + time_t seconds_in_future; + size_t total_num_samps; + double rx_rate, freq; + short srv_port; + std::string srv_ip; + + //setup the program options + po::options_description desc("Allowed options"); + desc.add_options() + ("help", "help message") + ("args", po::value(&args)->default_value(""), "simple uhd device address args") + ("secs", po::value(&seconds_in_future)->default_value(3), "number of seconds in the future to receive") + ("nsamps", po::value(&total_num_samps)->default_value(1000), "total number of samples to receive") + ("rxrate", po::value(&rx_rate)->default_value(100e6/16), "rate of incoming samples") + ("freq", po::value(&freq)->default_value(0), "rf center frequency in Hz") + ("port", po::value(&srv_port)->default_value(7124), "server port") + ("ip", po::value(&srv_ip)->default_value("192.168.1.10"), "server ip") + ("dilv", "specify to disable inner-loop verbose") + ; + 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 Timed Samples %s") % desc << std::endl; + return ~0; + } + + bool verbose = vm.count("dilv") == 0; + + //create a usrp device + std::cout << std::endl; + std::cout << boost::format("Creating the usrp device with: %s...") % args << std::endl; + uhd::usrp::simple_usrp::sptr sdev = uhd::usrp::simple_usrp::make(args); + uhd::device::sptr dev = sdev->get_device(); + std::cout << boost::format("Using Device: %s") % sdev->get_pp_string() << std::endl; + + //set properties on the device + std::cout << boost::format("Setting RX Rate: %f Msps...") % (rx_rate/1e6) << std::endl; + sdev->set_rx_rate(rx_rate); + std::cout << boost::format("Actual RX Rate: %f Msps...") % (sdev->get_rx_rate()/1e6) << std::endl; + std::cout << boost::format("Setting device timestamp to 0...") << std::endl; + sdev->set_rx_freq(freq); + sdev->set_time_now(uhd::time_spec_t(0.0)); + + uhd::gain_range_t rx_gain = sdev->get_rx_gain_range(); + std::cout << "Setting RX Gain to: " << rx_gain.max << std::endl; + sdev->set_rx_gain(rx_gain.max); + + sleep(1); + std::cout << "LO Locked = " << sdev->get_rx_lo_locked() << std::endl; + + //setup streaming + std::cout << std::endl; + std::cout << boost::format( + "Begin streaming %u samples, %d seconds in the future..." + ) % total_num_samps % seconds_in_future << std::endl; + uhd::stream_cmd_t stream_cmd(uhd::stream_cmd_t::STREAM_MODE_NUM_SAMPS_AND_DONE); + stream_cmd.num_samps = total_num_samps; + stream_cmd.stream_now = false; + stream_cmd.time_spec = uhd::time_spec_t(seconds_in_future); + sdev->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 > buff(368); + std::ofstream outfile("out.dat", std::ofstream::binary); + + int s; + struct sockaddr_in si_other; + if ((s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1) { + std::cout << "Failid to open socket." << std::endl; + return -1; + } + + memset((char *) &si_other, 0, sizeof(si_other)); + si_other.sin_family = AF_INET; + si_other.sin_port = htons(srv_port); + if (inet_aton(srv_ip.c_str(), &si_other.sin_addr) == 0) { + std::cout << "Bad inet addr: " << srv_ip << std::endl; + return -1; + } + + while(num_acc_samps < total_num_samps){ + size_t num_rx_samps = dev->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; + } + +// outfile.write((const char*)&buff[0], num_rx_samps * sizeof(std::complex)); + if (sendto(s, (const char *)&buff[0], num_rx_samps * sizeof(std::complex), 0 , (const sockaddr *)&si_other, sizeof(si_other)) == -1) + std::cout << "Sendto failed." << std::endl; + + if(verbose) std::cout << boost::format( + "Got packet: %u samples, %u full secs, %f frac secs" + ) % num_rx_samps % md.time_spec.get_full_secs() % md.time_spec.get_frac_secs() << std::endl; + + num_acc_samps += num_rx_samps; + } done_loop: + + outfile.close(); + + //finished + std::cout << std::endl << "Done!" << std::endl << std::endl; + + return 0; +} -- cgit v1.2.3 From fa7704be20005a705efdc96aa785d80911638107 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Wed, 27 Oct 2010 13:10:48 -0700 Subject: usrp-e: implemented fpga loading and compat checking --- host/examples/rx_to_file.cpp | 8 ++-- host/examples/rx_to_udp.cpp | 8 ++-- host/lib/usrp/usrp_e/fpga-downloader.cc | 30 ++++++++------ host/lib/usrp/usrp_e/usrp_e_impl.cpp | 69 ++++++++++++++++++++++++++++++--- host/lib/usrp/usrp_e/usrp_e_impl.hpp | 4 +- host/lib/usrp/usrp_e/usrp_e_regs.hpp | 2 +- 6 files changed, 94 insertions(+), 27 deletions(-) (limited to 'host/examples') diff --git a/host/examples/rx_to_file.cpp b/host/examples/rx_to_file.cpp index 79d3e9d8b..f08f7cee3 100644 --- a/host/examples/rx_to_file.cpp +++ b/host/examples/rx_to_file.cpp @@ -17,7 +17,7 @@ #include #include -#include +#include #include #include #include @@ -40,7 +40,7 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){ po::options_description desc("Allowed options"); desc.add_options() ("help", "help message") - ("args", po::value(&args)->default_value(""), "simple uhd device address args") + ("args", po::value(&args)->default_value(""), "single uhd device address args") ("secs", po::value(&seconds_in_future)->default_value(3), "number of seconds in the future to receive") ("nsamps", po::value(&total_num_samps)->default_value(1000), "total number of samples to receive") ("rxrate", po::value(&rx_rate)->default_value(100e6/16), "rate of incoming samples") @@ -53,7 +53,7 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){ //print the help message if (vm.count("help")){ - std::cout << boost::format("UHD RX Timed Samples %s") % desc << std::endl; + std::cout << boost::format("UHD RX to File %s") % desc << std::endl; return ~0; } @@ -62,7 +62,7 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){ //create a usrp device std::cout << std::endl; std::cout << boost::format("Creating the usrp device with: %s...") % args << std::endl; - uhd::usrp::simple_usrp::sptr sdev = uhd::usrp::simple_usrp::make(args); + uhd::usrp::single_usrp::sptr sdev = uhd::usrp::single_usrp::make(args); uhd::device::sptr dev = sdev->get_device(); std::cout << boost::format("Using Device: %s") % sdev->get_pp_string() << std::endl; diff --git a/host/examples/rx_to_udp.cpp b/host/examples/rx_to_udp.cpp index 34b278599..c8b3d506b 100644 --- a/host/examples/rx_to_udp.cpp +++ b/host/examples/rx_to_udp.cpp @@ -17,7 +17,7 @@ #include #include -#include +#include #include #include #include @@ -46,7 +46,7 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){ po::options_description desc("Allowed options"); desc.add_options() ("help", "help message") - ("args", po::value(&args)->default_value(""), "simple uhd device address args") + ("args", po::value(&args)->default_value(""), "single uhd device address args") ("secs", po::value(&seconds_in_future)->default_value(3), "number of seconds in the future to receive") ("nsamps", po::value(&total_num_samps)->default_value(1000), "total number of samples to receive") ("rxrate", po::value(&rx_rate)->default_value(100e6/16), "rate of incoming samples") @@ -61,7 +61,7 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){ //print the help message if (vm.count("help")){ - std::cout << boost::format("UHD RX Timed Samples %s") % desc << std::endl; + std::cout << boost::format("UHD RX to UDP %s") % desc << std::endl; return ~0; } @@ -70,7 +70,7 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){ //create a usrp device std::cout << std::endl; std::cout << boost::format("Creating the usrp device with: %s...") % args << std::endl; - uhd::usrp::simple_usrp::sptr sdev = uhd::usrp::simple_usrp::make(args); + uhd::usrp::single_usrp::sptr sdev = uhd::usrp::single_usrp::make(args); uhd::device::sptr dev = sdev->get_device(); std::cout << boost::format("Using Device: %s") % sdev->get_pp_string() << std::endl; diff --git a/host/lib/usrp/usrp_e/fpga-downloader.cc b/host/lib/usrp/usrp_e/fpga-downloader.cc index ff8671e98..b0d56e856 100644 --- a/host/lib/usrp/usrp_e/fpga-downloader.cc +++ b/host/lib/usrp/usrp_e/fpga-downloader.cc @@ -15,11 +15,14 @@ // along with this program. If not, see . // +#include + #include #include #include #include #include +#include #include #include @@ -82,8 +85,9 @@ gpio::gpio(unsigned int gpio_num, gpio_direction pin_direction) std::fstream export_file; export_file.open("/sys/class/gpio/export", std::ios::out); - if (!export_file.is_open()) ///\todo Poor error handling - std::cout << "Failed to open gpio export file." << std::endl; + if (not export_file.is_open()) throw std::runtime_error( + "Failed to open gpio export file." + ); export_file << gpio_num << std::endl; @@ -92,15 +96,17 @@ gpio::gpio(unsigned int gpio_num, gpio_direction pin_direction) std::fstream direction_file; std::string direction_file_name; - direction_file_name = base_path.str() + "/direction"; + if (gpio_num != 114) { + direction_file_name = base_path.str() + "/direction"; - direction_file.open(direction_file_name.c_str()); - if (!direction_file.is_open()) - std::cout << "Failed to open direction file." << std::endl; - if (pin_direction == OUT) - direction_file << "out" << std::endl; - else - direction_file << "in" << std::endl; + direction_file.open(direction_file_name.c_str()); + if (!direction_file.is_open()) + std::cout << "Failed to open direction file." << std::endl; + if (pin_direction == OUT) + direction_file << "out" << std::endl; + else + direction_file << "in" << std::endl; + } std::string value_file_name; @@ -251,11 +257,11 @@ void usrp_e_load_fpga(const std::string &bin_file){ gpio gpio_init_b(INIT_B, IN); gpio gpio_done (DONE, IN); - std::cout << "FPGA config file: " << bin_file << std::endl; + std::cout << "Loading FPGA image: " << bin_file << "... " << std::flush; prepare_fpga_for_configuration(gpio_prog_b, gpio_init_b); - std::cout << "Done = " << gpio_done.get_value() << std::endl; + std::cout << "done = " << gpio_done.get_value() << std::endl; send_file_to_fpga(bin_file, gpio_init_b, gpio_done); } diff --git a/host/lib/usrp/usrp_e/usrp_e_impl.cpp b/host/lib/usrp/usrp_e/usrp_e_impl.cpp index 5c0e1dbb0..0a7295ff9 100644 --- a/host/lib/usrp/usrp_e/usrp_e_impl.cpp +++ b/host/lib/usrp/usrp_e/usrp_e_impl.cpp @@ -16,13 +16,17 @@ // #include "usrp_e_impl.hpp" +#include "usrp_e_regs.hpp" #include #include #include #include +#include #include #include +#include #include +#include using namespace uhd; using namespace uhd::usrp; @@ -66,7 +70,64 @@ static device_addrs_t usrp_e_find(const device_addr_t &hint){ * Make **********************************************************************/ static device::sptr usrp_e_make(const device_addr_t &device_addr){ - return device::sptr(new usrp_e_impl(device_addr["node"])); + + //The fpga is loaded when: + // 1) The compatibility number matches. + // 2) The hash in the hash-file matches. + + //setup the main interface into fpga + std::string node = device_addr["node"]; + std::cout << boost::format("Opening USRP-E on %s") % node << std::endl; + usrp_e_iface::sptr iface = usrp_e_iface::make(node); + + //------------------------------------------------------------------ + //-- Handle the FPGA loading... + //-- The image can be confimed as already loaded when: + //-- 1) The compatibility number matches. + //-- 2) The hash in the hash-file matches. + //------------------------------------------------------------------ + + //extract the fpga path for usrp-e + std::string usrp_e_fpga_image = find_image_path( + device_addr.has_key("fpga")? device_addr["fpga"] : "usrp_e100_fpga.bin" + ); + + //calculate a hash of the fpga file + size_t fpga_hash = 0; + { + std::ifstream file(usrp_e_fpga_image.c_str()); + if (not file.good()) throw std::runtime_error( + "cannot open fpga file for read: " + usrp_e_fpga_image + ); + do{ + boost::hash_combine(fpga_hash, file.get()); + } while (file.good()); + file.close(); + } + + //read the compatibility number + boost::uint16_t fpga_compat_num = iface->peek16(UE_REG_MISC_COMPAT); + + //read the hash in the hash-file + size_t loaded_hash = 0; + try{std::ifstream(hash_file_path) >> loaded_hash;}catch(...){} + + //if not loaded: load the fpga image and write the hash-file + if (fpga_compat_num != USRP_E_COMPAT_NUM or loaded_hash != fpga_hash){ + usrp_e_load_fpga(usrp_e_fpga_image); + try{std::ofstream(hash_file_path) << fpga_hash;}catch(...){} + } + + //check that the compatibility is correct + fpga_compat_num = iface->peek16(UE_REG_MISC_COMPAT); + if (fpga_compat_num != USRP_E_COMPAT_NUM){ + throw std::runtime_error(str(boost::format( + "Expected fpga compatibility number 0x%x, but got 0x%x:\n" + "The fpga build is not compatible with the host code build." + ) % USRP_E_COMPAT_NUM % fpga_compat_num)); + } + + return device::sptr(new usrp_e_impl(iface)); } UHD_STATIC_BLOCK(register_usrp_e_device){ @@ -76,11 +137,9 @@ UHD_STATIC_BLOCK(register_usrp_e_device){ /*********************************************************************** * Structors **********************************************************************/ -usrp_e_impl::usrp_e_impl(const std::string &node){ - std::cout << boost::format("Opening USRP-E on %s") % node << std::endl; +usrp_e_impl::usrp_e_impl(usrp_e_iface::sptr iface): _iface(iface){ - //setup various interfaces into hardware - _iface = usrp_e_iface::make(node); + //setup interfaces into hardware _clock_ctrl = usrp_e_clock_ctrl::make(_iface); _codec_ctrl = usrp_e_codec_ctrl::make(_iface); diff --git a/host/lib/usrp/usrp_e/usrp_e_impl.hpp b/host/lib/usrp/usrp_e/usrp_e_impl.hpp index 9799cd645..421a9623d 100644 --- a/host/lib/usrp/usrp_e/usrp_e_impl.hpp +++ b/host/lib/usrp/usrp_e/usrp_e_impl.hpp @@ -31,6 +31,8 @@ #define INCLUDED_USRP_E_IMPL_HPP static const double MASTER_CLOCK_RATE = 64e6; //TODO get from clock control +static const char *hash_file_path = "/tmp/usrp_e100_hash"; +static const boost::uint16_t USRP_E_COMPAT_NUM = 0x02; //! load an fpga image from a bin file into the usrp-e fpga extern void usrp_e_load_fpga(const std::string &bin_file); @@ -79,7 +81,7 @@ private: class usrp_e_impl : public uhd::device{ public: //structors - usrp_e_impl(const std::string &node); + usrp_e_impl(usrp_e_iface::sptr); ~usrp_e_impl(void); //the io interface diff --git a/host/lib/usrp/usrp_e/usrp_e_regs.hpp b/host/lib/usrp/usrp_e/usrp_e_regs.hpp index a4f42093e..f74358f00 100644 --- a/host/lib/usrp/usrp_e/usrp_e_regs.hpp +++ b/host/lib/usrp/usrp_e/usrp_e_regs.hpp @@ -30,7 +30,7 @@ #define UE_REG_MISC_CGEN_ST UE_REG_MISC_BASE + 6 #define UE_REG_MISC_TEST UE_REG_MISC_BASE + 8 #define UE_REG_MISC_RX_LEN UE_REG_MISC_BASE + 10 -#define UE_REG_MISC_TX_LEN UE_REG_MISC_BASE + 12 +#define UE_REG_MISC_COMPAT UE_REG_MISC_BASE + 12 ///////////////////////////////////////////////////// // Slave 1 -- UART -- cgit v1.2.3