aboutsummaryrefslogtreecommitdiffstats
path: root/host
diff options
context:
space:
mode:
authorJosh Blum <josh@joshknows.com>2010-10-28 18:23:27 -0700
committerJosh Blum <josh@joshknows.com>2010-10-28 18:23:27 -0700
commita8d2c2944b329218af1c0b171b92f775b679b409 (patch)
tree02e558d525055cb82e8d00a7a2d75fe324015ae6 /host
parentef8ed898cbc6cb6cd1994d2a8b090112f4f3a664 (diff)
parent6a3e499f586513d48ef648aa910e252b7d8b046b (diff)
downloaduhd-a8d2c2944b329218af1c0b171b92f775b679b409.tar.gz
uhd-a8d2c2944b329218af1c0b171b92f775b679b409.tar.bz2
uhd-a8d2c2944b329218af1c0b171b92f775b679b409.zip
Merge branch 'next'
Diffstat (limited to 'host')
-rw-r--r--host/config/Python.cmake25
-rw-r--r--host/docs/dboards.rst36
-rw-r--r--host/docs/usrp2.rst2
-rw-r--r--host/examples/CMakeLists.txt45
-rw-r--r--host/examples/rx_samples_to_file.cpp135
-rw-r--r--host/examples/rx_samples_to_udp.cpp135
-rw-r--r--host/examples/rx_timed_samples.cpp19
-rw-r--r--host/examples/tx_timed_samples.cpp19
-rw-r--r--host/include/uhd/types/CMakeLists.txt2
-rw-r--r--host/include/uhd/types/dict.hpp78
-rw-r--r--host/include/uhd/types/dict.ipp120
-rw-r--r--host/include/uhd/types/metadata.hpp76
-rw-r--r--host/include/uhd/types/tune_request.hpp95
-rw-r--r--host/include/uhd/usrp/mimo_usrp.hpp20
-rw-r--r--host/include/uhd/usrp/multi_usrp.hpp39
-rw-r--r--host/include/uhd/usrp/simple_usrp.hpp18
-rw-r--r--host/include/uhd/usrp/single_usrp.hpp31
-rw-r--r--host/include/uhd/usrp/subdev_spec.hpp11
-rw-r--r--host/include/uhd/usrp/tune_helper.hpp31
-rw-r--r--host/include/uhd/utils/warning.hpp36
-rw-r--r--host/lib/CMakeLists.txt19
-rw-r--r--host/lib/transport/udp_zero_copy_asio.cpp2
-rw-r--r--host/lib/types.cpp21
-rw-r--r--host/lib/usrp/dboard/db_basic_and_lf.cpp39
-rw-r--r--host/lib/usrp/dboard/db_dbsrx.cpp12
-rw-r--r--host/lib/usrp/dboard/db_rfx.cpp21
-rw-r--r--host/lib/usrp/dboard/db_tvrx.cpp10
-rw-r--r--host/lib/usrp/dboard/db_unknown.cpp23
-rw-r--r--host/lib/usrp/dboard/db_wbx.cpp21
-rw-r--r--host/lib/usrp/dboard/db_xcvr2450.cpp8
-rw-r--r--host/lib/usrp/dboard_manager.cpp4
-rw-r--r--host/lib/usrp/multi_usrp.cpp35
-rw-r--r--host/lib/usrp/single_usrp.cpp24
-rw-r--r--host/lib/usrp/tune_helper.cpp141
-rw-r--r--host/lib/usrp/usrp1/mboard_impl.cpp2
-rw-r--r--host/lib/usrp/usrp1/usrp1_impl.cpp2
-rw-r--r--host/lib/usrp/wrapper_utils.hpp4
-rw-r--r--host/lib/utils/thread_priority.cpp2
-rw-r--r--host/lib/utils/warning.cpp59
-rw-r--r--host/test/tune_helper_test.cpp79
-rw-r--r--host/test/warning_test.cpp4
41 files changed, 1115 insertions, 390 deletions
diff --git a/host/config/Python.cmake b/host/config/Python.cmake
index 55ef6acca..a5080fc40 100644
--- a/host/config/Python.cmake
+++ b/host/config/Python.cmake
@@ -24,26 +24,23 @@ IF(NOT PYTHONINTERP_FOUND)
MESSAGE(FATAL_ERROR "Error: Python interpretor required by the build system.")
ENDIF(NOT PYTHONINTERP_FOUND)
-MACRO(PYTHON_CHECK_MODULE module have)
- MESSAGE(STATUS "Checking for python module ${module}")
+MACRO(PYTHON_CHECK_MODULE desc mod cmd have)
+ MESSAGE(STATUS "Python checking for ${desc}")
EXECUTE_PROCESS(
- COMMAND ${PYTHON_EXECUTABLE} -c "import ${module}"
+ COMMAND ${PYTHON_EXECUTABLE} -c "
+#########################################
+try: import ${mod}
+except: exit(-1)
+try: assert ${cmd}
+except: exit(-1)
+#########################################"
RESULT_VARIABLE ${have}
)
IF(${have} EQUAL 0)
- MESSAGE(STATUS "Checking for python module ${module} - found")
+ MESSAGE(STATUS "Python checking for ${desc} - found")
SET(${have} TRUE)
ELSE(${have} EQUAL 0)
- MESSAGE(STATUS "Checking for python module ${module} - not found")
+ MESSAGE(STATUS "Python checking for ${desc} - not found")
SET(${have} FALSE)
ENDIF(${have} EQUAL 0)
ENDMACRO(PYTHON_CHECK_MODULE)
-
-########################################################################
-# Check Modules
-########################################################################
-PYTHON_CHECK_MODULE("Cheetah" HAVE_PYTHON_MODULE_CHEETAH)
-
-IF(NOT HAVE_PYTHON_MODULE_CHEETAH)
- MESSAGE(FATAL_ERROR "Error: Cheetah Templates required by the build system.")
-ENDIF(NOT HAVE_PYTHON_MODULE_CHEETAH)
diff --git a/host/docs/dboards.rst b/host/docs/dboards.rst
index 080117651..b39c587f6 100644
--- a/host/docs/dboards.rst
+++ b/host/docs/dboards.rst
@@ -26,6 +26,14 @@ The boards have no tunable elements or programmable gains.
Though the magic of aliasing, you can down-convert signals
greater than the Nyquist rate of the ADC.
+BasicRX Bandwidth (Hz):
+ For Real-Mode (A or B subdevice): 250M
+ For Complex (AB or BA subdevice): 500M
+
+LFRX Bandwidth (Hz):
+ For Real-Mode (A or B subdevice): 33M
+ For Complex (AB or BA subdevice): 66M
+
^^^^^^^^^^^^^^^^^^^^^^^^^^^
Basic TX and and LFTX
^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -40,6 +48,14 @@ The boards have no tunable elements or programmable gains.
Though the magic of aliasing, you can up-convert signals
greater than the Nyquist rate of the DAC.
+BasicTX Bandwidth (Hz): 250M
+ For Real-Mode (A or B subdevice): 250M
+ For Complex (AB or BA subdevice): 500M
+
+LFTX Bandwidth (Hz): 33M
+ For Real-Mode (A or B subdevice): 33M
+ For Complex (AB or BA subdevice): 66M
+
^^^^^^^^^^^^^^^^^^^^^^^^^^^
DBSRX
^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -53,7 +69,7 @@ Receive Gains:
**GC1**, Range: 0-56dB
**GC2**, Range: 0-24dB
-Low-Pass Filter Bandwidth (Hz): 4M-33M
+Bandwidth (Hz): 8M-66M
^^^^^^^^^^^^^^^^^^^^^^^^^^^
RFX Series
@@ -68,6 +84,10 @@ the receive antenna will always be set to RX2, regardless of the settings.
Receive Gains: **PGA0**, Range: 0-70dB (except RFX400 range is 0-45dB)
+Bandwidths (Hz):
+ * **RX**: 40M
+ * **TX**: 40M
+
^^^^^^^^^^^^^^^^^^^^^^^^^^^
XCVR 2450
^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -93,9 +113,9 @@ Receive Gains:
* **LNA**, Range: 0-30.5dB
* **VGA**, Range: 0-62dB
-Low-Pass Filter Bandwidths (Hz):
- * **RX**: 7.5M, 9.5M, 14M, 18M; (each +-0, 5, or 10%)
- * **TX**: 12M, 18M, 24M
+Bandwidths (Hz):
+ * **RX**: 15M, 19M, 28M, 36M; (each +-0, 5, or 10%)
+ * **TX**: 24M, 36M, 48M
^^^^^^^^^^^^^^^^^^^^^^^^^^^
WBX Series
@@ -112,9 +132,9 @@ Transmit Gains: **PGA0**, Range: 0-25dB
Receive Gains: **PGA0**, Range: 0-31.5dB
-Low-Pass Filter Bandwidths (Hz):
- * **RX**: 20M (Fixed)
- * **TX**: 20M (Fixed)
+Bandwidths (Hz):
+ * **RX**: 40M
+ * **TX**: 40M
^^^^^^^^^^^^^^^^^^^^^^^^^^^
TVRX
@@ -125,7 +145,7 @@ Receive Gains:
* **RF**, Range: -13.3-50.3dB (frequency-dependent)
* **IF**, Range: -1.5-32.5dB
-Bandpass Filter Bandwidth: 6MHz
+Bandwidth: 6MHz
------------------------------------------------------------------------
Daughterboard Modifications
diff --git a/host/docs/usrp2.rst b/host/docs/usrp2.rst
index 0ddcaa4e5..ada98000d 100644
--- a/host/docs/usrp2.rst
+++ b/host/docs/usrp2.rst
@@ -179,7 +179,7 @@ The LEDs reveal the following about the state of the device:
* **LED B:** undocumented
* **LED C:** receiving
* **LED D:** firmware loaded
-* **LED E:** undocumented
+* **LED E:** reference lock
* **LED F:** FPGA loaded
diff --git a/host/examples/CMakeLists.txt b/host/examples/CMakeLists.txt
index a8873f8d3..ce2ca9640 100644
--- a/host/examples/CMakeLists.txt
+++ b/host/examples/CMakeLists.txt
@@ -16,34 +16,27 @@
#
########################################################################
-ADD_EXECUTABLE(benchmark_rx_rate benchmark_rx_rate.cpp)
-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(test_async_messages test_async_messages.cpp)
-TARGET_LINK_LIBRARIES(test_async_messages uhd)
-
-ADD_EXECUTABLE(test_pps_input test_pps_input.cpp)
-TARGET_LINK_LIBRARIES(test_pps_input uhd)
-
-ADD_EXECUTABLE(tx_timed_samples tx_timed_samples.cpp)
-TARGET_LINK_LIBRARIES(tx_timed_samples uhd)
-
-ADD_EXECUTABLE(tx_waveforms tx_waveforms.cpp)
-TARGET_LINK_LIBRARIES(tx_waveforms uhd)
-
-INSTALL(TARGETS
- benchmark_rx_rate
- rx_timed_samples
- test_async_messages
- test_pps_input
- tx_timed_samples
- tx_waveforms
- RUNTIME DESTINATION ${PKG_DATA_DIR}/examples
+# example applications
+########################################################################
+SET(example_sources
+ benchmark_rx_rate.cpp
+ rx_samples_to_file.cpp
+ rx_samples_to_udp.cpp
+ rx_timed_samples.cpp
+ test_async_messages.cpp
+ test_pps_input.cpp
+ tx_timed_samples.cpp
+ tx_waveforms.cpp
)
+#for each source: build an executable and install
+FOREACH(example_source ${example_sources})
+ GET_FILENAME_COMPONENT(example_name ${example_source} NAME_WE)
+ ADD_EXECUTABLE(${example_name} ${example_source})
+ TARGET_LINK_LIBRARIES(${example_name} uhd)
+ INSTALL(TARGETS ${example_name} RUNTIME DESTINATION ${PKG_DATA_DIR}/examples)
+ENDFOREACH(example_source)
+
########################################################################
# ASCII Art DFT - requires curses, so this part is optional
########################################################################
diff --git a/host/examples/rx_samples_to_file.cpp b/host/examples/rx_samples_to_file.cpp
new file mode 100644
index 000000000..c80d2a6de
--- /dev/null
+++ b/host/examples/rx_samples_to_file.cpp
@@ -0,0 +1,135 @@
+//
+// 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 <http://www.gnu.org/licenses/>.
+//
+
+#include <uhd/utils/thread_priority.hpp>
+#include <uhd/utils/safe_main.hpp>
+#include <uhd/usrp/single_usrp.hpp>
+#include <boost/program_options.hpp>
+#include <boost/format.hpp>
+#include <boost/thread.hpp>
+#include <iostream>
+#include <fstream>
+#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;
+ size_t total_num_samps;
+ double rate, freq;
+ float gain;
+
+ //setup the program options
+ po::options_description desc("Allowed options");
+ desc.add_options()
+ ("help", "help message")
+ ("args", po::value<std::string>(&args)->default_value(""), "single uhd device address args")
+ ("file", po::value<std::string>(&file)->default_value("out.16sc.dat"), "name of the file to write binary samples to")
+ ("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<float>(&gain)->default_value(0), "gain for the RF chain")
+ ;
+ 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 File %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::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;
+
+ //set the rx sample rate
+ std::cout << boost::format("Setting RX Rate: %f Msps...") % (rate/1e6) << std::endl;
+ sdev->set_rx_rate(rate);
+ std::cout << boost::format("Actual RX Rate: %f Msps...") % (sdev->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;
+ sdev->set_rx_freq(freq);
+ std::cout << boost::format("Actual RX Freq: %f Mhz...") % (sdev->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;
+ sdev->set_rx_gain(gain);
+ std::cout << boost::format("Actual RX Gain: %f dB...") % sdev->get_rx_gain() << std::endl << std::endl;
+
+ boost::this_thread::sleep(boost::posix_time::seconds(1)); //allow for some setup time
+ std::cout << "LO Locked = " << sdev->get_rx_lo_locked() << std::endl;
+
+ //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;
+ 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<std::complex<short> > buff(dev->get_max_recv_samps_per_packet());
+ std::ofstream outfile(file.c_str(), 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;
+ }
+
+ //write complex short integer samples to the binary file
+ outfile.write((const char*)&buff[0], num_rx_samps * sizeof(std::complex<short>));
+
+ num_acc_samps += num_rx_samps;
+ } done_loop:
+
+ outfile.close();
+
+ //finished
+ std::cout << std::endl << "Done!" << std::endl << std::endl;
+
+ return 0;
+}
diff --git a/host/examples/rx_samples_to_udp.cpp b/host/examples/rx_samples_to_udp.cpp
new file mode 100644
index 000000000..488c95494
--- /dev/null
+++ b/host/examples/rx_samples_to_udp.cpp
@@ -0,0 +1,135 @@
+//
+// 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 <http://www.gnu.org/licenses/>.
+//
+
+#include <uhd/utils/thread_priority.hpp>
+#include <uhd/utils/safe_main.hpp>
+#include <uhd/usrp/single_usrp.hpp>
+#include <uhd/transport/udp_simple.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;
+ size_t total_num_samps;
+ double rate, freq;
+ float gain;
+ 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(""), "single 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<float>(&gain)->default_value(0), "gain for the RF chain")
+ ("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")
+ ;
+ 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::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;
+
+ //set the rx sample rate
+ std::cout << boost::format("Setting RX Rate: %f Msps...") % (rate/1e6) << std::endl;
+ sdev->set_rx_rate(rate);
+ std::cout << boost::format("Actual RX Rate: %f Msps...") % (sdev->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;
+ sdev->set_rx_freq(freq);
+ std::cout << boost::format("Actual RX Freq: %f Mhz...") % (sdev->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;
+ sdev->set_rx_gain(gain);
+ std::cout << boost::format("Actual RX Gain: %f dB...") % sdev->get_rx_gain() << std::endl << std::endl;
+
+ boost::this_thread::sleep(boost::posix_time::seconds(1)); //allow for some setup time
+ std::cout << "LO Locked = " << sdev->get_rx_lo_locked() << std::endl;
+
+ //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;
+ 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<std::complex<float> > buff(dev->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 = 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;
+ }
+
+ //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;
+}
diff --git a/host/examples/rx_timed_samples.cpp b/host/examples/rx_timed_samples.cpp
index 441665900..8a810811f 100644
--- a/host/examples/rx_timed_samples.cpp
+++ b/host/examples/rx_timed_samples.cpp
@@ -32,7 +32,7 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){
std::string args;
time_t seconds_in_future;
size_t total_num_samps;
- double rx_rate, freq;
+ double rate, freq;
//setup the program options
po::options_description desc("Allowed options");
@@ -41,7 +41,7 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){
("args", po::value<std::string>(&args)->default_value(""), "single uhd device address args")
("secs", po::value<time_t>(&seconds_in_future)->default_value(3), "number of seconds in the future to receive")
("nsamps", po::value<size_t>(&total_num_samps)->default_value(1000), "total number of samples to receive")
- ("rxrate", po::value<double>(&rx_rate)->default_value(100e6/16), "rate of incoming samples")
+ ("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")
("dilv", "specify to disable inner-loop verbose")
;
@@ -64,12 +64,17 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){
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;
+ //set the rx sample rate
+ std::cout << boost::format("Setting RX Rate: %f Msps...") % (rate/1e6) << std::endl;
+ sdev->set_rx_rate(rate);
+ std::cout << boost::format("Actual RX Rate: %f Msps...") % (sdev->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;
sdev->set_rx_freq(freq);
+ std::cout << boost::format("Actual RX Freq: %f Mhz...") % (sdev->get_rx_freq()/1e6) << std::endl << std::endl;
+
+ std::cout << boost::format("Setting device timestamp to 0...") << std::endl;
sdev->set_time_now(uhd::time_spec_t(0.0));
//setup streaming
diff --git a/host/examples/tx_timed_samples.cpp b/host/examples/tx_timed_samples.cpp
index 863446682..799da37e0 100644
--- a/host/examples/tx_timed_samples.cpp
+++ b/host/examples/tx_timed_samples.cpp
@@ -33,7 +33,7 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){
time_t seconds_in_future;
size_t total_num_samps;
size_t samps_per_packet;
- double tx_rate, freq;
+ double rate, freq;
float ampl;
//setup the program options
@@ -44,7 +44,7 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){
("secs", po::value<time_t>(&seconds_in_future)->default_value(3), "number of seconds in the future to transmit")
("nsamps", po::value<size_t>(&total_num_samps)->default_value(1000), "total number of samples to transmit")
("spp", po::value<size_t>(&samps_per_packet)->default_value(1000), "number of samples per packet")
- ("txrate", po::value<double>(&tx_rate)->default_value(100e6/16), "rate of outgoing samples")
+ ("rate", po::value<double>(&rate)->default_value(100e6/16), "rate of outgoing samples")
("freq", po::value<double>(&freq)->default_value(0), "rf center frequency in Hz")
("ampl", po::value<float>(&ampl)->default_value(float(0.3)), "amplitude of each sample")
("dilv", "specify to disable inner-loop verbose")
@@ -68,12 +68,17 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){
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;
+ //set the tx sample rate
+ std::cout << boost::format("Setting TX Rate: %f Msps...") % (rate/1e6) << std::endl;
+ sdev->set_tx_rate(rate);
+ std::cout << boost::format("Actual TX Rate: %f Msps...") % (sdev->get_tx_rate()/1e6) << std::endl << std::endl;
+
+ //set the tx center frequency
+ std::cout << boost::format("Setting TX Freq: %f Mhz...") % (freq/1e6) << std::endl;
sdev->set_tx_freq(freq);
+ std::cout << boost::format("Actual TX Freq: %f Mhz...") % (sdev->get_tx_freq()/1e6) << std::endl << std::endl;
+
+ std::cout << boost::format("Setting device timestamp to 0...") << std::endl;
sdev->set_time_now(uhd::time_spec_t(0.0));
//allocate data to send
diff --git a/host/include/uhd/types/CMakeLists.txt b/host/include/uhd/types/CMakeLists.txt
index dbce21c98..a96976b5e 100644
--- a/host/include/uhd/types/CMakeLists.txt
+++ b/host/include/uhd/types/CMakeLists.txt
@@ -19,6 +19,7 @@
INSTALL(FILES
clock_config.hpp
device_addr.hpp
+ dict.ipp
dict.hpp
io_type.hpp
mac_addr.hpp
@@ -28,6 +29,7 @@ INSTALL(FILES
serial.hpp
stream_cmd.hpp
time_spec.hpp
+ tune_request.hpp
tune_result.hpp
DESTINATION ${INCLUDE_DIR}/uhd/types
)
diff --git a/host/include/uhd/types/dict.hpp b/host/include/uhd/types/dict.hpp
index de96ea768..b14fc5425 100644
--- a/host/include/uhd/types/dict.hpp
+++ b/host/include/uhd/types/dict.hpp
@@ -19,11 +19,6 @@
#define INCLUDED_UHD_TYPES_DICT_HPP
#include <uhd/config.hpp>
-#include <boost/foreach.hpp>
-#include <boost/format.hpp>
-#include <boost/lexical_cast.hpp>
-#include <stdexcept>
-#include <typeinfo>
#include <vector>
#include <list>
@@ -34,14 +29,10 @@ namespace uhd{
*/
template <typename Key, typename Val> class dict{
public:
- typedef std::pair<Key, Val> pair_t;
-
/*!
* Create a new empty dictionary.
*/
- dict(void){
- /* NOP */
- }
+ dict(void);
/*!
* Input iterator constructor:
@@ -50,64 +41,34 @@ namespace uhd{
* \param last the end iterator
*/
template <typename InputIterator>
- dict(InputIterator first, InputIterator last){
- for(InputIterator it = first; it != last; it++){
- _map.push_back(*it);
- }
- }
-
- /*!
- * Destroy this dict.
- */
- ~dict(void){
- /* NOP */
- }
+ dict(InputIterator first, InputIterator last);
/*!
* Get the number of elements in this dict.
* \return the number of elements
*/
- std::size_t size(void) const{
- return _map.size();
- }
+ std::size_t size(void) const;
/*!
* Get a list of the keys in this dict.
* Key order depends on insertion precedence.
* \return vector of keys
*/
- const std::vector<Key> keys(void) const{
- std::vector<Key> keys;
- BOOST_FOREACH(const pair_t &p, _map){
- keys.push_back(p.first);
- }
- return keys;
- }
+ const std::vector<Key> keys(void) const;
/*!
* Get a list of the values in this dict.
* Value order depends on insertion precedence.
* \return vector of values
*/
- const std::vector<Val> vals(void) const{
- std::vector<Val> vals;
- BOOST_FOREACH(const pair_t &p, _map){
- vals.push_back(p.second);
- }
- return vals;
- }
+ const std::vector<Val> vals(void) const;
/*!
* Does the dictionary contain this key?
* \param key the key to look for
* \return true if found
*/
- bool has_key(const Key &key) const{
- BOOST_FOREACH(const pair_t &p, _map){
- if (p.first == key) return true;
- }
- return false;
- }
+ bool has_key(const Key &key) const;
/*!
* Get a value for the given key if it exists.
@@ -116,15 +77,7 @@ namespace uhd{
* \return the value at the key
* \throw an exception when not found
*/
- const Val &operator[](const Key &key) const{
- BOOST_FOREACH(const pair_t &p, _map){
- if (p.first == key) return p.second;
- }
- throw std::invalid_argument(str(boost::format(
- "key \"%s\" not found in dict(%s, %s)"
- ) % boost::lexical_cast<std::string>(key)
- % typeid(Key).name() % typeid(Val).name()));
- }
+ const Val &operator[](const Key &key) const;
/*!
* Set a value for the given key, however, in reality
@@ -132,13 +85,7 @@ namespace uhd{
* \param key the key to set to
* \return a reference to the value
*/
- Val &operator[](const Key &key){
- BOOST_FOREACH(pair_t &p, _map){
- if (p.first == key) return p.second;
- }
- _map.push_back(std::make_pair(key, Val()));
- return _map.back().second;
- }
+ Val &operator[](const Key &key);
/*!
* Pop an item out of the dictionary.
@@ -146,16 +93,15 @@ namespace uhd{
* \return the value of the item
* \throw an exception when not found
*/
- Val pop(const Key &key){
- Val val = (*this)[key];
- _map.remove(pair_t(key, val));
- return val;
- }
+ Val pop(const Key &key);
private:
+ typedef std::pair<Key, Val> pair_t;
std::list<pair_t> _map; //private container
};
} //namespace uhd
+#include <uhd/types/dict.ipp>
+
#endif /* INCLUDED_UHD_TYPES_DICT_HPP */
diff --git a/host/include/uhd/types/dict.ipp b/host/include/uhd/types/dict.ipp
new file mode 100644
index 000000000..85071e6fd
--- /dev/null
+++ b/host/include/uhd/types/dict.ipp
@@ -0,0 +1,120 @@
+//
+// 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 <http://www.gnu.org/licenses/>.
+//
+
+#ifndef INCLUDED_UHD_TYPES_DICT_IPP
+#define INCLUDED_UHD_TYPES_DICT_IPP
+
+#include <boost/foreach.hpp>
+#include <boost/format.hpp>
+#include <boost/lexical_cast.hpp>
+#include <stdexcept>
+#include <typeinfo>
+
+namespace uhd{
+
+ namespace /*anon*/{
+ template<typename Key, typename Val>
+ struct UHD_API key_not_found: std::out_of_range{
+ key_not_found(const Key &key): std::out_of_range(
+ str(boost::format(
+ "key \"%s\" not found in dict(%s, %s)"
+ ) % boost::lexical_cast<std::string>(key)
+ % typeid(Key).name() % typeid(Val).name()
+ )
+ ){
+ /* NOP */
+ }
+ };
+ } // namespace /*anon*/
+
+ template <typename Key, typename Val>
+ dict<Key, Val>::dict(void){
+ /* NOP */
+ }
+
+ template <typename Key, typename Val>
+ template <typename InputIterator>
+ dict<Key, Val>::dict(InputIterator first, InputIterator last){
+ for(InputIterator it = first; it != last; it++){
+ _map.push_back(*it);
+ }
+ }
+
+ template <typename Key, typename Val>
+ std::size_t dict<Key, Val>::size(void) const{
+ return _map.size();
+ }
+
+ template <typename Key, typename Val>
+ const std::vector<Key> dict<Key, Val>::keys(void) const{
+ std::vector<Key> keys;
+ BOOST_FOREACH(const pair_t &p, _map){
+ keys.push_back(p.first);
+ }
+ return keys;
+ }
+
+ template <typename Key, typename Val>
+ const std::vector<Val> dict<Key, Val>::vals(void) const{
+ std::vector<Val> vals;
+ BOOST_FOREACH(const pair_t &p, _map){
+ vals.push_back(p.second);
+ }
+ return vals;
+ }
+
+ template <typename Key, typename Val>
+ bool dict<Key, Val>::has_key(const Key &key) const{
+ BOOST_FOREACH(const pair_t &p, _map){
+ if (p.first == key) return true;
+ }
+ return false;
+ }
+
+ template <typename Key, typename Val>
+ const Val &dict<Key, Val>::operator[](const Key &key) const{
+ BOOST_FOREACH(const pair_t &p, _map){
+ if (p.first == key) return p.second;
+ }
+ throw key_not_found<Key, Val>(key);
+ }
+
+ template <typename Key, typename Val>
+ Val &dict<Key, Val>::operator[](const Key &key){
+ BOOST_FOREACH(pair_t &p, _map){
+ if (p.first == key) return p.second;
+ }
+ _map.push_back(std::make_pair(key, Val()));
+ return _map.back().second;
+ }
+
+ template <typename Key, typename Val>
+ Val dict<Key, Val>::pop(const Key &key){
+ typename std::list<pair_t>::iterator it;
+ for (it = _map.begin(); it != _map.end(); it++){
+ if (it->first == key){
+ Val val = it->second;
+ _map.erase(it);
+ return val;
+ }
+ }
+ throw key_not_found<Key, Val>(key);
+ }
+
+} //namespace uhd
+
+#endif /* INCLUDED_UHD_TYPES_DICT_IPP */
diff --git a/host/include/uhd/types/metadata.hpp b/host/include/uhd/types/metadata.hpp
index 65952941c..3f250d13e 100644
--- a/host/include/uhd/types/metadata.hpp
+++ b/host/include/uhd/types/metadata.hpp
@@ -19,7 +19,6 @@
#define INCLUDED_UHD_TYPES_METADATA_HPP
#include <uhd/config.hpp>
-#include <boost/cstdint.hpp>
#include <uhd/types/time_spec.hpp>
namespace uhd{
@@ -30,58 +29,59 @@ namespace uhd{
* The receive routines will convert IF data headers into metadata.
*/
struct UHD_API rx_metadata_t{
- /*!
- * Time specification:
- * Set from timestamps on incoming data when provided.
- */
+ //! Has time specification?
bool has_time_spec;
+
+ //! Time of the first sample.
time_spec_t time_spec;
/*!
- * Fragmentation flag and offset:
+ * Fragmentation flag:
* Similar to IPv4 fragmentation: http://en.wikipedia.org/wiki/IPv4#Fragmentation_and_reassembly
* More fragments is true when the input buffer has insufficient size to fit
* an entire received packet. More fragments will be false for the last fragment.
- * The fragment offset is the sample number at the start of the receive buffer.
- * For non-fragmented receives, the fragment offset should always be zero.
*/
bool more_fragments;
- size_t fragment_offset;
/*!
- * Burst flags:
- * Start of burst will be true for the first packet in the chain.
- * End of burst will be true for the last packet in the chain.
+ * Fragmentation offset:
+ * The fragment offset is the sample number at the start of the receive buffer.
+ * For non-fragmented receives, the fragment offset should always be zero.
*/
+ size_t fragment_offset;
+
+ //! Start of burst will be true for the first packet in the chain.
bool start_of_burst;
+
+ //! End of burst will be true for the last packet in the chain.
bool end_of_burst;
/*!
- * Error conditions:
- * - none: no error associated with this metadata
- * - timeout: no packet received, underlying code timed-out
- * - late command: a stream command was issued in the past
- * - broken chain: expected another stream command
- * - overflow: an internal receive buffer has filled
- * - bad packet: the buffer was unrecognizable as a vrt packet
+ * The error condition on a receive call.
*
* Note: When an overrun occurs in continuous streaming mode,
* the device will continue to send samples to the host.
* For other streaming modes, streaming will discontinue
* until the user issues a new stream command.
*
- * Note: The metadata fields have meaning for the following error codes:
+ * The metadata fields have meaning for the following error codes:
* - none
* - late command
* - broken chain
* - overflow
*/
enum error_code_t {
+ //! No error associated with this metadata.
ERROR_CODE_NONE = 0x0,
+ //! No packet received, implementation timed-out.
ERROR_CODE_TIMEOUT = 0x1,
+ //! A stream command was issued in the past.
ERROR_CODE_LATE_COMMAND = 0x2,
+ //! Expected another stream command.
ERROR_CODE_BROKEN_CHAIN = 0x4,
+ //! An internal receive buffer has filled.
ERROR_CODE_OVERFLOW = 0x8,
+ //! The packet could not be parsed.
ERROR_CODE_BAD_PACKET = 0xf
} error_code;
};
@@ -93,19 +93,19 @@ namespace uhd{
*/
struct UHD_API tx_metadata_t{
/*!
- * Time specification:
- * Set has time spec to false to perform a send "now".
- * Or, set to true, and fill in time spec for a send "at".
+ * Has time specification?
+ * - Set false to send immediately.
+ * - Set true to send at the time specified by time spec.
*/
bool has_time_spec;
+
+ //! When to send the first sample.
time_spec_t time_spec;
- /*!
- * Burst flags:
- * Set start of burst to true for the first packet in the chain.
- * Set end of burst to true for the last packet in the chain.
- */
+ //! Set start of burst to true for the first packet in the chain.
bool start_of_burst;
+
+ //! Set end of burst to true for the last packet in the chain.
bool end_of_burst;
/*!
@@ -122,27 +122,27 @@ namespace uhd{
//! The channel number in a mimo configuration
size_t channel;
- /*!
- * Time specification: when the async event occurred.
- */
+ //! Has time specification?
bool has_time_spec;
+
+ //! When the async event occurred.
time_spec_t time_spec;
/*!
- * Event codes:
- * - success: a packet was successfully transmitted
- * - underflow: an internal send buffer has emptied
- * - sequence error: packet loss between host and device
- * - time error: packet had time that was late (or too early)
- * - underflow in packet: underflow occurred inside a packet
- * - sequence error in burst: packet loss within a burst
+ * The type of event for a receive async message call.
*/
enum event_code_t {
+ //! A packet was successfully transmitted.
EVENT_CODE_SUCCESS = 0x1,
+ //! An internal send buffer has emptied.
EVENT_CODE_UNDERFLOW = 0x2,
+ //! Packet loss between host and device.
EVENT_CODE_SEQ_ERROR = 0x4,
+ //! Packet had time that was late (or too early).
EVENT_CODE_TIME_ERROR = 0x8,
+ //! Underflow occurred inside a packet.
EVENT_CODE_UNDERFLOW_IN_PACKET = 0x10,
+ //! Packet loss within a burst.
EVENT_CODE_SEQ_ERROR_IN_BURST = 0x20
} event_code;
};
diff --git a/host/include/uhd/types/tune_request.hpp b/host/include/uhd/types/tune_request.hpp
new file mode 100644
index 000000000..942b93251
--- /dev/null
+++ b/host/include/uhd/types/tune_request.hpp
@@ -0,0 +1,95 @@
+//
+// 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 <http://www.gnu.org/licenses/>.
+//
+
+#ifndef INCLUDED_UHD_TYPES_TUNE_REQUEST_HPP
+#define INCLUDED_UHD_TYPES_TUNE_REQUEST_HPP
+
+#include <uhd/config.hpp>
+
+namespace uhd{
+
+ /*!
+ * A tune request instructs the implementation how to tune the RF chain.
+ * The policies can be used to select automatic tuning or
+ * fined control over the daughterboard IF and DSP tuning.
+ * Not all combinations of policies are applicable.
+ * Convenience constructors are supplied for most use cases.
+ */
+ struct UHD_API tune_request_t{
+ /*!
+ * Make a new tune request for a particular center frequency.
+ * Use an automatic policy for the intermediate and DSP frequency
+ * to tune the chain as close as possible to the target frequency.
+ * \param target_freq the target frequency in Hz
+ */
+ tune_request_t(double target_freq = 0);
+
+ /*!
+ * Make a new tune request for a particular center frequency.
+ * Use a manual policy for the intermediate frequency,
+ * and an automatic policy for the DSP frequency,
+ * to tune the chain as close as possible to the target frequency.
+ * \param target_freq the target frequency in Hz
+ * \param lo_off the LO offset frequency in Hz
+ */
+ tune_request_t(double target_freq, double lo_off);
+
+ //! Policy options for tunable elements in the RF chain.
+ enum policy_t {
+ //! Do not set this argument, use current setting.
+ POLICY_NONE = 'N',
+ //! Automatically determine the argument's value.
+ POLICY_AUTO = 'A',
+ //! Use the argument's value for the setting.
+ POLICY_MANUAL = 'M'
+ };
+
+ /*!
+ * The target frequency of the overall chain in Hz.
+ * Set this even if all policies are set to manual.
+ */
+ double target_freq;
+
+ /*!
+ * The policy for the intermediate frequency.
+ * Automatic behavior: the target frequency + default LO offset.
+ */
+ policy_t inter_freq_policy;
+
+ /*!
+ * The intermediate frequency in Hz.
+ * Set when the policy is set to manual.
+ */
+ double inter_freq;
+
+ /*!
+ * The policy for the DSP frequency.
+ * Automatic behavior: the difference between the target and IF.
+ */
+ policy_t dsp_freq_policy;
+
+ /*!
+ * The DSP frequency in Hz.
+ * Set when the policy is set to manual.
+ */
+ double dsp_freq;
+
+ };
+
+} //namespace uhd
+
+#endif /* INCLUDED_UHD_TYPES_TUNE_REQUEST_HPP */
diff --git a/host/include/uhd/usrp/mimo_usrp.hpp b/host/include/uhd/usrp/mimo_usrp.hpp
index 78833e24e..a2092f04f 100644
--- a/host/include/uhd/usrp/mimo_usrp.hpp
+++ b/host/include/uhd/usrp/mimo_usrp.hpp
@@ -127,7 +127,7 @@ public:
virtual double get_rx_rate_all(void) = 0;
virtual tune_result_t set_rx_freq(size_t chan, double freq) = 0;
- virtual tune_result_t set_rx_freq(size_t chan, double freq, double lo_off) = 0;
+ //virtual tune_result_t set_rx_freq(size_t chan, double freq, double lo_off) = 0;
virtual double get_rx_freq(size_t chan) = 0;
virtual freq_range_t get_rx_freq_range(size_t chan) = 0;
@@ -161,7 +161,7 @@ public:
virtual double get_tx_rate_all(void) = 0;
virtual tune_result_t set_tx_freq(size_t chan, double freq) = 0;
- virtual tune_result_t set_tx_freq(size_t chan, double freq, double lo_off) = 0;
+ //virtual tune_result_t set_tx_freq(size_t chan, double freq, double lo_off) = 0;
virtual double get_tx_freq(size_t chan) = 0;
virtual freq_range_t get_tx_freq_range(size_t chan) = 0;
@@ -298,7 +298,7 @@ public:
time_spec_t time_0 = _mboard(0)[MBOARD_PROP_TIME_NOW].as<time_spec_t>();
time_spec_t time_i = _mboard(chan)[MBOARD_PROP_TIME_NOW].as<time_spec_t>();
if (time_i < time_0 or (time_i - time_0) > time_spec_t(0.01)){ //10 ms: greater than RTT but not too big
- uhd::print_warning(str(boost::format(
+ uhd::warning::post(str(boost::format(
"Detected time deviation between board %d and board 0.\n"
"Board 0 time is %f seconds.\n"
"Board %d time is %f seconds.\n"
@@ -345,9 +345,9 @@ public:
return tune_rx_subdev_and_dsp(_rx_subdev(chan), _rx_dsp(chan), 0, target_freq);
}
- tune_result_t set_rx_freq(size_t chan, double target_freq, double lo_off){
- return tune_rx_subdev_and_dsp(_rx_subdev(chan), _rx_dsp(chan), 0, target_freq, lo_off);
- }
+ //tune_result_t set_rx_freq(size_t chan, double target_freq, double lo_off){
+ // return tune_rx_subdev_and_dsp(_rx_subdev(chan), _rx_dsp(chan), 0, target_freq, lo_off);
+ //}
double get_rx_freq(size_t chan){
return derive_freq_from_rx_subdev_and_dsp(_rx_subdev(chan), _rx_dsp(chan), 0);
@@ -425,9 +425,9 @@ public:
return tune_tx_subdev_and_dsp(_tx_subdev(chan), _tx_dsp(chan), 0, target_freq);
}
- tune_result_t set_tx_freq(size_t chan, double target_freq, double lo_off){
- return tune_tx_subdev_and_dsp(_tx_subdev(chan), _tx_dsp(chan), 0, target_freq, lo_off);
- }
+ //tune_result_t set_tx_freq(size_t chan, double target_freq, double lo_off){
+ // return tune_tx_subdev_and_dsp(_tx_subdev(chan), _tx_dsp(chan), 0, target_freq, lo_off);
+ //}
double get_tx_freq(size_t chan){
return derive_freq_from_tx_subdev_and_dsp(_tx_subdev(chan), _tx_dsp(chan), 0);
@@ -512,7 +512,7 @@ namespace uhd{ namespace usrp{
* The Make Function
**********************************************************************/
inline mimo_usrp::sptr mimo_usrp::make(const device_addr_t &dev_addr){
- uhd::print_warning(
+ uhd::warning::post(
"The mimo USRP interface has been deprecated.\n"
"Please switch to the multi USRP interface.\n"
"#include <uhd/usrp/multi_usrp.hpp>\n"
diff --git a/host/include/uhd/usrp/multi_usrp.hpp b/host/include/uhd/usrp/multi_usrp.hpp
index 2f71f80b1..98ba07fc0 100644
--- a/host/include/uhd/usrp/multi_usrp.hpp
+++ b/host/include/uhd/usrp/multi_usrp.hpp
@@ -23,6 +23,7 @@
#include <uhd/types/ranges.hpp>
#include <uhd/types/stream_cmd.hpp>
#include <uhd/types/clock_config.hpp>
+#include <uhd/types/tune_request.hpp>
#include <uhd/types/tune_result.hpp>
#include <uhd/usrp/subdev_spec.hpp>
#include <uhd/usrp/dboard_iface.hpp>
@@ -144,6 +145,14 @@ public:
virtual void set_time_unknown_pps(const time_spec_t &time_spec) = 0;
/*!
+ * Are the times across all motherboards in this configuration synchronized?
+ * Checks that all time registers are approximately close but not exact,
+ * given that the RTT may varying for a control packet transaction.
+ * \return true when all motherboards time registers are in sync
+ */
+ virtual bool get_time_synchronized(void) = 0;
+
+ /*!
* Issue a stream command to the usrp device.
* This tells the usrp to send samples into the host.
* See the documentation for stream_cmd_t for more info.
@@ -213,20 +222,13 @@ public:
/*!
* Set the RX center frequency.
- * \param freq the frequency in Hz
+ * \param tune_request tune request instructions
* \param chan the channel index 0 to N-1
* \return a tune result object
*/
- virtual tune_result_t set_rx_freq(double freq, size_t chan) = 0;
-
- /*!
- * Set the RX center frequency.
- * \param freq the frequency in Hz
- * \param lo_off an LO offset in Hz
- * \param chan the channel index 0 to N-1
- * \return a tune result object
- */
- virtual tune_result_t set_rx_freq(double freq, double lo_off, size_t chan) = 0;
+ virtual tune_result_t set_rx_freq(
+ const tune_request_t &tune_request, size_t chan = 0
+ ) = 0;
/*!
* Get the RX center frequency.
@@ -399,20 +401,13 @@ public:
/*!
* Set the TX center frequency.
- * \param freq the frequency in Hz
- * \param chan the channel index 0 to N-1
- * \return a tune result object
- */
- virtual tune_result_t set_tx_freq(double freq, size_t chan) = 0;
-
- /*!
- * Set the TX center frequency.
- * \param freq the frequency in Hz
- * \param lo_off an LO offset in Hz
+ * \param tune_request tune request instructions
* \param chan the channel index 0 to N-1
* \return a tune result object
*/
- virtual tune_result_t set_tx_freq(double freq, double lo_off, size_t chan) = 0;
+ virtual tune_result_t set_tx_freq(
+ const tune_request_t &tune_request, size_t chan = 0
+ ) = 0;
/*!
* Get the TX center frequency.
diff --git a/host/include/uhd/usrp/simple_usrp.hpp b/host/include/uhd/usrp/simple_usrp.hpp
index 22f4d64ba..77416dbbd 100644
--- a/host/include/uhd/usrp/simple_usrp.hpp
+++ b/host/include/uhd/usrp/simple_usrp.hpp
@@ -117,7 +117,7 @@ public:
virtual double get_rx_rate(void) = 0;
virtual tune_result_t set_rx_freq(double freq) = 0;
- virtual tune_result_t set_rx_freq(double freq, double lo_off) = 0;
+ //virtual tune_result_t set_rx_freq(double freq, double lo_off) = 0;
virtual double get_rx_freq(void) = 0;
virtual freq_range_t get_rx_freq_range(void) = 0;
@@ -152,7 +152,7 @@ public:
virtual double get_tx_rate(void) = 0;
virtual tune_result_t set_tx_freq(double freq) = 0;
- virtual tune_result_t set_tx_freq(double freq, double lo_off) = 0;
+ //virtual tune_result_t set_tx_freq(double freq, double lo_off) = 0;
virtual double get_tx_freq(void) = 0;
virtual freq_range_t get_tx_freq_range(void) = 0;
@@ -243,9 +243,9 @@ public:
return _sdev->set_rx_freq(target_freq);
}
- tune_result_t set_rx_freq(double target_freq, double lo_off){
- return _sdev->set_rx_freq(target_freq, lo_off);
- }
+ //tune_result_t set_rx_freq(double target_freq, double lo_off){
+ // return _sdev->set_rx_freq(target_freq, lo_off);
+ //}
double get_rx_freq(void){
return _sdev->get_rx_freq();
@@ -318,9 +318,9 @@ public:
return _sdev->set_tx_freq(target_freq);
}
- tune_result_t set_tx_freq(double target_freq, double lo_off){
- return _sdev->set_tx_freq(target_freq, lo_off);
- }
+ //tune_result_t set_tx_freq(double target_freq, double lo_off){
+ // return _sdev->set_tx_freq(target_freq, lo_off);
+ //}
double get_tx_freq(void){
return _sdev->get_tx_freq();
@@ -374,7 +374,7 @@ namespace uhd{ namespace usrp{
* The Make Function
**********************************************************************/
inline simple_usrp::sptr simple_usrp::make(const device_addr_t &dev_addr){
- uhd::print_warning(
+ uhd::warning::post(
"The simple USRP interface has been deprecated.\n"
"Please switch to the single USRP interface.\n"
"#include <uhd/usrp/single_usrp.hpp>\n"
diff --git a/host/include/uhd/usrp/single_usrp.hpp b/host/include/uhd/usrp/single_usrp.hpp
index a068fbed8..26303fe10 100644
--- a/host/include/uhd/usrp/single_usrp.hpp
+++ b/host/include/uhd/usrp/single_usrp.hpp
@@ -23,6 +23,7 @@
#include <uhd/types/ranges.hpp>
#include <uhd/types/stream_cmd.hpp>
#include <uhd/types/clock_config.hpp>
+#include <uhd/types/tune_request.hpp>
#include <uhd/types/tune_result.hpp>
#include <uhd/usrp/subdev_spec.hpp>
#include <uhd/usrp/dboard_iface.hpp>
@@ -154,20 +155,13 @@ public:
/*!
* Set the RX center frequency.
- * \param freq the frequency in Hz
+ * \param tune_request tune request instructions
* \param chan the channel index 0 to N-1
* \return a tune result object
*/
- virtual tune_result_t set_rx_freq(double freq, size_t chan = 0) = 0;
-
- /*!
- * Set the RX center frequency.
- * \param freq the frequency in Hz
- * \param lo_off an LO offset in Hz
- * \param chan the channel index 0 to N-1
- * \return a tune result object
- */
- virtual tune_result_t set_rx_freq(double freq, double lo_off, size_t chan = 0) = 0;
+ virtual tune_result_t set_rx_freq(
+ const tune_request_t &tune_request, size_t chan = 0
+ ) = 0;
/*!
* Get the RX center frequency.
@@ -330,20 +324,13 @@ public:
/*!
* Set the TX center frequency.
- * \param freq the frequency in Hz
- * \param chan the channel index 0 to N-1
- * \return a tune result object
- */
- virtual tune_result_t set_tx_freq(double freq, size_t chan = 0) = 0;
-
- /*!
- * Set the TX center frequency.
- * \param freq the frequency in Hz
- * \param lo_off an LO offset in Hz
+ * \param tune_request tune request instructions
* \param chan the channel index 0 to N-1
* \return a tune result object
*/
- virtual tune_result_t set_tx_freq(double freq, double lo_off, size_t chan = 0) = 0;
+ virtual tune_result_t set_tx_freq(
+ const tune_request_t &tune_request, size_t chan = 0
+ ) = 0;
/*!
* Get the TX center frequency.
diff --git a/host/include/uhd/usrp/subdev_spec.hpp b/host/include/uhd/usrp/subdev_spec.hpp
index 5de3bb3b8..b189724c9 100644
--- a/host/include/uhd/usrp/subdev_spec.hpp
+++ b/host/include/uhd/usrp/subdev_spec.hpp
@@ -26,10 +26,10 @@
namespace uhd{ namespace usrp{
/*!
- * A subdevice specification (daughterboard, subdevice) name pairing.
+ * A subdevice specification (daughterboard slot, subdevice) name pairing.
*/
struct UHD_API subdev_spec_pair_t : boost::equality_comparable<subdev_spec_pair_t>{
- //! The daughterboard name
+ //! The daughterboard slot name
std::string db_name;
//! The subdevice name
@@ -50,7 +50,7 @@ namespace uhd{ namespace usrp{
UHD_API bool operator==(const subdev_spec_pair_t &, const subdev_spec_pair_t &);
/*!
- * A list of (daughterboard name, subdevice name) pairs:
+ * A list of (daughterboard slot name, subdevice name) pairs:
*
* A subdevice specification represents a list of subdevices on a motherboard.
* The subdevices specified may span across multiple daughterboards;
@@ -62,6 +62,11 @@ namespace uhd{ namespace usrp{
* The markup-string is a whitespace separated list of dboard:subdev pairs.
* The first pair represents the subdevice for channel zero,
* the second pair represents the subdevice for channel one, and so on.
+ *
+ * Special handling for empty conditions:
+ * - An empty subdevice specification means: select the first subdevice found in the configuration
+ * - An empty daughterboard name means: select the only daughterboard slot or error if multiple exist
+ * - An empty subdevice name means: select the only subdevice on that board or error if multiple exist
*/
class UHD_API subdev_spec_t : public std::vector<subdev_spec_pair_t>{
public:
diff --git a/host/include/uhd/usrp/tune_helper.hpp b/host/include/uhd/usrp/tune_helper.hpp
index ec133fa08..db12241c1 100644
--- a/host/include/uhd/usrp/tune_helper.hpp
+++ b/host/include/uhd/usrp/tune_helper.hpp
@@ -20,6 +20,7 @@
#include <uhd/config.hpp>
#include <uhd/wax.hpp>
+#include <uhd/types/tune_request.hpp>
#include <uhd/types/tune_result.hpp>
namespace uhd{ namespace usrp{
@@ -32,23 +33,12 @@ namespace uhd{ namespace usrp{
* \param subdev the dboard subdevice object with properties
* \param ddc the mboard dsp object with properties
* \param chan the channel of the dsp to tune
- * \param target_freq the desired center frequency
- * \param lo_offset an offset for the subdevice IF from center
+ * \param tune_request tune request instructions
* \return a tune result struct
*/
UHD_API tune_result_t tune_rx_subdev_and_dsp(
wax::obj subdev, wax::obj ddc, size_t chan,
- double target_freq, double lo_offset
- );
-
- /*!
- * Tune a rx chain to the desired frequency:
- * Same as the above, except the LO offset
- * is calculated based on the subdevice and BW.
- */
- UHD_API tune_result_t tune_rx_subdev_and_dsp(
- wax::obj subdev, wax::obj ddc,
- size_t chan, double target_freq
+ const tune_request_t &tune_request
);
/*!
@@ -70,23 +60,12 @@ namespace uhd{ namespace usrp{
* \param subdev the dboard subdevice object with properties
* \param duc the mboard dsp object with properties
* \param chan the channel of the dsp to tune
- * \param target_freq the desired center frequency
- * \param lo_offset an offset for the subdevice IF from center
+ * \param tune_request tune request instructions
* \return a tune result struct
*/
UHD_API tune_result_t tune_tx_subdev_and_dsp(
wax::obj subdev, wax::obj duc, size_t chan,
- double target_freq, double lo_offset
- );
-
- /*!
- * Tune a tx chain to the desired frequency:
- * Same as the above, except the LO offset
- * is calculated based on the subdevice and BW.
- */
- UHD_API tune_result_t tune_tx_subdev_and_dsp(
- wax::obj subdev, wax::obj duc,
- size_t chan, double target_freq
+ const tune_request_t &tune_request
);
/*!
diff --git a/host/include/uhd/utils/warning.hpp b/host/include/uhd/utils/warning.hpp
index 91d8400ab..a1e3f0d1e 100644
--- a/host/include/uhd/utils/warning.hpp
+++ b/host/include/uhd/utils/warning.hpp
@@ -19,16 +19,44 @@
#define INCLUDED_UHD_UTILS_WARNING_HPP
#include <uhd/config.hpp>
+#include <boost/function.hpp>
+#include <vector>
#include <string>
-namespace uhd{
+namespace uhd{ namespace warning{
+
+ //! Callback function type for a message handler
+ typedef boost::function<void(std::string)> handler_t;
/*!
- * Print a formatted warning string to stderr.
+ * Post a warning message to all registered handlers.
* \param msg the multiline warning message
*/
- UHD_API void print_warning(const std::string &msg);
+ UHD_API void post(const std::string &msg);
+
+ /*!
+ * Register a new handler with this name.
+ * If the name was already registered for this name,
+ * the old registered handler will be replaced.
+ * \param name a unique name for this handler
+ * \param handler the callback handler function
+ */
+ UHD_API void register_handler(const std::string &name, const handler_t &handler);
+
+ /*!
+ * Unregister a handler for this name.
+ * \param name a unique name for a registered handler
+ * \return the handler that was registered
+ * \throw error when the name was not found in the registry
+ */
+ UHD_API handler_t unregister_handler(const std::string &name);
+
+ /*!
+ * Get a list of registered handler names.
+ * \return a vector of unique string names
+ */
+ UHD_API const std::vector<std::string> registry_names(void);
-} //namespace uhd
+}} //namespace uhd::warning
#endif /* INCLUDED_UHD_UTILS_WARNING_HPP */
diff --git a/host/lib/CMakeLists.txt b/host/lib/CMakeLists.txt
index 81845de21..e4de7bcc7 100644
--- a/host/lib/CMakeLists.txt
+++ b/host/lib/CMakeLists.txt
@@ -16,6 +16,25 @@
#
########################################################################
+# Check Python Modules
+########################################################################
+PYTHON_CHECK_MODULE(
+ "Python version 2.6 or greater"
+ "platform" "platform.python_version() >= '2.6'"
+ HAVE_PYTHON_PLAT_MIN_VERSION
+)
+
+PYTHON_CHECK_MODULE(
+ "Cheetah templates 2.0.0 or greater"
+ "Cheetah" "Cheetah.Version >= '2.0.0'"
+ HAVE_PYTHON_MODULE_CHEETAH
+)
+
+IF(NOT HAVE_PYTHON_PLAT_MIN_VERSION OR NOT HAVE_PYTHON_MODULE_CHEETAH)
+ MESSAGE(FATAL_ERROR "Error: python requirements not met for the build system.")
+ENDIF(NOT HAVE_PYTHON_PLAT_MIN_VERSION OR NOT HAVE_PYTHON_MODULE_CHEETAH)
+
+########################################################################
# Helpful Macros
########################################################################
MACRO(LIBUHD_APPEND_SOURCES)
diff --git a/host/lib/transport/udp_zero_copy_asio.cpp b/host/lib/transport/udp_zero_copy_asio.cpp
index d84aeefdd..ed29864e9 100644
--- a/host/lib/transport/udp_zero_copy_asio.cpp
+++ b/host/lib/transport/udp_zero_copy_asio.cpp
@@ -336,7 +336,7 @@ template<typename Opt> static void resize_buff_helper(
else std::cout << boost::format(
"Current %s sock buff size: %d bytes"
) % name % actual_size << std::endl;
- if (actual_size < target_size) uhd::print_warning(str(boost::format(
+ if (actual_size < target_size) uhd::warning::post(str(boost::format(
"The %s buffer is smaller than the requested size.\n"
"The minimum recommended buffer size is %d bytes.\n"
"See the transport application notes on buffer resizing.\n%s"
diff --git a/host/lib/types.cpp b/host/lib/types.cpp
index 6aa82b012..4188568aa 100644
--- a/host/lib/types.cpp
+++ b/host/lib/types.cpp
@@ -17,6 +17,7 @@
#include <uhd/utils/assert.hpp>
#include <uhd/types/ranges.hpp>
+#include <uhd/types/tune_request.hpp>
#include <uhd/types/tune_result.hpp>
#include <uhd/types/clock_config.hpp>
#include <uhd/types/stream_cmd.hpp>
@@ -58,6 +59,26 @@ freq_range_t::freq_range_t(double min, double max):
}
/***********************************************************************
+ * tune request
+ **********************************************************************/
+tune_request_t::tune_request_t(double target_freq):
+ target_freq(target_freq),
+ inter_freq_policy(POLICY_AUTO),
+ dsp_freq_policy(POLICY_AUTO)
+{
+ /* NOP */
+}
+
+tune_request_t::tune_request_t(double target_freq, double lo_off):
+ target_freq(target_freq),
+ inter_freq_policy(POLICY_MANUAL),
+ inter_freq(target_freq + lo_off),
+ dsp_freq_policy(POLICY_AUTO)
+{
+ /* NOP */
+}
+
+/***********************************************************************
* tune result
**********************************************************************/
std::string tune_result_t::to_pp_string(void) const{
diff --git a/host/lib/usrp/dboard/db_basic_and_lf.cpp b/host/lib/usrp/dboard/db_basic_and_lf.cpp
index 41f6f8002..f03dd43d1 100644
--- a/host/lib/usrp/dboard/db_basic_and_lf.cpp
+++ b/host/lib/usrp/dboard/db_basic_and_lf.cpp
@@ -20,6 +20,7 @@
#include <uhd/types/ranges.hpp>
#include <uhd/utils/assert.hpp>
#include <uhd/utils/static.hpp>
+#include <uhd/utils/warning.hpp>
#include <uhd/usrp/dboard_base.hpp>
#include <uhd/usrp/dboard_manager.hpp>
#include <boost/assign/list_of.hpp>
@@ -30,6 +31,16 @@ using namespace uhd::usrp;
using namespace boost::assign;
/***********************************************************************
+ * Constants
+ **********************************************************************/
+static const uhd::dict<std::string, double> subdev_bandwidth_scalar = map_list_of
+ ("A", 1.0)
+ ("B", 1.0)
+ ("AB", 2.0)
+ ("BA", 2.0)
+;
+
+/***********************************************************************
* The basic and lf boards:
* They share a common class because only the frequency bounds differ.
**********************************************************************/
@@ -68,11 +79,11 @@ static const uhd::dict<std::string, subdev_conn_t> sd_name_to_conn = map_list_of
* Register the basic and LF dboards
**********************************************************************/
static dboard_base::sptr make_basic_rx(dboard_base::ctor_args_t args){
- return dboard_base::sptr(new basic_rx(args, 90e9));
+ return dboard_base::sptr(new basic_rx(args, 250e6));
}
static dboard_base::sptr make_basic_tx(dboard_base::ctor_args_t args){
- return dboard_base::sptr(new basic_tx(args, 90e9));
+ return dboard_base::sptr(new basic_tx(args, 250e6));
}
static dboard_base::sptr make_lf_rx(dboard_base::ctor_args_t args){
@@ -161,6 +172,10 @@ void basic_rx::rx_get(const wax::obj &key_, wax::obj &val){
val = true; //there is no LO, so it must be true!
return;
+ case SUBDEV_PROP_BANDWIDTH:
+ val = subdev_bandwidth_scalar[get_subdev_name()]*_max_freq;
+ return;
+
default: UHD_THROW_PROP_GET_ERROR();
}
}
@@ -185,6 +200,14 @@ void basic_rx::rx_set(const wax::obj &key_, const wax::obj &val){
case SUBDEV_PROP_ENABLED:
return; //always enabled
+ case SUBDEV_PROP_BANDWIDTH:
+ uhd::warning::post(
+ str(boost::format("%s: No tunable bandwidth, fixed filtered to %0.2fMHz")
+ % get_rx_id().to_pp_string() % _max_freq
+ )
+ );
+ return;
+
default: UHD_THROW_PROP_SET_ERROR();
}
}
@@ -260,6 +283,10 @@ void basic_tx::tx_get(const wax::obj &key_, wax::obj &val){
val = true; //there is no LO, so it must be true!
return;
+ case SUBDEV_PROP_BANDWIDTH:
+ val = subdev_bandwidth_scalar[get_subdev_name()]*_max_freq;
+ return;
+
default: UHD_THROW_PROP_GET_ERROR();
}
}
@@ -284,6 +311,14 @@ void basic_tx::tx_set(const wax::obj &key_, const wax::obj &val){
case SUBDEV_PROP_ENABLED:
return; //always enabled
+ case SUBDEV_PROP_BANDWIDTH:
+ uhd::warning::post(
+ str(boost::format("%s: No tunable bandwidth, fixed filtered to %0.2fMHz")
+ % get_tx_id().to_pp_string() % _max_freq
+ )
+ );
+ return;
+
default: UHD_THROW_PROP_SET_ERROR();
}
}
diff --git a/host/lib/usrp/dboard/db_dbsrx.cpp b/host/lib/usrp/dboard/db_dbsrx.cpp
index aecd7249d..85251bdf9 100644
--- a/host/lib/usrp/dboard/db_dbsrx.cpp
+++ b/host/lib/usrp/dboard/db_dbsrx.cpp
@@ -175,7 +175,7 @@ UHD_STATIC_BLOCK(reg_dbsrx_dboard){
dbsrx::dbsrx(ctor_args_t args) : rx_dboard_base(args){
//warn user about incorrect DBID on USRP1, requires R193 populated
if (this->get_iface()->get_special_props().soft_clock_divider and this->get_rx_id() == 0x000D)
- uhd::print_warning(
+ uhd::warning::post(
str(boost::format(
"DBSRX: incorrect dbid\n"
"Expected dbid 0x0002 and R193\n"
@@ -186,7 +186,7 @@ dbsrx::dbsrx(ctor_args_t args) : rx_dboard_base(args){
//warn user about incorrect DBID on non-USRP1, requires R194 populated
if (not this->get_iface()->get_special_props().soft_clock_divider and this->get_rx_id() == 0x0002)
- uhd::print_warning(
+ uhd::warning::post(
str(boost::format(
"DBSRX: incorrect dbid\n"
"Expected dbid 0x000D and R194\n"
@@ -342,7 +342,7 @@ void dbsrx::set_lo_freq(double target_freq){
//vtune is too low, try lower frequency vco
if (_max2118_read_regs.adc == 0){
if (_max2118_write_regs.osc_band == 0){
- uhd::print_warning(
+ uhd::warning::post(
str(boost::format(
"DBSRX: Tuning exceeded vco range, _max2118_write_regs.osc_band == %d\n"
) % int(_max2118_write_regs.osc_band))
@@ -356,7 +356,7 @@ void dbsrx::set_lo_freq(double target_freq){
//vtune is too high, try higher frequency vco
if (_max2118_read_regs.adc == 7){
if (_max2118_write_regs.osc_band == 7){
- uhd::print_warning(
+ uhd::warning::post(
str(boost::format(
"DBSRX: Tuning exceeded vco range, _max2118_write_regs.osc_band == %d\n"
) % int(_max2118_write_regs.osc_band))
@@ -563,7 +563,7 @@ void dbsrx::rx_get(const wax::obj &key_, wax::obj &val){
return;
case SUBDEV_PROP_BANDWIDTH:
- val = _bandwidth;
+ val = 2*_bandwidth; //_bandwidth is low-pass, we want complex double-sided
return;
default: UHD_THROW_PROP_GET_ERROR();
@@ -588,7 +588,7 @@ void dbsrx::rx_set(const wax::obj &key_, const wax::obj &val){
return; //always enabled
case SUBDEV_PROP_BANDWIDTH:
- this->set_bandwidth(val.as<double>());
+ this->set_bandwidth(val.as<double>()/2.0); //complex double-sided, we want low-pass
return;
default: UHD_THROW_PROP_SET_ERROR();
diff --git a/host/lib/usrp/dboard/db_rfx.cpp b/host/lib/usrp/dboard/db_rfx.cpp
index 3c24d90db..152198c3a 100644
--- a/host/lib/usrp/dboard/db_rfx.cpp
+++ b/host/lib/usrp/dboard/db_rfx.cpp
@@ -43,6 +43,7 @@
#include <uhd/utils/assert.hpp>
#include <uhd/utils/static.hpp>
#include <uhd/utils/algorithm.hpp>
+#include <uhd/utils/warning.hpp>
#include <uhd/usrp/dboard_id.hpp>
#include <uhd/usrp/dboard_base.hpp>
#include <uhd/usrp/dboard_manager.hpp>
@@ -456,6 +457,10 @@ void rfx_xcvr::rx_get(const wax::obj &key_, wax::obj &val){
val = this->get_locked(dboard_iface::UNIT_RX);
return;
+ case SUBDEV_PROP_BANDWIDTH:
+ val = 2*20.0e6; //20MHz low-pass, we want complex double-sided
+ return;
+
default: UHD_THROW_PROP_GET_ERROR();
}
}
@@ -481,6 +486,12 @@ void rfx_xcvr::rx_set(const wax::obj &key_, const wax::obj &val){
case SUBDEV_PROP_ENABLED:
return; //always enabled
+ case SUBDEV_PROP_BANDWIDTH:
+ uhd::warning::post(
+ str(boost::format("RFX: No tunable bandwidth, fixed filtered to 40MHz"))
+ );
+ return;
+
default: UHD_THROW_PROP_SET_ERROR();
}
}
@@ -543,6 +554,10 @@ void rfx_xcvr::tx_get(const wax::obj &key_, wax::obj &val){
val = this->get_locked(dboard_iface::UNIT_TX);
return;
+ case SUBDEV_PROP_BANDWIDTH:
+ val = 2*20.0e6; //20MHz low-pass, we want complex double-sided
+ return;
+
default: UHD_THROW_PROP_GET_ERROR();
}
}
@@ -568,6 +583,12 @@ void rfx_xcvr::tx_set(const wax::obj &key_, const wax::obj &val){
case SUBDEV_PROP_ENABLED:
return; //always enabled
+ case SUBDEV_PROP_BANDWIDTH:
+ uhd::warning::post(
+ str(boost::format("RFX: No tunable bandwidth, fixed filtered to 40MHz"))
+ );
+ return;
+
default: UHD_THROW_PROP_SET_ERROR();
}
}
diff --git a/host/lib/usrp/dboard/db_tvrx.cpp b/host/lib/usrp/dboard/db_tvrx.cpp
index d39dc3bf8..2873e3d54 100644
--- a/host/lib/usrp/dboard/db_tvrx.cpp
+++ b/host/lib/usrp/dboard/db_tvrx.cpp
@@ -459,6 +459,10 @@ void tvrx::rx_get(const wax::obj &key_, wax::obj &val){
val = true;
return;
+ case SUBDEV_PROP_BANDWIDTH:
+ val = 6.0e6;
+ return;
+
default: UHD_THROW_PROP_GET_ERROR();
}
}
@@ -479,6 +483,12 @@ void tvrx::rx_set(const wax::obj &key_, const wax::obj &val){
case SUBDEV_PROP_ENABLED:
return; //always enabled
+ case SUBDEV_PROP_BANDWIDTH:
+ uhd::warning::post(
+ str(boost::format("TVRX: No tunable bandwidth, fixed filtered to 6MHz"))
+ );
+ return;
+
default: UHD_THROW_PROP_SET_ERROR();
}
}
diff --git a/host/lib/usrp/dboard/db_unknown.cpp b/host/lib/usrp/dboard/db_unknown.cpp
index ec7ab440b..a342471c4 100644
--- a/host/lib/usrp/dboard/db_unknown.cpp
+++ b/host/lib/usrp/dboard/db_unknown.cpp
@@ -19,6 +19,7 @@
#include <uhd/types/ranges.hpp>
#include <uhd/utils/assert.hpp>
#include <uhd/utils/static.hpp>
+#include <uhd/utils/warning.hpp>
#include <uhd/usrp/dboard_base.hpp>
#include <uhd/usrp/dboard_manager.hpp>
#include <boost/assign/list_of.hpp>
@@ -134,6 +135,10 @@ void unknown_rx::rx_get(const wax::obj &key_, wax::obj &val){
val = true; //there is no LO, so it must be true!
return;
+ case SUBDEV_PROP_BANDWIDTH:
+ val = 0.0;
+ return;
+
default: UHD_THROW_PROP_GET_ERROR();
}
}
@@ -158,12 +163,18 @@ void unknown_rx::rx_set(const wax::obj &key_, const wax::obj &val){
case SUBDEV_PROP_ENABLED:
return; //always enabled
+ case SUBDEV_PROP_BANDWIDTH:
+ uhd::warning::post(
+ str(boost::format("Unknown Daughterboard: No tunable bandwidth, fixed filtered to 0.0MHz"))
+ );
+ return;
+
default: UHD_THROW_PROP_SET_ERROR();
}
}
/***********************************************************************
- * Basic and LF TX dboard
+ * Unknown TX dboard
**********************************************************************/
unknown_tx::unknown_tx(ctor_args_t args) : tx_dboard_base(args){
/* NOP */
@@ -230,6 +241,10 @@ void unknown_tx::tx_get(const wax::obj &key_, wax::obj &val){
val = true; //there is no LO, so it must be true!
return;
+ case SUBDEV_PROP_BANDWIDTH:
+ val = 0.0;
+ return;
+
default: UHD_THROW_PROP_GET_ERROR();
}
}
@@ -254,6 +269,12 @@ void unknown_tx::tx_set(const wax::obj &key_, const wax::obj &val){
case SUBDEV_PROP_ENABLED:
return; //always enabled
+ case SUBDEV_PROP_BANDWIDTH:
+ uhd::warning::post(
+ str(boost::format("Unknown Daughterboard: No tunable bandwidth, fixed filtered to 0.0MHz"))
+ );
+ return;
+
default: UHD_THROW_PROP_SET_ERROR();
}
}
diff --git a/host/lib/usrp/dboard/db_wbx.cpp b/host/lib/usrp/dboard/db_wbx.cpp
index 907268aac..572f5de97 100644
--- a/host/lib/usrp/dboard/db_wbx.cpp
+++ b/host/lib/usrp/dboard/db_wbx.cpp
@@ -71,6 +71,7 @@
#include <uhd/utils/assert.hpp>
#include <uhd/utils/static.hpp>
#include <uhd/utils/algorithm.hpp>
+#include <uhd/utils/warning.hpp>
#include <uhd/usrp/dboard_base.hpp>
#include <uhd/usrp/dboard_manager.hpp>
#include <boost/assign/list_of.hpp>
@@ -525,6 +526,10 @@ void wbx_xcvr::rx_get(const wax::obj &key_, wax::obj &val){
val = this->get_locked(dboard_iface::UNIT_RX);
return;
+ case SUBDEV_PROP_BANDWIDTH:
+ val = 2*20.0e6; //20MHz low-pass, we want complex double-sided
+ return;
+
default: UHD_THROW_PROP_GET_ERROR();
}
}
@@ -550,6 +555,12 @@ void wbx_xcvr::rx_set(const wax::obj &key_, const wax::obj &val){
case SUBDEV_PROP_ENABLED:
return; //always enabled
+ case SUBDEV_PROP_BANDWIDTH:
+ uhd::warning::post(
+ str(boost::format("WBX: No tunable bandwidth, fixed filtered to 40MHz"))
+ );
+ return;
+
default: UHD_THROW_PROP_SET_ERROR();
}
}
@@ -616,6 +627,10 @@ void wbx_xcvr::tx_get(const wax::obj &key_, wax::obj &val){
val = this->get_locked(dboard_iface::UNIT_TX);
return;
+ case SUBDEV_PROP_BANDWIDTH:
+ val = 2*20.0e6; //20MHz low-pass, we want complex double-sided
+ return;
+
default: UHD_THROW_PROP_GET_ERROR();
}
}
@@ -641,6 +656,12 @@ void wbx_xcvr::tx_set(const wax::obj &key_, const wax::obj &val){
case SUBDEV_PROP_ENABLED:
return; //always enabled
+ case SUBDEV_PROP_BANDWIDTH:
+ uhd::warning::post(
+ str(boost::format("WBX: No tunable bandwidth, fixed filtered to 40MHz"))
+ );
+ return;
+
default: UHD_THROW_PROP_SET_ERROR();
}
}
diff --git a/host/lib/usrp/dboard/db_xcvr2450.cpp b/host/lib/usrp/dboard/db_xcvr2450.cpp
index fb1367113..be0e42b92 100644
--- a/host/lib/usrp/dboard/db_xcvr2450.cpp
+++ b/host/lib/usrp/dboard/db_xcvr2450.cpp
@@ -626,7 +626,7 @@ void xcvr2450::rx_get(const wax::obj &key_, wax::obj &val){
return;
case SUBDEV_PROP_BANDWIDTH:
- val = _rx_bandwidth;
+ val = 2*_rx_bandwidth; //_tx_bandwidth is low-pass, we want complex double-sided
return;
default: UHD_THROW_PROP_GET_ERROR();
@@ -652,7 +652,7 @@ void xcvr2450::rx_set(const wax::obj &key_, const wax::obj &val){
return;
case SUBDEV_PROP_BANDWIDTH:
- this->set_rx_bandwidth(val.as<double>());
+ this->set_rx_bandwidth(val.as<double>()/2.0); //complex double-sided, we want low-pass
return;
case SUBDEV_PROP_ENABLED:
@@ -725,7 +725,7 @@ void xcvr2450::tx_get(const wax::obj &key_, wax::obj &val){
return;
case SUBDEV_PROP_BANDWIDTH:
- val = _tx_bandwidth;
+ val = 2*_tx_bandwidth; //_tx_bandwidth is low-pass, we want complex double-sided
return;
default: UHD_THROW_PROP_GET_ERROR();
@@ -747,7 +747,7 @@ void xcvr2450::tx_set(const wax::obj &key_, const wax::obj &val){
return;
case SUBDEV_PROP_BANDWIDTH:
- this->set_tx_bandwidth(val.as<double>());
+ this->set_tx_bandwidth(val.as<double>()/2.0); //complex double-sided, we want low-pass
return;
case SUBDEV_PROP_ANTENNA:
diff --git a/host/lib/usrp/dboard_manager.cpp b/host/lib/usrp/dboard_manager.cpp
index d73a698ae..5a98bb8eb 100644
--- a/host/lib/usrp/dboard_manager.cpp
+++ b/host/lib/usrp/dboard_manager.cpp
@@ -189,7 +189,7 @@ static args_t get_dboard_args(
//verify that there is a registered constructor for this id
if (not get_id_to_args_map().has_key(dboard_id)){
- uhd::print_warning(str(boost::format(
+ uhd::warning::post(str(boost::format(
"Unknown dboard ID: %s.\n"
) % dboard_id.to_pp_string()));
return get_dboard_args(unit, dboard_id, true);
@@ -217,7 +217,7 @@ dboard_manager_impl::dboard_manager_impl(
//warn for invalid dboard id xcvr combinations
if (rx_dboard_is_xcvr != this_dboard_is_xcvr or tx_dboard_is_xcvr != this_dboard_is_xcvr){
- uhd::print_warning(str(boost::format(
+ uhd::warning::post(str(boost::format(
"Unknown transceiver board ID combination...\n"
"RX dboard ID: %s\n"
"TX dboard ID: %s\n"
diff --git a/host/lib/usrp/multi_usrp.cpp b/host/lib/usrp/multi_usrp.cpp
index 443b91594..876f1a3fc 100644
--- a/host/lib/usrp/multi_usrp.cpp
+++ b/host/lib/usrp/multi_usrp.cpp
@@ -145,7 +145,7 @@ public:
time_spec_t time_0 = _mboard(0)[MBOARD_PROP_TIME_NOW].as<time_spec_t>();
time_spec_t time_i = _mboard(m)[MBOARD_PROP_TIME_NOW].as<time_spec_t>();
if (time_i < time_0 or (time_i - time_0) > time_spec_t(0.01)){ //10 ms: greater than RTT but not too big
- uhd::print_warning(str(boost::format(
+ uhd::warning::post(str(boost::format(
"Detected time deviation between board %d and board 0.\n"
"Board 0 time is %f seconds.\n"
"Board %d time is %f seconds.\n"
@@ -154,6 +154,15 @@ public:
}
}
+ bool get_time_synchronized(void){
+ for (size_t m = 1; m < get_num_mboards(); m++){
+ time_spec_t time_0 = _mboard(0)[MBOARD_PROP_TIME_NOW].as<time_spec_t>();
+ time_spec_t time_i = _mboard(m)[MBOARD_PROP_TIME_NOW].as<time_spec_t>();
+ if (time_i < time_0 or (time_i - time_0) > time_spec_t(0.01)) return false;
+ }
+ return true;
+ }
+
void issue_stream_cmd(const stream_cmd_t &stream_cmd){
for (size_t m = 0; m < get_num_mboards(); m++){
_mboard(m)[MBOARD_PROP_STREAM_CMD] = stream_cmd;
@@ -210,15 +219,9 @@ public:
return _rx_dsp(0)[DSP_PROP_HOST_RATE].as<double>();
}
- tune_result_t set_rx_freq(double target_freq, size_t chan){
- tune_result_t r = tune_rx_subdev_and_dsp(_rx_subdev(chan), _rx_dsp(chan/rx_cpm()), chan%rx_cpm(), target_freq);
- do_tune_freq_warning_message(target_freq, get_rx_freq(chan), "RX");
- return r;
- }
-
- tune_result_t set_rx_freq(double target_freq, double lo_off, size_t chan){
- tune_result_t r = tune_rx_subdev_and_dsp(_rx_subdev(chan), _rx_dsp(chan/rx_cpm()), chan%rx_cpm(), target_freq, lo_off);
- do_tune_freq_warning_message(target_freq, get_rx_freq(chan), "RX");
+ tune_result_t set_rx_freq(const tune_request_t &tune_request, size_t chan){
+ tune_result_t r = tune_rx_subdev_and_dsp(_rx_subdev(chan), _rx_dsp(chan/rx_cpm()), chan%rx_cpm(), tune_request);
+ do_tune_freq_warning_message(tune_request.target_freq, get_rx_freq(chan), "RX");
return r;
}
@@ -314,15 +317,9 @@ public:
return _tx_dsp(0)[DSP_PROP_HOST_RATE].as<double>();
}
- tune_result_t set_tx_freq(double target_freq, size_t chan){
- tune_result_t r = tune_tx_subdev_and_dsp(_tx_subdev(chan), _tx_dsp(chan/tx_cpm()), chan%tx_cpm(), target_freq);
- do_tune_freq_warning_message(target_freq, get_tx_freq(chan), "TX");
- return r;
- }
-
- tune_result_t set_tx_freq(double target_freq, double lo_off, size_t chan){
- tune_result_t r = tune_tx_subdev_and_dsp(_tx_subdev(chan), _tx_dsp(chan/tx_cpm()), chan%tx_cpm(), target_freq, lo_off);
- do_tune_freq_warning_message(target_freq, get_tx_freq(chan), "TX");
+ tune_result_t set_tx_freq(const tune_request_t &tune_request, size_t chan){
+ tune_result_t r = tune_tx_subdev_and_dsp(_tx_subdev(chan), _tx_dsp(chan/tx_cpm()), chan%tx_cpm(), tune_request);
+ do_tune_freq_warning_message(tune_request.target_freq, get_tx_freq(chan), "TX");
return r;
}
diff --git a/host/lib/usrp/single_usrp.cpp b/host/lib/usrp/single_usrp.cpp
index 5e57849b8..a0456d1f0 100644
--- a/host/lib/usrp/single_usrp.cpp
+++ b/host/lib/usrp/single_usrp.cpp
@@ -146,15 +146,9 @@ public:
return _rx_dsp()[DSP_PROP_HOST_RATE].as<double>();
}
- tune_result_t set_rx_freq(double target_freq, size_t chan){
- tune_result_t r = tune_rx_subdev_and_dsp(_rx_subdev(chan), _rx_dsp(), chan, target_freq);
- do_tune_freq_warning_message(target_freq, get_rx_freq(chan), "RX");
- return r;
- }
-
- tune_result_t set_rx_freq(double target_freq, double lo_off, size_t chan){
- tune_result_t r = tune_rx_subdev_and_dsp(_rx_subdev(chan), _rx_dsp(), chan, target_freq, lo_off);
- do_tune_freq_warning_message(target_freq, get_rx_freq(chan), "RX");
+ tune_result_t set_rx_freq(const tune_request_t &tune_request, size_t chan){
+ tune_result_t r = tune_rx_subdev_and_dsp(_rx_subdev(chan), _rx_dsp(), chan, tune_request);
+ do_tune_freq_warning_message(tune_request.target_freq, get_rx_freq(chan), "RX");
return r;
}
@@ -238,15 +232,9 @@ public:
return _tx_dsp()[DSP_PROP_HOST_RATE].as<double>();
}
- tune_result_t set_tx_freq(double target_freq, size_t chan){
- tune_result_t r = tune_tx_subdev_and_dsp(_tx_subdev(chan), _tx_dsp(), chan, target_freq);
- do_tune_freq_warning_message(target_freq, get_tx_freq(chan), "TX");
- return r;
- }
-
- tune_result_t set_tx_freq(double target_freq, double lo_off, size_t chan){
- tune_result_t r = tune_tx_subdev_and_dsp(_tx_subdev(chan), _tx_dsp(), chan, target_freq, lo_off);
- do_tune_freq_warning_message(target_freq, get_tx_freq(chan), "TX");
+ tune_result_t set_tx_freq(const tune_request_t &tune_request, size_t chan){
+ tune_result_t r = tune_tx_subdev_and_dsp(_tx_subdev(chan), _tx_dsp(), chan, tune_request);
+ do_tune_freq_warning_message(tune_request.target_freq, get_tx_freq(chan), "TX");
return r;
}
diff --git a/host/lib/usrp/tune_helper.cpp b/host/lib/usrp/tune_helper.cpp
index 7633c67f2..fa40a8a26 100644
--- a/host/lib/usrp/tune_helper.cpp
+++ b/host/lib/usrp/tune_helper.cpp
@@ -19,6 +19,7 @@
#include <uhd/usrp/subdev_props.hpp>
#include <uhd/usrp/dsp_props.hpp>
#include <uhd/usrp/dboard_iface.hpp> //unit_t
+#include <uhd/utils/algorithm.hpp>
#include <boost/math/special_functions/sign.hpp>
#include <cmath>
@@ -28,55 +29,99 @@ using namespace uhd::usrp;
/***********************************************************************
* Tune Helper Functions
**********************************************************************/
-static tune_result_t tune_xx_subdev_and_dxc(
+static tune_result_t tune_xx_subdev_and_dsp(
dboard_iface::unit_t unit,
- wax::obj subdev, wax::obj dxc, size_t chan,
- double target_freq, double lo_offset
+ wax::obj subdev, wax::obj dsp, size_t chan,
+ const tune_request_t &tune_request
){
wax::obj subdev_freq_proxy = subdev[SUBDEV_PROP_FREQ];
- std::string freq_name = dxc[DSP_PROP_FREQ_SHIFT_NAMES].as<prop_names_t>().at(chan);
- wax::obj dxc_freq_proxy = dxc[named_prop_t(DSP_PROP_FREQ_SHIFT, freq_name)];
- double dxc_sample_rate = dxc[DSP_PROP_CODEC_RATE].as<double>();
+ std::string freq_name = dsp[DSP_PROP_FREQ_SHIFT_NAMES].as<prop_names_t>().at(chan);
+ wax::obj dsp_freq_proxy = dsp[named_prop_t(DSP_PROP_FREQ_SHIFT, freq_name)];
+ double dsp_sample_rate = dsp[DSP_PROP_CODEC_RATE].as<double>();
- // Ask the d'board to tune as closely as it can to target_freq+lo_offset
- double target_inter_freq = target_freq + lo_offset;
- subdev_freq_proxy = target_inter_freq;
- double actual_inter_freq = subdev_freq_proxy.as<double>();
-
- //perform the correction correction for dxc rates outside of nyquist
- double delta_freq = std::fmod(target_freq - actual_inter_freq, dxc_sample_rate);
- bool outside_of_nyquist = std::abs(delta_freq) > dxc_sample_rate/2.0;
- double target_dxc_freq = (outside_of_nyquist)?
- boost::math::sign(delta_freq)*dxc_sample_rate - delta_freq : -delta_freq;
+ //------------------------------------------------------------------
+ //-- calculate the LO offset, only used with automatic policy
+ //------------------------------------------------------------------
+ double lo_offset = 0.0;
+ if (subdev[SUBDEV_PROP_USE_LO_OFFSET].as<bool>()){
+ //If the local oscillator will be in the passband, use an offset.
+ //But constrain the LO offset by the width of the filter bandwidth.
+ double rate = dsp[DSP_PROP_HOST_RATE].as<double>();
+ double bw = subdev[SUBDEV_PROP_BANDWIDTH].as<double>();
+ if (bw > rate) lo_offset = std::min((bw - rate)/2, rate/2);
+ }
- //invert the sign on the dxc freq given the following conditions
- if (unit == dboard_iface::UNIT_TX) target_dxc_freq *= -1.0;
+ //------------------------------------------------------------------
+ //-- set the intermediate frequency depending upon the IF policy
+ //------------------------------------------------------------------
+ double target_inter_freq = 0.0;
+ switch (tune_request.inter_freq_policy){
+ case tune_request_t::POLICY_AUTO:
+ target_inter_freq = tune_request.target_freq + lo_offset;
+ subdev_freq_proxy = target_inter_freq;
+ break;
+
+ case tune_request_t::POLICY_MANUAL:
+ target_inter_freq = tune_request.inter_freq;
+ subdev_freq_proxy = target_inter_freq;
+ break;
+
+ case tune_request_t::POLICY_NONE: break; //does not set
+ }
+ double actual_inter_freq = subdev_freq_proxy.as<double>();
- dxc_freq_proxy = target_dxc_freq;
- double actual_dxc_freq = dxc_freq_proxy.as<double>();
+ //------------------------------------------------------------------
+ //-- calculate the dsp freq, only used with automatic policy
+ //------------------------------------------------------------------
+ double delta_freq = std::fmod(tune_request.target_freq - actual_inter_freq, dsp_sample_rate);
+ bool outside_of_nyquist = std::abs(delta_freq) > dsp_sample_rate/2.0;
+ double target_dsp_freq = (outside_of_nyquist)?
+ boost::math::sign(delta_freq)*dsp_sample_rate - delta_freq : -delta_freq;
+
+ //invert the sign on the dsp freq given the following conditions
+ if (unit == dboard_iface::UNIT_TX) target_dsp_freq *= -1.0;
+
+ //------------------------------------------------------------------
+ //-- set the dsp frequency depending upon the dsp frequency policy
+ //------------------------------------------------------------------
+ switch (tune_request.dsp_freq_policy){
+ case tune_request_t::POLICY_AUTO:
+ dsp_freq_proxy = target_dsp_freq;
+ break;
+
+ case tune_request_t::POLICY_MANUAL:
+ target_dsp_freq = tune_request.dsp_freq;
+ dsp_freq_proxy = target_dsp_freq;
+ break;
+
+ case tune_request_t::POLICY_NONE: break; //does not set
+ }
+ double actual_dsp_freq = dsp_freq_proxy.as<double>();
- //load and return the tune result
+ //------------------------------------------------------------------
+ //-- load and return the tune result
+ //------------------------------------------------------------------
tune_result_t tune_result;
tune_result.target_inter_freq = target_inter_freq;
tune_result.actual_inter_freq = actual_inter_freq;
- tune_result.target_dsp_freq = target_dxc_freq;
- tune_result.actual_dsp_freq = actual_dxc_freq;
+ tune_result.target_dsp_freq = target_dsp_freq;
+ tune_result.actual_dsp_freq = actual_dsp_freq;
return tune_result;
}
-static double derive_freq_from_xx_subdev_and_dxc(
+static double derive_freq_from_xx_subdev_and_dsp(
dboard_iface::unit_t unit,
- wax::obj subdev, wax::obj dxc, size_t chan
+ wax::obj subdev, wax::obj dsp, size_t chan
){
//extract actual dsp and IF frequencies
double actual_inter_freq = subdev[SUBDEV_PROP_FREQ].as<double>();
- std::string freq_name = dxc[DSP_PROP_FREQ_SHIFT_NAMES].as<prop_names_t>().at(chan);
- double actual_dxc_freq = dxc[named_prop_t(DSP_PROP_FREQ_SHIFT, freq_name)].as<double>();
+ std::string freq_name = dsp[DSP_PROP_FREQ_SHIFT_NAMES].as<prop_names_t>().at(chan);
+ double actual_dsp_freq = dsp[named_prop_t(DSP_PROP_FREQ_SHIFT, freq_name)].as<double>();
- //invert the sign on the dxc freq given the following conditions
- if (unit == dboard_iface::UNIT_TX) actual_dxc_freq *= -1.0;
+ //invert the sign on the dsp freq given the following conditions
+ if (unit == dboard_iface::UNIT_TX) actual_dsp_freq *= -1.0;
- return actual_inter_freq - actual_dxc_freq;
+ return actual_inter_freq - actual_dsp_freq;
}
/***********************************************************************
@@ -84,27 +129,15 @@ static double derive_freq_from_xx_subdev_and_dxc(
**********************************************************************/
tune_result_t usrp::tune_rx_subdev_and_dsp(
wax::obj subdev, wax::obj ddc, size_t chan,
- double target_freq, double lo_offset
-){
- return tune_xx_subdev_and_dxc(dboard_iface::UNIT_RX, subdev, ddc, chan, target_freq, lo_offset);
-}
-
-tune_result_t usrp::tune_rx_subdev_and_dsp(
- wax::obj subdev, wax::obj ddc,
- size_t chan, double target_freq
+ const tune_request_t &tune_request
){
- double lo_offset = 0.0;
- //if the local oscillator will be in the passband, use an offset
- if (subdev[SUBDEV_PROP_USE_LO_OFFSET].as<bool>()){
- lo_offset = 2.0*ddc[DSP_PROP_HOST_RATE].as<double>();
- }
- return tune_rx_subdev_and_dsp(subdev, ddc, chan, target_freq, lo_offset);
+ return tune_xx_subdev_and_dsp(dboard_iface::UNIT_RX, subdev, ddc, chan, tune_request);
}
double usrp::derive_freq_from_rx_subdev_and_dsp(
wax::obj subdev, wax::obj ddc, size_t chan
){
- return derive_freq_from_xx_subdev_and_dxc(dboard_iface::UNIT_RX, subdev, ddc, chan);
+ return derive_freq_from_xx_subdev_and_dsp(dboard_iface::UNIT_RX, subdev, ddc, chan);
}
/***********************************************************************
@@ -112,25 +145,13 @@ double usrp::derive_freq_from_rx_subdev_and_dsp(
**********************************************************************/
tune_result_t usrp::tune_tx_subdev_and_dsp(
wax::obj subdev, wax::obj duc, size_t chan,
- double target_freq, double lo_offset
+ const tune_request_t &tune_request
){
- return tune_xx_subdev_and_dxc(dboard_iface::UNIT_TX, subdev, duc, chan, target_freq, lo_offset);
-}
-
-tune_result_t usrp::tune_tx_subdev_and_dsp(
- wax::obj subdev, wax::obj duc,
- size_t chan, double target_freq
-){
- double lo_offset = 0.0;
- //if the local oscillator will be in the passband, use an offset
- if (subdev[SUBDEV_PROP_USE_LO_OFFSET].as<bool>()){
- lo_offset = 2.0*duc[DSP_PROP_HOST_RATE].as<double>();
- }
- return tune_tx_subdev_and_dsp(subdev, duc, chan, target_freq, lo_offset);
+ return tune_xx_subdev_and_dsp(dboard_iface::UNIT_TX, subdev, duc, chan, tune_request);
}
double usrp::derive_freq_from_tx_subdev_and_dsp(
wax::obj subdev, wax::obj duc, size_t chan
){
- return derive_freq_from_xx_subdev_and_dxc(dboard_iface::UNIT_TX, subdev, duc, chan);
+ return derive_freq_from_xx_subdev_and_dsp(dboard_iface::UNIT_TX, subdev, duc, chan);
}
diff --git a/host/lib/usrp/usrp1/mboard_impl.cpp b/host/lib/usrp/usrp1/mboard_impl.cpp
index fe3774eb4..669b20efa 100644
--- a/host/lib/usrp/usrp1/mboard_impl.cpp
+++ b/host/lib/usrp/usrp1/mboard_impl.cpp
@@ -98,7 +98,7 @@ static boost::uint32_t calc_rx_mux(
// for all quadrature sources: Z = 0
// for mixed sources: warning + Z = 0
int Z = (num_quads > 0)? 0 : 1;
- if (num_quads != 0 and num_reals != 0) uhd::print_warning(
+ if (num_quads != 0 and num_reals != 0) uhd::warning::post(
"Mixing real and quadrature rx subdevices is not supported.\n"
"The Q input to the real source(s) will be non-zero.\n"
);
diff --git a/host/lib/usrp/usrp1/usrp1_impl.cpp b/host/lib/usrp/usrp1/usrp1_impl.cpp
index 276ca86f6..314384e72 100644
--- a/host/lib/usrp/usrp1/usrp1_impl.cpp
+++ b/host/lib/usrp/usrp1/usrp1_impl.cpp
@@ -64,7 +64,7 @@ static device_addrs_t usrp1_find(const device_addr_t &hint)
);
}
catch(...){
- uhd::print_warning(
+ uhd::warning::post(
"Could not locate USRP1 firmware.\n"
"Please install the images package.\n"
);
diff --git a/host/lib/usrp/wrapper_utils.hpp b/host/lib/usrp/wrapper_utils.hpp
index aee230fc0..6f9fdbfca 100644
--- a/host/lib/usrp/wrapper_utils.hpp
+++ b/host/lib/usrp/wrapper_utils.hpp
@@ -40,7 +40,7 @@ static inline void do_samp_rate_warning_message(
){
static const double max_allowed_error = 1.0; //Sps
if (std::abs(target_rate - actual_rate) > max_allowed_error){
- uhd::print_warning(str(boost::format(
+ uhd::warning::post(str(boost::format(
"The hardware does not support the requested %s sample rate:\n"
"Target sample rate: %f MSps\n"
"Actual sample rate: %f MSps\n"
@@ -55,7 +55,7 @@ static inline void do_tune_freq_warning_message(
){
static const double max_allowed_error = 1.0; //Hz
if (std::abs(target_freq - actual_freq) > max_allowed_error){
- uhd::print_warning(str(boost::format(
+ uhd::warning::post(str(boost::format(
"The hardware does not support the requested %s frequency:\n"
"Target frequency: %f MHz\n"
"Actual frequency: %f MHz\n"
diff --git a/host/lib/utils/thread_priority.cpp b/host/lib/utils/thread_priority.cpp
index f09d1b1d6..40b74f655 100644
--- a/host/lib/utils/thread_priority.cpp
+++ b/host/lib/utils/thread_priority.cpp
@@ -26,7 +26,7 @@ bool uhd::set_thread_priority_safe(float priority, bool realtime){
set_thread_priority(priority, realtime);
return true;
}catch(const std::exception &e){
- uhd::print_warning(str(boost::format(
+ uhd::warning::post(str(boost::format(
"%s\n"
"Failed to set thread priority %d (%s):\n"
"Performance may be negatively affected.\n"
diff --git a/host/lib/utils/warning.cpp b/host/lib/utils/warning.cpp
index 8a7d35a23..05be7ae4d 100644
--- a/host/lib/utils/warning.cpp
+++ b/host/lib/utils/warning.cpp
@@ -17,16 +17,67 @@
#include <uhd/utils/warning.hpp>
#include <uhd/utils/algorithm.hpp>
+#include <uhd/utils/static.hpp>
+#include <uhd/types/dict.hpp>
#include <boost/foreach.hpp>
+#include <sstream>
+#include <stdexcept>
#include <iostream>
#include <vector>
using namespace uhd;
-void uhd::print_warning(const std::string &msg){
- //print the warning message
- std::cerr << std::endl << "Warning:" << std::endl;
+/***********************************************************************
+ * Registry implementation
+ **********************************************************************/
+//create the registry for the handlers
+typedef uhd::dict<std::string, warning::handler_t> registry_t;
+UHD_SINGLETON_FCN(registry_t, get_registry)
+
+//the default warning handler
+static void stderr_warning(const std::string &msg){
+ std::cerr << msg;
+}
+
+//register a default handler
+UHD_STATIC_BLOCK(warning_register_default){
+ warning::register_handler("default", &stderr_warning);
+}
+
+/***********************************************************************
+ * Post + format
+ **********************************************************************/
+void warning::post(const std::string &msg){
+ std::stringstream ss;
+
+ //format the warning message
+ ss << std::endl << "Warning:" << std::endl;
BOOST_FOREACH(const std::string &line, std::split_string(msg, "\n")){
- std::cerr << " " << line << std::endl;
+ ss << " " << line << std::endl;
+ }
+
+ //post the formatted message
+ BOOST_FOREACH(const std::string &name, get_registry().keys()){
+ get_registry()[name](ss.str());
}
}
+
+/***********************************************************************
+ * Registry accessor functions
+ **********************************************************************/
+void warning::register_handler(
+ const std::string &name, const handler_t &handler
+){
+ get_registry()[name] = handler;
+}
+
+warning::handler_t warning::unregister_handler(const std::string &name){
+ if (not get_registry().has_key(name)) throw std::runtime_error(
+ "The warning registry does not have a handler registered to " + name
+ );
+ return get_registry().pop(name);
+}
+
+const std::vector<std::string> warning::registry_names(void){
+ return get_registry().keys();
+}
diff --git a/host/test/tune_helper_test.cpp b/host/test/tune_helper_test.cpp
index 1ef4af330..e0500ae3f 100644
--- a/host/test/tune_helper_test.cpp
+++ b/host/test/tune_helper_test.cpp
@@ -91,6 +91,44 @@ private:
}
};
+class dummy_subdev_bw : public wax::obj{
+private:
+ void get(const wax::obj &key, wax::obj &val){
+ switch(key.as<subdev_prop_t>()){
+
+ case SUBDEV_PROP_FREQ:
+ val = _freq;
+ return;
+
+ case SUBDEV_PROP_USE_LO_OFFSET:
+ val = true;
+ return;
+
+ case SUBDEV_PROP_BANDWIDTH:
+ val = _bandwidth;
+ return;
+
+ default: UHD_THROW_PROP_GET_ERROR();
+ }
+ }
+
+ void set(const wax::obj &key, const wax::obj &val){
+ switch(key.as<subdev_prop_t>()){
+ case SUBDEV_PROP_FREQ:
+ _freq = val.as<double>();
+ return;
+
+ case SUBDEV_PROP_BANDWIDTH:
+ _bandwidth = val.as<double>();
+ return;
+
+ default: UHD_THROW_PROP_SET_ERROR();
+ }
+ }
+
+ double _freq, _bandwidth;
+};
+
class dummy_dsp : public wax::obj{
public:
dummy_dsp(double codec_rate):
@@ -106,6 +144,10 @@ private:
val = _codec_rate;
return;
+ case DSP_PROP_HOST_RATE:
+ val = _host_rate;
+ return;
+
case DSP_PROP_FREQ_SHIFT:
val = _freq_shift;
return;
@@ -125,11 +167,15 @@ private:
_freq_shift = val.as<double>();
return;
+ case DSP_PROP_HOST_RATE:
+ _host_rate = val.as<double>();
+ return;
+
default: UHD_THROW_PROP_SET_ERROR();
}
}
- double _codec_rate, _freq_shift;
+ double _codec_rate, _freq_shift, _host_rate;
};
/***********************************************************************
@@ -141,7 +187,7 @@ BOOST_AUTO_TEST_CASE(test_tune_helper_rx){
dummy_subdev subdev(1e6);
dummy_dsp dsp(100e6);
- std::cout << "Testing tune helper RX automatic LO offset" << std::endl;
+ std::cout << "Testing tune helper RX automatic IF offset" << std::endl;
tune_result_t tr = tune_rx_subdev_and_dsp(subdev.get_link(), dsp.get_link(), 0, 2.3451e9);
std::cout << tr.to_pp_string() << std::endl;
BOOST_CHECK_CLOSE(tr.actual_inter_freq, 2.345e9, tolerance);
@@ -155,7 +201,7 @@ BOOST_AUTO_TEST_CASE(test_tune_helper_tx){
dummy_subdev subdev(1e6);
dummy_dsp dsp(100e6);
- std::cout << "Testing tune helper TX automatic LO offset" << std::endl;
+ std::cout << "Testing tune helper TX automatic IF offset" << std::endl;
tune_result_t tr = tune_tx_subdev_and_dsp(subdev.get_link(), dsp.get_link(), 0, 2.3451e9);
std::cout << tr.to_pp_string() << std::endl;
BOOST_CHECK_CLOSE(tr.actual_inter_freq, 2.345e9, tolerance);
@@ -178,3 +224,30 @@ BOOST_AUTO_TEST_CASE(test_tune_helper_rx_nyquist){
double freq_derived = derive_freq_from_rx_subdev_and_dsp(subdev.get_link(), dsp.get_link(), 0);
BOOST_CHECK_CLOSE(freq_derived, -45e6, tolerance);
}
+
+BOOST_AUTO_TEST_CASE(test_tune_helper_rx_lo_off){
+ dummy_subdev_bw subdev;
+ dummy_dsp dsp(100e6);
+ tune_result_t tr;
+
+ std::cout << "Testing tune helper RX automatic LO offset B >> fs" << std::endl;
+ subdev[SUBDEV_PROP_BANDWIDTH] = double(40e6);
+ dsp[DSP_PROP_HOST_RATE] = double(4e6);
+ tr = tune_rx_subdev_and_dsp(subdev.get_link(), dsp.get_link(), 0, 2.45e9);
+ std::cout << tr.to_pp_string() << std::endl;
+ BOOST_CHECK_CLOSE(tr.actual_inter_freq, 2.45e9+4e6/2, tolerance);
+
+ std::cout << "Testing tune helper RX automatic LO offset B > fs" << std::endl;
+ subdev[SUBDEV_PROP_BANDWIDTH] = double(40e6);
+ dsp[DSP_PROP_HOST_RATE] = double(25e6);
+ tr = tune_rx_subdev_and_dsp(subdev.get_link(), dsp.get_link(), 0, 2.45e9);
+ std::cout << tr.to_pp_string() << std::endl;
+ BOOST_CHECK_CLOSE(tr.actual_inter_freq, 2.45e9+(40e6-25e6)/2, tolerance);
+
+ std::cout << "Testing tune helper RX automatic LO offset B < fs" << std::endl;
+ subdev[SUBDEV_PROP_BANDWIDTH] = double(20e6);
+ dsp[DSP_PROP_HOST_RATE] = double(25e6);
+ tr = tune_rx_subdev_and_dsp(subdev.get_link(), dsp.get_link(), 0, 2.45e9);
+ std::cout << tr.to_pp_string() << std::endl;
+ BOOST_CHECK_CLOSE(tr.actual_inter_freq, 2.45e9, tolerance);
+}
diff --git a/host/test/warning_test.cpp b/host/test/warning_test.cpp
index 6202c4270..db19955de 100644
--- a/host/test/warning_test.cpp
+++ b/host/test/warning_test.cpp
@@ -19,9 +19,9 @@
#include <uhd/utils/warning.hpp>
#include <iostream>
-BOOST_AUTO_TEST_CASE(test_print_warning){
+BOOST_AUTO_TEST_CASE(test_warning_post){
std::cerr << "---begin print test ---" << std::endl;
- uhd::print_warning(
+ uhd::warning::post(
"This is a test print for a warning message.\n"
"And this is the second line of the test print.\n"
);