summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--host/include/uhd/usrp/subdev_props.hpp21
-rw-r--r--host/lib/usrp/dboard/db_basic_and_lf.cpp24
-rw-r--r--host/lib/usrp/dboard/db_rfx.cpp16
-rw-r--r--host/lib/usrp/dboard/db_unknown.cpp16
-rw-r--r--host/lib/usrp/dboard/db_wbx.cpp16
-rw-r--r--host/lib/usrp/dboard/db_xcvr2450.cpp16
-rw-r--r--host/lib/usrp/dsp_utils.hpp40
-rw-r--r--host/lib/usrp/tune_helper.cpp27
-rw-r--r--host/lib/usrp/usrp2/dboard_impl.cpp5
-rw-r--r--host/test/tune_helper_test.cpp55
-rw-r--r--host/utils/uhd_usrp_probe.cpp3
11 files changed, 121 insertions, 118 deletions
diff --git a/host/include/uhd/usrp/subdev_props.hpp b/host/include/uhd/usrp/subdev_props.hpp
index cb7027ff1..f7bdcd161 100644
--- a/host/include/uhd/usrp/subdev_props.hpp
+++ b/host/include/uhd/usrp/subdev_props.hpp
@@ -23,6 +23,22 @@
namespace uhd{ namespace usrp{
/*!
+ * Possible subdev connection types:
+ *
+ * A complex subdevice is physically connected to both channels,
+ * which may be connected in one of two ways: IQ or QI (swapped).
+ *
+ * A real subdevice is only physically connected one channel,
+ * either only the I channel or only the Q channel.
+ */
+ enum subdev_conn_t{
+ SUBDEV_CONN_COMPLEX_IQ = 'C',
+ SUBDEV_CONN_COMPLEX_QI = 'c',
+ SUBDEV_CONN_REAL_I = 'R',
+ SUBDEV_CONN_REAL_Q = 'r'
+ };
+
+ /*!
* Possible device subdev properties
*/
enum subdev_prop_t{
@@ -36,8 +52,9 @@ namespace uhd{ namespace usrp{
SUBDEV_PROP_ANTENNA = 'a', //rw, std::string
SUBDEV_PROP_ANTENNA_NAMES = 'A', //ro, prop_names_t
SUBDEV_PROP_LO_LOCKED = 'L', //ro, bool
- SUBDEV_PROP_QUADRATURE = 'q', //ro, bool
- SUBDEV_PROP_IQ_SWAPPED = 'i', //ro, bool
+ SUBDEV_PROP_CONNECTION = 'c', //ro, subdev_conn_t
+ //SUBDEV_PROP_QUADRATURE = 'q', //ro, bool
+ //SUBDEV_PROP_IQ_SWAPPED = 'i', //ro, bool
SUBDEV_PROP_USE_LO_OFFSET = 'l', //ro, bool
SUBDEV_PROP_RSSI = 'R', //ro, float
SUBDEV_PROP_BANDWIDTH = 'B' //rw, double
diff --git a/host/lib/usrp/dboard/db_basic_and_lf.cpp b/host/lib/usrp/dboard/db_basic_and_lf.cpp
index b40be9dea..9180828d8 100644
--- a/host/lib/usrp/dboard/db_basic_and_lf.cpp
+++ b/host/lib/usrp/dboard/db_basic_and_lf.cpp
@@ -16,6 +16,7 @@
//
#include <uhd/usrp/subdev_props.hpp>
+#include <uhd/types/dict.hpp>
#include <uhd/types/ranges.hpp>
#include <uhd/utils/assert.hpp>
#include <uhd/utils/static.hpp>
@@ -138,13 +139,14 @@ void basic_rx::rx_get(const wax::obj &key_, wax::obj &val){
val = prop_names_t(1, ""); //vector of 1 empty string
return;
- case SUBDEV_PROP_QUADRATURE:
- val = (get_subdev_name() == "AB"); //only quadrature in ab mode
- return;
-
- case SUBDEV_PROP_IQ_SWAPPED:
- val = false;
- return;
+ case SUBDEV_PROP_CONNECTION:{
+ static const uhd::dict<std::string, subdev_conn_t> name_to_conn = map_list_of
+ ("A", SUBDEV_CONN_REAL_I)
+ ("B", SUBDEV_CONN_REAL_Q)
+ ("AB", SUBDEV_CONN_COMPLEX_IQ)
+ ;
+ val = name_to_conn[get_subdev_name()];
+ } return;
case SUBDEV_PROP_USE_LO_OFFSET:
val = false;
@@ -233,12 +235,8 @@ void basic_tx::tx_get(const wax::obj &key_, wax::obj &val){
val = prop_names_t(1, ""); //vector of 1 empty string
return;
- case SUBDEV_PROP_QUADRATURE:
- val = true;
- return;
-
- case SUBDEV_PROP_IQ_SWAPPED:
- val = false;
+ case SUBDEV_PROP_CONNECTION:
+ val = SUBDEV_CONN_COMPLEX_IQ;
return;
case SUBDEV_PROP_USE_LO_OFFSET:
diff --git a/host/lib/usrp/dboard/db_rfx.cpp b/host/lib/usrp/dboard/db_rfx.cpp
index 9e5fcd6c6..914ca5e19 100644
--- a/host/lib/usrp/dboard/db_rfx.cpp
+++ b/host/lib/usrp/dboard/db_rfx.cpp
@@ -426,12 +426,8 @@ void rfx_xcvr::rx_get(const wax::obj &key_, wax::obj &val){
val = rfx_rx_antennas;
return;
- case SUBDEV_PROP_QUADRATURE:
- val = true;
- return;
-
- case SUBDEV_PROP_IQ_SWAPPED:
- val = true;
+ case SUBDEV_PROP_CONNECTION:
+ val = SUBDEV_CONN_COMPLEX_QI;
return;
case SUBDEV_PROP_USE_LO_OFFSET:
@@ -512,12 +508,8 @@ void rfx_xcvr::tx_get(const wax::obj &key_, wax::obj &val){
val = rfx_tx_antennas;
return;
- case SUBDEV_PROP_QUADRATURE:
- val = true;
- return;
-
- case SUBDEV_PROP_IQ_SWAPPED:
- val = false;
+ case SUBDEV_PROP_CONNECTION:
+ val = SUBDEV_CONN_COMPLEX_IQ;
return;
case SUBDEV_PROP_USE_LO_OFFSET:
diff --git a/host/lib/usrp/dboard/db_unknown.cpp b/host/lib/usrp/dboard/db_unknown.cpp
index 8b247c289..9dd9b550b 100644
--- a/host/lib/usrp/dboard/db_unknown.cpp
+++ b/host/lib/usrp/dboard/db_unknown.cpp
@@ -119,12 +119,8 @@ void unknown_rx::rx_get(const wax::obj &key_, wax::obj &val){
val = prop_names_t(1, ""); //vector of 1 empty string
return;
- case SUBDEV_PROP_QUADRATURE:
- val = false;
- return;
-
- case SUBDEV_PROP_IQ_SWAPPED:
- val = false;
+ case SUBDEV_PROP_CONNECTION:
+ val = SUBDEV_CONN_COMPLEX_IQ;
return;
case SUBDEV_PROP_USE_LO_OFFSET:
@@ -214,12 +210,8 @@ void unknown_tx::tx_get(const wax::obj &key_, wax::obj &val){
val = prop_names_t(1, ""); //vector of 1 empty string
return;
- case SUBDEV_PROP_QUADRATURE:
- val = true;
- return;
-
- case SUBDEV_PROP_IQ_SWAPPED:
- val = false;
+ case SUBDEV_PROP_CONNECTION:
+ val = SUBDEV_CONN_COMPLEX_IQ;
return;
case SUBDEV_PROP_USE_LO_OFFSET:
diff --git a/host/lib/usrp/dboard/db_wbx.cpp b/host/lib/usrp/dboard/db_wbx.cpp
index 23eb5ca44..3038ce30b 100644
--- a/host/lib/usrp/dboard/db_wbx.cpp
+++ b/host/lib/usrp/dboard/db_wbx.cpp
@@ -510,12 +510,8 @@ void wbx_xcvr::rx_get(const wax::obj &key_, wax::obj &val){
val = wbx_rx_antennas;
return;
- case SUBDEV_PROP_QUADRATURE:
- val = true;
- return;
-
- case SUBDEV_PROP_IQ_SWAPPED:
- val = false;
+ case SUBDEV_PROP_CONNECTION:
+ val = SUBDEV_CONN_COMPLEX_IQ;
return;
case SUBDEV_PROP_USE_LO_OFFSET:
@@ -600,12 +596,8 @@ void wbx_xcvr::tx_get(const wax::obj &key_, wax::obj &val){
val = wbx_tx_antennas;
return;
- case SUBDEV_PROP_QUADRATURE:
- val = true;
- return;
-
- case SUBDEV_PROP_IQ_SWAPPED:
- val = false;
+ case SUBDEV_PROP_CONNECTION:
+ val = SUBDEV_CONN_COMPLEX_IQ;
return;
case SUBDEV_PROP_USE_LO_OFFSET:
diff --git a/host/lib/usrp/dboard/db_xcvr2450.cpp b/host/lib/usrp/dboard/db_xcvr2450.cpp
index fabf3dffd..2c94bcd2d 100644
--- a/host/lib/usrp/dboard/db_xcvr2450.cpp
+++ b/host/lib/usrp/dboard/db_xcvr2450.cpp
@@ -481,12 +481,8 @@ void xcvr2450::rx_get(const wax::obj &key_, wax::obj &val){
val = xcvr_antennas;
return;
- case SUBDEV_PROP_QUADRATURE:
- val = true;
- return;
-
- case SUBDEV_PROP_IQ_SWAPPED:
- val = false;
+ case SUBDEV_PROP_CONNECTION:
+ val = SUBDEV_CONN_COMPLEX_IQ;
return;
case SUBDEV_PROP_USE_LO_OFFSET:
@@ -575,12 +571,8 @@ void xcvr2450::tx_get(const wax::obj &key_, wax::obj &val){
val = xcvr_antennas;
return;
- case SUBDEV_PROP_QUADRATURE:
- val = true;
- return;
-
- case SUBDEV_PROP_IQ_SWAPPED:
- val = true;
+ case SUBDEV_PROP_CONNECTION:
+ val = SUBDEV_CONN_COMPLEX_QI;
return;
case SUBDEV_PROP_USE_LO_OFFSET:
diff --git a/host/lib/usrp/dsp_utils.hpp b/host/lib/usrp/dsp_utils.hpp
index 13186f354..2f246c788 100644
--- a/host/lib/usrp/dsp_utils.hpp
+++ b/host/lib/usrp/dsp_utils.hpp
@@ -22,6 +22,7 @@
#include <uhd/types/dict.hpp>
#include <uhd/utils/assert.hpp>
#include <uhd/types/stream_cmd.hpp>
+#include <uhd/usrp/subdev_props.hpp>
#include <boost/cstdint.hpp>
#include <boost/assign/list_of.hpp>
#include <boost/tuple/tuple.hpp>
@@ -37,37 +38,36 @@ namespace dsp_type1{
/*!
* Calculate the rx mux word from properties.
- * \param is_quadrature true if the subdev is complex
- * \param is_iq_swapped true if the i and q are reversed
+ * \param subdev_conn the subdev connection type
* \param the 32-bit rx mux control word
*/
static inline boost::uint32_t calc_rx_mux_word(
- bool is_quadrature,
- bool is_iq_swapped
+ subdev_conn_t subdev_conn
){
- boost::uint32_t rx_mux = 0;
- if (is_quadrature){
- rx_mux = (0x01 << 2) | (0x00 << 0); //Q=ADC1, I=ADC0
- }else{
- rx_mux = (0x11 << 2) | (0x00 << 0); //Q=ZERO, I=ADC0
+ switch(subdev_conn){
+ case SUBDEV_CONN_COMPLEX_IQ: return (0x1 << 2) | (0x0 << 0); //DDC0Q=ADC1, DDC0I=ADC0
+ case SUBDEV_CONN_COMPLEX_QI: return (0x0 << 2) | (0x1 << 0); //DDC0Q=ADC0, DDC0I=ADC1
+ case SUBDEV_CONN_REAL_I: return (0x3 << 2) | (0x0 << 0); //DDC0Q=ZERO, DDC0I=ADC0
+ case SUBDEV_CONN_REAL_Q: return (0x1 << 2) | (0x3 << 0); //DDC0Q=ADC1, DDC0I=ZERO
+ default: UHD_THROW_INVALID_CODE_PATH();
}
- if (is_iq_swapped){
- rx_mux = (rx_mux << 2) | (rx_mux >> 2);
- }
- return rx_mux;
}
/*!
* Calculate the tx mux word from properties.
- * \param is_iq_swapped true if the i and q are reversed
+ * \param subdev_conn the subdev connection type
* \param the 32-bit tx mux control word
*/
- static inline boost::uint32_t calc_tx_mux_word(bool is_iq_swapped){
- boost::uint32_t tx_mux = 0x10;
- if (is_iq_swapped){
- tx_mux = (tx_mux << 4) | (tx_mux >> 4);
+ static inline boost::uint32_t calc_tx_mux_word(
+ subdev_conn_t subdev_conn
+ ){
+ switch(subdev_conn){
+ case SUBDEV_CONN_COMPLEX_IQ: return (0x1 << 4) | (0x0 << 0); //DAC1=DUC0Q, DAC0=DUC0I
+ case SUBDEV_CONN_COMPLEX_QI: return (0x0 << 4) | (0x1 << 0); //DAC1=DUC0I, DAC0=DUC0Q
+ case SUBDEV_CONN_REAL_I: return (0xf << 4) | (0x0 << 0); //DAC1=ZERO, DAC0=DUC0I
+ case SUBDEV_CONN_REAL_Q: return (0x0 << 4) | (0xf << 0); //DAC1=DUC0I, DAC0=ZERO
+ default: UHD_THROW_INVALID_CODE_PATH();
}
- return tx_mux;
}
/*!
@@ -82,7 +82,7 @@ namespace dsp_type1{
double &freq,
double codec_rate
){
- UHD_ASSERT_THROW(std::abs(freq) < codec_rate/2.0);
+ UHD_ASSERT_THROW(freq >= -codec_rate/2.0 and freq < codec_rate/2.0);
static const double scale_factor = std::pow(2.0, 32);
//calculate the freq register word (signed)
diff --git a/host/lib/usrp/tune_helper.cpp b/host/lib/usrp/tune_helper.cpp
index dd2985d88..c5cce3ecf 100644
--- a/host/lib/usrp/tune_helper.cpp
+++ b/host/lib/usrp/tune_helper.cpp
@@ -28,23 +28,12 @@ using namespace uhd::usrp;
/***********************************************************************
* Tune Helper Functions
**********************************************************************/
-static bool invert_dxc_freq(
- bool outside_of_nyquist,
- bool subdev_quadrature,
- dboard_iface::unit_t unit
-){
- bool is_tx = unit == dboard_iface::UNIT_TX;
- if (subdev_quadrature) return is_tx;
- return outside_of_nyquist xor is_tx;
-}
-
static tune_result_t tune_xx_subdev_and_dxc(
dboard_iface::unit_t unit,
wax::obj subdev, wax::obj dxc,
double target_freq, double lo_offset
){
wax::obj subdev_freq_proxy = subdev[SUBDEV_PROP_FREQ];
- bool subdev_quadrature = subdev[SUBDEV_PROP_QUADRATURE].as<bool>();
wax::obj dxc_freq_proxy = dxc[DSP_PROP_FREQ_SHIFT];
double dxc_sample_rate = dxc[DSP_PROP_CODEC_RATE].as<double>();
@@ -54,14 +43,13 @@ static tune_result_t tune_xx_subdev_and_dxc(
double actual_inter_freq = subdev_freq_proxy.as<double>();
//perform the correction correction for dxc rates outside of nyquist
- double target_dxc_freq = std::fmod(target_freq - actual_inter_freq, dxc_sample_rate);
- if (target_dxc_freq >= dxc_sample_rate/2.0) target_dxc_freq -= dxc_sample_rate;
- else if (target_dxc_freq < -dxc_sample_rate/2.0) target_dxc_freq += dxc_sample_rate;
- else target_dxc_freq *= -1.0;
+ 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)?
+ std::signum(delta_freq)*dxc_sample_rate - delta_freq : -delta_freq;
//invert the sign on the dxc freq given the following conditions
- bool outside_of_nyquist = std::abs(target_freq - actual_inter_freq) > dxc_sample_rate/2.0;
- if (invert_dxc_freq(outside_of_nyquist, subdev_quadrature, unit)) target_dxc_freq *= -1.0;
+ if (unit == dboard_iface::UNIT_TX) target_dxc_freq *= -1.0;
dxc_freq_proxy = target_dxc_freq;
double actual_dxc_freq = dxc_freq_proxy.as<double>();
@@ -79,15 +67,12 @@ static double derive_freq_from_xx_subdev_and_dxc(
dboard_iface::unit_t unit,
wax::obj subdev, wax::obj dxc
){
- //extract subdev properties
- bool subdev_quadrature = subdev[SUBDEV_PROP_QUADRATURE].as<bool>();
-
//extract actual dsp and IF frequencies
double actual_inter_freq = subdev[SUBDEV_PROP_FREQ].as<double>();
double actual_dxc_freq = dxc[DSP_PROP_FREQ_SHIFT].as<double>();
//invert the sign on the dxc freq given the following conditions
- if (invert_dxc_freq(false, subdev_quadrature, unit)) actual_dxc_freq *= -1.0;
+ if (unit == dboard_iface::UNIT_TX) actual_dxc_freq *= -1.0;
return actual_inter_freq - actual_dxc_freq;
}
diff --git a/host/lib/usrp/usrp2/dboard_impl.cpp b/host/lib/usrp/usrp2/dboard_impl.cpp
index fa8d1a674..8942f9d31 100644
--- a/host/lib/usrp/usrp2/dboard_impl.cpp
+++ b/host/lib/usrp/usrp2/dboard_impl.cpp
@@ -104,8 +104,7 @@ void usrp2_mboard_impl::rx_dboard_set(const wax::obj &key, const wax::obj &val){
wax::obj rx_subdev = _dboard_manager->get_rx_subdev(_rx_subdevs_in_use.at(0));
std::cout << "Using: " << rx_subdev[SUBDEV_PROP_NAME].as<std::string>() << std::endl;
_iface->poke32(U2_REG_DSP_RX_MUX, dsp_type1::calc_rx_mux_word(
- rx_subdev[SUBDEV_PROP_QUADRATURE].as<bool>(),
- rx_subdev[SUBDEV_PROP_IQ_SWAPPED].as<bool>()
+ rx_subdev[SUBDEV_PROP_CONNECTION].as<subdev_conn_t>()
));
}
return;
@@ -164,7 +163,7 @@ void usrp2_mboard_impl::tx_dboard_set(const wax::obj &key, const wax::obj &val){
wax::obj tx_subdev = _dboard_manager->get_tx_subdev(_tx_subdevs_in_use.at(0));
std::cout << "Using: " << tx_subdev[SUBDEV_PROP_NAME].as<std::string>() << std::endl;
_iface->poke32(U2_REG_DSP_TX_MUX, dsp_type1::calc_tx_mux_word(
- tx_subdev[SUBDEV_PROP_IQ_SWAPPED].as<bool>()
+ tx_subdev[SUBDEV_PROP_CONNECTION].as<subdev_conn_t>()
));
}
return;
diff --git a/host/test/tune_helper_test.cpp b/host/test/tune_helper_test.cpp
index a6e6f4cc9..3df1f2471 100644
--- a/host/test/tune_helper_test.cpp
+++ b/host/test/tune_helper_test.cpp
@@ -29,8 +29,7 @@ using namespace uhd::usrp;
**********************************************************************/
class dummy_subdev : public wax::obj{
public:
- dummy_subdev(bool is_quadrature, double resolution):
- _is_quadrature(is_quadrature),
+ dummy_subdev(double resolution):
_resolution(resolution)
{
/* NOP */
@@ -38,9 +37,6 @@ public:
private:
void get(const wax::obj &key, wax::obj &val){
switch(key.as<subdev_prop_t>()){
- case SUBDEV_PROP_QUADRATURE:
- val = _is_quadrature;
- return;
case SUBDEV_PROP_FREQ:
val = _freq;
@@ -64,10 +60,37 @@ private:
}
}
- bool _is_quadrature;
double _freq, _resolution;
};
+class dummy_subdev_basic : public wax::obj{
+private:
+ void get(const wax::obj &key, wax::obj &val){
+ switch(key.as<subdev_prop_t>()){
+
+ case SUBDEV_PROP_FREQ:
+ val = double(0.0); //always zero
+ return;
+
+ case SUBDEV_PROP_USE_LO_OFFSET:
+ val = false;
+ return;
+
+ default: UHD_THROW_PROP_GET_ERROR();
+ }
+ }
+
+ void set(const wax::obj &key, const wax::obj &){
+ switch(key.as<subdev_prop_t>()){
+ case SUBDEV_PROP_FREQ:
+ // do nothing
+ return;
+
+ default: UHD_THROW_PROP_SET_ERROR();
+ }
+ }
+};
+
class dummy_dsp : public wax::obj{
public:
dummy_dsp(double codec_rate):
@@ -104,12 +127,12 @@ private:
};
/***********************************************************************
- * Tests
+ * Test cases
**********************************************************************/
static const double tolerance = 0.001;
BOOST_AUTO_TEST_CASE(test_tune_helper_rx){
- dummy_subdev subdev(true, 1e6);
+ dummy_subdev subdev(1e6);
dummy_dsp dsp(100e6);
std::cout << "Testing tune helper RX automatic LO offset" << std::endl;
@@ -123,7 +146,7 @@ BOOST_AUTO_TEST_CASE(test_tune_helper_rx){
}
BOOST_AUTO_TEST_CASE(test_tune_helper_tx){
- dummy_subdev subdev(true, 1e6);
+ dummy_subdev subdev(1e6);
dummy_dsp dsp(100e6);
std::cout << "Testing tune helper TX automatic LO offset" << std::endl;
@@ -135,3 +158,17 @@ BOOST_AUTO_TEST_CASE(test_tune_helper_tx){
double freq_derived = derive_freq_from_tx_subdev_and_dsp(subdev.get_link(), dsp.get_link());
BOOST_CHECK_CLOSE(freq_derived, 2.3451e9, tolerance);
}
+
+BOOST_AUTO_TEST_CASE(test_tune_helper_rx_nyquist){
+ dummy_subdev_basic subdev;
+ dummy_dsp dsp(100e6);
+
+ std::cout << "Testing tune helper RX dummy basic board" << std::endl;
+ tune_result_t tr = tune_rx_subdev_and_dsp(subdev.get_link(), dsp.get_link(), 55e6);
+ std::cout << tr.to_pp_string() << std::endl;
+ BOOST_CHECK_CLOSE(tr.actual_inter_freq, 0, tolerance);
+ BOOST_CHECK_CLOSE(tr.actual_dsp_freq, 45e6, tolerance);
+
+ double freq_derived = derive_freq_from_rx_subdev_and_dsp(subdev.get_link(), dsp.get_link());
+ BOOST_CHECK_CLOSE(freq_derived, -45e6, tolerance);
+}
diff --git a/host/utils/uhd_usrp_probe.cpp b/host/utils/uhd_usrp_probe.cpp
index 611c6919d..1b73b5788 100644
--- a/host/utils/uhd_usrp_probe.cpp
+++ b/host/utils/uhd_usrp_probe.cpp
@@ -88,8 +88,7 @@ static std::string get_subdev_pp_string(const std::string &type, wax::obj subdev
ss << boost::format("Gain range %s: %.1f to %.1f step %.1f dB") % gain_name % gain_range.min % gain_range.max % gain_range.step << std::endl;
}
- ss << boost::format("Is Quadrature: %s") % (subdev[usrp::SUBDEV_PROP_QUADRATURE].as<bool>()? "Yes" : "No") << std::endl;
- ss << boost::format("Is IQ Swapped: %s") % (subdev[usrp::SUBDEV_PROP_IQ_SWAPPED].as<bool>()? "Yes" : "No") << std::endl;
+ ss << boost::format("Connection Type: %c") % (subdev[usrp::SUBDEV_PROP_CONNECTION].as<usrp::subdev_conn_t>()) << std::endl;
ss << boost::format("Uses LO offset: %s") % (subdev[usrp::SUBDEV_PROP_USE_LO_OFFSET].as<bool>()? "Yes" : "No") << std::endl;
return ss.str();