diff options
Diffstat (limited to 'host/lib')
| -rw-r--r-- | host/lib/usrp/cores/rx_dsp_core_200.cpp | 31 | ||||
| -rw-r--r-- | host/lib/usrp/cores/tx_dsp_core_200.cpp | 30 | ||||
| -rw-r--r-- | host/lib/usrp/usrp2/usrp2_impl.cpp | 27 | 
3 files changed, 55 insertions, 33 deletions
| diff --git a/host/lib/usrp/cores/rx_dsp_core_200.cpp b/host/lib/usrp/cores/rx_dsp_core_200.cpp index 2eafd6c59..160124b3e 100644 --- a/host/lib/usrp/cores/rx_dsp_core_200.cpp +++ b/host/lib/usrp/cores/rx_dsp_core_200.cpp @@ -25,6 +25,7 @@  #include <boost/thread/thread.hpp> //thread sleep  #include <boost/math/special_functions/round.hpp>  #include <boost/math/special_functions/sign.hpp> +#include <boost/numeric/conversion/bounds.hpp>  #include <algorithm>  #include <cmath> @@ -228,14 +229,36 @@ public:          if (std::abs(freq) > _tick_rate/2.0)              freq -= boost::math::sign(freq)*_tick_rate; -        //calculate the freq register word (signed) +        //confirm that the target frequency is within range of the CORDIC          UHD_ASSERT_THROW(std::abs(freq) <= _tick_rate/2.0); + +        /* Now calculate the frequency word. It is possible for this calculation +         * to cause an overflow. As the requested DSP frequency approaches the +         * master clock rate, that ratio multiplied by the scaling factor (2^32) +         * will generally overflow within the last few kHz of tunable range. +         * Thus, we check to see if the operation will overflow before doing it, +         * and if it will, we set it to the integer min or max of this system. +         */ +        boost::int32_t freq_word = 0; +          static const double scale_factor = std::pow(2.0, 32); -        const boost::int32_t freq_word = boost::int32_t(boost::math::round((freq / _tick_rate) * scale_factor)); +        static const boost::int32_t int_max = boost::numeric::bounds<boost::int32_t>::highest(); +        static const boost::int32_t int_min = boost::numeric::bounds<boost::int32_t>::lowest(); +        if((freq / _tick_rate) >= (int_max / scale_factor)) { +            /* Operation would have caused a positive overflow of int32. */ +            freq_word = boost::numeric::bounds<boost::int32_t>::highest(); + +        } else if((freq / _tick_rate) <= (int_min / scale_factor)) { +            /* Operation would have caused a negative overflow of int32. */ +            freq_word = boost::numeric::bounds<boost::int32_t>::lowest(); + +        } else { +            /* The operation is safe. Perform normally. */ +            freq_word = boost::int32_t(boost::math::round((freq / _tick_rate) * scale_factor)); +        } -        //update the actual frequency +        //program the frequency word into the device DSP          const double actual_freq = (double(freq_word) / scale_factor) * _tick_rate; -          _iface->poke32(REG_DSP_RX_FREQ, boost::uint32_t(freq_word));          return actual_freq; diff --git a/host/lib/usrp/cores/tx_dsp_core_200.cpp b/host/lib/usrp/cores/tx_dsp_core_200.cpp index 0e83a698b..3f397dd6a 100644 --- a/host/lib/usrp/cores/tx_dsp_core_200.cpp +++ b/host/lib/usrp/cores/tx_dsp_core_200.cpp @@ -169,14 +169,36 @@ public:          if (std::abs(freq) > _tick_rate/2.0)              freq -= boost::math::sign(freq)*_tick_rate; -        //calculate the freq register word (signed) +        //confirm that the target frequency is within range of the CORDIC          UHD_ASSERT_THROW(std::abs(freq) <= _tick_rate/2.0); + +        /* Now calculate the frequency word. It is possible for this calculation +         * to cause an overflow. As the requested DSP frequency approaches the +         * master clock rate, that ratio multiplied by the scaling factor (2^32) +         * will generally overflow within the last few kHz of tunable range. +         * Thus, we check to see if the operation will overflow before doing it, +         * and if it will, we set it to the integer min or max of this system. +         */ +        boost::int32_t freq_word = 0; +          static const double scale_factor = std::pow(2.0, 32); -        const boost::int32_t freq_word = boost::int32_t(boost::math::round((freq / _tick_rate) * scale_factor)); +        static const boost::int32_t int_max = boost::numeric::bounds<boost::int32_t>::highest(); +        static const boost::int32_t int_min = boost::numeric::bounds<boost::int32_t>::lowest(); +        if((freq / _tick_rate) >= (int_max / scale_factor)) { +            /* Operation would have caused a positive overflow of int32. */ +            freq_word = boost::numeric::bounds<boost::int32_t>::highest(); + +        } else if((freq / _tick_rate) <= (int_min / scale_factor)) { +            /* Operation would have caused a negative overflow of int32. */ +            freq_word = boost::numeric::bounds<boost::int32_t>::lowest(); + +        } else { +            /* The operation is safe. Perform normally. */ +            freq_word = boost::int32_t(boost::math::round((freq / _tick_rate) * scale_factor)); +        } -        //update the actual frequency +        //program the frequency word into the device DSP          const double actual_freq = (double(freq_word) / scale_factor) * _tick_rate; -          _iface->poke32(REG_DSP_TX_FREQ, boost::uint32_t(freq_word));          return actual_freq; diff --git a/host/lib/usrp/usrp2/usrp2_impl.cpp b/host/lib/usrp/usrp2/usrp2_impl.cpp index 217c1d434..16e8a1f22 100644 --- a/host/lib/usrp/usrp2/usrp2_impl.cpp +++ b/host/lib/usrp/usrp2/usrp2_impl.cpp @@ -623,9 +623,9 @@ usrp2_impl::usrp2_impl(const device_addr_t &_device_addr){              .coerce(boost::bind(&tx_dsp_core_200::set_host_rate, _mbc[mb].tx_dsp, _1))              .subscribe(boost::bind(&usrp2_impl::update_tx_samp_rate, this, mb, 0, _1));          _tree->create<double>(mb_path / "tx_dsps/0/freq/value") -            .coerce(boost::bind(&usrp2_impl::set_tx_dsp_freq, this, mb, _1)); +            .coerce(boost::bind(&tx_dsp_core_200::set_freq, _mbc[mb].tx_dsp, _1));          _tree->create<meta_range_t>(mb_path / "tx_dsps/0/freq/range") -            .publish(boost::bind(&usrp2_impl::get_tx_dsp_freq_range, this, mb)); +            .publish(boost::bind(&tx_dsp_core_200::get_freq_range, _mbc[mb].tx_dsp));          //setup dsp flow control          const double ups_per_sec = device_args_i.cast<double>("ups_per_sec", 20); @@ -809,29 +809,6 @@ void usrp2_impl::set_tx_fe_corrections(const std::string &mb, const double lo_fr  #include <boost/math/special_functions/round.hpp>  #include <boost/math/special_functions/sign.hpp> -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 - -    //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 tick_rate = _tree->access<double>("/mboards/"+mb+"/tick_rate").get(); -    const meta_range_t dsp_range = _mbc[mb].tx_dsp->get_freq_range(); -    return meta_range_t(dsp_range.start() - tick_rate*2, dsp_range.stop() + tick_rate*2, dsp_range.step()); -} -  void usrp2_impl::update_clock_source(const std::string &mb, const std::string &source){      //NOTICE: U2_REG_MISC_CTRL_CLOCK is on the wb clock, and cannot be set from fifo_ctrl      //clock source ref 10mhz | 
