mirror of
https://github.com/saymrwulf/uhd.git
synced 2026-05-16 21:10:10 +00:00
uhd: fixing TX DSP tuning on gen2 devices, special changes for n2xx
This fixes RX DSP core 200 from tuning outside range and causing overflows.
This commit is contained in:
parent
fe88d80653
commit
b29e80cc27
3 changed files with 55 additions and 33 deletions
|
|
@ -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();
|
||||
|
||||
//update the actual frequency
|
||||
} 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));
|
||||
}
|
||||
|
||||
//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;
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
||||
//update the actual frequency
|
||||
} 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));
|
||||
}
|
||||
|
||||
//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;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Reference in a new issue