aboutsummaryrefslogtreecommitdiffstats
path: root/host/lib/usrp
diff options
context:
space:
mode:
Diffstat (limited to 'host/lib/usrp')
-rw-r--r--host/lib/usrp/b200/b200_impl.cpp20
-rw-r--r--host/lib/usrp/b200/b200_impl.hpp7
-rw-r--r--host/lib/usrp/cores/rx_dsp_core_3000.cpp27
-rw-r--r--host/lib/usrp/cores/tx_dsp_core_3000.cpp17
-rw-r--r--host/lib/usrp/e300/e300_fpga_defs.hpp2
-rw-r--r--host/lib/usrp/x300/x300_fw_common.h2
-rw-r--r--host/lib/usrp/x300/x300_impl.cpp8
-rw-r--r--host/lib/usrp/x300/x300_impl.hpp2
8 files changed, 50 insertions, 35 deletions
diff --git a/host/lib/usrp/b200/b200_impl.cpp b/host/lib/usrp/b200/b200_impl.cpp
index 19b01caaf..ffce08567 100644
--- a/host/lib/usrp/b200/b200_impl.cpp
+++ b/host/lib/usrp/b200/b200_impl.cpp
@@ -94,7 +94,7 @@ public:
digital_interface_delays_t get_digital_interface_timing() {
digital_interface_delays_t delays;
delays.rx_clk_delay = 0;
- delays.rx_data_delay = 0x6;
+ delays.rx_data_delay = 0xF;
delays.tx_clk_delay = 0;
delays.tx_data_delay = 0xF;
return delays;
@@ -555,8 +555,7 @@ b200_impl::b200_impl(const uhd::device_addr_t& device_addr, usb_device_handle::s
client_settings = boost::make_shared<b200_ad9361_client_t>();
}
_codec_ctrl = ad9361_ctrl::make_spi(client_settings, _spi_iface, AD9361_SLAVENO);
- this->reset_codec_dcm();
-
+
////////////////////////////////////////////////////////////////////
// create codec control objects
////////////////////////////////////////////////////////////////////
@@ -908,9 +907,6 @@ double b200_impl::set_tick_rate(const double new_tick_rate)
_tick_rate = _codec_ctrl->set_clock_rate(new_tick_rate);
UHD_MSG(status) << std::endl << (boost::format("Actually got clock rate %.6f MHz.") % (_tick_rate/1e6)) << std::endl;
- //reset after clock rate change
- this->reset_codec_dcm();
-
BOOST_FOREACH(radio_perifs_t &perif, _radio_perifs)
{
perif.time64->set_tick_rate(_tick_rate);
@@ -1136,7 +1132,7 @@ void b200_impl::update_gpio_state(void)
| (_gpio_state.rx_bandsel_a << 5)
| (_gpio_state.rx_bandsel_b << 4)
| (_gpio_state.rx_bandsel_c << 3)
- | (_gpio_state.codec_arst << 2)
+ // Bit 2 currently not used.
| (_gpio_state.mimo << 1)
| (_gpio_state.ref_sel << 0)
;
@@ -1144,15 +1140,6 @@ void b200_impl::update_gpio_state(void)
_local_ctrl->poke32(TOREG(SR_CORE_MISC), misc_word);
}
-void b200_impl::reset_codec_dcm(void)
-{
- _gpio_state.codec_arst = 1;
- this->update_gpio_state();
- boost::this_thread::sleep(boost::posix_time::milliseconds(10));
- _gpio_state.codec_arst = 0;
- this->update_gpio_state();
-}
-
void b200_impl::update_atrs(void)
{
if (_radio_perifs.size() > _fe1 and _radio_perifs[_fe1].atr)
@@ -1219,7 +1206,6 @@ void b200_impl::update_enables(void)
//setup the active chains in the codec
_codec_ctrl->set_active_chains(enb_tx1, enb_tx2, enb_rx1, enb_rx2);
if ((num_rx + num_tx) == 0) _codec_ctrl->set_active_chains(true, false, true, false); //enable something
- this->reset_codec_dcm(); //set_active_chains could cause a clock rate change - reset dcm
//figure out if mimo is enabled based on new state
_gpio_state.mimo = (mimo)? 1 : 0;
diff --git a/host/lib/usrp/b200/b200_impl.hpp b/host/lib/usrp/b200/b200_impl.hpp
index b291f8e5c..25fef7d4b 100644
--- a/host/lib/usrp/b200/b200_impl.hpp
+++ b/host/lib/usrp/b200/b200_impl.hpp
@@ -49,8 +49,8 @@
#include "recv_packet_demuxer_3000.hpp"
static const boost::uint8_t B200_FW_COMPAT_NUM_MAJOR = 8;
static const boost::uint8_t B200_FW_COMPAT_NUM_MINOR = 0;
-static const boost::uint16_t B200_FPGA_COMPAT_NUM = 10;
-static const boost::uint16_t B205_FPGA_COMPAT_NUM = 1;
+static const boost::uint16_t B200_FPGA_COMPAT_NUM = 11;
+static const boost::uint16_t B205_FPGA_COMPAT_NUM = 2;
static const double B200_BUS_CLOCK_RATE = 100e6;
static const boost::uint32_t B200_GPSDO_ST_NONE = 0x83;
static const size_t B200_MAX_RATE_USB2 = 53248000; // bytes/s
@@ -204,7 +204,7 @@ private:
void handle_overflow(const size_t radio_index);
struct gpio_state {
- boost::uint32_t tx_bandsel_a, tx_bandsel_b, rx_bandsel_a, rx_bandsel_b, rx_bandsel_c, codec_arst, mimo, ref_sel, swap_atr;
+ boost::uint32_t tx_bandsel_a, tx_bandsel_b, rx_bandsel_a, rx_bandsel_b, rx_bandsel_c, mimo, ref_sel, swap_atr;
gpio_state() {
tx_bandsel_a = 0;
@@ -212,7 +212,6 @@ private:
rx_bandsel_a = 0;
rx_bandsel_b = 0;
rx_bandsel_c = 0;
- codec_arst = 0;
mimo = 0;
ref_sel = 0;
swap_atr = 0;
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);
}
diff --git a/host/lib/usrp/e300/e300_fpga_defs.hpp b/host/lib/usrp/e300/e300_fpga_defs.hpp
index f514ec9e6..a8fa60d9d 100644
--- a/host/lib/usrp/e300/e300_fpga_defs.hpp
+++ b/host/lib/usrp/e300/e300_fpga_defs.hpp
@@ -21,7 +21,7 @@ namespace uhd { namespace usrp { namespace e300 { namespace fpga {
static const size_t NUM_RADIOS = 2;
-static const boost::uint32_t COMPAT_MAJOR = 10;
+static const boost::uint32_t COMPAT_MAJOR = 11;
static const boost::uint32_t COMPAT_MINOR = 0;
}}}} // namespace
diff --git a/host/lib/usrp/x300/x300_fw_common.h b/host/lib/usrp/x300/x300_fw_common.h
index b0b7cfd02..1b88db69a 100644
--- a/host/lib/usrp/x300/x300_fw_common.h
+++ b/host/lib/usrp/x300/x300_fw_common.h
@@ -33,7 +33,7 @@ extern "C" {
#define X300_REVISION_MIN 2
#define X300_FW_COMPAT_MAJOR 4
#define X300_FW_COMPAT_MINOR 0
-#define X300_FPGA_COMPAT_MAJOR 14
+#define X300_FPGA_COMPAT_MAJOR 15
//shared memory sections - in between the stack and the program space
#define X300_FW_SHMEM_BASE 0x6000
diff --git a/host/lib/usrp/x300/x300_impl.cpp b/host/lib/usrp/x300/x300_impl.cpp
index f57556a8b..1e424414e 100644
--- a/host/lib/usrp/x300/x300_impl.cpp
+++ b/host/lib/usrp/x300/x300_impl.cpp
@@ -1334,6 +1334,14 @@ void x300_impl::register_loopback_self_test(wb_iface::sptr iface)
UHD_MSG(status) << ((test_fail)? " fail" : "pass") << std::endl;
}
+void x300_impl::radio_loopback(wb_iface::sptr iface, const bool on)
+{
+ iface->poke32(radio::sr_addr(radio::LOOPBACK), (on ? 0x1 : 0x0));
+ UHD_MSG(status) << ((on)? "Radio Loopback On" : "Radio Loopback Off") << std::endl;
+}
+
+
+
/***********************************************************************
* clock and time control logic
**********************************************************************/
diff --git a/host/lib/usrp/x300/x300_impl.hpp b/host/lib/usrp/x300/x300_impl.hpp
index 78c497ad9..1630047af 100644
--- a/host/lib/usrp/x300/x300_impl.hpp
+++ b/host/lib/usrp/x300/x300_impl.hpp
@@ -250,6 +250,8 @@ private:
void register_loopback_self_test(uhd::wb_iface::sptr iface);
+ void radio_loopback(uhd::wb_iface::sptr iface, const bool on);
+
/*! \brief Initialize the radio component on a given slot.
*
* Call this function once per slot (A and B) and motherboard to initialize all the radio components.