diff options
| -rw-r--r-- | host/lib/usrp/dsp_utils.cpp | 13 | ||||
| -rw-r--r-- | host/lib/usrp/tune_helper.cpp | 7 | ||||
| -rw-r--r-- | host/lib/usrp/usrp2/codec_ctrl.cpp | 23 | ||||
| -rw-r--r-- | host/lib/usrp/usrp2/codec_ctrl.hpp | 9 | ||||
| -rw-r--r-- | host/lib/usrp/usrp2/dsp_impl.cpp | 19 | ||||
| -rw-r--r-- | host/test/tune_helper_test.cpp | 2 | 
6 files changed, 60 insertions, 13 deletions
| diff --git a/host/lib/usrp/dsp_utils.cpp b/host/lib/usrp/dsp_utils.cpp index 2553e4a25..576c4639f 100644 --- a/host/lib/usrp/dsp_utils.cpp +++ b/host/lib/usrp/dsp_utils.cpp @@ -21,6 +21,8 @@  #include <boost/assign/list_of.hpp>  #include <boost/tuple/tuple.hpp>  #include <boost/math/special_functions/round.hpp> +#include <boost/math/special_functions/sign.hpp> +#include <algorithm>  #include <cmath>  using namespace uhd; @@ -65,13 +67,16 @@ boost::uint32_t dsp_type1::calc_tx_mux_word(subdev_conn_t subdev_conn){  }  boost::uint32_t dsp_type1::calc_cordic_word_and_update( -    double &freq, -    double codec_rate +    double &freq, double codec_rate  ){ -    UHD_ASSERT_THROW(std::abs(freq) <= codec_rate/2.0); -    static const double scale_factor = std::pow(2.0, 32); +    //correct for outside of rate (wrap around) +    freq = std::fmod(freq, codec_rate); +    if (std::abs(freq) > codec_rate/2.0) +        freq -= boost::math::sign(freq)*codec_rate;      //calculate the freq register word (signed) +    UHD_ASSERT_THROW(std::abs(freq) <= codec_rate/2.0); +    static const double scale_factor = std::pow(2.0, 32);      boost::int32_t freq_word = boost::int32_t(boost::math::round((freq / codec_rate) * scale_factor));      //update the actual frequency diff --git a/host/lib/usrp/tune_helper.cpp b/host/lib/usrp/tune_helper.cpp index fa40a8a26..eccee7f4b 100644 --- a/host/lib/usrp/tune_helper.cpp +++ b/host/lib/usrp/tune_helper.cpp @@ -20,7 +20,6 @@  #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>  using namespace uhd; @@ -37,7 +36,6 @@ static tune_result_t tune_xx_subdev_and_dsp(      wax::obj subdev_freq_proxy = subdev[SUBDEV_PROP_FREQ];      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>();      //------------------------------------------------------------------      //-- calculate the LO offset, only used with automatic policy @@ -73,10 +71,7 @@ static tune_result_t tune_xx_subdev_and_dsp(      //------------------------------------------------------------------      //-- 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; +    double target_dsp_freq = actual_inter_freq - tune_request.target_freq;      //invert the sign on the dsp freq given the following conditions      if (unit == dboard_iface::UNIT_TX) target_dsp_freq *= -1.0; diff --git a/host/lib/usrp/usrp2/codec_ctrl.cpp b/host/lib/usrp/usrp2/codec_ctrl.cpp index ad1ae1acb..4f2cd88bb 100644 --- a/host/lib/usrp/usrp2/codec_ctrl.cpp +++ b/host/lib/usrp/usrp2/codec_ctrl.cpp @@ -39,7 +39,7 @@ public:          //setup the ad9777 dac          _ad9777_regs.x_1r_2r_mode = ad9777_regs_t::X_1R_2R_MODE_1R;          _ad9777_regs.filter_interp_rate = ad9777_regs_t::FILTER_INTERP_RATE_4X; -        _ad9777_regs.mix_mode = ad9777_regs_t::MIX_MODE_REAL; +        _ad9777_regs.mix_mode = ad9777_regs_t::MIX_MODE_COMPLEX;          _ad9777_regs.pll_divide_ratio = ad9777_regs_t::PLL_DIVIDE_RATIO_DIV1;          _ad9777_regs.pll_state = ad9777_regs_t::PLL_STATE_ON;          _ad9777_regs.auto_cp_control = ad9777_regs_t::AUTO_CP_CONTROL_AUTO; @@ -57,6 +57,7 @@ public:          for(boost::uint8_t addr = 0; addr <= 0xC; addr++){              this->send_ad9777_reg(addr);          } +        set_tx_mod_mode(0);          //power-up adc          switch(_iface->get_rev()){ @@ -102,6 +103,26 @@ public:          }      } +    void set_tx_mod_mode(int mod_mode){ +        //set the sign of the frequency shift +        _ad9777_regs.modulation_form = (mod_mode > 0)? +            ad9777_regs_t::MODULATION_FORM_E_PLUS_JWT: +            ad9777_regs_t::MODULATION_FORM_E_MINUS_JWT +        ; + +        //set the frequency shift +        switch(std::abs(mod_mode)){ +        case 0: +        case 1: _ad9777_regs.modulation_mode = ad9777_regs_t::MODULATION_MODE_NONE; break; +        case 2: _ad9777_regs.modulation_mode = ad9777_regs_t::MODULATION_MODE_FS_2; break; +        case 4: _ad9777_regs.modulation_mode = ad9777_regs_t::MODULATION_MODE_FS_4; break; +        case 8: _ad9777_regs.modulation_mode = ad9777_regs_t::MODULATION_MODE_FS_8; break; +        default: throw std::runtime_error("unknown modulation mode for ad9777"); +        } + +        this->send_ad9777_reg(0x01); //set the register +    } +      void set_rx_digital_gain(float gain) {  //fine digital gain          switch(_iface->get_rev()){          case usrp2_iface::USRP_N200: diff --git a/host/lib/usrp/usrp2/codec_ctrl.hpp b/host/lib/usrp/usrp2/codec_ctrl.hpp index 57a37b94b..c8d977a1f 100644 --- a/host/lib/usrp/usrp2/codec_ctrl.hpp +++ b/host/lib/usrp/usrp2/codec_ctrl.hpp @@ -34,6 +34,15 @@ public:      static sptr make(usrp2_iface::sptr iface);      /*! +     * Set the modulation mode for the DAC. +     * Possible modes are 0, +/-1, +/-2, +/-4, +/-8 +     * which correspond to shifts of fs/mod_mode. +     * A mode of 0 or +/-1 means no modulation. +     * \param mod_mode the modulation mode +     */ +    virtual void set_tx_mod_mode(int mod_mode) = 0; + +    /*!       * Set the analog preamplifier on the USRP2+ ADC (ADS62P44).       * \param gain enable or disable the 3.5dB preamp       */ diff --git a/host/lib/usrp/usrp2/dsp_impl.cpp b/host/lib/usrp/usrp2/dsp_impl.cpp index 77ed594f5..8340f7cdd 100644 --- a/host/lib/usrp/usrp2/dsp_impl.cpp +++ b/host/lib/usrp/usrp2/dsp_impl.cpp @@ -20,6 +20,9 @@  #include <uhd/usrp/dsp_utils.hpp>  #include <uhd/usrp/dsp_props.hpp>  #include <boost/bind.hpp> +#include <boost/math/special_functions/round.hpp> +#include <boost/math/special_functions/sign.hpp> +#include <algorithm>  #include <cmath>  using namespace uhd; @@ -177,11 +180,23 @@ void usrp2_mboard_impl::duc_set(const wax::obj &key_, const wax::obj &val){      switch(key.as<dsp_prop_t>()){      case DSP_PROP_FREQ_SHIFT:{ +            const double codec_rate = get_master_clock_freq();              double new_freq = val.as<double>(); + +            //calculate the DAC shift (multiples of rate) +            const int sign = boost::math::sign(new_freq); +            const int zone = std::min(boost::math::iround(new_freq/codec_rate), 2); +            const double dac_shift = sign*zone*codec_rate; +            new_freq -= dac_shift; //update FPGA DSP target freq + +            //set the DAC shift (modulation mode) +            if (zone == 0) _codec_ctrl->set_tx_mod_mode(0); //no shift +            else _codec_ctrl->set_tx_mod_mode(sign*4/zone); //DAC interp = 4 +              _iface->poke32(_iface->regs.dsp_tx_freq, -                dsp_type1::calc_cordic_word_and_update(new_freq, get_master_clock_freq()) +                dsp_type1::calc_cordic_word_and_update(new_freq, codec_rate)              ); -            _duc_freq = new_freq; //shadow +            _duc_freq = new_freq + dac_shift; //shadow          }          return; diff --git a/host/test/tune_helper_test.cpp b/host/test/tune_helper_test.cpp index e0500ae3f..735e7e948 100644 --- a/host/test/tune_helper_test.cpp +++ b/host/test/tune_helper_test.cpp @@ -19,6 +19,7 @@  #include <uhd/usrp/tune_helper.hpp>  #include <uhd/usrp/subdev_props.hpp>  #include <uhd/usrp/dsp_props.hpp> +#include <uhd/usrp/dsp_utils.hpp>  #include <iostream>  using namespace uhd; @@ -165,6 +166,7 @@ private:          switch(key.as<dsp_prop_t>()){          case DSP_PROP_FREQ_SHIFT:              _freq_shift = val.as<double>(); +            dsp_type1::calc_cordic_word_and_update(_freq_shift, _codec_rate);              return;          case DSP_PROP_HOST_RATE: | 
