aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAshish Chaudhari <ashish@ettus.com>2016-03-13 18:30:21 -0700
committerAshish Chaudhari <ashish@ettus.com>2016-03-21 17:46:23 -0700
commit7fad896c07fbdda4cf112e9e4999a5ab8f5484a5 (patch)
tree1090e59026bb9ca1958ad48b72722d3960e79d54
parent9d6c0b7f875ac24c284e355ef54f52ed41f8137e (diff)
downloaduhd-7fad896c07fbdda4cf112e9e4999a5ab8f5484a5.tar.gz
uhd-7fad896c07fbdda4cf112e9e4999a5ab8f5484a5.tar.bz2
uhd-7fad896c07fbdda4cf112e9e4999a5ab8f5484a5.zip
usrp3: Added RX DSP support for heterodyne sampling
- rx_dsp_core: set_mux takes in a fe_connection obj to determine IQ mapping and sampling mode parameters - rx_dsp_core: Support a non-zero IF for downconversion The current strategy applies a software DSP freq offset which eats into the range of the CORDIC which is OK because heterodyne assumes real-mode sampling
-rw-r--r--host/lib/usrp/b200/b200_impl.cpp2
-rw-r--r--host/lib/usrp/cores/rx_dsp_core_3000.cpp54
-rw-r--r--host/lib/usrp/cores/rx_dsp_core_3000.hpp3
-rw-r--r--host/lib/usrp/e300/e300_io_impl.cpp2
-rw-r--r--host/lib/usrp/x300/x300_io_impl.cpp2
5 files changed, 46 insertions, 17 deletions
diff --git a/host/lib/usrp/b200/b200_impl.cpp b/host/lib/usrp/b200/b200_impl.cpp
index 565ce681a..bfb32b2c8 100644
--- a/host/lib/usrp/b200/b200_impl.cpp
+++ b/host/lib/usrp/b200/b200_impl.cpp
@@ -765,7 +765,7 @@ void b200_impl::setup_radio(const size_t dspno)
perif.framer = rx_vita_core_3000::make(perif.ctrl, TOREG(SR_RX_CTRL));
perif.ddc = rx_dsp_core_3000::make(perif.ctrl, TOREG(SR_RX_DSP), true /*is_b200?*/);
perif.ddc->set_link_rate(10e9/8); //whatever
- perif.ddc->set_mux("IQ", false, dspno == 1 ? true : false, dspno == 1 ? true : false);
+ perif.ddc->set_mux(usrp::fe_connection_t(dspno == 1 ? "IbQb" : "IQ"));
perif.ddc->set_freq(rx_dsp_core_3000::DEFAULT_CORDIC_FREQ);
perif.deframer = tx_vita_core_3000::make_no_radio_buff(perif.ctrl, TOREG(SR_TX_CTRL));
perif.duc = tx_dsp_core_3000::make(perif.ctrl, TOREG(SR_TX_DSP));
diff --git a/host/lib/usrp/cores/rx_dsp_core_3000.cpp b/host/lib/usrp/cores/rx_dsp_core_3000.cpp
index 0c11c5a12..eedbbef95 100644
--- a/host/lib/usrp/cores/rx_dsp_core_3000.cpp
+++ b/host/lib/usrp/cores/rx_dsp_core_3000.cpp
@@ -69,6 +69,7 @@ public:
_scaling_adjustment = 1.0;
_dsp_extra_scaling = 1.0;
_tick_rate = 1.0;
+ _dsp_freq_offset = 0.0;
}
~rx_dsp_core_3000_impl(void)
@@ -79,17 +80,41 @@ public:
)
}
- void set_mux(const std::string &mode, const bool fe_swapped, const bool invert_i, const bool invert_q){
- static const uhd::dict<std::string, boost::uint32_t> mode_to_mux = boost::assign::map_list_of
- ("IQ", 0)
- ("QI", FLAG_DSP_RX_MUX_SWAP_IQ)
- ("I", FLAG_DSP_RX_MUX_REAL_MODE)
- ("Q", FLAG_DSP_RX_MUX_SWAP_IQ | FLAG_DSP_RX_MUX_REAL_MODE)
- ;
- _iface->poke32(REG_DSP_RX_MUX, mode_to_mux[mode]
- | (fe_swapped ? FLAG_DSP_RX_MUX_SWAP_IQ : 0)
- | (invert_i ? FLAG_DSP_RX_MUX_INVERT_I : 0)
- | (invert_q ? FLAG_DSP_RX_MUX_INVERT_Q : 0));
+ void set_mux(const uhd::usrp::fe_connection_t& fe_conn){
+ boost::uint32_t reg_val = 0;
+ switch (fe_conn.get_sampling_mode()) {
+ case uhd::usrp::fe_connection_t::REAL:
+ case uhd::usrp::fe_connection_t::HETERODYNE:
+ reg_val = FLAG_DSP_RX_MUX_REAL_MODE;
+ break;
+ default:
+ reg_val = 0;
+ break;
+ }
+
+ if (fe_conn.is_iq_swapped()) reg_val |= FLAG_DSP_RX_MUX_SWAP_IQ;
+ if (fe_conn.is_i_inverted()) reg_val |= FLAG_DSP_RX_MUX_INVERT_I;
+ if (fe_conn.is_q_inverted()) reg_val |= FLAG_DSP_RX_MUX_INVERT_Q;
+
+ _iface->poke32(REG_DSP_RX_MUX, reg_val);
+
+ if (fe_conn.get_sampling_mode() == uhd::usrp::fe_connection_t::HETERODYNE) {
+ //1. Remember the sign of the IF frequency.
+ // It will be discarded in the next step
+ int if_freq_sign = boost::math::sign(fe_conn.get_if_freq());
+ //2. Map IF frequency to the range [0, _tick_rate)
+ double if_freq = std::abs(std::fmod(fe_conn.get_if_freq(), _tick_rate));
+ //3. Map IF frequency to the range [-_tick_rate/2, _tick_rate/2)
+ // This is the aliased frequency
+ if (if_freq > (_tick_rate / 2.0)) {
+ if_freq -= _tick_rate;
+ }
+ //4. Set DSP offset to spin the signal in the opposite
+ // direction as the aliased frequency
+ _dsp_freq_offset = if_freq * (-if_freq_sign);
+ } else {
+ _dsp_freq_offset = 0.0;
+ }
}
void set_tick_rate(const double rate){
@@ -212,13 +237,15 @@ public:
double set_freq(const double requested_freq){
double actual_freq;
int32_t freq_word;
- get_freq_and_freq_word(requested_freq, _tick_rate, actual_freq, freq_word);
+ get_freq_and_freq_word(requested_freq + _dsp_freq_offset, _tick_rate, actual_freq, freq_word);
_iface->poke32(REG_DSP_RX_FREQ, boost::uint32_t(freq_word));
return actual_freq;
}
uhd::meta_range_t get_freq_range(void){
- return uhd::meta_range_t(-_tick_rate/2, +_tick_rate/2, _tick_rate/std::pow(2.0, 32));
+ //Too keep the DSP range symmetric about 0, we use abs(_dsp_freq_offset)
+ const double offset = std::abs<double>(_dsp_freq_offset);
+ return uhd::meta_range_t(-(_tick_rate-offset)/2, +(_tick_rate-offset)/2, _tick_rate/std::pow(2.0, 32));
}
void setup(const uhd::stream_args_t &stream_args){
@@ -274,6 +301,7 @@ private:
const bool _is_b200; //TODO: Obsolete this when we switch to the new DDC on the B200
double _tick_rate, _link_rate;
double _scaling_adjustment, _dsp_extra_scaling, _host_extra_scaling, _fxpt_scalar_correction;
+ double _dsp_freq_offset;
};
rx_dsp_core_3000::sptr rx_dsp_core_3000::make(wb_iface::sptr iface, const size_t dsp_base, const bool is_b200 /* = false */)
diff --git a/host/lib/usrp/cores/rx_dsp_core_3000.hpp b/host/lib/usrp/cores/rx_dsp_core_3000.hpp
index 65801de1d..41b328357 100644
--- a/host/lib/usrp/cores/rx_dsp_core_3000.hpp
+++ b/host/lib/usrp/cores/rx_dsp_core_3000.hpp
@@ -24,6 +24,7 @@
#include <uhd/types/stream_cmd.hpp>
#include <uhd/types/wb_iface.hpp>
#include <uhd/property_tree.hpp>
+#include <uhd/usrp/fe_connection.hpp>
#include <boost/utility.hpp>
#include <boost/shared_ptr.hpp>
#include <string>
@@ -43,7 +44,7 @@ public:
const bool is_b200 = false //TODO: Obsolete this when we switch to the new DDC on the B200
);
- virtual void set_mux(const std::string &mode, const bool fe_swapped = false, const bool invert_i = false, const bool invert_q = false) = 0;
+ virtual void set_mux(const uhd::usrp::fe_connection_t& fe_conn) = 0;
virtual void set_tick_rate(const double rate) = 0;
diff --git a/host/lib/usrp/e300/e300_io_impl.cpp b/host/lib/usrp/e300/e300_io_impl.cpp
index f9ca7b0b2..c84042e98 100644
--- a/host/lib/usrp/e300/e300_io_impl.cpp
+++ b/host/lib/usrp/e300/e300_io_impl.cpp
@@ -157,7 +157,7 @@ void e300_impl::_update_subdev_spec(
const std::string conn = _tree->access<std::string>(
mb_path / "dboards" / spec[i].db_name /
("rx_frontends") / spec[i].sd_name / "connection").get();
- _radio_perifs[i].ddc->set_mux(conn);
+ _radio_perifs[i].ddc->set_mux(usrp::fe_connection_t(conn));
_radio_perifs[i].rx_fe->set_mux(false);
}
}
diff --git a/host/lib/usrp/x300/x300_io_impl.cpp b/host/lib/usrp/x300/x300_io_impl.cpp
index 01cbc3ca7..a9fb5d830 100644
--- a/host/lib/usrp/x300/x300_io_impl.cpp
+++ b/host/lib/usrp/x300/x300_io_impl.cpp
@@ -111,7 +111,7 @@ void x300_impl::update_subdev_spec(const std::string &tx_rx, const size_t mb_i,
//swap condition
_mb[mb_i].radio_perifs[radio_idx].tx_fe->set_mux(conn);
} else {
- _mb[mb_i].radio_perifs[radio_idx].ddc->set_mux(conn);
+ _mb[mb_i].radio_perifs[radio_idx].ddc->set_mux(usrp::fe_connection_t(conn));
_mb[mb_i].radio_perifs[radio_idx].rx_fe->set_mux(false);
}
}