summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--host/lib/usrp/dsp_utils.cpp13
-rw-r--r--host/lib/usrp/tune_helper.cpp7
-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
-rw-r--r--host/test/tune_helper_test.cpp2
6 files changed, 60 insertions, 13 deletions
diff --git a/host/lib/usrp/dsp_utils.cpp b/host/lib/usrp/dsp_utils.cpp
index 2553e4a25..576c4639f 100644
--- a/host/lib/usrp/dsp_utils.cpp
+++ b/host/lib/usrp/dsp_utils.cpp
@@ -21,6 +21,8 @@
#include <boost/assign/list_of.hpp>
#include <boost/tuple/tuple.hpp>
#include <boost/math/special_functions/round.hpp>
+#include <boost/math/special_functions/sign.hpp>
+#include <algorithm>
#include <cmath>
using namespace uhd;
@@ -65,13 +67,16 @@ boost::uint32_t dsp_type1::calc_tx_mux_word(subdev_conn_t subdev_conn){
}
boost::uint32_t dsp_type1::calc_cordic_word_and_update(
- double &freq,
- double codec_rate
+ double &freq, double codec_rate
){
- UHD_ASSERT_THROW(std::abs(freq) <= codec_rate/2.0);
- static const double scale_factor = std::pow(2.0, 32);
+ //correct for outside of rate (wrap around)
+ freq = std::fmod(freq, codec_rate);
+ if (std::abs(freq) > codec_rate/2.0)
+ freq -= boost::math::sign(freq)*codec_rate;
//calculate the freq register word (signed)
+ UHD_ASSERT_THROW(std::abs(freq) <= codec_rate/2.0);
+ static const double scale_factor = std::pow(2.0, 32);
boost::int32_t freq_word = boost::int32_t(boost::math::round((freq / codec_rate) * scale_factor));
//update the actual frequency
diff --git a/host/lib/usrp/tune_helper.cpp b/host/lib/usrp/tune_helper.cpp
index fa40a8a26..eccee7f4b 100644
--- a/host/lib/usrp/tune_helper.cpp
+++ b/host/lib/usrp/tune_helper.cpp
@@ -20,7 +20,6 @@
#include <uhd/usrp/dsp_props.hpp>
#include <uhd/usrp/dboard_iface.hpp> //unit_t
#include <uhd/utils/algorithm.hpp>
-#include <boost/math/special_functions/sign.hpp>
#include <cmath>
using namespace uhd;
@@ -37,7 +36,6 @@ static tune_result_t tune_xx_subdev_and_dsp(
wax::obj subdev_freq_proxy = subdev[SUBDEV_PROP_FREQ];
std::string freq_name = dsp[DSP_PROP_FREQ_SHIFT_NAMES].as<prop_names_t>().at(chan);
wax::obj dsp_freq_proxy = dsp[named_prop_t(DSP_PROP_FREQ_SHIFT, freq_name)];
- double dsp_sample_rate = dsp[DSP_PROP_CODEC_RATE].as<double>();
//------------------------------------------------------------------
//-- calculate the LO offset, only used with automatic policy
@@ -73,10 +71,7 @@ static tune_result_t tune_xx_subdev_and_dsp(
//------------------------------------------------------------------
//-- calculate the dsp freq, only used with automatic policy
//------------------------------------------------------------------
- double delta_freq = std::fmod(tune_request.target_freq - actual_inter_freq, dsp_sample_rate);
- bool outside_of_nyquist = std::abs(delta_freq) > dsp_sample_rate/2.0;
- double target_dsp_freq = (outside_of_nyquist)?
- boost::math::sign(delta_freq)*dsp_sample_rate - delta_freq : -delta_freq;
+ double target_dsp_freq = actual_inter_freq - tune_request.target_freq;
//invert the sign on the dsp freq given the following conditions
if (unit == dboard_iface::UNIT_TX) target_dsp_freq *= -1.0;
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;
diff --git a/host/test/tune_helper_test.cpp b/host/test/tune_helper_test.cpp
index e0500ae3f..735e7e948 100644
--- a/host/test/tune_helper_test.cpp
+++ b/host/test/tune_helper_test.cpp
@@ -19,6 +19,7 @@
#include <uhd/usrp/tune_helper.hpp>
#include <uhd/usrp/subdev_props.hpp>
#include <uhd/usrp/dsp_props.hpp>
+#include <uhd/usrp/dsp_utils.hpp>
#include <iostream>
using namespace uhd;
@@ -165,6 +166,7 @@ private:
switch(key.as<dsp_prop_t>()){
case DSP_PROP_FREQ_SHIFT:
_freq_shift = val.as<double>();
+ dsp_type1::calc_cordic_word_and_update(_freq_shift, _codec_rate);
return;
case DSP_PROP_HOST_RATE: