aboutsummaryrefslogtreecommitdiffstats
path: root/host/lib/usrp/common/ad9361_ctrl.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'host/lib/usrp/common/ad9361_ctrl.cpp')
-rw-r--r--host/lib/usrp/common/ad9361_ctrl.cpp245
1 files changed, 59 insertions, 186 deletions
diff --git a/host/lib/usrp/common/ad9361_ctrl.cpp b/host/lib/usrp/common/ad9361_ctrl.cpp
index 4cdfaa6e1..0754d2c86 100644
--- a/host/lib/usrp/common/ad9361_ctrl.cpp
+++ b/host/lib/usrp/common/ad9361_ctrl.cpp
@@ -3,20 +3,19 @@
//
#include "ad9361_ctrl.hpp"
-#include "ad9361_transaction.h"
-#include "ad9361_dispatch.h"
-#include <ad9361_platform.h>
#include <uhd/exception.hpp>
#include <uhd/types/ranges.hpp>
#include <uhd/utils/msg.hpp>
#include <uhd/types/serial.hpp>
-#include <boost/thread/mutex.hpp>
-#include <boost/format.hpp>
#include <cstring>
+#include <boost/format.hpp>
#include <boost/utility.hpp>
#include <boost/function.hpp>
+#include <boost/make_shared.hpp>
+#include <boost/thread.hpp>
using namespace uhd;
+using namespace uhd::usrp;
/***********************************************************************
* AD9361 IO Implementation Classes
@@ -28,7 +27,9 @@ public:
ad9361_io_spi(uhd::spi_iface::sptr spi_iface, uint32_t slave_num) :
_spi_iface(spi_iface), _slave_num(slave_num) { }
- uint8_t peek8(uint32_t reg)
+ virtual ~ad9361_io_spi() { }
+
+ virtual uint8_t peek8(uint32_t reg)
{
uhd::spi_config_t config;
config.mosi_edge = uhd::spi_config_t::EDGE_FALL;
@@ -43,7 +44,7 @@ public:
return static_cast<uint8_t>(val);
}
- void poke8(uint32_t reg, uint8_t val)
+ virtual void poke8(uint32_t reg, uint8_t val)
{
uhd::spi_config_t config;
config.mosi_edge = uhd::spi_config_t::EDGE_FALL;
@@ -58,6 +59,7 @@ public:
//networked devices, it makes writes blocking which will considerably slow down the programming
peek8(reg);
}
+
private:
uhd::spi_iface::sptr _spi_iface;
uint32_t _slave_num;
@@ -72,126 +74,31 @@ private:
};
/***********************************************************************
- * AD9361 Transport Implementation Classes
- **********************************************************************/
-
-//----------------------------------------------------------------------
-//Over a zero-copy device transport
-//----------------------------------------------------------------------
-class ad9361_ctrl_transport_zc_impl : public ad9361_ctrl_transport
-{
-public:
- ad9361_ctrl_transport_zc_impl(uhd::transport::zero_copy_if::sptr xport)
- {
- _xport = xport;
- }
-
- void ad9361_transact(const unsigned char in_buff[AD9361_DISPATCH_PACKET_SIZE], unsigned char out_buff[AD9361_DISPATCH_PACKET_SIZE])
- {
- {
- uhd::transport::managed_send_buffer::sptr buff = _xport->get_send_buff(10.0);
- if (not buff or buff->size() < AD9361_DISPATCH_PACKET_SIZE) throw std::runtime_error("ad9361_ctrl_over_zc send timeout");
- std::memcpy(buff->cast<void *>(), in_buff, AD9361_DISPATCH_PACKET_SIZE);
- buff->commit(AD9361_DISPATCH_PACKET_SIZE);
- }
- {
- uhd::transport::managed_recv_buffer::sptr buff = _xport->get_recv_buff(10.0);
- if (not buff or buff->size() < AD9361_DISPATCH_PACKET_SIZE) throw std::runtime_error("ad9361_ctrl_over_zc recv timeout");
- std::memcpy(out_buff, buff->cast<const void *>(), AD9361_DISPATCH_PACKET_SIZE);
- }
- }
-
- uint64_t get_device_handle()
- {
- return 0; //Unused for zero-copy transport because chip class is in FW
- }
-
-private:
- uhd::transport::zero_copy_if::sptr _xport;
-};
-
-//----------------------------------------------------------------------
-//Over a software transport
-//----------------------------------------------------------------------
-class ad9361_ctrl_transport_sw_spi_impl : public ad9361_ctrl_transport
-{
-public:
- ad9361_ctrl_transport_sw_spi_impl(
- ad9361_product_t product,
- uhd::spi_iface::sptr spi_iface,
- boost::uint32_t slave_num) :
- _io_iface(spi_iface, slave_num)
- {
- _device.product = product;
- _device.io_iface = reinterpret_cast<void*>(&_io_iface);
- }
-
- void ad9361_transact(const unsigned char in_buff[AD9361_DISPATCH_PACKET_SIZE], unsigned char out_buff[AD9361_DISPATCH_PACKET_SIZE])
- {
- ad9361_dispatch((const char*)in_buff, (char*)out_buff);
- }
-
- uint64_t get_device_handle()
- {
- return reinterpret_cast<uint64_t>(reinterpret_cast<void*>(&_device));
- }
-
-private:
- ad9361_device_t _device;
- ad9361_io_spi _io_iface;
-};
-
-//----------------------------------------------------------------------
-// Make an instance of the AD9361 Transport
-//----------------------------------------------------------------------
-ad9361_ctrl_transport::sptr ad9361_ctrl_transport::make_zero_copy(uhd::transport::zero_copy_if::sptr xport)
-{
- return sptr(new ad9361_ctrl_transport_zc_impl(xport));
-}
-
-ad9361_ctrl_transport::sptr ad9361_ctrl_transport::make_software_spi(
- ad9361_product_t product,
- uhd::spi_iface::sptr spi_iface,
- boost::uint32_t slave_num)
-{
- return sptr(new ad9361_ctrl_transport_sw_spi_impl(product, spi_iface, slave_num));
-}
-
-/***********************************************************************
- * AD9361 Software API Class
+ * AD9361 Control API Class
**********************************************************************/
class ad9361_ctrl_impl : public ad9361_ctrl
{
public:
- ad9361_ctrl_impl(ad9361_ctrl_transport::sptr iface):
- _iface(iface), _seq(0)
+ ad9361_ctrl_impl(ad9361_params::sptr client_settings, ad9361_io::sptr io_iface):
+ _device(client_settings, io_iface)
{
- ad9361_transaction_t request;
-
- request.action = AD9361_ACTION_ECHO;
- this->do_transaction(request);
-
- request.action = AD9361_ACTION_INIT;
- this->do_transaction(request);
+ _device.initialize();
}
double set_gain(const std::string &which, const double value)
{
- ad9361_transaction_t request;
-
- if (which == "RX1") request.action = AD9361_ACTION_SET_RX1_GAIN;
- if (which == "RX2") request.action = AD9361_ACTION_SET_RX2_GAIN;
- if (which == "TX1") request.action = AD9361_ACTION_SET_TX1_GAIN;
- if (which == "TX2") request.action = AD9361_ACTION_SET_TX2_GAIN;
+ boost::lock_guard<boost::mutex> lock(_mutex);
- ad9361_double_pack(value, request.value.gain);
- const ad9361_transaction_t reply = this->do_transaction(request);
- return ad9361_double_unpack(reply.value.gain);
+ 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);
}
//! set a new clock rate, return the exact value
double set_clock_rate(const double rate)
{
+ boost::lock_guard<boost::mutex> lock(_mutex);
+
//warning for known trouble rates
if (rate > 56e6) UHD_MSG(warning) << boost::format(
"The requested clock rate %f MHz may cause slow configuration.\n"
@@ -202,110 +109,76 @@ public:
const meta_range_t clock_rate_range = ad9361_ctrl::get_clock_rate_range();
const double clipped_rate = clock_rate_range.clip(rate);
- ad9361_transaction_t request;
- request.action = AD9361_ACTION_SET_CLOCK_RATE;
- ad9361_double_pack(clipped_rate, request.value.rate);
- const ad9361_transaction_t reply = this->do_transaction(request);
- return ad9361_double_unpack(reply.value.rate);
+ return _device.set_clock_rate(clipped_rate);
}
//! set which RX and TX chains/antennas are active
void set_active_chains(bool tx1, bool tx2, bool rx1, bool rx2)
{
- boost::uint32_t mask = 0;
- if (tx1) mask |= (1 << 0);
- if (tx2) mask |= (1 << 1);
- if (rx1) mask |= (1 << 2);
- if (rx2) mask |= (1 << 3);
-
- ad9361_transaction_t request;
- request.action = AD9361_ACTION_SET_ACTIVE_CHAINS;
- request.value.enable_mask = mask;
- this->do_transaction(request);
+ boost::lock_guard<boost::mutex> lock(_mutex);
+
+ _device.set_active_chains(tx1, tx2, rx1, rx2);
}
//! tune the given frontend, return the exact value
double tune(const std::string &which, const double freq)
{
+ boost::lock_guard<boost::mutex> lock(_mutex);
+
//clip to known bounds
const meta_range_t freq_range = ad9361_ctrl::get_rf_freq_range();
const double clipped_freq = freq_range.clip(freq);
-
- ad9361_transaction_t request;
-
- if (which[0] == 'R') request.action = AD9361_ACTION_SET_RX_FREQ;
- if (which[0] == 'T') request.action = AD9361_ACTION_SET_TX_FREQ;
-
const double value = ad9361_ctrl::get_rf_freq_range().clip(clipped_freq);
- ad9361_double_pack(value, request.value.freq);
- const ad9361_transaction_t reply = this->do_transaction(request);
- return ad9361_double_unpack(reply.value.freq);
+
+ ad9361_device_t::direction_t direction = _get_direction_from_antenna(which);
+ return _device.tune(direction, value);
}
//! turn on/off Catalina's data port loopback
void data_port_loopback(const bool on)
{
- ad9361_transaction_t request;
- request.action = AD9361_ACTION_SET_CODEC_LOOP;
- request.value.codec_loop = on? 1 : 0;
- this->do_transaction(request);
- }
-
- ad9361_transaction_t do_transaction(const ad9361_transaction_t &request)
- {
- boost::mutex::scoped_lock lock(_mutex);
-
- //declare in/out buffers
- unsigned char in_buff[AD9361_DISPATCH_PACKET_SIZE] = {};
- unsigned char out_buff[AD9361_DISPATCH_PACKET_SIZE] = {};
-
- //copy the input transaction
- std::memcpy(in_buff, &request, sizeof(request));
-
- //fill in other goodies
- ad9361_transaction_t *in = (ad9361_transaction_t *)in_buff;
- in->handle = _iface->get_device_handle();
- in->version = AD9361_TRANSACTION_VERSION;
- in->sequence = _seq++;
+ boost::lock_guard<boost::mutex> lock(_mutex);
- //initialize error message to "no error"
- std::memset(in->error_msg, 0, AD9361_TRANSACTION_MAX_ERROR_MSG);
-
- //transact
- _iface->ad9361_transact(in_buff, out_buff);
- ad9361_transaction_t *out = (ad9361_transaction_t *)out_buff;
-
- //sanity checks
- UHD_ASSERT_THROW(out->version == in->version);
- UHD_ASSERT_THROW(out->sequence == in->sequence);
-
- //handle errors
- const size_t len = my_strnlen(out->error_msg, AD9361_TRANSACTION_MAX_ERROR_MSG);
- const std::string error_msg(out->error_msg, len);
- if (not error_msg.empty()) throw uhd::runtime_error("[ad9361_ctrl::do_transaction] firmware reported: \"" + error_msg + "\"");
-
- //return result done!
- return *out;
+ _device.data_port_loopback(on);
}
private:
- //! compat strnlen for platforms that dont have it
- static size_t my_strnlen(const char *str, size_t max)
+ static ad9361_device_t::direction_t _get_direction_from_antenna(const std::string& antenna)
+ {
+ std::string sub = antenna.substr(0, 2);
+ if (sub == "RX") {
+ return ad9361_device_t::RX;
+ } else if (sub == "TX") {
+ return ad9361_device_t::RX;
+ } else {
+ throw uhd::runtime_error("ad9361_ctrl got an invalid channel string.");
+ }
+ return ad9361_device_t::RX;
+ }
+
+ static ad9361_device_t::chain_t _get_chain_from_antenna(const std::string& antenna)
{
- const char *end = (const char *)std::memchr((const void *)str, 0, max);
- if (end == NULL) return max;
- return (size_t)(end - str);
+ std::string sub = antenna.substr(2, 1);
+ if (sub == "1") {
+ return ad9361_device_t::CHAIN_1;
+ } else if (sub == "2") {
+ return ad9361_device_t::CHAIN_2;
+ } else {
+ throw uhd::runtime_error("ad9361_ctrl::set_gain got an invalid channel string.");
+ }
+ return ad9361_device_t::CHAIN_1;
}
- ad9361_ctrl_transport::sptr _iface;
- size_t _seq;
- boost::mutex _mutex;
+ ad9361_device_t _device;
+ boost::mutex _mutex;
};
//----------------------------------------------------------------------
// Make an instance of the AD9361 Control interface
//----------------------------------------------------------------------
-ad9361_ctrl::sptr ad9361_ctrl::make(ad9361_ctrl_transport::sptr iface)
+ad9361_ctrl::sptr ad9361_ctrl::make_spi(
+ ad9361_params::sptr client_settings, uhd::spi_iface::sptr spi_iface, uint32_t slave_num)
{
- return sptr(new ad9361_ctrl_impl(iface));
+ 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));
}