aboutsummaryrefslogtreecommitdiffstats
path: root/host
diff options
context:
space:
mode:
authorMartin Braun <martin.braun@ettus.com>2017-07-17 18:44:48 -0700
committerMartin Braun <martin.braun@ettus.com>2017-07-17 18:44:48 -0700
commit3d5176874f90f9155c1591656df8a7d663b3c712 (patch)
tree3693c123057a9420b273f595e6609fb32343130c /host
parent47c853f9dd518ef25d23b94bc0e77dbda3c2ddab (diff)
parent684fd3a3ffaf31b9fa726ccf2fdea2627f6ea10d (diff)
downloaduhd-3d5176874f90f9155c1591656df8a7d663b3c712.tar.gz
uhd-3d5176874f90f9155c1591656df8a7d663b3c712.tar.bz2
uhd-3d5176874f90f9155c1591656df8a7d663b3c712.zip
Merge branch 'maint'
Diffstat (limited to 'host')
-rw-r--r--host/examples/latency_test.cpp79
-rw-r--r--host/lib/usrp/dboard/db_sbx_common.cpp27
-rw-r--r--host/lib/usrp/dboard/db_sbx_common.hpp29
-rw-r--r--host/lib/usrp/dboard/db_ubx.cpp16
-rw-r--r--host/lib/usrp/x300/x300_impl.cpp16
-rw-r--r--host/tests/convert_test.cpp9
-rw-r--r--host/utils/uhd_images_downloader.py.in14
7 files changed, 158 insertions, 32 deletions
diff --git a/host/examples/latency_test.cpp b/host/examples/latency_test.cpp
index 7282e70f5..eac5c1071 100644
--- a/host/examples/latency_test.cpp
+++ b/host/examples/latency_test.cpp
@@ -58,8 +58,14 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){
" and tries to send a packet at time t + rtt,\n"
" where rtt is the round trip time sample time\n"
" from device to host and back to the device.\n"
+ " This can be used to test latency between UHD and the device.\n"
+ " If the value rtt is chosen too small, the transmit packet will.\n"
+ " arrive too late at the device indicate an error.\n"
+ " The smallest value of rtt that does not indicate an error is an\n"
+ " approximation for the time it takes for a sample packet to\n"
+ " go to UHD and back to the device."
<< std::endl;
- return ~0;
+ return EXIT_SUCCESS;
}
bool verbose = vm.count("verbose") != 0;
@@ -74,11 +80,17 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){
//set the tx sample rate
usrp->set_tx_rate(rate);
- std::cout << boost::format("Actual TX Rate: %f Msps...") % (usrp->get_tx_rate()/1e6) << std::endl;
+ std::cout
+ << boost::format("Actual TX Rate: %f Msps...")
+ % (usrp->get_tx_rate()/1e6)
+ << std::endl;
//set the rx sample rate
usrp->set_rx_rate(rate);
- std::cout << boost::format("Actual RX Rate: %f Msps...") % (usrp->get_rx_rate()/1e6) << std::endl;
+ std::cout
+ << boost::format("Actual RX Rate: %f Msps...")
+ % (usrp->get_rx_rate()/1e6)
+ << std::endl;
//allocate a buffer to use
std::vector<std::complex<float> > buffer(nsamps);
@@ -113,8 +125,18 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){
&buffer.front(), buffer.size(), rx_md
);
- if(verbose) std::cout << boost::format("Got packet: %u samples, %u full secs, %f frac secs")
- % num_rx_samps % rx_md.time_spec.get_full_secs() % rx_md.time_spec.get_frac_secs() << std::endl;
+ if (verbose) {
+ std::cout << boost::format(
+ "Run %d: Got packet: %u samples, %u full secs, %f frac secs"
+ )
+ % nrun
+ % num_rx_samps
+ % rx_md.time_spec.get_full_secs()
+ % rx_md.time_spec.get_frac_secs()
+ << std::endl;
+ } else {
+ std::cout << "." << std::flush;
+ }
/***************************************************************
* Transmit a packet with delta time after received packet
@@ -127,7 +149,11 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){
size_t num_tx_samps = tx_stream->send(
&buffer.front(), buffer.size(), tx_md
);
- if(verbose) std::cout << boost::format("Sent %d samples") % num_tx_samps << std::endl;
+ if (verbose) {
+ std::cout
+ << boost::format("Sent %d samples") % num_tx_samps
+ << std::endl;
+ }
/***************************************************************
* Check the async messages for result
@@ -159,10 +185,47 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){
}
}
+ while (true) {
+ uhd::async_metadata_t async_md;
+ if (not tx_stream->recv_async_msg(async_md)) {
+ break;
+ }
+ switch(async_md.event_code){
+ case uhd::async_metadata_t::EVENT_CODE_TIME_ERROR:
+ time_error++;
+ break;
+
+ case uhd::async_metadata_t::EVENT_CODE_BURST_ACK:
+ ack++;
+ break;
+
+ case uhd::async_metadata_t::EVENT_CODE_UNDERFLOW:
+ underflow++;
+ break;
+
+ default:
+ std::cerr << boost::format(
+ "failed:\n Got unexpected event code 0x%x.\n"
+ ) % async_md.event_code << std::endl;
+ other++;
+ break;
+ }
+ }
+ if (!verbose) {
+ std::cout << std::endl;
+ }
+
/***************************************************************
* Print the summary
**************************************************************/
- std::cout << boost::format("\nACK %d, UNDERFLOW %d, TIME_ERR %d, other %d")
- % ack % underflow % time_error % other << std::endl;
+ std::cout << "Summary\n"
+ << "================\n"
+ << "Number of runs: " << nruns << std::endl
+ << "RTT value tested: " << (rtt*1e3) << " ms" << std::endl
+ << "ACKs received: " << ack << "/" << nruns << std::endl
+ << "Underruns: " << underflow << std::endl
+ << "Late packets: " << time_error << std::endl
+ << "Other errors: " << other << std::endl
+ << std::endl;
return EXIT_SUCCESS;
}
diff --git a/host/lib/usrp/dboard/db_sbx_common.cpp b/host/lib/usrp/dboard/db_sbx_common.cpp
index 8df4028e7..42c080155 100644
--- a/host/lib/usrp/dboard/db_sbx_common.cpp
+++ b/host/lib/usrp/dboard/db_sbx_common.cpp
@@ -118,27 +118,24 @@ sbx_xcvr::sbx_xcvr(ctor_args_t args) : xcvr_dboard_base(args){
switch(get_rx_id().to_uint16()) {
case 0x0054:
db_actual = sbx_versionx_sptr(new sbx_version3(this));
- freq_range = sbx_freq_range;
+ freq_range = sbx_freq_range;
+ enable_rx_lo_filter = sbx_enable_rx_lo_filter;
+ enable_tx_lo_filter = sbx_enable_tx_lo_filter;
break;
case 0x0065:
- db_actual = sbx_versionx_sptr(new sbx_version4(this));
- freq_range = sbx_freq_range;
- break;
- case 0x0067:
- db_actual = sbx_versionx_sptr(new cbx(this));
- freq_range = cbx_freq_range;
- break;
case 0x0069:
- db_actual = sbx_versionx_sptr(new sbx_version4(this));
- freq_range = sbx_freq_range;
- break;
case 0x0083:
db_actual = sbx_versionx_sptr(new sbx_version4(this));
- freq_range = sbx_freq_range;
+ freq_range = sbx_freq_range;
+ enable_rx_lo_filter = sbx_enable_rx_lo_filter;
+ enable_tx_lo_filter = sbx_enable_tx_lo_filter;
break;
+ case 0x0067:
case 0x0085:
db_actual = sbx_versionx_sptr(new cbx(this));
- freq_range = cbx_freq_range;
+ freq_range = cbx_freq_range;
+ enable_rx_lo_filter = cbx_enable_rx_lo_filter;
+ enable_tx_lo_filter = cbx_enable_tx_lo_filter;
break;
default:
/* We didn't recognize the version of the board... */
@@ -256,8 +253,8 @@ void sbx_xcvr::update_atr(void){
//calculate atr pins
int rx_pga0_iobits = rx_pga0_gain_to_iobits(_rx_gains["PGA0"]);
int tx_pga0_iobits = tx_pga0_gain_to_iobits(_tx_gains["PGA0"]);
- int rx_lo_lpf_en = (_rx_lo_freq == sbx_enable_rx_lo_filter.clip(_rx_lo_freq)) ? LO_LPF_EN : 0;
- int tx_lo_lpf_en = (_tx_lo_freq == sbx_enable_tx_lo_filter.clip(_tx_lo_freq)) ? LO_LPF_EN : 0;
+ int rx_lo_lpf_en = (_rx_lo_freq == enable_rx_lo_filter.clip(_rx_lo_freq)) ? LO_LPF_EN : 0;
+ int tx_lo_lpf_en = (_tx_lo_freq == enable_tx_lo_filter.clip(_tx_lo_freq)) ? LO_LPF_EN : 0;
int rx_ld_led = _rx_lo_lock_cache ? 0 : RX_LED_LD;
int tx_ld_led = _tx_lo_lock_cache ? 0 : TX_LED_LD;
int rx_ant_led = _rx_ant == "TX/RX" ? RX_LED_RX1RX2 : 0;
diff --git a/host/lib/usrp/dboard/db_sbx_common.hpp b/host/lib/usrp/dboard/db_sbx_common.hpp
index 0e4dc5ace..8f305a7c4 100644
--- a/host/lib/usrp/dboard/db_sbx_common.hpp
+++ b/host/lib/usrp/dboard/db_sbx_common.hpp
@@ -116,6 +116,14 @@ static const freq_range_t sbx_enable_rx_lo_filter = list_of
(range_t(0.4e9, 1.5e9))
;
+static const freq_range_t cbx_enable_tx_lo_filter = list_of
+ (range_t(1.2e9, 2e9))
+;
+
+static const freq_range_t cbx_enable_rx_lo_filter = list_of
+ (range_t(1.2e9, 2e9))
+;
+
static const std::vector<std::string> sbx_tx_antennas = list_of("TX/RX")("CAL");
static const std::vector<std::string> sbx_rx_antennas = list_of("TX/RX")("RX2")("CAL");
@@ -226,9 +234,12 @@ protected:
/*!
* CBX daughterboard
*
- * The only driver difference between SBX and CBX is the MAX2870 vs. ADF435x.
- * There is also no LO filter switching required, but the GPIO is left blank
- * so we don't worry about it.
+ * There are a few differences between SBX and CBX
+ * - The CBX and SBX use the MAX2870 and ADF435x respectively for LOs
+ * - There are different frequency ranges
+ * - There are different LO LPF cutoff frequencies
+ * There is also no LO filter switching required on CBX, but the GPIO is left
+ * blank so we don't worry about it.
*/
class cbx : public sbx_versionx {
public:
@@ -252,6 +263,18 @@ protected:
freq_range_t freq_range;
/*!
+ * Frequency range to use the LO LPF in RX; this is set in the constructor
+ * to correspond either to SBX or CBX.
+ */
+ freq_range_t enable_rx_lo_filter;
+
+ /*!
+ * Frequency range to use the LO LPF in TX; this is set in the constructor
+ * to correspond either to SBX or CBX.
+ */
+ freq_range_t enable_tx_lo_filter;
+
+ /*!
* Handle to the version-specific implementation of the SBX.
*
* Since many of this class's functions are dependent on the version of the
diff --git a/host/lib/usrp/dboard/db_ubx.cpp b/host/lib/usrp/dboard/db_ubx.cpp
index d25aabe98..21308b08c 100644
--- a/host/lib/usrp/dboard/db_ubx.cpp
+++ b/host/lib/usrp/dboard/db_ubx.cpp
@@ -295,6 +295,7 @@ public:
_tx_target_pfd_freq = pfd_freq_max;
if (_rev >= 1)
{
+ bool can_set_clock_rate = true;
// set dboard clock rates to as close to the max PFD freq as possible
if (_iface->get_clock_rate(dboard_iface::UNIT_RX) > pfd_freq_max)
{
@@ -305,10 +306,15 @@ public:
if (rate <= pfd_freq_max and rate > highest_rate)
highest_rate = rate;
}
- _iface->set_clock_rate(dboard_iface::UNIT_RX, highest_rate);
+ try {
+ _iface->set_clock_rate(dboard_iface::UNIT_RX, highest_rate);
+ } catch (const uhd::not_implemented_error &) {
+ UHD_MSG(warning) << "Unable to set dboard clock rate - phase will vary" << std::endl;
+ can_set_clock_rate = false;
+ }
_rx_target_pfd_freq = highest_rate;
}
- if (_iface->get_clock_rate(dboard_iface::UNIT_TX) > pfd_freq_max)
+ if (can_set_clock_rate and _iface->get_clock_rate(dboard_iface::UNIT_TX) > pfd_freq_max)
{
std::vector<double> rates = _iface->get_clock_rates(dboard_iface::UNIT_TX);
double highest_rate = 0.0;
@@ -317,7 +323,11 @@ public:
if (rate <= pfd_freq_max and rate > highest_rate)
highest_rate = rate;
}
- _iface->set_clock_rate(dboard_iface::UNIT_TX, highest_rate);
+ try {
+ _iface->set_clock_rate(dboard_iface::UNIT_TX, highest_rate);
+ } catch (const uhd::not_implemented_error &) {
+ UHD_MSG(warning) << "Unable to set dboard clock rate - phase will vary" << std::endl;
+ }
_tx_target_pfd_freq = highest_rate;
}
}
diff --git a/host/lib/usrp/x300/x300_impl.cpp b/host/lib/usrp/x300/x300_impl.cpp
index 1c8eeab51..1e22f7fb7 100644
--- a/host/lib/usrp/x300/x300_impl.cpp
+++ b/host/lib/usrp/x300/x300_impl.cpp
@@ -332,7 +332,21 @@ device_addrs_t x300_find(const device_addr_t &hint_)
//call discover with the new hint and append results
device_addrs_t new_addrs = x300_find(new_hint);
- addrs.insert(addrs.begin(), new_addrs.begin(), new_addrs.end());
+ //if we are looking for a serial, only add the one device with a matching serial
+ if (hint.has_key("serial")) {
+ bool found_serial = false; //signal to break out of the interface loop
+ for (device_addrs_t::iterator new_addr_it=new_addrs.begin(); new_addr_it != new_addrs.end(); new_addr_it++) {
+ if ((*new_addr_it)["serial"] == hint["serial"]) {
+ addrs.insert(addrs.begin(), *new_addr_it);
+ found_serial = true;
+ break;
+ }
+ }
+ if (found_serial) break;
+ } else {
+ // Otherwise, add all devices we find
+ addrs.insert(addrs.begin(), new_addrs.begin(), new_addrs.end());
+ }
}
}
diff --git a/host/tests/convert_test.cpp b/host/tests/convert_test.cpp
index b4a616133..af2828a17 100644
--- a/host/tests/convert_test.cpp
+++ b/host/tests/convert_test.cpp
@@ -550,7 +550,10 @@ static void test_convert_types_fc32(
std::swap(out_id.input_format, out_id.output_format);
std::swap(out_id.num_inputs, out_id.num_outputs);
loopback(nsamps, in_id, out_id, input, output);
- BOOST_CHECK_EQUAL_COLLECTIONS(input.begin(), input.end(), output.begin(), output.end());
+ for (size_t i = 0; i < nsamps; i++){
+ MY_CHECK_CLOSE(input[i].real(), output[i].real(), float(1./(1 << 16)));
+ MY_CHECK_CLOSE(input[i].imag(), output[i].imag(), float(1./(1 << 16)));
+ }
}
BOOST_AUTO_TEST_CASE(test_convert_types_fc32_and_fc32){
@@ -588,7 +591,9 @@ static void test_convert_types_f32(
std::swap(out_id.input_format, out_id.output_format);
std::swap(out_id.num_inputs, out_id.num_outputs);
loopback(nsamps, in_id, out_id, input, output);
- BOOST_CHECK_EQUAL_COLLECTIONS(input.begin(), input.end(), output.begin(), output.end());
+ for (size_t i = 0; i < nsamps; i++){
+ MY_CHECK_CLOSE(input[i], output[i], float(1./(1 << 16)));
+ }
}
BOOST_AUTO_TEST_CASE(test_convert_types_f32_and_f32){
diff --git a/host/utils/uhd_images_downloader.py.in b/host/utils/uhd_images_downloader.py.in
index 593f7759f..84be10902 100644
--- a/host/utils/uhd_images_downloader.py.in
+++ b/host/utils/uhd_images_downloader.py.in
@@ -252,6 +252,8 @@ def main():
help="Do not clear images directory before extracting new files [default=%default]")
parser.add_option("-v", "--verbose", action="store_true", default=False,
help="Enable verbose output [default=%default]")
+ parser.add_option("--force-delete", action="store_true", default=False,
+ help="Delete all files in the target images directory without prompting [default=%default]")
(options, args) = parser.parse_args()
if options.buffer_size <= 0:
print("Invalid buffer size: %s" % (options.buffer_size))
@@ -287,6 +289,18 @@ def main():
else:
print("Images destination: %s" % (images_dir))
+ ### Check contradictory arguments
+ if options.force_delete and options.keep:
+ print("Error: Keep and force delete options contradict.\n")
+ parser.print_help()
+ return 1
+
+ ### Prevent accidental file deletion
+ if options.install_location != default_images_dir and options.force_delete == False and options.keep != True:
+ print("Custom install location specified, defaulting to overwriting only image files.\n"
+ "Use \'--force-delete\' to clean the target directory first.")
+ options.keep = True
+
### Download or copy
downloader = uhd_images_downloader()
try: