diff options
| -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(); | 
