aboutsummaryrefslogtreecommitdiffstats
path: root/host/lib/usrp/cores
diff options
context:
space:
mode:
Diffstat (limited to 'host/lib/usrp/cores')
-rw-r--r--host/lib/usrp/cores/rx_dsp_core_3000.cpp27
-rw-r--r--host/lib/usrp/cores/tx_dsp_core_3000.cpp17
2 files changed, 32 insertions, 12 deletions
diff --git a/host/lib/usrp/cores/rx_dsp_core_3000.cpp b/host/lib/usrp/cores/rx_dsp_core_3000.cpp
index 18dabade0..035bc6a3f 100644
--- a/host/lib/usrp/cores/rx_dsp_core_3000.cpp
+++ b/host/lib/usrp/cores/rx_dsp_core_3000.cpp
@@ -173,20 +173,35 @@ public:
}
}
- // Calculate CIC decimation (i.e., without halfband decimators)
- // Calculate closest multiplier constant to reverse gain absent scale multipliers
+ // Caclulate algorithmic gain of CIC for a given decimation.
+ // For Ettus CIC R=decim, M=1, N=4. Gain = (R * M) ^ N
const double rate_pow = std::pow(double(decim & 0xff), 4);
- _scaling_adjustment = std::pow(2, ceil_log2(rate_pow))/(1.65*rate_pow);
+ // Calculate compensation gain values for algorithmic gain of CORDIC and CIC taking into account
+ // gain compensation blocks already hardcoded in place in DDC (that provide simple 1/2^n gain compensation).
+ // CORDIC algorithmic gain limits asymptotically around 1.647 after many iterations.
+ //
+ // The polar rotation of [I,Q] = [1,1] by Pi/8 also yields max magnitude of SQRT(2) (~1.4142) however
+ // input to the CORDIC thats outside the unit circle can only be sourced from a saturated RF frontend.
+ // To provide additional dynamic range head room accordingly using scale factor applied at egress from DDC would
+ // cost us small signal performance, thus we do no provide compensation gain for a saturated front end and allow
+ // the signal to clip in the H/W as needed. If we wished to avoid the signal clipping in these circumstances then adjust code to read:
+ // _scaling_adjustment = std::pow(2, ceil_log2(rate_pow))/(1.648*rate_pow*1.415);
+ _scaling_adjustment = std::pow(2, ceil_log2(rate_pow))/(1.648*rate_pow);
+
this->update_scalar();
return _tick_rate/decim_rate;
}
+ // Calculate compensation gain values for algorithmic gain of CORDIC and CIC taking into account
+ // gain compensation blocks already hardcoded in place in DDC (that provide simple 1/2^n gain compensation).
+ // Further more factor in OTW format which adds further gain factor to weight output samples correctly.
void update_scalar(void){
- const double factor = 1.0 + std::max(ceil_log2(_scaling_adjustment), 0.0);
- const double target_scalar = (1 << (_is_b200 ? 17 : 15))*_scaling_adjustment/_dsp_extra_scaling/factor;
+ const double target_scalar = (1 << (_is_b200 ? 16 : 15))*_scaling_adjustment/_dsp_extra_scaling;
const boost::int32_t actual_scalar = boost::math::iround(target_scalar);
- _fxpt_scalar_correction = target_scalar/actual_scalar*factor; //should be small
+ // Calculate the error introduced by using integer representation for the scalar, can be corrected in host later.
+ _fxpt_scalar_correction = target_scalar/actual_scalar;
+ // Write DDC with scaling correction for CIC and CORDIC that maximizes dynamic range in 32/16/12/8bits.
_iface->poke32(REG_DSP_RX_SCALE_IQ, actual_scalar);
}
diff --git a/host/lib/usrp/cores/tx_dsp_core_3000.cpp b/host/lib/usrp/cores/tx_dsp_core_3000.cpp
index 93b70435f..7e447ae7d 100644
--- a/host/lib/usrp/cores/tx_dsp_core_3000.cpp
+++ b/host/lib/usrp/cores/tx_dsp_core_3000.cpp
@@ -110,20 +110,25 @@ public:
) % interp_rate % (_tick_rate/1e6) % (rate/1e6);
}
- // Calculate CIC interpolation (i.e., without halfband interpolators)
- // Calculate closest multiplier constant to reverse gain absent scale multipliers
+ // Caclulate algorithmic gain of CIC for a given interpolation
+ // For Ettus CIC R=decim, M=1, N=3. Gain = (R * M) ^ N
const double rate_pow = std::pow(double(interp & 0xff), 3);
- _scaling_adjustment = std::pow(2, ceil_log2(rate_pow))/(1.65*rate_pow);
+ // Calculate compensation gain values for algorithmic gain of CORDIC and CIC taking into account
+ // gain compensation blocks already hardcoded in place in DDC (that provide simple 1/2^n gain compensation).
+ // CORDIC algorithmic gain limits asymptotically around 1.647 after many iterations.
+ _scaling_adjustment = std::pow(2, ceil_log2(rate_pow))/(1.648*rate_pow);
this->update_scalar();
return _tick_rate/interp_rate;
}
+ // Calculate compensation gain values for algorithmic gain of CORDIC and CIC taking into account
+ // gain compensation blocks already hardcoded in place in DDC (that provide simple 1/2^n gain compensation).
+ // Further more factor in OTW format which adds further gain factor to weight output samples correctly.
void update_scalar(void){
- const double factor = 1.0 + std::max(ceil_log2(_scaling_adjustment), 0.0);
- const double target_scalar = (1 << 17)*_scaling_adjustment/_dsp_extra_scaling/factor;
+ const double target_scalar = (1 << 16)*_scaling_adjustment/_dsp_extra_scaling;
const boost::int32_t actual_scalar = boost::math::iround(target_scalar);
- _fxpt_scalar_correction = target_scalar/actual_scalar*factor; //should be small
+ _fxpt_scalar_correction = target_scalar/actual_scalar; //should be small
_iface->poke32(REG_DSP_TX_SCALE_IQ, actual_scalar);
}