diff options
| author | Martin Braun <martin.braun@ettus.com> | 2018-03-26 14:48:12 -0700 | 
|---|---|---|
| committer | Martin Braun <martin.braun@ettus.com> | 2018-03-28 14:21:35 -0700 | 
| commit | 18cda8029ff7ab1255579d81b0b27de68dacc88e (patch) | |
| tree | 7edbad8e0b648a6557daa720d6847cb3f65b5650 | |
| parent | 92a6c10979a2dea341349a44acbed43dc892dffc (diff) | |
| download | uhd-18cda8029ff7ab1255579d81b0b27de68dacc88e.tar.gz uhd-18cda8029ff7ab1255579d81b0b27de68dacc88e.tar.bz2 uhd-18cda8029ff7ab1255579d81b0b27de68dacc88e.zip | |
usrp2: Re-add ability to modulate in the DAC
This partially reverts b29e80cc. That commit fixed a bug with numerical
overflows, but also removed the ability to tune using the DAC,
effectively reducing the DSP tuning range.
This commit allows to tune within +/- 200 MHz using a combination of
both the DAC and the DSP tuning in the FPGA.
Reviewed-by: Derek Kozek <derek.kozel@ettus.com>
| -rw-r--r-- | host/lib/usrp/usrp2/codec_ctrl.cpp | 5 | ||||
| -rw-r--r-- | host/lib/usrp/usrp2/codec_ctrl.hpp | 7 | ||||
| -rw-r--r-- | host/lib/usrp/usrp2/usrp2_impl.cpp | 80 | 
3 files changed, 85 insertions, 7 deletions
| diff --git a/host/lib/usrp/usrp2/codec_ctrl.cpp b/host/lib/usrp/usrp2/codec_ctrl.cpp index c3e7b332f..5c1c006fb 100644 --- a/host/lib/usrp/usrp2/codec_ctrl.cpp +++ b/host/lib/usrp/usrp2/codec_ctrl.cpp @@ -179,6 +179,11 @@ public:          }      } +    size_t get_tx_interpolation() const +    { +        return 4; +    } +  private:      ad9777_regs_t _ad9777_regs;      ads62p44_regs_t _ads62p44_regs; diff --git a/host/lib/usrp/usrp2/codec_ctrl.hpp b/host/lib/usrp/usrp2/codec_ctrl.hpp index e32b508e9..ac808e357 100644 --- a/host/lib/usrp/usrp2/codec_ctrl.hpp +++ b/host/lib/usrp/usrp2/codec_ctrl.hpp @@ -56,6 +56,13 @@ public:      virtual void set_rx_digital_fine_gain(double gain) = 0; +    /*! Return the internal interpolation on the TX side. This is the factor +     *  between the rate of incoming samples and rate at which the DAC is +     *  actually clocked. Values > 1 will enable features, such as internal +     *  modulation. +     */ +    virtual size_t get_tx_interpolation() const = 0; +  };  #endif /* INCLUDED_CODEC_CTRL_HPP */ diff --git a/host/lib/usrp/usrp2/usrp2_impl.cpp b/host/lib/usrp/usrp2/usrp2_impl.cpp index 88591333a..d6ab11969 100644 --- a/host/lib/usrp/usrp2/usrp2_impl.cpp +++ b/host/lib/usrp/usrp2/usrp2_impl.cpp @@ -622,21 +622,44 @@ usrp2_impl::usrp2_impl(const device_addr_t &_device_addr) :          // create tx dsp control objects          ////////////////////////////////////////////////////////////////          _mbc[mb].tx_dsp = tx_dsp_core_200::make( -            _mbc[mb].wbiface, U2_REG_SR_ADDR(SR_TX_DSP), U2_REG_SR_ADDR(SR_TX_CTRL), USRP2_TX_ASYNC_SID +            _mbc[mb].wbiface, +            U2_REG_SR_ADDR(SR_TX_DSP), +            U2_REG_SR_ADDR(SR_TX_CTRL), +            USRP2_TX_ASYNC_SID          );          _mbc[mb].tx_dsp->set_link_rate(USRP2_LINK_RATE_BPS); +        { // This scope can be removed once we're able to do named captures +        auto this_tx_dsp = _mbc[mb].tx_dsp; // This can then also go away          _tree->access<double>(mb_path / "tick_rate") -            .add_coerced_subscriber(boost::bind(&tx_dsp_core_200::set_tick_rate, _mbc[mb].tx_dsp, _1)); +            .add_coerced_subscriber([this_tx_dsp](const double rate){ +                this_tx_dsp->set_tick_rate(rate); +            }) +        ;          _tree->create<meta_range_t>(mb_path / "tx_dsps/0/rate/range") -            .set_publisher(boost::bind(&tx_dsp_core_200::get_host_rates, _mbc[mb].tx_dsp)); +            .set_publisher([this_tx_dsp](){ +                return this_tx_dsp->get_host_rates(); +            }) +        ;          _tree->create<double>(mb_path / "tx_dsps/0/rate/value")              .set(1e6) //some default -            .set_coercer(boost::bind(&tx_dsp_core_200::set_host_rate, _mbc[mb].tx_dsp, _1)) -            .add_coerced_subscriber(boost::bind(&usrp2_impl::update_tx_samp_rate, this, mb, 0, _1)); +            .set_coercer([this_tx_dsp](const double rate){ +                return this_tx_dsp->set_host_rate(rate); +            }) +            .add_coerced_subscriber([this, mb](const double rate){ +                this->update_tx_samp_rate(mb, 0, rate); +            }) +        ; +        } // End of non-C++14 scope (to release reference to this_tx_dsp)          _tree->create<double>(mb_path / "tx_dsps/0/freq/value") -            .set_coercer(boost::bind(&tx_dsp_core_200::set_freq, _mbc[mb].tx_dsp, _1)); +            .set_coercer([this, mb](const double rate){ +                return this->set_tx_dsp_freq(mb, rate); +            }) +        ;          _tree->create<meta_range_t>(mb_path / "tx_dsps/0/freq/range") -            .set_publisher(boost::bind(&tx_dsp_core_200::get_freq_range, _mbc[mb].tx_dsp)); +            .set_publisher([this, mb](){ +                return this->get_tx_dsp_freq_range(mb); +            }) +        ;          //setup dsp flow control          const double ups_per_sec = device_args_i.cast<double>("ups_per_sec", 20); @@ -810,6 +833,49 @@ void usrp2_impl::set_tx_fe_corrections(const std::string &mb, const double lo_fr      }  } +double usrp2_impl::set_tx_dsp_freq( +    const std::string &mb, +    const double freq_ +) { +    double new_freq = freq_; +    const double tick_rate = +        _tree->access<double>("/mboards/"+mb+"/tick_rate").get(); + +    //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/tick_rate), 2); +    const double dac_shift = sign*zone*tick_rate; +    new_freq -= dac_shift; //update FPGA DSP target freq +    UHD_LOG_TRACE("USRP2", +        "DSP Tuning: Requested " + std::to_string(freq_/1e6) + " MHz, Using " +        "Nyquist zone " + std::to_string(sign*zone) + ", leftover DSP tuning: " +        + std::to_string(new_freq/1e6) + " MHz."); + +    //set the DAC shift (modulation mode) +    if (zone == 0) { +        _mbc[mb].codec->set_tx_mod_mode(0); //no shift +    } else { +        _mbc[mb].codec->set_tx_mod_mode(sign*4/zone); //DAC interp = 4 +    } + +    return _mbc[mb].tx_dsp->set_freq(new_freq) + dac_shift; //actual freq +} + +meta_range_t usrp2_impl::get_tx_dsp_freq_range(const std::string &mb) +{ +    const double dac_rate = +        _tree->access<double>("/mboards/" + mb + "/tick_rate").get() +        * _mbc[mb].codec->get_tx_interpolation(); +    const auto dsp_range_step = _mbc[mb].tx_dsp->get_freq_range().step(); +    // The DSP tuning rate is the entire range of the DAC clock rate. The step +    // size is determined by the FPGA IP, however. +    return meta_range_t( +        -dac_rate / 2, +        +dac_rate / 2, +        dsp_range_step +    ); +} +  #include <boost/math/special_functions/round.hpp>  #include <boost/math/special_functions/sign.hpp> | 
