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_iface.hpp3
-rw-r--r--host/lib/usrp/b200/b200_impl.cpp122
-rw-r--r--host/lib/usrp/b200/b200_impl.hpp55
-rw-r--r--host/lib/usrp/b200/b200_io_impl.cpp156
-rw-r--r--host/lib/usrp/common/ad9361_ctrl.cpp23
-rw-r--r--host/lib/usrp/common/ad9361_ctrl.hpp27
-rw-r--r--host/lib/usrp/common/ad9361_driver/ad9361_device.cpp171
-rw-r--r--host/lib/usrp/common/ad9361_driver/ad9361_device.h16
-rw-r--r--host/lib/usrp/common/ad9361_driver/ad9361_gain_tables.h162
-rw-r--r--host/lib/usrp/e300/e300_impl.cpp2
-rw-r--r--host/lib/usrp/e300/e300_network.cpp8
-rw-r--r--host/lib/usrp/e300/e300_remote_codec_ctrl.cpp40
-rw-r--r--host/lib/usrp/e300/e300_remote_codec_ctrl.hpp6
-rw-r--r--host/lib/usrp/multi_usrp.cpp71
-rw-r--r--host/lib/usrp/x300/x300_impl.cpp50
-rw-r--r--host/lib/usrp/x300/x300_io_impl.cpp52
-rw-r--r--host/lib/usrp/x300/x300_regs.hpp140
17 files changed, 818 insertions, 286 deletions
diff --git a/host/lib/usrp/b200/b200_iface.hpp b/host/lib/usrp/b200/b200_iface.hpp
index 83adfdd64..1821865d3 100644
--- a/host/lib/usrp/b200/b200_iface.hpp
+++ b/host/lib/usrp/b200/b200_iface.hpp
@@ -26,7 +26,10 @@
#include "ad9361_ctrl.hpp"
const static boost::uint16_t B200_VENDOR_ID = 0x2500;
+const static boost::uint16_t B200_VENDOR_NI_ID = 0x3923;
const static boost::uint16_t B200_PRODUCT_ID = 0x0020;
+const static boost::uint16_t B200_PRODUCT_NI_ID = 0x7813;
+const static boost::uint16_t B210_PRODUCT_NI_ID = 0x7814;
const static boost::uint16_t FX3_VID = 0x04b4;
const static boost::uint16_t FX3_DEFAULT_PID = 0x00f3;
const static boost::uint16_t FX3_REENUM_PID = 0x00f0;
diff --git a/host/lib/usrp/b200/b200_impl.cpp b/host/lib/usrp/b200/b200_impl.cpp
index 13169a5ed..ada25ad59 100644
--- a/host/lib/usrp/b200/b200_impl.cpp
+++ b/host/lib/usrp/b200/b200_impl.cpp
@@ -90,14 +90,16 @@ static device_addrs_t b200_find(const device_addr_t &hint)
if (hint_i.has_key("addr") || hint_i.has_key("resource")) return b200_addrs;
}
- boost::uint16_t vid, pid;
+ size_t found = 0;
+ std::vector<usb_device_handle::vid_pid_pair_t> vid_pid_pair_list;//vid pid pair search list for devices.
if(hint.has_key("vid") && hint.has_key("pid") && hint.has_key("type") && hint["type"] == "b200") {
- vid = uhd::cast::hexstr_cast<boost::uint16_t>(hint.get("vid"));
- pid = uhd::cast::hexstr_cast<boost::uint16_t>(hint.get("pid"));
+ vid_pid_pair_list.push_back(usb_device_handle::vid_pid_pair_t(uhd::cast::hexstr_cast<boost::uint16_t>(hint.get("vid")),
+ uhd::cast::hexstr_cast<boost::uint16_t>(hint.get("pid"))));
} else {
- vid = B200_VENDOR_ID;
- pid = B200_PRODUCT_ID;
+ vid_pid_pair_list.push_back(usb_device_handle::vid_pid_pair_t(B200_VENDOR_ID, B200_PRODUCT_ID));
+ vid_pid_pair_list.push_back(usb_device_handle::vid_pid_pair_t(B200_VENDOR_NI_ID, B200_PRODUCT_NI_ID));
+ vid_pid_pair_list.push_back(usb_device_handle::vid_pid_pair_t(B200_VENDOR_NI_ID, B210_PRODUCT_NI_ID));
}
// Important note:
@@ -107,8 +109,9 @@ static device_addrs_t b200_find(const device_addr_t &hint)
// This requirement is a courtesy of libusb1.0 on windows.
//find the usrps and load firmware
- size_t found = 0;
- BOOST_FOREACH(usb_device_handle::sptr handle, usb_device_handle::get_device_list(vid, pid)) {
+ std::vector<usb_device_handle::sptr> uhd_usb_device_vector = usb_device_handle::get_device_list(vid_pid_pair_list);
+
+ BOOST_FOREACH(usb_device_handle::sptr handle, uhd_usb_device_vector) {
//extract the firmware path for the b200
std::string b200_fw_image;
try{
@@ -139,7 +142,7 @@ static device_addrs_t b200_find(const device_addr_t &hint)
//search for the device until found or timeout
while (boost::get_system_time() < timeout_time and b200_addrs.empty() and found != 0)
{
- BOOST_FOREACH(usb_device_handle::sptr handle, usb_device_handle::get_device_list(vid, pid))
+ BOOST_FOREACH(usb_device_handle::sptr handle, usb_device_handle::get_device_list(vid_pid_pair_list))
{
usb_control::sptr control;
try{control = usb_control::make(handle, 0);}
@@ -156,12 +159,16 @@ static device_addrs_t b200_find(const device_addr_t &hint)
{
switch (boost::lexical_cast<boost::uint16_t>(mb_eeprom["product"]))
{
+ //0x0001 and 0x7737 are Ettus B200 product Ids.
case 0x0001:
case 0x7737:
+ case B200_PRODUCT_NI_ID:
new_addr["product"] = "B200";
break;
- case 0x7738:
+ //0x0002 and 0x7738 are Ettus B210 product Ids.
case 0x0002:
+ case 0x7738:
+ case B210_PRODUCT_NI_ID:
new_addr["product"] = "B210";
break;
default: UHD_MSG(error) << "B200 unknown product code: " << mb_eeprom["product"] << std::endl;
@@ -205,13 +212,50 @@ b200_impl::b200_impl(const device_addr_t &device_addr)
//try to match the given device address with something on the USB bus
boost::uint16_t vid = B200_VENDOR_ID;
boost::uint16_t pid = B200_PRODUCT_ID;
+ bool specified_vid = false;
+ bool specified_pid = false;
+
if (device_addr.has_key("vid"))
+ {
vid = uhd::cast::hexstr_cast<boost::uint16_t>(device_addr.get("vid"));
+ specified_vid = true;
+ }
+
if (device_addr.has_key("pid"))
+ {
pid = uhd::cast::hexstr_cast<boost::uint16_t>(device_addr.get("pid"));
+ specified_pid = true;
+ }
- std::vector<usb_device_handle::sptr> device_list =
- usb_device_handle::get_device_list(vid, pid);
+ std::vector<usb_device_handle::vid_pid_pair_t> vid_pid_pair_list;//search list for devices.
+
+ // Search only for specified VID and PID if both specified
+ if (specified_vid && specified_pid)
+ {
+ vid_pid_pair_list.push_back(usb_device_handle::vid_pid_pair_t(vid,pid));
+ }
+ // Search for all supported PIDs limited to specified VID if only VID specified
+ else if (specified_vid)
+ {
+ vid_pid_pair_list.push_back(usb_device_handle::vid_pid_pair_t(vid,B200_PRODUCT_ID));
+ vid_pid_pair_list.push_back(usb_device_handle::vid_pid_pair_t(vid,B200_PRODUCT_NI_ID));
+ vid_pid_pair_list.push_back(usb_device_handle::vid_pid_pair_t(vid,B210_PRODUCT_NI_ID));
+ }
+ // Search for all supported VIDs limited to specified PID if only PID specified
+ else if (specified_pid)
+ {
+ vid_pid_pair_list.push_back(usb_device_handle::vid_pid_pair_t(B200_VENDOR_ID,pid));
+ vid_pid_pair_list.push_back(usb_device_handle::vid_pid_pair_t(B200_VENDOR_NI_ID,pid));
+ }
+ // Search for all supported devices if neither VID nor PID specified
+ else
+ {
+ vid_pid_pair_list.push_back(usb_device_handle::vid_pid_pair_t(B200_VENDOR_ID,B200_PRODUCT_ID));
+ vid_pid_pair_list.push_back(usb_device_handle::vid_pid_pair_t(B200_VENDOR_NI_ID,B200_PRODUCT_NI_ID));
+ vid_pid_pair_list.push_back(usb_device_handle::vid_pid_pair_t(B200_VENDOR_NI_ID,B210_PRODUCT_NI_ID));
+ }
+
+ std::vector<usb_device_handle::sptr> device_list = usb_device_handle::get_device_list(vid_pid_pair_list);
//locate the matching handle in the device list
usb_device_handle::sptr handle;
@@ -245,13 +289,17 @@ b200_impl::b200_impl(const device_addr_t &device_addr)
{
switch (boost::lexical_cast<boost::uint16_t>(mb_eeprom["product"]))
{
+ //0x0001 and 0x7737 are Ettus B200 product Ids.
case 0x0001:
case 0x7737:
+ case B200_PRODUCT_NI_ID:
product_name = "B200";
default_file_name = B200_FPGA_FILE_NAME;
break;
- case 0x7738:
+ //0x0002 and 0x7738 are Ettus B210 product Ids.
case 0x0002:
+ case 0x7738:
+ case B210_PRODUCT_NI_ID:
product_name = "B210";
default_file_name = B210_FPGA_FILE_NAME;
break;
@@ -417,6 +465,7 @@ b200_impl::b200_impl(const device_addr_t &device_addr)
.publish(boost::bind(&b200_impl::get_tick_rate, this))
.subscribe(boost::bind(&b200_impl::update_tick_rate, this, _1));
_tree->create<time_spec_t>(mb_path / "time" / "cmd");
+ _tree->create<bool>(mb_path / "auto_tick_rate").set(false);
////////////////////////////////////////////////////////////////////
// and do the misc mboard sensors
@@ -517,6 +566,11 @@ b200_impl::b200_impl(const device_addr_t &device_addr)
_tree->access<double>(mb_path / "rx_dsps" / str(boost::format("%u") % i)/ "rate/value").set(B200_DEFAULT_RATE);
_tree->access<double>(mb_path / "tx_dsps" / str(boost::format("%u") % i) / "rate/value").set(B200_DEFAULT_RATE);
}
+ // We can automatically choose a master clock rate, but not if the user specifies one
+ _tree->access<bool>(mb_path / "auto_tick_rate").set(not device_addr.has_key("master_clock_rate"));
+ if (not device_addr.has_key("master_clock_rate")) {
+ UHD_MSG(status) << "Setting master clock rate selection to 'automatic'." << std::endl;
+ }
//GPS installed: use external ref, time, and init time spec
if (_gps and _gps->gps_detected())
@@ -537,7 +591,7 @@ b200_impl::b200_impl(const device_addr_t &device_addr)
b200_impl::~b200_impl(void)
{
- UHD_SAFE_CALL
+ UHD_SAFE_CALL
(
_async_task.reset();
)
@@ -580,7 +634,7 @@ void b200_impl::setup_radio(const size_t dspno)
_tree->create<meta_range_t>(rx_dsp_path / "rate" / "range")
.publish(boost::bind(&rx_dsp_core_3000::get_host_rates, perif.ddc));
_tree->create<double>(rx_dsp_path / "rate" / "value")
- .coerce(boost::bind(&rx_dsp_core_3000::set_host_rate, perif.ddc, _1))
+ .coerce(boost::bind(&b200_impl::coerce_rx_samp_rate, this, perif.ddc, dspno, _1))
.subscribe(boost::bind(&b200_impl::update_rx_samp_rate, this, dspno, _1))
.set(0.0); // Can only set this after tick rate is initialized.
_tree->create<double>(rx_dsp_path / "freq" / "value")
@@ -604,7 +658,7 @@ void b200_impl::setup_radio(const size_t dspno)
_tree->create<meta_range_t>(tx_dsp_path / "rate" / "range")
.publish(boost::bind(&tx_dsp_core_3000::get_host_rates, perif.duc));
_tree->create<double>(tx_dsp_path / "rate" / "value")
- .coerce(boost::bind(&tx_dsp_core_3000::set_host_rate, perif.duc, _1))
+ .coerce(boost::bind(&b200_impl::coerce_tx_samp_rate, this, perif.duc, dspno, _1))
.subscribe(boost::bind(&b200_impl::update_tx_samp_rate, this, dspno, _1))
.set(0.0); // Can only set this after tick rate is initialized.
_tree->create<double>(tx_dsp_path / "freq" / "value")
@@ -648,7 +702,7 @@ void b200_impl::setup_radio(const size_t dspno)
_tree->create<bool>(rf_fe_path / "use_lo_offset").set(false);
_tree->create<double>(rf_fe_path / "bandwidth" / "value")
.coerce(boost::bind(&ad9361_ctrl::set_bw_filter, _codec_ctrl, key, _1))
- .set(40e6);
+ .set(56e6);
_tree->create<meta_range_t>(rf_fe_path / "bandwidth" / "range")
.publish(boost::bind(&ad9361_ctrl::get_bw_filter_range, key));
_tree->create<double>(rf_fe_path / "freq" / "value")
@@ -657,8 +711,20 @@ void b200_impl::setup_radio(const size_t dspno)
.set(B200_DEFAULT_FREQ);
_tree->create<meta_range_t>(rf_fe_path / "freq" / "range")
.publish(boost::bind(&ad9361_ctrl::get_rf_freq_range));
+ _tree->create<sensor_value_t>(rf_fe_path / "sensors" / "temp")
+ .publish(boost::bind(&ad9361_ctrl::get_temperature, _codec_ctrl));
//setup RX related stuff
+ if(direction)
+ {
+ _tree->create<bool>(rf_fe_path / "dc_offset" / "enable" )
+ .subscribe(boost::bind(&ad9361_ctrl::set_dc_offset_auto, _codec_ctrl, key, _1)).set(true);
+
+ _tree->create<bool>(rf_fe_path / "iq_balance" / "enable" )
+ .subscribe(boost::bind(&ad9361_ctrl::set_iq_balance_auto, _codec_ctrl, key, _1)).set(true);
+ }
+
+ //setup antenna stuff
if (key[0] == 'R')
{
static const std::vector<std::string> ants = boost::assign::list_of("TX/RX")("RX2");
@@ -724,7 +790,7 @@ void b200_impl::codec_loopback_self_test(wb_iface::sptr iface)
/***********************************************************************
* Sample and tick rate comprehension below
**********************************************************************/
-void b200_impl::enforce_tick_rate_limits(size_t chan_count, double tick_rate, const char* direction /*= NULL*/)
+void b200_impl::enforce_tick_rate_limits(size_t chan_count, double tick_rate, const std::string &direction /*= ""*/)
{
const size_t max_chans = 2;
if (chan_count > max_chans)
@@ -732,7 +798,7 @@ void b200_impl::enforce_tick_rate_limits(size_t chan_count, double tick_rate, co
throw uhd::value_error(boost::str(
boost::format("cannot not setup %d %s channels (maximum is %d)")
% chan_count
- % (direction ? direction : "data")
+ % (direction.empty() ? "data" : direction)
% max_chans
));
}
@@ -746,20 +812,26 @@ void b200_impl::enforce_tick_rate_limits(size_t chan_count, double tick_rate, co
% (tick_rate/1e6)
% (max_tick_rate/1e6)
% chan_count
- % (direction ? direction : "data")
+ % (direction.empty() ? "data" : direction)
));
}
}
}
-double b200_impl::set_tick_rate(const double rate)
+double b200_impl::set_tick_rate(const double new_tick_rate)
{
- UHD_MSG(status) << (boost::format("Asking for clock rate %.6f MHz\n") % (rate/1e6));
-
- check_tick_rate_with_current_streamers(rate); // Defined in b200_io_impl.cpp
+ UHD_MSG(status) << (boost::format("Asking for clock rate %.6f MHz... ") % (new_tick_rate/1e6)) << std::flush;
+ check_tick_rate_with_current_streamers(new_tick_rate); // Defined in b200_io_impl.cpp
+
+ // Make sure the clock rate is actually changed before doing
+ // the full Monty of setting regs and loopback tests etc.
+ if (std::abs(new_tick_rate - _tick_rate) < 1.0) {
+ UHD_MSG(status) << "OK" << std::endl;
+ return _tick_rate;
+ }
- _tick_rate = _codec_ctrl->set_clock_rate(rate);
- UHD_MSG(status) << (boost::format("Actually got clock rate %.6f MHz\n") % (_tick_rate/1e6));
+ _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();
diff --git a/host/lib/usrp/b200/b200_impl.hpp b/host/lib/usrp/b200/b200_impl.hpp
index 396819f9a..64d7aa7d0 100644
--- a/host/lib/usrp/b200/b200_impl.hpp
+++ b/host/lib/usrp/b200/b200_impl.hpp
@@ -98,7 +98,13 @@ public:
uhd::rx_streamer::sptr get_rx_stream(const uhd::stream_args_t &args);
uhd::tx_streamer::sptr get_tx_stream(const uhd::stream_args_t &args);
bool recv_async_msg(uhd::async_metadata_t &, double);
- void check_streamer_args(const uhd::stream_args_t &args, double tick_rate, const char* direction = NULL);
+
+ //! Check that the combination of stream args and tick rate are valid.
+ //
+ // Basically figures out the arguments for enforce_tick_rate_limits()
+ // and calls said method. If arguments are invalid, throws a
+ // uhd::value_error.
+ void check_streamer_args(const uhd::stream_args_t &args, double tick_rate, const std::string &direction = "");
private:
//controllers
@@ -191,11 +197,56 @@ private:
double _tick_rate;
double get_tick_rate(void){return _tick_rate;}
double set_tick_rate(const double rate);
+
+ /*! \brief Choose a tick rate (master clock rate) that works well for the given sampling rate.
+ *
+ * This function will try and choose a master clock rate automatically.
+ * See the function definition for details on the algorithm.
+ *
+ * The chosen tick rate is the largest multiple of two that is smaler
+ * than the max tick rate.
+ * The base rate is either given explicitly, or is the lcm() of the tx
+ * and rx sampling rates. In that case, it reads the rates directly
+ * from the property tree. It also tries to guess the number of channels
+ * (for the max possible tick rate) by checking the available streamers.
+ * This value, too, can explicitly be given.
+ *
+ * \param rate If this is given, it will be used as a minimum rate, or
+ * argument to lcm().
+ * \param tree_dsp_path The sampling rate from this property tree path
+ * will be ignored.
+ * \param num_chans If given, specifies the number of channels.
+ */
+ void set_auto_tick_rate(
+ const double rate=0,
+ const uhd::fs_path &tree_dsp_path="",
+ size_t num_chans=0
+ );
+
void update_tick_rate(const double);
- void enforce_tick_rate_limits(size_t chan_count, double tick_rate, const char* direction = NULL);
+
+ /*! Check if \p tick_rate works with \p chan_count channels.
+ *
+ * Throws a uhd::value_error if not.
+ */
+ void enforce_tick_rate_limits(size_t chan_count, double tick_rate, const std::string &direction = "");
void check_tick_rate_with_current_streamers(double rate);
+ /*! Return the max number of channels on active rx_streamer or tx_streamer objects associated with this device.
+ *
+ * \param direction Set to "TX" to only check tx_streamers, "RX" to only check
+ * rx_streamers. Any other value will check if \e any active
+ * streamers are available.
+ * \return Return the number of tx streamers (direction=="TX"), the number of rx
+ * streamers (direction=="RX") or the total number of streamers.
+ */
+ size_t max_chan_count(const std::string &direction="");
+
+ //! Coercer, attached to the "rate/value" property on the rx dsps.
+ double coerce_rx_samp_rate(rx_dsp_core_3000::sptr, size_t, const double);
void update_rx_samp_rate(const size_t, const double);
+ //! Coercer, attached to the "rate/value" property on the tx dsps.
+ double coerce_tx_samp_rate(tx_dsp_core_3000::sptr, size_t, const double);
void update_tx_samp_rate(const size_t, const double);
};
diff --git a/host/lib/usrp/b200/b200_io_impl.cpp b/host/lib/usrp/b200/b200_io_impl.cpp
index 262c95f0d..60b925517 100644
--- a/host/lib/usrp/b200/b200_io_impl.cpp
+++ b/host/lib/usrp/b200/b200_io_impl.cpp
@@ -1,5 +1,5 @@
//
-// Copyright 2012-2013 Ettus Research LLC
+// Copyright 2012-2014 Ettus Research LLC
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
@@ -21,8 +21,10 @@
#include "../../transport/super_recv_packet_handler.hpp"
#include "../../transport/super_send_packet_handler.hpp"
#include "async_packet_handler.hpp"
+#include <uhd/utils/math.hpp>
#include <boost/bind.hpp>
#include <boost/make_shared.hpp>
+#include <boost/math/common_factor.hpp>
#include <set>
using namespace uhd;
@@ -34,30 +36,32 @@ using namespace uhd::transport;
**********************************************************************/
void b200_impl::check_tick_rate_with_current_streamers(double rate)
{
- size_t max_tx_chan_count = 0, max_rx_chan_count = 0;
+ // Defined in b200_impl.cpp
+ enforce_tick_rate_limits(max_chan_count("RX"), rate, "RX");
+ enforce_tick_rate_limits(max_chan_count("TX"), rate, "TX");
+}
+
+// direction can either be "TX", "RX", or empty (default)
+size_t b200_impl::max_chan_count(const std::string &direction /* = "" */)
+{
+ size_t max_count = 0;
BOOST_FOREACH(radio_perifs_t &perif, _radio_perifs)
{
- {
+ if ((direction == "RX" or direction.empty()) and not perif.rx_streamer.expired()) {
boost::shared_ptr<sph::recv_packet_streamer> rx_streamer =
boost::dynamic_pointer_cast<sph::recv_packet_streamer>(perif.rx_streamer.lock());
- if (rx_streamer)
- max_rx_chan_count = std::max(max_rx_chan_count, rx_streamer->get_num_channels());
+ max_count = std::max(max_count, rx_streamer->get_num_channels());
}
-
- {
+ if ((direction == "TX" or direction.empty()) and not perif.tx_streamer.expired()) {
boost::shared_ptr<sph::send_packet_streamer> tx_streamer =
boost::dynamic_pointer_cast<sph::send_packet_streamer>(perif.tx_streamer.lock());
- if (tx_streamer)
- max_tx_chan_count = std::max(max_tx_chan_count, tx_streamer->get_num_channels());
+ max_count = std::max(max_count, tx_streamer->get_num_channels());
}
}
-
- // Defined in b200_impl.cpp
- enforce_tick_rate_limits(max_rx_chan_count, rate, "RX");
- enforce_tick_rate_limits(max_tx_chan_count, rate, "TX");
+ return max_count;
}
-void b200_impl::check_streamer_args(const uhd::stream_args_t &args, double tick_rate, const char* direction /*= NULL*/)
+void b200_impl::check_streamer_args(const uhd::stream_args_t &args, double tick_rate, const std::string &direction /*= ""*/)
{
std::set<size_t> chans_set;
for (size_t stream_i = 0; stream_i < args.channels.size(); stream_i++)
@@ -69,26 +73,120 @@ void b200_impl::check_streamer_args(const uhd::stream_args_t &args, double tick_
enforce_tick_rate_limits(chans_set.size(), tick_rate, direction); // Defined in b200_impl.cpp
}
-void b200_impl::update_tick_rate(const double rate)
+void b200_impl::set_auto_tick_rate(
+ const double rate,
+ const fs_path &tree_dsp_path,
+ size_t num_chans
+) {
+ if (num_chans == 0) { // Divine them
+ num_chans = std::max(size_t(1), max_chan_count());
+ }
+
+ // See also the doxygen documentation for these steps in b200_impl.hpp
+ // Step 1: Obtain LCM and max rate from all relevant dsps
+ boost::uint32_t lcm_rate = (rate == 0) ? 1 : static_cast<boost::uint32_t>(floor(rate + 0.5));
+ for (int i = 0; i < 2; i++) { // Loop through rx and tx
+ std::string dir = (i == 0) ? "tx" : "rx";
+ // We have no way of knowing which DSPs are used, so we check them all.
+ BOOST_FOREACH(const std::string &dsp_no, _tree->list(str(boost::format("/mboards/0/%s_dsps") % dir))) {
+ fs_path dsp_path = str(boost::format("/mboards/0/%s_dsps/%s") % dir % dsp_no);
+ if (dsp_path == tree_dsp_path) {
+ continue;
+ }
+ double this_dsp_rate = _tree->access<double>(dsp_path / "rate/value").get();
+ // If this_dsp_rate == B200_DEFAULT_RATE, we assume the user did not actually set
+ // the sampling rate. If the user *did* set the rate to
+ // B200_DEFAULT_RATE on all DSPs, then this will still work (see below).
+ // If the user set one DSP to B200_DEFAULT_RATE and the other to
+ // a different rate, this also works if the rates are integer multiples
+ // of one another. Only for certain configurations of B200_DEFAULT_RATE
+ // and another rate that is not an integer multiple, this will be problematic.
+ // Since this case is less common than the case where a rate is left unset,
+ // we don't handle that but rather explain that corner case in the documentation.
+ if (this_dsp_rate == B200_DEFAULT_RATE) {
+ continue;
+ }
+ lcm_rate = boost::math::lcm<boost::uint32_t>(
+ lcm_rate,
+ static_cast<boost::uint32_t>(floor(this_dsp_rate + 0.5))
+ );
+ }
+ }
+ if (lcm_rate == 1) {
+ lcm_rate = static_cast<boost::uint32_t>(B200_DEFAULT_RATE);
+ }
+
+ // Step 2: Determine whether if we can use lcm_rate (preferred),
+ // or have to give up because too large:
+ const double max_tick_rate =
+ ((num_chans <= 1) ? ad9361_device_t::AD9361_RECOMMENDED_MAX_CLOCK_RATE : ad9361_device_t::AD9361_MAX_CLOCK_RATE/2);
+ double base_rate = static_cast<double>(lcm_rate);
+ if (base_rate > max_tick_rate) {
+ UHD_MSG(warning)
+ << "Cannot automatically determine an appropriate tick rate for these sampling rates." << std::endl
+ << "Consider using different sampling rates, or manually specify a suitable master clock rate." << std::endl;
+ return; // Let the others handle this
+ }
+
+ // Step 3: Choose the new rate
+ // Rules for choosing the tick rate:
+ // Choose a rate that is a power of 2 larger than the sampling rate,
+ // but at least 4. Cannot exceed the max tick rate, of course, but must
+ // be larger than the minimum tick rate.
+ // An equation that does all that is:
+ //
+ // f_auto = r * 2^floor(log2(f_max/r))
+ //
+ // where r is the base rate and f_max is the maximum tick rate. The case
+ // where floor() yields 1 must be caught.
+ const double min_tick_rate = _codec_ctrl->get_clock_rate_range().start();
+ // We use shifts here instead of 2^x because exp2() is not available in all compilers,
+ // also this guarantees no rounding issues. The type cast to int32_t serves as floor():
+ boost::int32_t multiplier = (1 << boost::int32_t(uhd::math::log2(max_tick_rate / base_rate)));
+ if (multiplier == 2 and base_rate >= min_tick_rate) {
+ // Don't bother (see above)
+ multiplier = 1;
+ }
+ double new_rate = base_rate * multiplier;
+ UHD_ASSERT_THROW(new_rate >= min_tick_rate);
+ UHD_ASSERT_THROW(new_rate <= max_tick_rate);
+
+ if (_tree->access<double>("/mboards/0/tick_rate").get() != new_rate) {
+ _tree->access<double>("/mboards/0/tick_rate").set(new_rate);
+ }
+}
+
+void b200_impl::update_tick_rate(const double new_tick_rate)
{
- check_tick_rate_with_current_streamers(rate);
+ check_tick_rate_with_current_streamers(new_tick_rate);
BOOST_FOREACH(radio_perifs_t &perif, _radio_perifs)
{
boost::shared_ptr<sph::recv_packet_streamer> my_streamer =
boost::dynamic_pointer_cast<sph::recv_packet_streamer>(perif.rx_streamer.lock());
- if (my_streamer) my_streamer->set_tick_rate(rate);
- perif.framer->set_tick_rate(_tick_rate);
+ if (my_streamer) my_streamer->set_tick_rate(new_tick_rate);
+ perif.framer->set_tick_rate(new_tick_rate);
}
BOOST_FOREACH(radio_perifs_t &perif, _radio_perifs)
{
boost::shared_ptr<sph::send_packet_streamer> my_streamer =
boost::dynamic_pointer_cast<sph::send_packet_streamer>(perif.tx_streamer.lock());
- if (my_streamer) my_streamer->set_tick_rate(rate);
- perif.deframer->set_tick_rate(_tick_rate);
+ if (my_streamer) my_streamer->set_tick_rate(new_tick_rate);
+ perif.deframer->set_tick_rate(new_tick_rate);
}
}
+
+double b200_impl::coerce_rx_samp_rate(rx_dsp_core_3000::sptr ddc, size_t dspno, const double rx_rate)
+{
+ // Have to set tick rate first, or the ddc will change the requested rate based on default tick rate
+ if (_tree->access<bool>("/mboards/0/auto_tick_rate").get()) {
+ const std::string dsp_path = (boost::format("/mboards/0/rx_dsps/%s") % dspno).str();
+ set_auto_tick_rate(rx_rate, dsp_path);
+ }
+ return ddc->set_host_rate(rx_rate);
+}
+
void b200_impl::update_rx_samp_rate(const size_t dspno, const double rate)
{
boost::shared_ptr<sph::recv_packet_streamer> my_streamer =
@@ -99,6 +197,16 @@ void b200_impl::update_rx_samp_rate(const size_t dspno, const double rate)
my_streamer->set_scale_factor(adj);
}
+double b200_impl::coerce_tx_samp_rate(tx_dsp_core_3000::sptr duc, size_t dspno, const double tx_rate)
+{
+ // Have to set tick rate first, or the duc will change the requested rate based on default tick rate
+ if (_tree->access<bool>("/mboards/0/auto_tick_rate").get()) {
+ const std::string dsp_path = (boost::format("/mboards/0/tx_dsps/%s") % dspno).str();
+ set_auto_tick_rate(tx_rate, dsp_path);
+ }
+ return duc->set_host_rate(tx_rate);
+}
+
void b200_impl::update_tx_samp_rate(const size_t dspno, const double rate)
{
boost::shared_ptr<sph::send_packet_streamer> my_streamer =
@@ -264,6 +372,9 @@ rx_streamer::sptr b200_impl::get_rx_stream(const uhd::stream_args_t &args_)
if (args.otw_format.empty()) args.otw_format = "sc16";
args.channels = args.channels.empty()? std::vector<size_t>(1, 0) : args.channels;
+ if (_tree->access<bool>("/mboards/0/auto_tick_rate").get()) {
+ set_auto_tick_rate(0, "", args.channels.size());
+ }
check_streamer_args(args, this->get_tick_rate(), "RX");
boost::shared_ptr<sph::recv_packet_streamer> my_streamer;
@@ -371,7 +482,10 @@ tx_streamer::sptr b200_impl::get_tx_stream(const uhd::stream_args_t &args_)
if (args.otw_format.empty()) args.otw_format = "sc16";
args.channels = args.channels.empty()? std::vector<size_t>(1, 0) : args.channels;
- check_streamer_args(args, this->get_tick_rate(), "TX");
+ if (_tree->access<bool>("/mboards/0/auto_tick_rate").get()) {
+ set_auto_tick_rate(0, "", args.channels.size());
+ }
+ check_streamer_args(args, this->get_tick_rate(), "RX");
boost::shared_ptr<sph::send_packet_streamer> my_streamer;
for (size_t stream_i = 0; stream_i < args.channels.size(); stream_i++)
diff --git a/host/lib/usrp/common/ad9361_ctrl.cpp b/host/lib/usrp/common/ad9361_ctrl.cpp
index 85510530d..ada74cda5 100644
--- a/host/lib/usrp/common/ad9361_ctrl.cpp
+++ b/host/lib/usrp/common/ad9361_ctrl.cpp
@@ -16,7 +16,6 @@
//
#include "ad9361_ctrl.hpp"
-#include <uhd/exception.hpp>
#include <uhd/types/ranges.hpp>
#include <uhd/utils/msg.hpp>
#include <uhd/types/serial.hpp>
@@ -172,6 +171,28 @@ public:
return sensor_value_t("RSSI", _device.get_rssi(chain), "dB");
}
+ //! read the internal temp sensor. Average over 3 results
+ sensor_value_t get_temperature()
+ {
+ return sensor_value_t("temp", _device.get_average_temperature(), "C");
+ }
+
+ void set_dc_offset_auto(const std::string &which, const bool on)
+ {
+ boost::lock_guard<boost::mutex> lock(_mutex);
+
+ ad9361_device_t::direction_t direction = _get_direction_from_antenna(which);
+ _device.set_dc_offset_auto(direction,on);
+ }
+
+ void set_iq_balance_auto(const std::string &which, const bool on)
+ {
+ boost::lock_guard<boost::mutex> lock(_mutex);
+
+ ad9361_device_t::direction_t direction = _get_direction_from_antenna(which);
+ _device.set_iq_balance_auto(direction,on);
+ }
+
private:
static ad9361_device_t::direction_t _get_direction_from_antenna(const std::string& antenna)
{
diff --git a/host/lib/usrp/common/ad9361_ctrl.hpp b/host/lib/usrp/common/ad9361_ctrl.hpp
index c5718302f..5396de225 100644
--- a/host/lib/usrp/common/ad9361_ctrl.hpp
+++ b/host/lib/usrp/common/ad9361_ctrl.hpp
@@ -22,9 +22,11 @@
#include <uhd/types/ranges.hpp>
#include <uhd/types/serial.hpp>
#include <uhd/types/sensors.hpp>
+#include <uhd/exception.hpp>
#include <boost/shared_ptr.hpp>
#include <ad9361_device.h>
#include <string>
+#include <complex>
namespace uhd { namespace usrp {
@@ -95,11 +97,34 @@ public:
//! tune the given frontend, return the exact value
virtual double tune(const std::string &which, const double value) = 0;
- //! turn on/off data port loopback
+ //! set the DC offset for I and Q manually
+ void set_dc_offset(const std::string &, const std::complex<double>)
+ {
+ //This feature should not be used according to Analog Devices
+ throw uhd::runtime_error("ad9361_ctrl::set_dc_offset this feature is not supported on this device.");
+ }
+
+ //! enable or disable the BB/RF DC tracking feature
+ virtual void set_dc_offset_auto(const std::string &which, const bool on) = 0;
+
+ //! set the IQ correction value manually
+ void set_iq_balance(const std::string &, const std::complex<double>)
+ {
+ //This feature should not be used according to Analog Devices
+ throw uhd::runtime_error("ad9361_ctrl::set_iq_balance this feature is not supported on this device.");
+ }
+
+ //! enable or disable the quadrature calibration
+ virtual void set_iq_balance_auto(const std::string &which, const bool on) = 0;
+
+ //! turn on/off Catalina's data port loopback
virtual void data_port_loopback(const bool on) = 0;
//! read internal RSSI sensor
virtual sensor_value_t get_rssi(const std::string &which) = 0;
+
+ //! read the internal temp sensor
+ virtual sensor_value_t get_temperature() = 0;
};
}}
diff --git a/host/lib/usrp/common/ad9361_driver/ad9361_device.cpp b/host/lib/usrp/common/ad9361_driver/ad9361_device.cpp
index 7268aff2d..e5938184c 100644
--- a/host/lib/usrp/common/ad9361_driver/ad9361_device.cpp
+++ b/host/lib/usrp/common/ad9361_driver/ad9361_device.cpp
@@ -11,6 +11,7 @@
#include <cmath>
#include <uhd/exception.hpp>
#include <uhd/utils/log.hpp>
+#include <uhd/utils/msg.hpp>
#include <boost/cstdint.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>
#include <boost/thread/thread.hpp>
@@ -650,11 +651,12 @@ void ad9361_device_t::_setup_adc()
}
/* Calibrate the baseband DC offset.
- *
- * Note that this function is called from within the TX quadrature
- * calibration function! */
+ * Disables tracking
+ */
void ad9361_device_t::_calibrate_baseband_dc_offset()
{
+ _io_iface->poke8(0x18b, 0x83); //Reset RF DC tracking flag
+
_io_iface->poke8(0x193, 0x3f); // Calibration settings
_io_iface->poke8(0x190, 0x0f); // Set tracking coefficient
//write_ad9361_reg(device, 0x190, /*0x0f*//*0xDF*/0x80*1 | 0x40*1 | (16+8/*+4*/)); // Set tracking coefficient: don't *4 counter, do decim /4, increased gain shift
@@ -674,9 +676,8 @@ void ad9361_device_t::_calibrate_baseband_dc_offset()
}
/* Calibrate the RF DC offset.
- *
- * Note that this function is called from within the TX quadrature
- * calibration function. */
+ * Disables tracking
+ */
void ad9361_device_t::_calibrate_rf_dc_offset()
{
/* Some settings are frequency-dependent. */
@@ -691,7 +692,7 @@ void ad9361_device_t::_calibrate_rf_dc_offset()
}
_io_iface->poke8(0x185, 0x20); // RF DC Offset wait count
- _io_iface->poke8(0x18b, 0x83);
+ _io_iface->poke8(0x18b, 0x83); // Disable tracking
_io_iface->poke8(0x189, 0x30);
/* Run the calibration! */
@@ -707,6 +708,16 @@ void ad9361_device_t::_calibrate_rf_dc_offset()
}
}
+void ad9361_device_t::_configure_bb_rf_dc_tracking(const bool on)
+{
+ if(on)
+ {
+ _io_iface->poke8(0x18b, 0xad); // Enable BB and RF DC tracking
+ } else {
+ _io_iface->poke8(0x18b, 0x83); // Disable BB and RF DC tracking
+ }
+}
+
/* Start the RX quadrature calibration.
*
* Note that we are using AD9361's 'tracking' feature for RX quadrature
@@ -719,16 +730,20 @@ void ad9361_device_t::_calibrate_rx_quadrature()
_io_iface->poke8(0x16e, 0x25); // RX Gain index to use for cal
_io_iface->poke8(0x16a, 0x75); // Set Kexp phase
_io_iface->poke8(0x16b, 0x15); // Set Kexp amplitude
- _io_iface->poke8(0x169, 0xcf); // Continuous tracking mode
- _io_iface->poke8(0x18b, 0xad);
+
+ if(_use_iq_balance_correction)
+ {
+ _io_iface->poke8(0x169, 0xcf); // Continuous tracking mode. Gets disabled in _tx_quadrature_cal_routine!
+ }
}
-/* TX quadtrature calibration routine.
+/* TX quadrature calibration routine.
*
* The TX quadrature needs to be done twice, once for each TX chain, with
* only one register change in between. Thus, this function enacts the
* calibrations, and it is called from calibrate_tx_quadrature. */
void ad9361_device_t::_tx_quadrature_cal_routine() {
+
/* This is a weird process, but here is how it works:
* 1) Read the calibrated NCO frequency bits out of 0A3.
* 2) Write the two bits to the RX NCO freq part of 0A0.
@@ -773,12 +788,6 @@ void ad9361_device_t::_tx_quadrature_cal_routine() {
_io_iface->poke8(0x0a4, 0xf0); // Cal setting conut
_io_iface->poke8(0x0ae, 0x00); // Cal LPF gain index (split mode)
- /* First, calibrate the baseband DC offset. */
- _calibrate_baseband_dc_offset();
-
- /* Second, calibrate the RF DC offset. */
- _calibrate_rf_dc_offset();
-
/* Now, calibrate the TX quadrature! */
size_t count = 0;
_io_iface->poke8(0x016, 0x10);
@@ -793,9 +802,7 @@ void ad9361_device_t::_tx_quadrature_cal_routine() {
}
/* Run the TX quadrature calibration.
- *
- * Note that from within this function we are also triggering the baseband
- * and RF DC calibrations. */
+ */
void ad9361_device_t::_calibrate_tx_quadrature()
{
/* Make sure we are, in fact, in the ALERT state. If not, something is
@@ -879,7 +886,7 @@ void ad9361_device_t::_program_mixer_gm_subtable()
void ad9361_device_t::_program_gain_table() {
/* Figure out which gain table we should be using for our current
* frequency band. */
- boost::uint8_t (*gain_table)[5] = NULL;
+ boost::uint8_t (*gain_table)[3] = NULL;
boost::uint8_t new_gain_table;
if (_rx_freq < 1300e6) {
gain_table = gain_table_sub_1300mhz;
@@ -910,9 +917,9 @@ void ad9361_device_t::_program_gain_table() {
boost::uint8_t index = 0;
for (; index < 77; index++) {
_io_iface->poke8(0x130, index);
- _io_iface->poke8(0x131, gain_table[index][1]);
- _io_iface->poke8(0x132, gain_table[index][2]);
- _io_iface->poke8(0x133, gain_table[index][3]);
+ _io_iface->poke8(0x131, gain_table[index][0]);
+ _io_iface->poke8(0x132, gain_table[index][1]);
+ _io_iface->poke8(0x133, gain_table[index][2]);
_io_iface->poke8(0x137, 0x1E);
_io_iface->poke8(0x134, 0x00);
_io_iface->poke8(0x134, 0x00);
@@ -1256,6 +1263,7 @@ double ad9361_device_t::_setup_rates(const double rate)
int divfactor = 0;
_tfir_factor = 0;
_rfir_factor = 0;
+
if (rate < 0.33e6) {
// RX1 + RX2 enabled, 3, 2, 2, 4
_regs.rxfilt = B8(11101111);
@@ -1411,6 +1419,8 @@ void ad9361_device_t::initialize()
_rx2_gain = 0;
_tx1_gain = 0;
_tx2_gain = 0;
+ _use_dc_offset_correction = true;
+ _use_iq_balance_correction = true;
/* Reset the device. */
_io_iface->poke8(0x000, 0x01);
@@ -1500,7 +1510,7 @@ void ad9361_device_t::initialize()
/* Setup AuxADC */
_io_iface->poke8(0x00B, 0x00); // Temp Sensor Setup (Offset)
_io_iface->poke8(0x00C, 0x00); // Temp Sensor Setup (Temp Window)
- _io_iface->poke8(0x00D, 0x03); // Temp Sensor Setup (Periodic Measure)
+ _io_iface->poke8(0x00D, 0x00); // Temp Sensor Setup (Manual Measure)
_io_iface->poke8(0x00F, 0x04); // Temp Sensor Setup (Decimation)
_io_iface->poke8(0x01C, 0x10); // AuxADC Setup (Clock Div)
_io_iface->poke8(0x01D, 0x01); // AuxADC Setup (Decimation/Enable)
@@ -1563,8 +1573,11 @@ void ad9361_device_t::initialize()
_setup_adc();
+ _calibrate_baseband_dc_offset();
+ _calibrate_rf_dc_offset();
_calibrate_tx_quadrature();
_calibrate_rx_quadrature();
+ _configure_bb_rf_dc_tracking(_use_dc_offset_correction);
// cals done, set PPORT config
switch (_client_params->get_digital_interface_mode()) {
@@ -1687,8 +1700,11 @@ double ad9361_device_t::set_clock_rate(const double req_rate)
_setup_adc();
+ _calibrate_baseband_dc_offset();
+ _calibrate_rf_dc_offset();
_calibrate_tx_quadrature();
_calibrate_rx_quadrature();
+ _configure_bb_rf_dc_tracking(_use_dc_offset_correction);
// cals done, set PPORT config
switch (_client_params->get_digital_interface_mode()) {
@@ -1841,9 +1857,11 @@ double ad9361_device_t::tune(direction_t direction, const double value)
_reprogram_gains();
/* Run the calibration algorithms. */
+ _calibrate_baseband_dc_offset();
+ _calibrate_rf_dc_offset();
_calibrate_tx_quadrature();
_calibrate_rx_quadrature();
-
+ _configure_bb_rf_dc_tracking(_use_dc_offset_correction); //if this is not done here, bb dc offset is not good
/* If we were in the FDD state, return it now. */
if (not_in_alert) {
_io_iface->poke8(0x014, 0x21);
@@ -1946,4 +1964,107 @@ double ad9361_device_t::get_rssi(chain_t chain)
return rssi;
}
+/*
+ * Returns the reading of the internal temperature sensor.
+ * One point calibration of the sensor was done according to datasheet
+ * leading to the given default constant correction factor.
+ */
+double ad9361_device_t::_get_temperature(const double cal_offset, const double timeout)
+{
+ //set 0x01D[0] to 1 to disable AuxADC GPIO reading
+ boost::uint8_t tmp = 0;
+ tmp = _io_iface->peek8(0x01D);
+ _io_iface->poke8(0x01D, (tmp | 0x01));
+ _io_iface->poke8(0x00B, 0); //set offset to 0
+
+ _io_iface->poke8(0x00C, 0x01); //start reading, clears bit 0x00C[1]
+ boost::posix_time::ptime start_time = boost::posix_time::microsec_clock::local_time();
+ boost::posix_time::time_duration elapsed;
+ //wait for valid data (toggle of bit 1 in 0x00C)
+ while(((_io_iface->peek8(0x00C) >> 1) & 0x01) == 0) {
+ boost::this_thread::sleep(boost::posix_time::microseconds(100));
+ elapsed = boost::posix_time::microsec_clock::local_time() - start_time;
+ if(elapsed.total_milliseconds() > (timeout*1000))
+ {
+ throw uhd::runtime_error("[ad9361_device_t] timeout while reading temperature");
+ }
+ }
+ _io_iface->poke8(0x00C, 0x00); //clear read flag
+
+ boost::uint8_t temp = _io_iface->peek8(0x00E); //read temperature.
+ double tmp_temp = temp/1.140f; //according to ADI driver
+ tmp_temp = tmp_temp + cal_offset; //Constant offset acquired by one point calibration.
+
+ return tmp_temp;
+}
+
+double ad9361_device_t::get_average_temperature(const double cal_offset, const size_t num_samples)
+{
+ double d_temp = 0;
+ for(size_t i = 0; i < num_samples; i++) {
+ double tmp_temp = _get_temperature(cal_offset);
+ d_temp += (tmp_temp/num_samples);
+ }
+ return d_temp;
+}
+
+void ad9361_device_t::set_dc_offset_auto(direction_t direction, const bool on)
+{
+ if(direction == RX)
+ {
+ _use_dc_offset_correction = on;
+ _configure_bb_rf_dc_tracking(_use_dc_offset_correction);
+ if(on)
+ {
+ _io_iface->poke8(0x182, (_io_iface->peek8(0x182) & (~((1 << 7) | (1 << 6) | (1 << 3) | (1 << 2))))); //Clear force bits
+ //Do a single shot DC offset cal before enabling tracking (Not possible if not in ALERT state. Is it necessary?)
+ } else {
+ //clear current config values
+ _io_iface->poke8(0x182, (_io_iface->peek8(0x182) | ((1 << 7) | (1 << 6) | (1 << 3) | (1 << 2)))); //Set input A and input B&C force enable bits
+ _io_iface->poke8(0x174, 0x00);
+ _io_iface->poke8(0x175, 0x00);
+ _io_iface->poke8(0x176, 0x00);
+ _io_iface->poke8(0x177, 0x00);
+ _io_iface->poke8(0x178, 0x00);
+ _io_iface->poke8(0x17D, 0x00);
+ _io_iface->poke8(0x17E, 0x00);
+ _io_iface->poke8(0x17F, 0x00);
+ _io_iface->poke8(0x180, 0x00);
+ _io_iface->poke8(0x181, 0x00);
+ }
+ } else {
+ // DC offset is removed during TX quad cal
+ throw uhd::runtime_error("[ad9361_device_t] [set_iq_balance_auto] INVALID_CODE_PATH");
+ }
+}
+
+void ad9361_device_t::set_iq_balance_auto(direction_t direction, const bool on)
+{
+ if(direction == RX)
+ {
+ _use_iq_balance_correction = on;
+ if(on)
+ {
+ //disable force registers and enable tracking
+ _io_iface->poke8(0x182, (_io_iface->peek8(0x182) & (~ ( (1<<1) | (1<<0) | (1<<5) | (1<<4) ))));
+ _calibrate_rx_quadrature();
+ } else {
+ //disable IQ tracking
+ _io_iface->poke8(0x169, 0xc0);
+ //clear current config values
+ _io_iface->poke8(0x182, (_io_iface->peek8(0x182) | ((1 << 1) | (1 << 0) | (1 << 5) | (1 << 4)))); //Set Rx2 input B&C force enable bit
+ _io_iface->poke8(0x17B, 0x00);
+ _io_iface->poke8(0x17C, 0x00);
+ _io_iface->poke8(0x179, 0x00);
+ _io_iface->poke8(0x17A, 0x00);
+ _io_iface->poke8(0x170, 0x00);
+ _io_iface->poke8(0x171, 0x00);
+ _io_iface->poke8(0x172, 0x00);
+ _io_iface->poke8(0x173, 0x00);
+ }
+ } else {
+ throw uhd::runtime_error("[ad9361_device_t] [set_iq_balance_auto] INVALID_CODE_PATH");
+ }
+}
+
}}
diff --git a/host/lib/usrp/common/ad9361_driver/ad9361_device.h b/host/lib/usrp/common/ad9361_driver/ad9361_device.h
index ca83f3037..93dc413d5 100644
--- a/host/lib/usrp/common/ad9361_driver/ad9361_device.h
+++ b/host/lib/usrp/common/ad9361_driver/ad9361_device.h
@@ -66,6 +66,18 @@ public:
/* Read back the internal RSSI measurement data. */
double get_rssi(chain_t chain);
+ /*! Read the internal temperature sensor
+ *\param calibrate return raw sensor readings or apply calibration factor.
+ *\param num_samples number of measurements to average over
+ */
+ double get_average_temperature(const double cal_offset = -30.0, const size_t num_samples = 3);
+
+ /* Turn on/off AD9361's RX DC offset correction */
+ void set_dc_offset_auto(direction_t direction, const bool on);
+
+ /* Turn on/off AD9361's RX IQ imbalance correction */
+ void set_iq_balance_auto(direction_t direction, const bool on);
+
//Constants
static const double AD9361_MAX_GAIN;
static const double AD9361_MAX_CLOCK_RATE;
@@ -95,6 +107,8 @@ private: //Methods
void _reprogram_gains();
double _tune_helper(direction_t direction, const double value);
double _setup_rates(const double rate);
+ double _get_temperature(const double cal_offset, const double timeout = 0.1);
+ void _configure_bb_rf_dc_tracking(const bool on);
private: //Members
typedef struct {
@@ -123,6 +137,8 @@ private: //Members
chip_regs_t _regs;
//Synchronization
boost::recursive_mutex _mutex;
+ bool _use_dc_offset_correction;
+ bool _use_iq_balance_correction;
};
}} //namespace
diff --git a/host/lib/usrp/common/ad9361_driver/ad9361_gain_tables.h b/host/lib/usrp/common/ad9361_driver/ad9361_gain_tables.h
index 786029d6e..553655fa5 100644
--- a/host/lib/usrp/common/ad9361_driver/ad9361_gain_tables.h
+++ b/host/lib/usrp/common/ad9361_driver/ad9361_gain_tables.h
@@ -7,91 +7,91 @@
#include <boost/cstdint.hpp>
-boost::uint8_t gain_table_sub_1300mhz[77][5] = { {0,0x00,0x00,0x20,1},
- {1,0x00,0x00,0x00,0}, {2,0x00,0x00,0x00,0}, {3,0x00,0x01,0x00,0},
- {4,0x00,0x02,0x00,0}, {5,0x00,0x03,0x00,0}, {6,0x00,0x04,0x00,0},
- {7,0x00,0x05,0x00,0}, {8,0x01,0x03,0x20,1}, {9,0x01,0x04,0x00,0},
- {10,0x01,0x05,0x00,0}, {11,0x01,0x06,0x00,0}, {12,0x01,0x07,0x00,0},
- {13,0x01,0x08,0x00,0}, {14,0x01,0x09,0x00,0}, {15,0x01,0x0A,0x00,0},
- {16,0x01,0x0B,0x00,0}, {17,0x01,0x0C,0x00,0}, {18,0x01,0x0D,0x00,0},
- {19,0x01,0x0E,0x00,0}, {20,0x02,0x09,0x20,1}, {21,0x02,0x0A,0x00,0},
- {22,0x02,0x0B,0x00,0}, {23,0x02,0x0C,0x00,0}, {24,0x02,0x0D,0x00,0},
- {25,0x02,0x0E,0x00,0}, {26,0x02,0x0F,0x00,0}, {27,0x02,0x10,0x00,0},
- {28,0x02,0x2B,0x20,1}, {29,0x02,0x2C,0x00,0}, {30,0x04,0x27,0x20,1},
- {31,0x04,0x28,0x00,0}, {32,0x04,0x29,0x00,0}, {33,0x04,0x2A,0x00,0},
- {34,0x04,0x2B,0x00,1}, {35,0x24,0x21,0x20,0}, {36,0x24,0x22,0x00,1},
- {37,0x44,0x20,0x20,0}, {38,0x44,0x21,0x00,0}, {39,0x44,0x22,0x00,0},
- {40,0x44,0x23,0x00,0}, {41,0x44,0x24,0x00,0}, {42,0x44,0x25,0x00,0},
- {43,0x44,0x26,0x00,0}, {44,0x44,0x27,0x00,0}, {45,0x44,0x28,0x00,0},
- {46,0x44,0x29,0x00,0}, {47,0x44,0x2A,0x00,0}, {48,0x44,0x2B,0x00,0},
- {49,0x44,0x2C,0x00,0}, {50,0x44,0x2D,0x00,0}, {51,0x44,0x2E,0x00,0},
- {52,0x44,0x2F,0x00,0}, {53,0x44,0x30,0x00,0}, {54,0x44,0x31,0x00,0},
- {55,0x64,0x2E,0x20,1}, {56,0x64,0x2F,0x00,0}, {57,0x64,0x30,0x00,0},
- {58,0x64,0x31,0x00,0}, {59,0x64,0x32,0x00,0}, {60,0x64,0x33,0x00,0},
- {61,0x64,0x34,0x00,0}, {62,0x64,0x35,0x00,0}, {63,0x64,0x36,0x00,0},
- {64,0x64,0x37,0x00,0}, {65,0x64,0x38,0x00,0}, {66,0x65,0x38,0x20,1},
- {67,0x66,0x38,0x20,1}, {68,0x67,0x38,0x20,1}, {69,0x68,0x38,0x20,1},
- {70,0x69,0x38,0x20,1}, {71,0x6A,0x38,0x20,1}, {72,0x6B,0x38,0x20,1},
- {73,0x6C,0x38,0x20,1}, {74,0x6D,0x38,0x20,1}, {75,0x6E,0x38,0x20,1},
- {76,0x6F,0x38,0x20,1}};
+boost::uint8_t gain_table_sub_1300mhz[77][3] = {
+{ 0x00, 0x00, 0x20 }, { 0x00, 0x00, 0x00 }, { 0x00, 0x00, 0x00 },
+{ 0x00, 0x01, 0x00 }, { 0x00, 0x02, 0x00 }, { 0x00, 0x03, 0x00 },
+{ 0x00, 0x04, 0x00 }, { 0x00, 0x05, 0x00 }, { 0x01, 0x03, 0x20 },
+{ 0x01, 0x04, 0x00 }, { 0x01, 0x05, 0x00 }, { 0x01, 0x06, 0x00 },
+{ 0x01, 0x07, 0x00 }, { 0x01, 0x08, 0x00 }, { 0x01, 0x09, 0x00 },
+{ 0x01, 0x0A, 0x00 }, { 0x01, 0x0B, 0x00 }, { 0x01, 0x0C, 0x00 },
+{ 0x01, 0x0D, 0x00 }, { 0x01, 0x0E, 0x00 }, { 0x02, 0x09, 0x20 },
+{ 0x02, 0x0A, 0x00 }, { 0x02, 0x0B, 0x00 }, { 0x02, 0x0C, 0x00 },
+{ 0x02, 0x0D, 0x00 }, { 0x02, 0x0E, 0x00 }, { 0x02, 0x0F, 0x00 },
+{ 0x02, 0x10, 0x00 }, { 0x02, 0x2B, 0x20 }, { 0x02, 0x2C, 0x00 },
+{ 0x04, 0x28, 0x20 }, { 0x04, 0x29, 0x00 }, { 0x04, 0x2A, 0x00 },
+{ 0x04, 0x2B, 0x00 }, { 0x24, 0x20, 0x20 }, { 0x24, 0x21, 0x00 },
+{ 0x44, 0x20, 0x20 }, { 0x44, 0x21, 0x00 }, { 0x44, 0x22, 0x00 },
+{ 0x44, 0x23, 0x00 }, { 0x44, 0x24, 0x00 }, { 0x44, 0x25, 0x00 },
+{ 0x44, 0x26, 0x00 }, { 0x44, 0x27, 0x00 }, { 0x44, 0x28, 0x00 },
+{ 0x44, 0x29, 0x00 }, { 0x44, 0x2A, 0x00 }, { 0x44, 0x2B, 0x00 },
+{ 0x44, 0x2C, 0x00 }, { 0x44, 0x2D, 0x00 }, { 0x44, 0x2E, 0x00 },
+{ 0x44, 0x2F, 0x00 }, { 0x44, 0x30, 0x00 }, { 0x44, 0x31, 0x00 },
+{ 0x44, 0x32, 0x00 }, { 0x64, 0x2E, 0x20 }, { 0x64, 0x2F, 0x00 },
+{ 0x64, 0x30, 0x00 }, { 0x64, 0x31, 0x00 }, { 0x64, 0x32, 0x00 },
+{ 0x64, 0x33, 0x00 }, { 0x64, 0x34, 0x00 }, { 0x64, 0x35, 0x00 },
+{ 0x64, 0x36, 0x00 }, { 0x64, 0x37, 0x00 }, { 0x64, 0x38, 0x00 },
+{ 0x65, 0x38, 0x20 }, { 0x66, 0x38, 0x20 }, { 0x67, 0x38, 0x20 },
+{ 0x68, 0x38, 0x20 }, { 0x69, 0x38, 0x20 }, { 0x6A, 0x38, 0x20 },
+{ 0x6B, 0x38, 0x20 }, { 0x6C, 0x38, 0x20 }, { 0x6D, 0x38, 0x20 },
+{ 0x6E, 0x38, 0x20 }, { 0x6F, 0x38, 0x20 } };
-boost::uint8_t gain_table_1300mhz_to_4000mhz[77][5] = { {0,0x00,0x00,0x20,1},
- {1,0x00,0x00,0x00,0}, {2,0x00,0x00,0x00,0}, {3,0x00,0x01,0x00,0},
- {4,0x00,0x02,0x00,0}, {5,0x00,0x03,0x00,0}, {6,0x00,0x04,0x00,0},
- {7,0x00,0x05,0x00,0}, {8,0x01,0x03,0x20,1}, {9,0x01,0x04,0x00,0},
- {10,0x01,0x05,0x00,0}, {11,0x01,0x06,0x00,0}, {12,0x01,0x07,0x00,0},
- {13,0x01,0x08,0x00,0}, {14,0x01,0x09,0x00,0}, {15,0x01,0x0A,0x00,0},
- {16,0x01,0x0B,0x00,0}, {17,0x01,0x0C,0x00,0}, {18,0x01,0x0D,0x00,0},
- {19,0x01,0x0E,0x00,0}, {20,0x02,0x09,0x20,1}, {21,0x02,0x0A,0x00,0},
- {22,0x02,0x0B,0x00,0}, {23,0x02,0x0C,0x00,0}, {24,0x02,0x0D,0x00,0},
- {25,0x02,0x0E,0x00,0}, {26,0x02,0x0F,0x00,0}, {27,0x02,0x10,0x00,0},
- {28,0x02,0x2B,0x20,1}, {29,0x02,0x2C,0x00,0}, {30,0x04,0x28,0x20,1},
- {31,0x04,0x29,0x00,0}, {32,0x04,0x2A,0x00,0}, {33,0x04,0x2B,0x00,0},
- {34,0x24,0x20,0x20,0}, {35,0x24,0x21,0x00,1}, {36,0x44,0x20,0x20,0},
- {37,0x44,0x21,0x00,1}, {38,0x44,0x22,0x00,0}, {39,0x44,0x23,0x00,0},
- {40,0x44,0x24,0x00,0}, {41,0x44,0x25,0x00,0}, {42,0x44,0x26,0x00,0},
- {43,0x44,0x27,0x00,0}, {44,0x44,0x28,0x00,0}, {45,0x44,0x29,0x00,0},
- {46,0x44,0x2A,0x00,0}, {47,0x44,0x2B,0x00,0}, {48,0x44,0x2C,0x00,0},
- {49,0x44,0x2D,0x00,0}, {50,0x44,0x2E,0x00,0}, {51,0x44,0x2F,0x00,0},
- {52,0x44,0x30,0x00,0}, {53,0x44,0x31,0x00,0}, {54,0x44,0x32,0x00,0},
- {55,0x64,0x2E,0x20,1}, {56,0x64,0x2F,0x00,0}, {57,0x64,0x30,0x00,0},
- {58,0x64,0x31,0x00,0}, {59,0x64,0x32,0x00,0}, {60,0x64,0x33,0x00,0},
- {61,0x64,0x34,0x00,0}, {62,0x64,0x35,0x00,0}, {63,0x64,0x36,0x00,0},
- {64,0x64,0x37,0x00,0}, {65,0x64,0x38,0x00,0}, {66,0x65,0x38,0x20,1},
- {67,0x66,0x38,0x20,1}, {68,0x67,0x38,0x20,1}, {69,0x68,0x38,0x20,1},
- {70,0x69,0x38,0x20,1}, {71,0x6A,0x38,0x20,1}, {72,0x6B,0x38,0x20,1},
- {73,0x6C,0x38,0x20,1}, {74,0x6D,0x38,0x20,1}, {75,0x6E,0x38,0x20,1},
- {76,0x6F,0x38,0x20,1}};
+boost::uint8_t gain_table_1300mhz_to_4000mhz[77][3] = {
+{ 0x00, 0x00, 0x20 }, { 0x00, 0x00, 0x00 }, { 0x00, 0x00, 0x00 },
+{ 0x00, 0x01, 0x00 }, { 0x00, 0x02, 0x00 }, { 0x00, 0x03, 0x00 },
+{ 0x00, 0x04, 0x00 }, { 0x00, 0x05, 0x00 }, { 0x01, 0x03, 0x20 },
+{ 0x01, 0x04, 0x00 }, { 0x01, 0x05, 0x00 }, { 0x01, 0x06, 0x00 },
+{ 0x01, 0x07, 0x00 }, { 0x01, 0x08, 0x00 }, { 0x01, 0x09, 0x00 },
+{ 0x01, 0x0A, 0x00 }, { 0x01, 0x0B, 0x00 }, { 0x01, 0x0C, 0x00 },
+{ 0x01, 0x0D, 0x00 }, { 0x01, 0x0E, 0x00 }, { 0x02, 0x09, 0x20 },
+{ 0x02, 0x0A, 0x00 }, { 0x02, 0x0B, 0x00 }, { 0x02, 0x0C, 0x00 },
+{ 0x02, 0x0D, 0x00 }, { 0x02, 0x0E, 0x00 }, { 0x02, 0x0F, 0x00 },
+{ 0x02, 0x10, 0x00 }, { 0x02, 0x2B, 0x20 }, { 0x02, 0x2C, 0x00 },
+{ 0x04, 0x27, 0x20 }, { 0x04, 0x28, 0x00 }, { 0x04, 0x29, 0x00 },
+{ 0x04, 0x2A, 0x00 }, { 0x04, 0x2B, 0x00 }, { 0x24, 0x21, 0x20 },
+{ 0x24, 0x22, 0x00 }, { 0x44, 0x20, 0x20 }, { 0x44, 0x21, 0x00 },
+{ 0x44, 0x22, 0x00 }, { 0x44, 0x23, 0x00 }, { 0x44, 0x24, 0x00 },
+{ 0x44, 0x25, 0x00 }, { 0x44, 0x26, 0x00 }, { 0x44, 0x27, 0x00 },
+{ 0x44, 0x28, 0x00 }, { 0x44, 0x29, 0x00 }, { 0x44, 0x2A, 0x00 },
+{ 0x44, 0x2B, 0x00 }, { 0x44, 0x2C, 0x00 }, { 0x44, 0x2D, 0x00 },
+{ 0x44, 0x2E, 0x00 }, { 0x44, 0x2F, 0x00 }, { 0x44, 0x30, 0x00 },
+{ 0x44, 0x31, 0x00 }, { 0x64, 0x2E, 0x20 }, { 0x64, 0x2F, 0x00 },
+{ 0x64, 0x30, 0x00 }, { 0x64, 0x31, 0x00 }, { 0x64, 0x32, 0x00 },
+{ 0x64, 0x33, 0x00 }, { 0x64, 0x34, 0x00 }, { 0x64, 0x35, 0x00 },
+{ 0x64, 0x36, 0x00 }, { 0x64, 0x37, 0x00 }, { 0x64, 0x38, 0x00 },
+{ 0x65, 0x38, 0x20 }, { 0x66, 0x38, 0x20 }, { 0x67, 0x38, 0x20 },
+{ 0x68, 0x38, 0x20 }, { 0x69, 0x38, 0x20 }, { 0x6A, 0x38, 0x20 },
+{ 0x6B, 0x38, 0x20 }, { 0x6C, 0x38, 0x20 }, { 0x6D, 0x38, 0x20 },
+{ 0x6E, 0x38, 0x20 }, { 0x6F, 0x38, 0x20 } };
-boost::uint8_t gain_table_4000mhz_to_6000mhz[77][5] = { {0,0x00,0x00,0x20,1},
- {1,0x00,0x00,0x00,0}, {2,0x00,0x00,0x00,0}, {3,0x00,0x00,0x00,0},
- {4,0x00,0x00,0x00,0}, {5,0x00,0x01,0x00,0}, {6,0x00,0x02,0x00,0},
- {7,0x00,0x03,0x00,0}, {8,0x01,0x01,0x20,1}, {9,0x01,0x02,0x00,0},
- {10,0x01,0x03,0x00,0}, {11,0x01,0x04,0x20,1}, {12,0x01,0x05,0x00,0},
- {13,0x01,0x06,0x00,0}, {14,0x01,0x07,0x00,0}, {15,0x01,0x08,0x00,0},
- {16,0x01,0x09,0x00,0}, {17,0x01,0x0A,0x00,0}, {18,0x01,0x0B,0x00,0},
- {19,0x01,0x0C,0x00,0}, {20,0x02,0x08,0x20,1}, {21,0x02,0x09,0x00,0},
- {22,0x02,0x0A,0x00,0}, {23,0x02,0x0B,0x20,1}, {24,0x02,0x0C,0x00,0},
- {25,0x02,0x0D,0x00,0}, {26,0x02,0x0E,0x00,0}, {27,0x02,0x0F,0x00,0},
- {28,0x02,0x2A,0x20,1}, {29,0x02,0x2B,0x00,0}, {30,0x04,0x27,0x20,1},
- {31,0x04,0x28,0x00,0}, {32,0x04,0x29,0x00,0}, {33,0x04,0x2A,0x00,0},
- {34,0x04,0x2B,0x00,0}, {35,0x04,0x2C,0x00,0}, {36,0x04,0x2D,0x00,0},
- {37,0x24,0x20,0x20,1}, {38,0x24,0x21,0x00,0}, {39,0x24,0x22,0x00,0},
- {40,0x44,0x20,0x20,1}, {41,0x44,0x21,0x00,0}, {42,0x44,0x22,0x00,0},
- {43,0x44,0x23,0x00,0}, {44,0x44,0x24,0x00,0}, {45,0x44,0x25,0x00,0},
- {46,0x44,0x26,0x00,0}, {47,0x44,0x27,0x00,0}, {48,0x44,0x28,0x00,0},
- {49,0x44,0x29,0x00,0}, {50,0x44,0x2A,0x00,0}, {51,0x44,0x2B,0x00,0},
- {52,0x44,0x2C,0x00,0}, {53,0x44,0x2D,0x00,0}, {54,0x44,0x2E,0x00,0},
- {55,0x64,0x2E,0x20,1}, {56,0x64,0x2F,0x00,0}, {57,0x64,0x30,0x00,0},
- {58,0x64,0x31,0x00,0}, {59,0x64,0x32,0x00,0}, {60,0x64,0x33,0x00,0},
- {61,0x64,0x34,0x00,0}, {62,0x64,0x35,0x00,0}, {63,0x64,0x36,0x00,0},
- {64,0x64,0x37,0x00,0}, {65,0x64,0x38,0x00,0}, {66,0x65,0x38,0x20,1},
- {67,0x66,0x38,0x20,1}, {68,0x67,0x38,0x20,1}, {69,0x68,0x38,0x20,1},
- {70,0x69,0x38,0x20,1}, {71,0x6A,0x38,0x20,1}, {72,0x6B,0x38,0x20,1},
- {73,0x6C,0x38,0x20,1}, {74,0x6D,0x38,0x20,1}, {75,0x6E,0x38,0x20,1},
- {76,0x6F,0x38,0x20,1}};
+boost::uint8_t gain_table_4000mhz_to_6000mhz[77][3] = {
+{ 0x00, 0x00, 0x20 }, { 0x00, 0x00, 0x00 }, { 0x00, 0x00, 0x00 },
+{ 0x00, 0x00, 0x00 }, { 0x00, 0x00, 0x00 }, { 0x00, 0x01, 0x00 },
+{ 0x00, 0x02, 0x00 }, { 0x00, 0x03, 0x00 }, { 0x01, 0x01, 0x20 },
+{ 0x01, 0x02, 0x00 }, { 0x01, 0x03, 0x00 }, { 0x01, 0x04, 0x20 },
+{ 0x01, 0x05, 0x00 }, { 0x01, 0x06, 0x00 }, { 0x01, 0x07, 0x00 },
+{ 0x01, 0x08, 0x00 }, { 0x01, 0x09, 0x00 }, { 0x01, 0x0A, 0x00 },
+{ 0x01, 0x0B, 0x00 }, { 0x01, 0x0C, 0x00 }, { 0x02, 0x08, 0x20 },
+{ 0x02, 0x09, 0x00 }, { 0x02, 0x0A, 0x00 }, { 0x02, 0x0B, 0x20 },
+{ 0x02, 0x0C, 0x00 }, { 0x02, 0x0D, 0x00 }, { 0x02, 0x0E, 0x00 },
+{ 0x02, 0x0F, 0x00 }, { 0x02, 0x2A, 0x20 }, { 0x02, 0x2B, 0x00 },
+{ 0x04, 0x27, 0x20 }, { 0x04, 0x28, 0x00 }, { 0x04, 0x29, 0x00 },
+{ 0x04, 0x2A, 0x00 }, { 0x04, 0x2B, 0x00 }, { 0x04, 0x2C, 0x00 },
+{ 0x04, 0x2D, 0x00 }, { 0x24, 0x20, 0x20 }, { 0x24, 0x21, 0x00 },
+{ 0x24, 0x22, 0x00 }, { 0x44, 0x20, 0x20 }, { 0x44, 0x21, 0x00 },
+{ 0x44, 0x22, 0x00 }, { 0x44, 0x23, 0x00 }, { 0x44, 0x24, 0x00 },
+{ 0x44, 0x25, 0x00 }, { 0x44, 0x26, 0x00 }, { 0x44, 0x27, 0x00 },
+{ 0x44, 0x28, 0x00 }, { 0x44, 0x29, 0x00 }, { 0x44, 0x2A, 0x00 },
+{ 0x44, 0x2B, 0x00 }, { 0x44, 0x2C, 0x00 }, { 0x44, 0x2D, 0x00 },
+{ 0x44, 0x2E, 0x00 }, { 0x64, 0x2E, 0x20 }, { 0x64, 0x2F, 0x00 },
+{ 0x64, 0x30, 0x00 }, { 0x64, 0x31, 0x00 }, { 0x64, 0x32, 0x00 },
+{ 0x64, 0x33, 0x00 }, { 0x64, 0x34, 0x00 }, { 0x64, 0x35, 0x00 },
+{ 0x64, 0x36, 0x00 }, { 0x64, 0x37, 0x00 }, { 0x64, 0x38, 0x00 },
+{ 0x65, 0x38, 0x20 }, { 0x66, 0x38, 0x20 }, { 0x67, 0x38, 0x20 },
+{ 0x68, 0x38, 0x20 }, { 0x69, 0x38, 0x20 }, { 0x6A, 0x38, 0x20 },
+{ 0x6B, 0x38, 0x20 }, { 0x6C, 0x38, 0x20 }, { 0x6D, 0x38, 0x20 },
+{ 0x6E, 0x38, 0x20 }, { 0x6F, 0x38, 0x20 } };
#endif /* INCLUDED_AD9361_GAIN_TABLES_HPP */
diff --git a/host/lib/usrp/e300/e300_impl.cpp b/host/lib/usrp/e300/e300_impl.cpp
index ac6294d5a..ce94147e8 100644
--- a/host/lib/usrp/e300/e300_impl.cpp
+++ b/host/lib/usrp/e300/e300_impl.cpp
@@ -1028,6 +1028,8 @@ void e300_impl::_setup_radio(const size_t dspno)
_tree->create<int>(rf_fe_path / "sensors"); //empty TODO
_tree->create<sensor_value_t>(rf_fe_path / "sensors" / "lo_locked")
.publish(boost::bind(&e300_impl::_get_fe_pll_lock, this, direction == "tx"));
+ _tree->create<sensor_value_t>(rf_fe_path / "sensors" / "temp")
+ .publish(boost::bind(&ad9361_ctrl::get_temperature, _codec_ctrl));
BOOST_FOREACH(const std::string &name, ad9361_ctrl::get_gain_names(key))
{
_tree->create<meta_range_t>(rf_fe_path / "gains" / name / "range")
diff --git a/host/lib/usrp/e300/e300_network.cpp b/host/lib/usrp/e300/e300_network.cpp
index bb904773b..3396931e3 100644
--- a/host/lib/usrp/e300/e300_network.cpp
+++ b/host/lib/usrp/e300/e300_network.cpp
@@ -226,6 +226,14 @@ static void e300_codec_ctrl_tunnel(
break;
case codec_xact_t::ACTION_GET_RSSI:
out->rssi = _codec_ctrl->get_rssi(which_str).to_real();
+ case codec_xact_t::ACTION_GET_TEMPERATURE:
+ out->temp = _codec_ctrl->get_temperature().to_real();
+ break;
+ case codec_xact_t::ACTION_SET_DC_OFFSET_AUTO:
+ _codec_ctrl->set_dc_offset_auto(which_str, in->use_dc_correction == 1);
+ break;
+ case codec_xact_t::ACTION_SET_IQ_BALANCE_AUTO:
+ _codec_ctrl->set_iq_balance_auto(which_str, in->use_iq_correction == 1);
break;
default:
UHD_MSG(status) << "Got unknown request?!" << std::endl;
diff --git a/host/lib/usrp/e300/e300_remote_codec_ctrl.cpp b/host/lib/usrp/e300/e300_remote_codec_ctrl.cpp
index ed8131e2f..15222a96a 100644
--- a/host/lib/usrp/e300/e300_remote_codec_ctrl.cpp
+++ b/host/lib/usrp/e300/e300_remote_codec_ctrl.cpp
@@ -116,10 +116,48 @@ public:
_args.bits = uhd::htonx<boost::uint32_t>(0);
_transact();
-
return sensor_value_t("RSSI", _retval.rssi, "dB");
}
+ sensor_value_t get_temperature()
+ {
+ _clear();
+ _args.action = uhd::htonx<boost::uint32_t>(transaction_t::ACTION_GET_TEMPERATURE);
+ _args.which = uhd::htonx<boost::uint32_t>(transaction_t::CHAIN_NONE); /*Unused*/
+ _args.bits = uhd::htonx<boost::uint32_t>(0);
+
+ _transact();
+ return sensor_value_t("temp", _retval.temp, "C");
+ }
+
+ void set_dc_offset_auto(const std::string &which, const bool on)
+ {
+ _clear();
+ _args.action = uhd::htonx<boost::uint32_t>(transaction_t::ACTION_SET_DC_OFFSET_AUTO);
+ if (which == "TX1") _args.which = uhd::htonx<boost::uint32_t>(transaction_t::CHAIN_TX1);
+ else if (which == "TX2") _args.which = uhd::htonx<boost::uint32_t>(transaction_t::CHAIN_TX2);
+ else if (which == "RX1") _args.which = uhd::htonx<boost::uint32_t>(transaction_t::CHAIN_RX1);
+ else if (which == "RX2") _args.which = uhd::htonx<boost::uint32_t>(transaction_t::CHAIN_RX2);
+ else throw std::runtime_error("e300_remote_codec_ctrl_impl incorrect chain string.");
+ _args.use_dc_correction = on ? 1 : 0;
+
+ _transact();
+ }
+
+ void set_iq_balance_auto(const std::string &which, const bool on)
+ {
+ _clear();
+ _args.action = uhd::htonx<boost::uint32_t>(transaction_t::ACTION_SET_IQ_BALANCE_AUTO);
+ if (which == "TX1") _args.which = uhd::htonx<boost::uint32_t>(transaction_t::CHAIN_TX1);
+ else if (which == "TX2") _args.which = uhd::htonx<boost::uint32_t>(transaction_t::CHAIN_TX2);
+ else if (which == "RX1") _args.which = uhd::htonx<boost::uint32_t>(transaction_t::CHAIN_RX1);
+ else if (which == "RX2") _args.which = uhd::htonx<boost::uint32_t>(transaction_t::CHAIN_RX2);
+ else throw std::runtime_error("e300_remote_codec_ctrl_impl incorrect chain string.");
+ _args.use_iq_correction = on ? 1 : 0;
+
+ _transact();
+ }
+
private:
void _transact() {
{
diff --git a/host/lib/usrp/e300/e300_remote_codec_ctrl.hpp b/host/lib/usrp/e300/e300_remote_codec_ctrl.hpp
index cbc4b52d2..855ab0f42 100644
--- a/host/lib/usrp/e300/e300_remote_codec_ctrl.hpp
+++ b/host/lib/usrp/e300/e300_remote_codec_ctrl.hpp
@@ -34,6 +34,9 @@ public:
double gain;
double freq;
double rssi;
+ double temp;
+ boost::uint32_t use_dc_correction;
+ boost::uint32_t use_iq_correction;
boost::uint64_t bits;
};
@@ -44,6 +47,9 @@ public:
static const boost::uint32_t ACTION_TUNE = 13;
static const boost::uint32_t ACTION_SET_LOOPBACK = 14;
static const boost::uint32_t ACTION_GET_RSSI = 15;
+ static const boost::uint32_t ACTION_GET_TEMPERATURE = 16;
+ static const boost::uint32_t ACTION_SET_DC_OFFSET_AUTO = 17;
+ static const boost::uint32_t ACTION_SET_IQ_BALANCE_AUTO = 18;
//Values for "which"
static const boost::uint32_t CHAIN_NONE = 0;
diff --git a/host/lib/usrp/multi_usrp.cpp b/host/lib/usrp/multi_usrp.cpp
index 175633c4c..e7d39b244 100644
--- a/host/lib/usrp/multi_usrp.cpp
+++ b/host/lib/usrp/multi_usrp.cpp
@@ -431,6 +431,9 @@ public:
******************************************************************/
void set_master_clock_rate(double rate, size_t mboard){
if (mboard != ALL_MBOARDS){
+ if (_tree->exists(mb_root(mboard) / "auto_tick_rate")) {
+ _tree->access<bool>(mb_root(mboard) / "auto_tick_rate").set(false);
+ }
_tree->access<double>(mb_root(mboard) / "tick_rate").set(rate);
return;
}
@@ -828,6 +831,16 @@ public:
}
}
+ void set_normalized_rx_gain(double gain, size_t chan = 0)
+ {
+ if (gain > 1.0 || gain < 0.0) {
+ throw uhd::runtime_error("Normalized gain out of range, must be in [0, 1].");
+ }
+ gain_range_t gain_range = get_rx_gain_range(ALL_GAINS, chan);
+ double abs_gain = (gain * (gain_range.stop() - gain_range.start())) + gain_range.start();
+ set_rx_gain(abs_gain, ALL_GAINS, chan);
+ }
+
double get_rx_gain(const std::string &name, size_t chan){
try {
return rx_gain_group(chan)->get_value(name);
@@ -836,6 +849,21 @@ public:
}
}
+ double get_normalized_rx_gain(size_t chan)
+ {
+ gain_range_t gain_range = get_rx_gain_range(ALL_GAINS, chan);
+ double gain_range_width = gain_range.stop() - gain_range.start();
+ // In case we have a device without a range of gains:
+ if (gain_range_width == 0.0) {
+ return 0;
+ }
+ double norm_gain = (get_rx_gain(ALL_GAINS, chan) - gain_range.start()) / gain_range_width;
+ // Avoid rounding errors:
+ if (norm_gain > 1.0) return 1.0;
+ if (norm_gain < 0.0) return 0.0;
+ return norm_gain;
+ }
+
gain_range_t get_rx_gain_range(const std::string &name, size_t chan){
try {
return rx_gain_group(chan)->get_range(name);
@@ -888,6 +916,9 @@ public:
if (chan != ALL_CHANS){
if (_tree->exists(rx_fe_root(chan) / "dc_offset" / "enable")) {
_tree->access<bool>(rx_fe_root(chan) / "dc_offset" / "enable").set(enb);
+ } else if (_tree->exists(rx_rf_fe_root(chan) / "dc_offset" / "enable")) {
+ /*For B2xx devices the dc-offset correction is implemented in the rf front-end*/
+ _tree->access<bool>(rx_rf_fe_root(chan) / "dc_offset" / "enable").set(enb);
} else {
UHD_MSG(warning) << "Setting DC offset compensation is not possible on this device." << std::endl;
}
@@ -912,6 +943,20 @@ public:
}
}
+ void set_rx_iq_balance(const bool enb, size_t chan){
+ if (chan != ALL_CHANS){
+ if (_tree->exists(rx_rf_fe_root(chan) / "iq_balance" / "enable")) {
+ _tree->access<bool>(rx_rf_fe_root(chan) / "iq_balance" / "enable").set(enb);
+ } else {
+ UHD_MSG(warning) << "Setting IQ imbalance compensation is not possible on this device." << std::endl;
+ }
+ return;
+ }
+ for (size_t c = 0; c < get_rx_num_channels(); c++){
+ this->set_rx_iq_balance(enb, c);
+ }
+ }
+
void set_rx_iq_balance(const std::complex<double> &offset, size_t chan){
if (chan != ALL_CHANS){
if (_tree->exists(rx_fe_root(chan) / "iq_balance" / "value")) {
@@ -1029,6 +1074,17 @@ public:
}
}
+ void set_normalized_tx_gain(double gain, size_t chan = 0)
+ {
+ if (gain > 1.0 || gain < 0.0) {
+ throw uhd::runtime_error("Normalized gain out of range, must be in [0, 1].");
+ }
+ gain_range_t gain_range = get_tx_gain_range(ALL_GAINS, chan);
+ double abs_gain = (gain * (gain_range.stop() - gain_range.start())) + gain_range.start();
+ set_tx_gain(abs_gain, ALL_GAINS, chan);
+ }
+
+
double get_tx_gain(const std::string &name, size_t chan){
try {
return tx_gain_group(chan)->get_value(name);
@@ -1037,6 +1093,21 @@ public:
}
}
+ double get_normalized_tx_gain(size_t chan)
+ {
+ gain_range_t gain_range = get_tx_gain_range(ALL_GAINS, chan);
+ double gain_range_width = gain_range.stop() - gain_range.start();
+ // In case we have a device without a range of gains:
+ if (gain_range_width == 0.0) {
+ return 0.0;
+ }
+ double norm_gain = (get_rx_gain(ALL_GAINS, chan) - gain_range.start()) / gain_range_width;
+ // Avoid rounding errors:
+ if (norm_gain > 1.0) return 1.0;
+ if (norm_gain < 0.0) return 0.0;
+ return norm_gain;
+ }
+
gain_range_t get_tx_gain_range(const std::string &name, size_t chan){
try {
return tx_gain_group(chan)->get_range(name);
diff --git a/host/lib/usrp/x300/x300_impl.cpp b/host/lib/usrp/x300/x300_impl.cpp
index e35f73eab..bf676b661 100644
--- a/host/lib/usrp/x300/x300_impl.cpp
+++ b/host/lib/usrp/x300/x300_impl.cpp
@@ -41,7 +41,7 @@
#define NIUSRPRIO_DEFAULT_RPC_PORT "5444"
-#define X300_REV(x) (x - "A" + 1)
+#define X300_REV(x) ((x) - "A" + 1)
using namespace uhd;
using namespace uhd::usrp;
@@ -1432,8 +1432,8 @@ bool x300_impl::wait_for_ref_locked(wb_iface::sptr ctrl, double timeout)
boost::this_thread::sleep(boost::posix_time::milliseconds(1));
} while (boost::get_system_time() < timeout_time);
- //failed to lock on reference
- return false;
+ //Check one last time
+ return get_ref_locked(ctrl).to_bool();
}
sensor_value_t x300_impl::get_ref_locked(wb_iface::sptr ctrl)
@@ -1720,14 +1720,20 @@ x300_impl::x300_mboard_t x300_impl::get_mb_type_from_pcie(const std::string& res
case X300_USRP_PCIE_SSID:
mb_type = USRP_X300_MB; break;
case X310_USRP_PCIE_SSID:
- case X310_2940R_PCIE_SSID:
- case X310_2942R_PCIE_SSID:
- case X310_2943R_PCIE_SSID:
- case X310_2944R_PCIE_SSID:
- case X310_2950R_PCIE_SSID:
- case X310_2952R_PCIE_SSID:
- case X310_2953R_PCIE_SSID:
- case X310_2954R_PCIE_SSID:
+ case X310_2940R_40MHz_PCIE_SSID:
+ case X310_2940R_120MHz_PCIE_SSID:
+ case X310_2942R_40MHz_PCIE_SSID:
+ case X310_2942R_120MHz_PCIE_SSID:
+ case X310_2943R_40MHz_PCIE_SSID:
+ case X310_2943R_120MHz_PCIE_SSID:
+ case X310_2944R_40MHz_PCIE_SSID:
+ case X310_2950R_40MHz_PCIE_SSID:
+ case X310_2950R_120MHz_PCIE_SSID:
+ case X310_2952R_40MHz_PCIE_SSID:
+ case X310_2952R_120MHz_PCIE_SSID:
+ case X310_2953R_40MHz_PCIE_SSID:
+ case X310_2953R_120MHz_PCIE_SSID:
+ case X310_2954R_40MHz_PCIE_SSID:
mb_type = USRP_X310_MB; break;
default:
mb_type = UNKNOWN; break;
@@ -1755,14 +1761,20 @@ x300_impl::x300_mboard_t x300_impl::get_mb_type_from_eeprom(const uhd::usrp::mbo
case X300_USRP_PCIE_SSID:
mb_type = USRP_X300_MB; break;
case X310_USRP_PCIE_SSID:
- case X310_2940R_PCIE_SSID:
- case X310_2942R_PCIE_SSID:
- case X310_2943R_PCIE_SSID:
- case X310_2944R_PCIE_SSID:
- case X310_2950R_PCIE_SSID:
- case X310_2952R_PCIE_SSID:
- case X310_2953R_PCIE_SSID:
- case X310_2954R_PCIE_SSID:
+ case X310_2940R_40MHz_PCIE_SSID:
+ case X310_2940R_120MHz_PCIE_SSID:
+ case X310_2942R_40MHz_PCIE_SSID:
+ case X310_2942R_120MHz_PCIE_SSID:
+ case X310_2943R_40MHz_PCIE_SSID:
+ case X310_2943R_120MHz_PCIE_SSID:
+ case X310_2944R_40MHz_PCIE_SSID:
+ case X310_2950R_40MHz_PCIE_SSID:
+ case X310_2950R_120MHz_PCIE_SSID:
+ case X310_2952R_40MHz_PCIE_SSID:
+ case X310_2952R_120MHz_PCIE_SSID:
+ case X310_2953R_40MHz_PCIE_SSID:
+ case X310_2953R_120MHz_PCIE_SSID:
+ case X310_2954R_40MHz_PCIE_SSID:
mb_type = USRP_X310_MB; break;
default:
UHD_MSG(warning) << "X300 unknown product code in EEPROM: " << product_num << std::endl;
diff --git a/host/lib/usrp/x300/x300_io_impl.cpp b/host/lib/usrp/x300/x300_io_impl.cpp
index 334ae8168..e3515af0c 100644
--- a/host/lib/usrp/x300/x300_io_impl.cpp
+++ b/host/lib/usrp/x300/x300_io_impl.cpp
@@ -23,6 +23,7 @@
#include <uhd/transport/nirio_zero_copy.hpp>
#include "async_packet_handler.hpp"
#include <uhd/transport/bounded_buffer.hpp>
+#include <uhd/transport/chdr.hpp>
#include <boost/bind.hpp>
#include <uhd/utils/tasks.hpp>
#include <uhd/utils/log.hpp>
@@ -124,41 +125,6 @@ void x300_impl::update_subdev_spec(const std::string &tx_rx, const size_t mb_i,
/***********************************************************************
- * VITA stuff
- **********************************************************************/
-static void x300_if_hdr_unpack_be(
- const boost::uint32_t *packet_buff,
- vrt::if_packet_info_t &if_packet_info
-){
- if_packet_info.link_type = vrt::if_packet_info_t::LINK_TYPE_CHDR;
- return vrt::if_hdr_unpack_be(packet_buff, if_packet_info);
-}
-
-static void x300_if_hdr_pack_be(
- boost::uint32_t *packet_buff,
- vrt::if_packet_info_t &if_packet_info
-){
- if_packet_info.link_type = vrt::if_packet_info_t::LINK_TYPE_CHDR;
- return vrt::if_hdr_pack_be(packet_buff, if_packet_info);
-}
-
-static void x300_if_hdr_unpack_le(
- const boost::uint32_t *packet_buff,
- vrt::if_packet_info_t &if_packet_info
-){
- if_packet_info.link_type = vrt::if_packet_info_t::LINK_TYPE_CHDR;
- return vrt::if_hdr_unpack_le(packet_buff, if_packet_info);
-}
-
-static void x300_if_hdr_pack_le(
- boost::uint32_t *packet_buff,
- vrt::if_packet_info_t &if_packet_info
-){
- if_packet_info.link_type = vrt::if_packet_info_t::LINK_TYPE_CHDR;
- return vrt::if_hdr_pack_le(packet_buff, if_packet_info);
-}
-
-/***********************************************************************
* RX flow control handler
**********************************************************************/
static size_t get_rx_flow_control_window(size_t frame_size, size_t sw_buff_size, const device_addr_t& rx_args)
@@ -209,9 +175,9 @@ static void handle_rx_flowctrl(const boost::uint32_t sid, zero_copy_if::sptr xpo
//load header
if (big_endian)
- x300_if_hdr_pack_be(pkt, packet_info);
+ vrt::chdr::if_hdr_pack_be(pkt, packet_info);
else
- x300_if_hdr_pack_le(pkt, packet_info);
+ vrt::chdr::if_hdr_pack_le(pkt, packet_info);
//load payload
pkt[packet_info.num_header_words32+0] = uhd::htonx<boost::uint32_t>(0);
@@ -276,12 +242,12 @@ static void handle_tx_async_msgs(boost::shared_ptr<x300_tx_fc_guts_t> guts, zero
{
if (big_endian)
{
- x300_if_hdr_unpack_be(packet_buff, if_packet_info);
+ vrt::chdr::if_hdr_unpack_be(packet_buff, if_packet_info);
endian_conv = uhd::ntohx;
}
else
{
- x300_if_hdr_unpack_le(packet_buff, if_packet_info);
+ vrt::chdr::if_hdr_unpack_le(packet_buff, if_packet_info);
endian_conv = uhd::wtohx;
}
}
@@ -430,10 +396,10 @@ rx_streamer::sptr x300_impl::get_rx_stream(const uhd::stream_args_t &args_)
//init some streamer stuff
std::string conv_endianness;
if (mb.if_pkt_is_big_endian) {
- my_streamer->set_vrt_unpacker(&x300_if_hdr_unpack_be);
+ my_streamer->set_vrt_unpacker(&vrt::chdr::if_hdr_unpack_be);
conv_endianness = "be";
} else {
- my_streamer->set_vrt_unpacker(&x300_if_hdr_unpack_le);
+ my_streamer->set_vrt_unpacker(&vrt::chdr::if_hdr_unpack_le);
conv_endianness = "le";
}
@@ -594,10 +560,10 @@ tx_streamer::sptr x300_impl::get_tx_stream(const uhd::stream_args_t &args_)
std::string conv_endianness;
if (mb.if_pkt_is_big_endian) {
- my_streamer->set_vrt_packer(&x300_if_hdr_pack_be);
+ my_streamer->set_vrt_packer(&vrt::chdr::if_hdr_pack_be);
conv_endianness = "be";
} else {
- my_streamer->set_vrt_packer(&x300_if_hdr_pack_le);
+ my_streamer->set_vrt_packer(&vrt::chdr::if_hdr_pack_le);
conv_endianness = "le";
}
diff --git a/host/lib/usrp/x300/x300_regs.hpp b/host/lib/usrp/x300/x300_regs.hpp
index f920b5ae2..4c5729efe 100644
--- a/host/lib/usrp/x300/x300_regs.hpp
+++ b/host/lib/usrp/x300/x300_regs.hpp
@@ -25,40 +25,40 @@
#define localparam static const int
-localparam SR_DACSYNC = 5;
-localparam SR_LOOPBACK = 6;
-localparam SR_TEST = 7;
-localparam SR_SPI = 8;
-localparam SR_GPIO = 16;
-localparam SR_MISC_OUTS = 24;
-localparam SR_READBACK = 32;
-localparam SR_TX_CTRL = 64;
-localparam SR_RX_CTRL = 96;
-localparam SR_TIME = 128;
-localparam SR_RX_DSP = 144;
-localparam SR_TX_DSP = 184;
-localparam SR_LEDS = 195;
-localparam SR_FP_GPIO = 200;
-localparam SR_RX_FRONT = 208;
-localparam SR_TX_FRONT = 216;
-
-localparam RB32_GPIO = 0;
-localparam RB32_SPI = 4;
-localparam RB64_TIME_NOW = 8;
-localparam RB64_TIME_PPS = 16;
-localparam RB32_TEST = 24;
-localparam RB32_RX = 28;
-localparam RB32_FP_GPIO = 32;
-
-localparam BL_ADDRESS = 0;
-localparam BL_DATA = 1;
+localparam SR_DACSYNC = 5;
+localparam SR_LOOPBACK = 6;
+localparam SR_TEST = 7;
+localparam SR_SPI = 8;
+localparam SR_GPIO = 16;
+localparam SR_MISC_OUTS = 24;
+localparam SR_READBACK = 32;
+localparam SR_TX_CTRL = 64;
+localparam SR_RX_CTRL = 96;
+localparam SR_TIME = 128;
+localparam SR_RX_DSP = 144;
+localparam SR_TX_DSP = 184;
+localparam SR_LEDS = 195;
+localparam SR_FP_GPIO = 200;
+localparam SR_RX_FRONT = 208;
+localparam SR_TX_FRONT = 216;
+
+localparam RB32_GPIO = 0;
+localparam RB32_SPI = 4;
+localparam RB64_TIME_NOW = 8;
+localparam RB64_TIME_PPS = 16;
+localparam RB32_TEST = 24;
+localparam RB32_RX = 28;
+localparam RB32_FP_GPIO = 32;
+
+localparam BL_ADDRESS = 0;
+localparam BL_DATA = 1;
//wishbone settings map - relevant to host code
-#define SET0_BASE 0xa000
-#define SETXB_BASE 0xb000
-#define BOOT_LDR_BASE 0xFA00
-#define I2C0_BASE 0xfe00
-#define I2C1_BASE 0xff00
+#define SET0_BASE 0xa000
+#define SETXB_BASE 0xb000
+#define BOOT_LDR_BASE 0xfa00
+#define I2C0_BASE 0xfe00
+#define I2C1_BASE 0xff00
#define SR_ADDR(base, offset) ((base) + (offset)*4)
localparam ZPU_SR_LEDS = 00;
@@ -70,56 +70,62 @@ localparam ZPU_SR_ETHINT0 = 40;
localparam ZPU_SR_ETHINT1 = 56;
//clock controls
-#define ZPU_SR_CLOCK_CTRL_CLK_SRC_EXTERNAL 0x00
-#define ZPU_SR_CLOCK_CTRL_CLK_SRC_INTERNAL 0x02
-#define ZPU_SR_CLOCK_CTRL_CLK_SRC_GPSDO 0x03
-#define ZPU_SR_CLOCK_CTRL_PPS_SRC_EXTERNAL 0x00
-#define ZPU_SR_CLOCK_CTRL_PPS_SRC_INTERNAL 0x02
-#define ZPU_SR_CLOCK_CTRL_PPS_SRC_GPSDO 0x03
-
-localparam ZPU_RB_SPI = 2;
+#define ZPU_SR_CLOCK_CTRL_CLK_SRC_EXTERNAL 0x00
+#define ZPU_SR_CLOCK_CTRL_CLK_SRC_INTERNAL 0x02
+#define ZPU_SR_CLOCK_CTRL_CLK_SRC_GPSDO 0x03
+#define ZPU_SR_CLOCK_CTRL_PPS_SRC_EXTERNAL 0x00
+#define ZPU_SR_CLOCK_CTRL_PPS_SRC_INTERNAL 0x02
+#define ZPU_SR_CLOCK_CTRL_PPS_SRC_GPSDO 0x03
+
+localparam ZPU_RB_SPI = 2;
localparam ZPU_RB_CLK_STATUS = 3;
localparam ZPU_RB_COMPAT_NUM = 6;
localparam ZPU_RB_ETH_TYPE0 = 4;
localparam ZPU_RB_ETH_TYPE1 = 5;
//clock status
-#define ZPU_RB_CLK_STATUS_LMK_STATUS (0x3 << 0)
-#define ZPU_RB_CLK_STATUS_LMK_LOCK (0x1 << 2)
-#define ZPU_RB_CLK_STATUS_LMK_HOLDOVER (0x1 << 3)
-#define ZPU_RB_CLK_STATUS_PPS_DETECT (0x1 << 4)
+#define ZPU_RB_CLK_STATUS_LMK_STATUS (0x3 << 0)
+#define ZPU_RB_CLK_STATUS_LMK_LOCK (0x1 << 2)
+#define ZPU_RB_CLK_STATUS_LMK_HOLDOVER (0x1 << 3)
+#define ZPU_RB_CLK_STATUS_PPS_DETECT (0x1 << 4)
//spi slaves on radio
-#define DB_DAC_SEN (1 << 7)
-#define DB_ADC_SEN (1 << 6)
+#define DB_DAC_SEN (1 << 7)
+#define DB_ADC_SEN (1 << 6)
#define DB_RX_LSADC_SEN (1 << 5)
#define DB_RX_LSDAC_SEN (1 << 4)
#define DB_TX_LSADC_SEN (1 << 3)
#define DB_TX_LSDAC_SEN (1 << 2)
-#define DB_RX_SEN (1 << 1)
-#define DB_TX_SEN (1 << 0)
+#define DB_RX_SEN (1 << 1)
+#define DB_TX_SEN (1 << 0)
//-------------------------------------------------------------------
// PCIe Registers
//-------------------------------------------------------------------
-static const uint32_t X300_PCIE_VID = 0x1093;
-static const uint32_t X300_PCIE_PID = 0xC4C4;
-static const uint32_t X300_USRP_PCIE_SSID = 0x7736;
-static const uint32_t X310_USRP_PCIE_SSID = 0x76CA;
-static const uint32_t X310_2940R_PCIE_SSID = 0x772B;
-static const uint32_t X310_2942R_PCIE_SSID = 0x772C;
-static const uint32_t X310_2943R_PCIE_SSID = 0x772D;
-static const uint32_t X310_2944R_PCIE_SSID = 0x772E;
-static const uint32_t X310_2950R_PCIE_SSID = 0x772F;
-static const uint32_t X310_2952R_PCIE_SSID = 0x7730;
-static const uint32_t X310_2953R_PCIE_SSID = 0x7731;
-static const uint32_t X310_2954R_PCIE_SSID = 0x7732;
+static const uint32_t X300_PCIE_VID = 0x1093;
+static const uint32_t X300_PCIE_PID = 0xC4C4;
+static const uint32_t X300_USRP_PCIE_SSID = 0x7736;
+static const uint32_t X310_USRP_PCIE_SSID = 0x76CA;
+static const uint32_t X310_2940R_40MHz_PCIE_SSID = 0x772B;
+static const uint32_t X310_2940R_120MHz_PCIE_SSID = 0x77FB;
+static const uint32_t X310_2942R_40MHz_PCIE_SSID = 0x772C;
+static const uint32_t X310_2942R_120MHz_PCIE_SSID = 0x77FC;
+static const uint32_t X310_2943R_40MHz_PCIE_SSID = 0x772D;
+static const uint32_t X310_2943R_120MHz_PCIE_SSID = 0x77FD;
+static const uint32_t X310_2944R_40MHz_PCIE_SSID = 0x772E;
+static const uint32_t X310_2950R_40MHz_PCIE_SSID = 0x772F;
+static const uint32_t X310_2950R_120MHz_PCIE_SSID = 0x77FE;
+static const uint32_t X310_2952R_40MHz_PCIE_SSID = 0x7730;
+static const uint32_t X310_2952R_120MHz_PCIE_SSID = 0x77FF;
+static const uint32_t X310_2953R_40MHz_PCIE_SSID = 0x7731;
+static const uint32_t X310_2953R_120MHz_PCIE_SSID = 0x7800;
+static const uint32_t X310_2954R_40MHz_PCIE_SSID = 0x7732;
static const uint32_t FPGA_X3xx_SIG_VALUE = 0x58333030;
static const uint32_t PCIE_FPGA_ADDR_BASE = 0xC0000;
-#define PCIE_FPGA_REG(X) (PCIE_FPGA_ADDR_BASE + X)
+#define PCIE_FPGA_REG(X) (PCIE_FPGA_ADDR_BASE + (X))
static const uint32_t FPGA_PCIE_SIG_REG = PCIE_FPGA_REG(0x0000);
static const uint32_t FPGA_CNTR_LO_REG = PCIE_FPGA_REG(0x0004);
@@ -140,8 +146,8 @@ static const uint32_t DMA_FRAME_SIZE_REG = 0x4;
static const uint32_t DMA_SAMPLE_COUNT_REG = 0x8;
static const uint32_t DMA_PKT_COUNT_REG = 0xC;
-#define PCIE_TX_DMA_REG(REG, CHAN) (PCIE_TX_DMA_REG_BASE + (CHAN*DMA_REG_GRP_SIZE) + REG)
-#define PCIE_RX_DMA_REG(REG, CHAN) (PCIE_RX_DMA_REG_BASE + (CHAN*DMA_REG_GRP_SIZE) + REG)
+#define PCIE_TX_DMA_REG(REG, CHAN) (PCIE_TX_DMA_REG_BASE + ((CHAN)*DMA_REG_GRP_SIZE) + (REG))
+#define PCIE_RX_DMA_REG(REG, CHAN) (PCIE_RX_DMA_REG_BASE + ((CHAN)*DMA_REG_GRP_SIZE) + (REG))
static const uint32_t DMA_CTRL_DISABLED = 0x00000000;
static const uint32_t DMA_CTRL_ENABLED = 0x00000002;
@@ -154,15 +160,15 @@ static const uint32_t DMA_STATUS_ERROR = 0x00000001;
static const uint32_t DMA_STATUS_BUSY = 0x00000002;
static const uint32_t PCIE_ROUTER_REG_BASE = PCIE_FPGA_REG(0x0500);
-#define PCIE_ROUTER_REG(X) (PCIE_ROUTER_REG_BASE + X)
+#define PCIE_ROUTER_REG(X) (PCIE_ROUTER_REG_BASE + (X))
static const uint32_t PCIE_ZPU_DATA_BASE = 0x30000;
static const uint32_t PCIE_ZPU_READ_BASE = 0x20000; //Trig and Status share the same base
static const uint32_t PCIE_ZPU_STATUS_BASE = 0x20000;
-#define PCIE_ZPU_DATA_REG(X) (PCIE_FPGA_REG(PCIE_ZPU_DATA_BASE) + X)
-#define PCIE_ZPU_READ_REG(X) (PCIE_FPGA_REG(PCIE_ZPU_READ_BASE) + X)
-#define PCIE_ZPU_STATUS_REG(X) (PCIE_FPGA_REG(PCIE_ZPU_STATUS_BASE) + X)
+#define PCIE_ZPU_DATA_REG(X) (PCIE_FPGA_REG(PCIE_ZPU_DATA_BASE) + (X))
+#define PCIE_ZPU_READ_REG(X) (PCIE_FPGA_REG(PCIE_ZPU_READ_BASE) + (X))
+#define PCIE_ZPU_STATUS_REG(X) (PCIE_FPGA_REG(PCIE_ZPU_STATUS_BASE) + (X))
static const uint32_t PCIE_ZPU_READ_START = 0x0;
static const uint32_t PCIE_ZPU_READ_CLOBBER = 0x80000000;