diff options
-rw-r--r-- | host/CMakeLists.txt | 4 | ||||
-rw-r--r-- | host/docs/sync.dox | 3 | ||||
-rw-r--r-- | host/lib/transport/super_recv_packet_handler.hpp | 4 | ||||
-rw-r--r-- | host/lib/usrp/b200/b200_impl.cpp | 20 | ||||
-rw-r--r-- | host/lib/usrp/b200/b200_impl.hpp | 7 | ||||
-rw-r--r-- | host/lib/usrp/cores/rx_dsp_core_3000.cpp | 27 | ||||
-rw-r--r-- | host/lib/usrp/cores/tx_dsp_core_3000.cpp | 17 | ||||
-rw-r--r-- | host/lib/usrp/e300/e300_fpga_defs.hpp | 2 | ||||
-rw-r--r-- | host/lib/usrp/x300/x300_fw_common.h | 2 | ||||
-rw-r--r-- | host/lib/usrp/x300/x300_impl.cpp | 8 | ||||
-rw-r--r-- | host/lib/usrp/x300/x300_impl.hpp | 2 | ||||
-rw-r--r-- | host/utils/uhd-usrp.rules | 1 |
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" |