aboutsummaryrefslogtreecommitdiffstats
path: root/host/lib/usrp/common
diff options
context:
space:
mode:
authorJonathon Pendlum <jonathon.pendlum@ettus.com>2016-08-01 14:26:30 -0700
committerMartin Braun <martin.braun@ettus.com>2016-08-09 10:21:53 -0700
commit8607cf96932120bab3d4775ff297801add6403a0 (patch)
tree798a2404900f708dc33a08247b420aa752c50d83 /host/lib/usrp/common
parent1356f89fbf3cc8deb770f6532f9d887567dc3668 (diff)
downloaduhd-8607cf96932120bab3d4775ff297801add6403a0.tar.gz
uhd-8607cf96932120bab3d4775ff297801add6403a0.tar.bz2
uhd-8607cf96932120bab3d4775ff297801add6403a0.zip
ad9361: Added option for safe SPI
- Also added check for reading chip ID
Diffstat (limited to 'host/lib/usrp/common')
-rw-r--r--host/lib/usrp/common/ad9361_ctrl.cpp54
-rw-r--r--host/lib/usrp/common/ad9361_ctrl.hpp8
-rw-r--r--host/lib/usrp/common/ad9361_driver/ad9361_device.cpp10
-rw-r--r--host/lib/usrp/common/ad9361_driver/ad9361_device.h3
4 files changed, 65 insertions, 10 deletions
diff --git a/host/lib/usrp/common/ad9361_ctrl.cpp b/host/lib/usrp/common/ad9361_ctrl.cpp
index 54f0fcdbf..654311424 100644
--- a/host/lib/usrp/common/ad9361_ctrl.cpp
+++ b/host/lib/usrp/common/ad9361_ctrl.cpp
@@ -93,18 +93,30 @@ class ad9361_ctrl_impl : public ad9361_ctrl
{
public:
ad9361_ctrl_impl(ad9361_params::sptr client_settings, ad9361_io::sptr io_iface):
- _device(client_settings, io_iface)
+ _device(client_settings, io_iface), _safe_spi(io_iface), _timed_spi(io_iface)
{
_device.initialize();
}
+ void set_timed_spi(uhd::spi_iface::sptr spi_iface, boost::uint32_t slave_num)
+ {
+ _timed_spi = boost::make_shared<ad9361_io_spi>(spi_iface, slave_num);
+ _use_timed_spi();
+ }
+
+ void set_safe_spi(uhd::spi_iface::sptr spi_iface, boost::uint32_t slave_num)
+ {
+ _safe_spi = boost::make_shared<ad9361_io_spi>(spi_iface, slave_num);
+ }
+
double set_gain(const std::string &which, const double value)
{
boost::lock_guard<boost::mutex> lock(_mutex);
ad9361_device_t::direction_t direction = _get_direction_from_antenna(which);
ad9361_device_t::chain_t chain =_get_chain_from_antenna(which);
- return _device.set_gain(direction, chain, value);
+ double return_val = _device.set_gain(direction, chain, value);
+ return return_val;
}
void set_agc(const std::string &which, bool enable)
@@ -112,7 +124,7 @@ public:
boost::lock_guard<boost::mutex> lock(_mutex);
ad9361_device_t::chain_t chain =_get_chain_from_antenna(which);
- _device.set_agc(chain, enable);
+ _device.set_agc(chain, enable);
}
void set_agc_mode(const std::string &which, const std::string &mode)
@@ -133,6 +145,9 @@ public:
{
boost::lock_guard<boost::mutex> lock(_mutex);
+ // Changing clock rate will disrupt AD9361's sample clock
+ _use_safe_spi();
+
//clip to known bounds
const meta_range_t clock_rate_range = ad9361_ctrl::get_clock_rate_range();
const double clipped_rate = clock_rate_range.clip(rate);
@@ -144,7 +159,11 @@ public:
) % (rate/1e6) % (clipped_rate/1e6) << std::endl;
}
- return _device.set_clock_rate(clipped_rate);
+ double return_rate = _device.set_clock_rate(clipped_rate);
+
+ _use_timed_spi();
+
+ return return_rate;
}
//! set which RX and TX chains/antennas are active
@@ -152,7 +171,11 @@ public:
{
boost::lock_guard<boost::mutex> lock(_mutex);
+ // If both RX chains are disabled then the AD9361's sample clock is disabled
+ _use_safe_spi();
_device.set_active_chains(tx1, tx2, rx1, rx2);
+ _use_timed_spi();
+
}
//! tune the given frontend, return the exact value
@@ -166,7 +189,8 @@ public:
const double value = ad9361_ctrl::get_rf_freq_range().clip(clipped_freq);
ad9361_device_t::direction_t direction = _get_direction_from_antenna(which);
- return _device.tune(direction, value);
+ double return_val = _device.tune(direction, value);
+ return return_val;
}
//! get the current frequency for the given frontend
@@ -283,16 +307,28 @@ private:
return ad9361_device_t::CHAIN_1;
}
- ad9361_device_t _device;
- boost::mutex _mutex;
+ void _use_safe_spi() {
+ _device.set_io_iface(_safe_spi);
+ }
+
+ void _use_timed_spi() {
+ _device.set_io_iface(_timed_spi);
+ }
+
+ ad9361_device_t _device;
+ ad9361_io::sptr _safe_spi; // SPI core that uses an always available clock
+ ad9361_io::sptr _timed_spi; // SPI core that has a dependency on the AD9361's sample clock (i.e. radio clk)
+ boost::mutex _mutex;
};
//----------------------------------------------------------------------
// Make an instance of the AD9361 Control interface
//----------------------------------------------------------------------
ad9361_ctrl::sptr ad9361_ctrl::make_spi(
- ad9361_params::sptr client_settings, uhd::spi_iface::sptr spi_iface, boost::uint32_t slave_num)
-{
+ ad9361_params::sptr client_settings,
+ uhd::spi_iface::sptr spi_iface,
+ boost::uint32_t slave_num
+) {
boost::shared_ptr<ad9361_io_spi> spi_io_iface = boost::make_shared<ad9361_io_spi>(spi_iface, slave_num);
return sptr(new ad9361_ctrl_impl(client_settings, spi_io_iface));
}
diff --git a/host/lib/usrp/common/ad9361_ctrl.hpp b/host/lib/usrp/common/ad9361_ctrl.hpp
index 8cd75d539..5770c3ec4 100644
--- a/host/lib/usrp/common/ad9361_ctrl.hpp
+++ b/host/lib/usrp/common/ad9361_ctrl.hpp
@@ -56,7 +56,13 @@ public:
//! make a new codec control object
static sptr make_spi(
- ad9361_params::sptr client_settings, uhd::spi_iface::sptr spi_iface, boost::uint32_t slave_num);
+ ad9361_params::sptr client_settings,
+ uhd::spi_iface::sptr spi_iface,
+ boost::uint32_t slave_num
+ );
+
+ virtual void set_timed_spi(uhd::spi_iface::sptr spi_iface, boost::uint32_t slave_num) = 0;
+ virtual void set_safe_spi(uhd::spi_iface::sptr spi_iface, boost::uint32_t slave_num) = 0;
//! Get a list of gain names for RX or TX
static std::vector<std::string> get_gain_names(const std::string &/*which*/)
diff --git a/host/lib/usrp/common/ad9361_driver/ad9361_device.cpp b/host/lib/usrp/common/ad9361_driver/ad9361_device.cpp
index bb25379c0..095017bb6 100644
--- a/host/lib/usrp/common/ad9361_driver/ad9361_device.cpp
+++ b/host/lib/usrp/common/ad9361_driver/ad9361_device.cpp
@@ -1565,6 +1565,12 @@ void ad9361_device_t::initialize()
_io_iface->poke8(0x000, 0x00);
boost::this_thread::sleep(boost::posix_time::milliseconds(20));
+ /* Check device ID to make sure iface works */
+ boost::uint32_t device_id = (_io_iface->peek8(0x037) & 0x8);
+ if (device_id != 0x8) {
+ throw uhd::runtime_error(str(boost::format("[ad9361_device_t::initialize] Device ID readback failure. Expected: 0x8, Received: 0x%x") % device_id));
+ }
+
/* There is not a WAT big enough for this. */
_io_iface->poke8(0x3df, 0x01);
@@ -1774,6 +1780,10 @@ void ad9361_device_t::initialize()
_io_iface->poke8(0x014, 0x21);
}
+void ad9361_device_t::set_io_iface(ad9361_io::sptr io_iface)
+{
+ _io_iface = io_iface;
+}
/* This function sets the RX / TX rate between AD9361 and the FPGA, and
* thus determines the interpolation / decimation required in the FPGA to
diff --git a/host/lib/usrp/common/ad9361_driver/ad9361_device.h b/host/lib/usrp/common/ad9361_driver/ad9361_device.h
index 73b1d9a35..d0e8a7e39 100644
--- a/host/lib/usrp/common/ad9361_driver/ad9361_device.h
+++ b/host/lib/usrp/common/ad9361_driver/ad9361_device.h
@@ -75,6 +75,9 @@ public:
/* Initialize the AD9361 codec. */
void initialize();
+ /* Set SPI interface */
+ void set_io_iface(ad9361_io::sptr io_iface);
+
/* This function sets the RX / TX rate between AD9361 and the FPGA, and
* thus determines the interpolation / decimation required in the FPGA to
* achieve the user's requested rate.