diff options
author | Josh Blum <josh@joshknows.com> | 2010-07-16 16:43:06 -0700 |
---|---|---|
committer | Josh Blum <josh@joshknows.com> | 2010-07-16 16:51:30 -0700 |
commit | 9a9ca6dfad4b81c42f3cda6a44b018358999d701 (patch) | |
tree | 8e14ee690aa0fb13db9581415492ef889e73e656 | |
parent | 2a3d0e653e9d38dc3eed729d1442f3d98aadb1e5 (diff) | |
download | uhd-9a9ca6dfad4b81c42f3cda6a44b018358999d701.tar.gz uhd-9a9ca6dfad4b81c42f3cda6a44b018358999d701.tar.bz2 uhd-9a9ca6dfad4b81c42f3cda6a44b018358999d701.zip |
uhd: work on tune logic, and subdev connection logic
-rw-r--r-- | host/include/uhd/usrp/subdev_props.hpp | 21 | ||||
-rw-r--r-- | host/lib/usrp/dboard/db_basic_and_lf.cpp | 24 | ||||
-rw-r--r-- | host/lib/usrp/dboard/db_rfx.cpp | 16 | ||||
-rw-r--r-- | host/lib/usrp/dboard/db_unknown.cpp | 16 | ||||
-rw-r--r-- | host/lib/usrp/dboard/db_wbx.cpp | 16 | ||||
-rw-r--r-- | host/lib/usrp/dboard/db_xcvr2450.cpp | 16 | ||||
-rw-r--r-- | host/lib/usrp/dsp_utils.hpp | 40 | ||||
-rw-r--r-- | host/lib/usrp/tune_helper.cpp | 27 | ||||
-rw-r--r-- | host/lib/usrp/usrp2/dboard_impl.cpp | 5 | ||||
-rw-r--r-- | host/test/tune_helper_test.cpp | 55 | ||||
-rw-r--r-- | host/utils/uhd_usrp_probe.cpp | 3 |
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(); |