aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--host/CMakeLists.txt4
-rw-r--r--host/docs/sync.dox3
-rw-r--r--host/lib/transport/super_recv_packet_handler.hpp4
-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
-rw-r--r--host/utils/uhd-usrp.rules1
12 files changed, 57 insertions, 40 deletions
diff --git a/host/CMakeLists.txt b/host/CMakeLists.txt
index 3dd563592..5736acf90 100644
--- a/host/CMakeLists.txt
+++ b/host/CMakeLists.txt
@@ -269,8 +269,8 @@ UHD_INSTALL(FILES
#{{{IMG_SECTION
# This section is written automatically by /images/create_imgs_package.py
# Any manual changes in here will be overwritten.
-SET(UHD_IMAGES_MD5SUM "0df3492fda2bd52db47d9f9e6ae475ca")
-SET(UHD_IMAGES_DOWNLOAD_SRC "uhd-images_003.009.000-release.zip")
+SET(UHD_IMAGES_MD5SUM "033ee49251ee21be656f2fe7546fbbb2")
+SET(UHD_IMAGES_DOWNLOAD_SRC "uhd-images_003.009.000-16-g5284e247.zip")
#}}}
########################################################################
diff --git a/host/docs/sync.dox b/host/docs/sync.dox
index aaae88702..59f849e1a 100644
--- a/host/docs/sync.dox
+++ b/host/docs/sync.dox
@@ -152,7 +152,7 @@ metadata should have a time spec set: :
size_t num_tx_samps = tx_streamer->send(buffs, samps_to_send, md);
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-\subsection sync_phase_lo Align LOs in the front-end (SBX, WBX, UBX)
+\subsection sync_phase_lo Align LOs in the front-end (SBX, UBX)
Using timed commands, multiple frontends can be tuned at a specific
time. This timed-tuning ensures that the phase offsets between VCO/PLL
@@ -161,7 +161,6 @@ chains will remain constant after each re-tune. See notes below:
- There is a random phase offset between any two frontends
- This phase offset is different for different LO frequencies
- This phase offset remains constant after retuning
- - Due to a divider, WBX phase offset will be randomly +/- 180 deg after re-tune on all USRPs.
- Due to a divider, UBX phase offset will be randomly +/- 180 deg after re-tune on N200/N210.
On X300/X310, phase sync with UBX fully works.
- This phase offset will drift over time due to thermal and other characteristics
diff --git a/host/lib/transport/super_recv_packet_handler.hpp b/host/lib/transport/super_recv_packet_handler.hpp
index 66852f705..3fcf9c1e6 100644
--- a/host/lib/transport/super_recv_packet_handler.hpp
+++ b/host/lib/transport/super_recv_packet_handler.hpp
@@ -203,7 +203,9 @@ public:
//! Overload call to issue stream commands
void issue_stream_cmd(const stream_cmd_t &stream_cmd)
{
- if (stream_cmd.stream_now and _props.size() > 1) {
+ if (stream_cmd.stream_now
+ and stream_cmd.stream_mode != stream_cmd_t::STREAM_MODE_STOP_CONTINUOUS
+ and _props.size() > 1) {
throw uhd::runtime_error("Attempting to do multi-channel receive with stream_now == true will result in misaligned channels. Aborting.");
}
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.
diff --git a/host/utils/uhd-usrp.rules b/host/utils/uhd-usrp.rules
index 10d68a290..e10c86f13 100644
--- a/host/utils/uhd-usrp.rules
+++ b/host/utils/uhd-usrp.rules
@@ -23,5 +23,6 @@ SUBSYSTEMS=="usb", ATTRS{idVendor}=="2500", ATTRS{idProduct}=="0002", MODE:="066
#B200
SUBSYSTEMS=="usb", ATTRS{idVendor}=="2500", ATTRS{idProduct}=="0020", MODE:="0666"
+SUBSYSTEMS=="usb", ATTRS{idVendor}=="2500", ATTRS{idProduct}=="0021", MODE:="0666"
SUBSYSTEMS=="usb", ATTRS{idVendor}=="3923", ATTRS{idProduct}=="7813", MODE:="0666"
SUBSYSTEMS=="usb", ATTRS{idVendor}=="3923", ATTRS{idProduct}=="7814", MODE:="0666"