aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--host/lib/usrp/usrp2/codec_ctrl.cpp23
-rw-r--r--host/lib/usrp/usrp2/codec_ctrl.hpp9
-rw-r--r--host/lib/usrp/usrp2/dsp_impl.cpp19
3 files changed, 48 insertions, 3 deletions
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;