b200: Moved AD9361 driver to host

- Switched to FPGA SPI engine
- Moved firmware AD9361 driver to UHD
- Bumped FW compat to 5, FPGA compat to 4
- Known Issue: AD9361 SPI rate is too slow
This commit is contained in:
Ashish Chaudhari 2014-08-01 13:14:56 -07:00
parent 9eb403f429
commit c7274790a0
23 changed files with 2899 additions and 163 deletions

3
firmware/fx3/.gitignore vendored Normal file
View File

@ -0,0 +1,3 @@
common
lpp_source
u3p_firmware

View File

@ -12,7 +12,7 @@ extern "C" {
#endif
//various constants
#define AD9361_TRANSACTION_VERSION 0x4
#define AD9361_TRANSACTION_VERSION 0x5
#define AD9361_DISPATCH_PACKET_SIZE 64
//action types
@ -53,6 +53,9 @@ typedef struct
//sequence number - increment every call for sanity
uint32_t sequence;
//location info for the ad9361 chip class
uint64_t handle;
//action tells us what to do, see AD9361_ACTION_*
uint32_t action;

View File

@ -485,7 +485,7 @@ void calibrate_secondary_tx_filter() {
} else if((bbbw_mhz * 2) > 24) {
reg0d0 = 0x57;
} else {
post_err_msg("Cal2ndTxFil: INVALID_CODE_PATH bad bbbw_mhz");
post_err_msg("Cal2ndTxFil: bad bbbw_mhz INV_PATH");
reg0d0 = 0x00;
}
@ -548,7 +548,7 @@ void calibrate_rx_TIAs() {
} else if(ceil_bbbw_mhz > 10) {
reg1db = 0x20;
} else {
post_err_msg("CalRxTias: INVALID_CODE_PATH bad bbbw_mhz");
post_err_msg("CalRxTias: bad bbbw_mhz INV_PATH");
}
if(CTIA_fF > 2920) {
@ -718,7 +718,7 @@ void calibrate_baseband_dc_offset() {
write_ad9361_reg(0x016, 0x01);
while(read_ad9361_reg(0x016) & 0x01) {
if(count > 100) {
post_err_msg("Baseband DC Offset Calibration Failure");
post_err_msg("Baseband DC Offset Cal Failure");
break;
}
@ -752,7 +752,7 @@ void calibrate_rf_dc_offset() {
write_ad9361_reg(0x016, 0x02);
while(read_ad9361_reg(0x016) & 0x02) {
if(count > 100) {
post_err_msg("RF DC Offset Calibration Failure");
post_err_msg("RF DC Offset Cal Failure");
break;
}
@ -837,7 +837,7 @@ void tx_quadrature_cal_routine(void) {
write_ad9361_reg(0x016, 0x10);
while(read_ad9361_reg(0x016) & 0x10) {
if(count > 100) {
post_err_msg("TX Quadrature Calibration Failure");
post_err_msg("TX Quadrature Cal Failure");
break;
}
@ -854,7 +854,7 @@ void calibrate_tx_quadrature(void) {
/* Make sure we are, in fact, in the ALERT state. If not, something is
* terribly wrong in the driver execution flow. */
if((read_ad9361_reg(0x017) & 0x0F) != 5) {
post_err_msg("TX Quad Cal started, but not in ALERT");
post_err_msg("TXQuadCal started,but not in ALERT");
}
/* Turn off free-running and continuous calibrations. Note that this
@ -1599,7 +1599,7 @@ void init_ad9361(void) {
* This is the only clock setting function that is exposed to the outside. */
double set_clock_rate(const double req_rate) {
if(req_rate > 61.44e6) {
post_err_msg("Requested master clock rate outside range");
post_err_msg("Req. master clk rate outside range");
}
msg("[set_clock_rate] req_rate=%.10f", req_rate);
@ -1628,7 +1628,7 @@ double set_clock_rate(const double req_rate) {
break;
default:
post_err_msg("[set_clock_rate:1] AD9361 in unknown state");
post_err_msg("[set_clock_rate:1] Unknown state");
break;
};
@ -1692,7 +1692,7 @@ double set_clock_rate(const double req_rate) {
break;
default:
post_err_msg("[set_clock_rate:2] AD9361 in unknown state");
post_err_msg("[set_clock_rate:2] Unknown state");
break;
};

View File

@ -10,7 +10,7 @@
#include "cyu3types.h"
#include "cyu3usbconst.h"
#define FX3_COMPAT_MAJOR (uint8_t)(4)
#define FX3_COMPAT_MAJOR (uint8_t)(5)
#define FX3_COMPAT_MINOR (uint8_t)(0)
/* GPIO Pins */

View File

@ -35,8 +35,7 @@ static const std::string B200_FW_FILE_NAME = "usrp_b200_fw.hex";
static const std::string B200_FPGA_FILE_NAME = "usrp_b200_fpga.bin";
static const std::string B210_FPGA_FILE_NAME = "usrp_b210_fpga.bin";
class UHD_API b200_iface: boost::noncopyable, public virtual uhd::i2c_iface,
public ad9361_ctrl_iface_type {
class UHD_API b200_iface: boost::noncopyable, public virtual uhd::i2c_iface {
public:
typedef boost::shared_ptr<b200_iface> sptr;

View File

@ -338,11 +338,19 @@ b200_impl::b200_impl(const device_addr_t &device_addr)
while (_data_transport->get_recv_buff(0.0)){} //flush ctrl xport
_demux = recv_packet_demuxer_3000::make(_data_transport);
////////////////////////////////////////////////////////////////////
// create time and clock control objects
////////////////////////////////////////////////////////////////////
_spi_iface = spi_core_3000::make(_local_ctrl, TOREG(SR_CORE_SPI), RB32_CORE_SPI);
_spi_iface->set_divider(B200_BUS_CLOCK_RATE/ADF4001_SPI_RATE);
_adf4001_iface = boost::shared_ptr<adf4001_ctrl>(new adf4001_ctrl(_spi_iface, ADF4001_SLAVENO));
////////////////////////////////////////////////////////////////////
// Init codec - turns on clocks
////////////////////////////////////////////////////////////////////
UHD_MSG(status) << "Initialize CODEC control..." << std::endl;
_codec_ctrl = ad9361_ctrl::make(_iface);
_codec_ctrl = ad9361_ctrl::make(
ad9361_ctrl_transport::make_software_spi(AD9361_B200, _spi_iface, AD9361_SLAVENO));
this->reset_codec_dcm();
////////////////////////////////////////////////////////////////////
@ -405,13 +413,6 @@ b200_impl::b200_impl(const device_addr_t &device_addr)
}
_codec_ctrl->data_port_loopback(false);
////////////////////////////////////////////////////////////////////
// create time and clock control objects
////////////////////////////////////////////////////////////////////
_spi_iface = spi_core_3000::make(_local_ctrl, TOREG(SR_CORE_SPI), RB32_CORE_SPI);
_spi_iface->set_divider(B200_BUS_CLOCK_RATE/ADF4001_SPI_RATE);
_adf4001_iface = boost::shared_ptr<adf4001_ctrl>(new adf4001_ctrl(_spi_iface, ADF4001_SLAVENO));
//register time now and pps onto available radio cores
_tree->create<time_spec_t>(mb_path / "time" / "now")
.publish(boost::bind(&time_core_3000::get_time_now, _radio_perifs[0].time64));

View File

@ -44,9 +44,9 @@
#include <uhd/transport/bounded_buffer.hpp>
#include <boost/weak_ptr.hpp>
#include "recv_packet_demuxer_3000.hpp"
static const boost::uint8_t B200_FW_COMPAT_NUM_MAJOR = 0x04;
static const boost::uint8_t B200_FW_COMPAT_NUM_MAJOR = 0x05;
static const boost::uint8_t B200_FW_COMPAT_NUM_MINOR = 0x00;
static const boost::uint16_t B200_FPGA_COMPAT_NUM = 0x03;
static const boost::uint16_t B200_FPGA_COMPAT_NUM = 0x04;
static const double B200_BUS_CLOCK_RATE = 100e6;
static const double B200_DEFAULT_TICK_RATE = 32e6;
static const boost::uint32_t B200_GPSDO_ST_NONE = 0x83;

View File

@ -52,6 +52,7 @@ localparam RB64_TIME_PPS = 16;
localparam RB64_CODEC_READBACK = 24;
//pll constants
static const int AD9361_SLAVENO = (1 << 0);
static const int ADF4001_SLAVENO = (1 << 1);
static const double ADF4001_SPI_RATE = 10e3; //slow for large time constant on spi lines

View File

@ -27,13 +27,22 @@ IF(ENABLE_USB)
ENDIF(ENABLE_USB)
INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR})
INCLUDE_DIRECTORIES("${CMAKE_CURRENT_SOURCE_DIR}/ad9361_driver")
LIBUHD_APPEND_SOURCES(
${CMAKE_CURRENT_SOURCE_DIR}/adf4001_ctrl.cpp
${CMAKE_CURRENT_SOURCE_DIR}/adf435x_common.cpp
${CMAKE_CURRENT_SOURCE_DIR}/ad9361_ctrl.cpp
${CMAKE_CURRENT_SOURCE_DIR}/ad9361_driver/ad9361_impl.c
${CMAKE_CURRENT_SOURCE_DIR}/ad9361_platform_uhd.cpp
${CMAKE_CURRENT_SOURCE_DIR}/ad9361_client.cpp
${CMAKE_CURRENT_SOURCE_DIR}/apply_corrections.cpp
${CMAKE_CURRENT_SOURCE_DIR}/validate_subdev_spec.cpp
${CMAKE_CURRENT_SOURCE_DIR}/recv_packet_demuxer.cpp
${CMAKE_CURRENT_SOURCE_DIR}/fifo_ctrl_excelsior.cpp
)
SET_SOURCE_FILES_PROPERTIES(
${CMAKE_CURRENT_SOURCE_DIR}/ad9361_driver/ad9361_impl.c
PROPERTIES LANGUAGE CXX
)

View File

@ -0,0 +1,56 @@
//
// Copyright 2014 Ettus Research LLC
//
#include <ad9361_client.h>
double ad9361_client_get_band_edge(ad9361_product_t product, frequency_band_t band)
{
switch (product) {
default:
switch (band) {
case AD9361_RX_BAND0: return 2.2e9;
case AD9361_RX_BAND1: return 4.0e9;
case AD9361_TX_BAND0: return 2.5e9;
default: return 0;
}
}
}
clocking_mode_t ad9361_client_get_clocking_mode(ad9361_product_t product)
{
switch (product) {
case AD9361_B200:
return AD9361_XTAL_N_CLK_PATH;
default:
return AD9361_XTAL_N_CLK_PATH;
}
}
digital_interface_mode_t ad9361_client_get_digital_interface_mode(ad9361_product_t product)
{
switch (product) {
case AD9361_B200: return AD9361_DDR_FDD_LVCMOS;
default: return AD9361_DDR_FDD_LVCMOS;
}
}
digital_interface_delays_t ad9361_client_get_digital_interface_timing(ad9361_product_t product)
{
digital_interface_delays_t delays;
switch (product) {
case AD9361_B200:
delays.rx_clk_delay = 0;
delays.rx_data_delay = 0xF;
delays.tx_clk_delay = 0;
delays.tx_data_delay = 0xF;
break;
default:
delays.rx_clk_delay = 0;
delays.rx_data_delay = 0;
delays.tx_clk_delay = 0;
delays.tx_data_delay = 0;
break;
}
return delays;
}

View File

@ -1,42 +1,169 @@
//
// Copyright 2012-2013 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
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
// Copyright 2014 Ettus Research LLC
//
#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>
//! compat strnlen for platforms that dont have it
static size_t my_strnlen(const char *str, size_t max)
{
const char *end = (const char *)std::memchr((const void *)str, 0, max);
if (end == NULL) return max;
return (size_t)(end - str);
}
#include <boost/utility.hpp>
#include <boost/function.hpp>
using namespace uhd;
struct ad9361_ctrl_impl : public ad9361_ctrl
/***********************************************************************
* AD9361 IO Implementation Classes
**********************************************************************/
class ad9361_io_spi : public ad9361_io
{
ad9361_ctrl_impl(ad9361_ctrl_iface_sptr iface):
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)
{
uhd::spi_config_t config;
config.mosi_edge = uhd::spi_config_t::EDGE_FALL;
config.miso_edge = uhd::spi_config_t::EDGE_FALL; //TODO (Ashish): FPGA SPI workaround. This should be EDGE_RISE
uint32_t rd_word = AD9361_SPI_READ_CMD |
((uint32_t(reg) << AD9361_SPI_ADDR_SHIFT) & AD9361_SPI_ADDR_MASK);
uint32_t val = (_spi_iface->read_spi(_slave_num, config, rd_word, AD9361_SPI_NUM_BITS));
val &= 0xFF;
return static_cast<uint8_t>(val);
}
void poke8(uint32_t reg, uint8_t val)
{
uhd::spi_config_t config;
config.mosi_edge = uhd::spi_config_t::EDGE_FALL;
config.miso_edge = uhd::spi_config_t::EDGE_FALL; //TODO (Ashish): FPGA SPI workaround. This should be EDGE_RISE
uint32_t wr_word = AD9361_SPI_WRITE_CMD |
((uint32_t(reg) << AD9361_SPI_ADDR_SHIFT) & AD9361_SPI_ADDR_MASK) |
((uint32_t(val) << AD9361_SPI_DATA_SHIFT) & AD9361_SPI_DATA_MASK);
_spi_iface->write_spi(_slave_num, config, wr_word, AD9361_SPI_NUM_BITS);
//TODO (Ashish): Is this necessary? The FX3 firmware does it right now but for
//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;
static const uint32_t AD9361_SPI_WRITE_CMD = 0x00800000;
static const uint32_t AD9361_SPI_READ_CMD = 0x00000000;
static const uint32_t AD9361_SPI_ADDR_MASK = 0x003FFF00;
static const uint32_t AD9361_SPI_ADDR_SHIFT = 8;
static const uint32_t AD9361_SPI_DATA_MASK = 0x000000FF;
static const uint32_t AD9361_SPI_DATA_SHIFT = 0;
static const uint32_t AD9361_SPI_NUM_BITS = 24;
};
/***********************************************************************
* 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
**********************************************************************/
class ad9361_ctrl_impl : public ad9361_ctrl
{
public:
ad9361_ctrl_impl(ad9361_ctrl_transport::sptr iface):
_iface(iface), _seq(0)
{
ad9361_transaction_t request;
@ -129,17 +256,21 @@ struct ad9361_ctrl_impl : public ad9361_ctrl
boost::mutex::scoped_lock lock(_mutex);
//declare in/out buffers
unsigned char in_buff[64] = {};
unsigned char out_buff[64] = {};
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++;
//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;
@ -157,17 +288,24 @@ struct ad9361_ctrl_impl : public ad9361_ctrl
return *out;
}
ad9361_ctrl_iface_sptr _iface;
size_t _seq;
boost::mutex _mutex;
private:
//! compat strnlen for platforms that dont have it
static size_t my_strnlen(const char *str, size_t max)
{
const char *end = (const char *)std::memchr((const void *)str, 0, max);
if (end == NULL) return max;
return (size_t)(end - str);
}
ad9361_ctrl_transport::sptr _iface;
size_t _seq;
boost::mutex _mutex;
};
/***********************************************************************
* Make an instance of the implementation
**********************************************************************/
ad9361_ctrl::sptr ad9361_ctrl::make(ad9361_ctrl_iface_sptr iface)
//----------------------------------------------------------------------
// Make an instance of the AD9361 Control interface
//----------------------------------------------------------------------
ad9361_ctrl::sptr ad9361_ctrl::make(ad9361_ctrl_transport::sptr iface)
{
return sptr(new ad9361_ctrl_impl(iface));
}

View File

@ -1,79 +1,62 @@
//
// Copyright 2012-2013 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
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
// Copyright 2014 Ettus Research LLC
//
#ifndef INCLUDED_AD9361_CTRL_HPP
#define INCLUDED_AD9361_CTRL_HPP
#include <uhd/transport/zero_copy.hpp>
#include <uhd/types/serial.hpp>
#include <uhd/types/ranges.hpp>
#include <uhd/types/serial.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/utility.hpp>
#include <boost/function.hpp>
#include <vector>
#include <ad9361_device.h>
#include <string>
#include <stdint.h>
#include "ad9361_transaction.h"
static const double AD9361_CLOCK_RATE_MAX = 61.44e6;
static const double AD9361_1_CHAN_CLOCK_RATE_MAX = AD9361_CLOCK_RATE_MAX;
static const double AD9361_2_CHAN_CLOCK_RATE_MAX = (AD9361_1_CHAN_CLOCK_RATE_MAX / 2);
struct ad9361_ctrl_iface_type
/***********************************************************************
* AD9361 Transport Interface
**********************************************************************/
class ad9361_io
{
public:
virtual uint8_t peek8(uint32_t reg) = 0;
virtual void poke8(uint32_t reg, uint8_t val) = 0;
};
/***********************************************************************
* AD9361 Transport Interface
**********************************************************************/
class ad9361_ctrl_transport
{
public:
typedef boost::shared_ptr<ad9361_ctrl_transport> sptr;
virtual uint64_t get_device_handle() = 0;
virtual void ad9361_transact(const unsigned char in_buff[AD9361_DISPATCH_PACKET_SIZE], unsigned char out_buff[AD9361_DISPATCH_PACKET_SIZE]) = 0;
static ad9361_ctrl_transport::sptr make_zero_copy(
uhd::transport::zero_copy_if::sptr xport);
static ad9361_ctrl_transport::sptr make_software_spi(
ad9361_product_t product,
uhd::spi_iface::sptr spi_iface,
boost::uint32_t slave_num);
};
typedef boost::shared_ptr<ad9361_ctrl_iface_type> ad9361_ctrl_iface_sptr;
struct ad9361_ctrl_over_zc : ad9361_ctrl_iface_type
/***********************************************************************
* AD9361 Control Interface
**********************************************************************/
class ad9361_ctrl : public boost::noncopyable
{
ad9361_ctrl_over_zc(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);
}
}
uhd::transport::zero_copy_if::sptr _xport;
};
class ad9361_ctrl : boost::noncopyable{
public:
typedef boost::shared_ptr<ad9361_ctrl> sptr;
//! make a new codec control object
static sptr make(ad9361_ctrl_iface_sptr iface);
static sptr make(ad9361_ctrl_transport::sptr iface);
//! Get a list of gain names for RX or TX
static std::vector<std::string> get_gain_names(const std::string &/*which*/)

View File

@ -0,0 +1,59 @@
//
// Copyright 2014 Ettus Research LLC
//
#ifndef INCLUDED_AD9361_CLIENT_SETTINGS_H
#define INCLUDED_AD9361_CLIENT_SETTINGS_H
#include <stdint.h>
#include <ad9361_device.h>
#ifdef __cplusplus
extern "C" {
#endif
/*!
* Frequency band settings
*/
typedef enum {
AD9361_RX_BAND0,
AD9361_RX_BAND1,
AD9361_TX_BAND0
} frequency_band_t;
double ad9361_client_get_band_edge(ad9361_product_t product, frequency_band_t band);
/*!
* Clocking mode
*/
typedef enum {
AD9361_XTAL_P_CLK_PATH,
AD9361_XTAL_N_CLK_PATH
} clocking_mode_t;
clocking_mode_t ad9361_client_get_clocking_mode(ad9361_product_t product);
/*!
* Digital interface specific
*/
typedef enum {
AD9361_DDR_FDD_LVCMOS,
AD9361_DDR_FDD_LVDS
} digital_interface_mode_t;
digital_interface_mode_t ad9361_client_get_digital_interface_mode(ad9361_product_t product);
typedef struct {
uint8_t rx_clk_delay;
uint8_t rx_data_delay;
uint8_t tx_clk_delay;
uint8_t tx_data_delay;
} digital_interface_delays_t;
digital_interface_delays_t ad9361_client_get_digital_interface_timing(ad9361_product_t product);
#ifdef __cplusplus
}
#endif
#endif /* INCLUDED_AD9361_CLIENT_SETTINGS_H */

View File

@ -0,0 +1,53 @@
//
// Copyright 2014 Ettus Research LLC
//
#ifndef INCLUDED_AD9361_CHIP_H
#define INCLUDED_AD9361_CHIP_H
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
typedef enum {
AD9361_GENERIC, AD9361_B200
} ad9361_product_t;
////////////////////////////////////////////////////////////
// shadow registers
typedef struct {
uint8_t vcodivs;
uint8_t inputsel;
uint8_t rxfilt;
uint8_t txfilt;
uint8_t bbpll;
uint8_t bbftune_config;
uint8_t bbftune_mode;
} ad9361_chip_regs_t;
////////////////////////////////////////////////////////////
// other private data fields for VRQ handler
typedef struct {
//Product
ad9361_product_t product;
//Intermediate state
double rx_freq, tx_freq, req_rx_freq, req_tx_freq;
double baseband_bw, bbpll_freq, adcclock_freq;
double req_clock_rate, req_coreclk;
uint16_t rx_bbf_tunediv;
uint8_t curr_gain_table;
uint32_t rx1_gain, rx2_gain, tx1_gain, tx2_gain;
int32_t tfir_factor;
//Register soft-copies
ad9361_chip_regs_t regs;
//IO Interface
void* io_iface;
} ad9361_device_t;
#ifdef __cplusplus
}
#endif
#endif /* INCLUDED_AD9361_CHIP_H */

View File

@ -0,0 +1,24 @@
//
// Copyright 2014 Ettus Research LLC
//
#ifndef INCLUDED_AD9361_DISPATCH_H
#define INCLUDED_AD9361_DISPATCH_H
#ifdef __cplusplus
extern "C" {
#endif
#include <ad9361_transaction.h>
extern void ad9361_dispatch(const char* request, char* response);
typedef void (*msgfn)(const char*, ...);
extern void ad9361_set_msgfn(msgfn pfn);
#ifdef __cplusplus
}
#endif
#endif /* INCLUDED_AD9361_DISPATCH_H */

View File

@ -0,0 +1,71 @@
//
// Copyright 2014 Ettus Research LLC
//
#ifndef INCLUDED_AD9361_FILTER_TAPS_HPP
#define INCLUDED_AD9361_FILTER_TAPS_HPP
/* A default 128-tap filter that can be used for generic circumstances. */
/* static uint16_t default_128tap_coeffs[] = {
0x0001,0xfff1,0xffcf,0xffc0,0xffe8,0x0020,0x001a,0xffe3,
0xffe1,0x001f,0x0028,0xffdf,0xffcc,0x0024,0x0043,0xffdb,
0xffac,0x0026,0x0068,0xffdb,0xff80,0x0022,0x009a,0xffe2,
0xff47,0x0017,0x00db,0xfff3,0xfeff,0xffff,0x012b,0x0013,
0xfea5,0xffd7,0x0190,0x0046,0xfe35,0xff97,0x020e,0x0095,
0xfda7,0xff36,0x02ae,0x010d,0xfcf0,0xfea1,0x0383,0x01c6,
0xfbf3,0xfdb6,0x04b7,0x02f8,0xfa6d,0xfc1a,0x06be,0x0541,
0xf787,0xf898,0x0b60,0x0b6d,0xee88,0xea40,0x2786,0x7209
};
*/
/* The below pair of filters is from ADI and "optimized for a 10MHz LTE application". */
/*
static uint16_t lte10mhz_rx_coeffs[] = {
0xffe2,0x0042,0x0024,0x0095,0x0056,0x004d,0xffcf,0xffb7,
0xffb1,0x0019,0x0059,0x006a,0x0004,0xff9d,0xff72,0xffd4,
0x0063,0x00b7,0x0062,0xffac,0xff21,0xff59,0x0032,0x0101,
0x00f8,0x0008,0xfeea,0xfeac,0xffa3,0x0117,0x01b5,0x00d0,
0xff05,0xfdea,0xfe9e,0x00ba,0x026f,0x0215,0xffb5,0xfd4a,
0xfd18,0xffa0,0x02de,0x03dc,0x0155,0xfd2a,0xfb0d,0xfd54,
0x0287,0x062f,0x048a,0xfe37,0xf862,0xf8c1,0x004d,0x0963,
0x0b88,0x02a4,0xf3e7,0xebdd,0xf5f8,0x1366,0x3830,0x518b
};
static uint16_t lte10mhz_tx_coeffs[] = {
0xfffb,0x0000,0x0004,0x0017,0x0024,0x0028,0x0013,0xfff3,
0xffdc,0xffe5,0x000b,0x0030,0x002e,0xfffe,0xffc4,0xffb8,
0xfff0,0x0045,0x0068,0x002b,0xffb6,0xff72,0xffad,0x0047,
0x00b8,0x0088,0xffc8,0xff1c,0xff33,0x001a,0x0110,0x0124,
0x0019,0xfec8,0xfe74,0xff9a,0x0156,0x0208,0x00d3,0xfe9b,
0xfd68,0xfe96,0x015d,0x033f,0x0236,0xfecd,0xfc00,0xfcb5,
0x00d7,0x04e5,0x04cc,0xffd5,0xf9fe,0xf8fb,0xfef2,0x078c,
0x0aae,0x036d,0xf5c0,0xed89,0xf685,0x12af,0x36a4,0x4faa
};
*/
/* 127 tap Halfband designed with: round(2^16 * halfgen4(0.9/4,32)) (center tap tweaked to 32767) */
static int16_t hb127_coeffs[] = {
-0,0,1,-0,-2,0,3,-0,-5,0,8,-0,-11,0,17,-0,-24,0,33,-0,-45,0,61,-0,-80,0,104,-0,-134,0,169,-0,
-213,0,264,-0,-327,0,401,-0,-489,0,595,-0,-724,0,880,-0,-1075,0,1323,-0,-1652,0,2114,-0,-2819,0,4056,-0,-6883,0,20837,32767,
20837,0,-6883,-0,4056,0,-2819,-0,2114,0,-1652,-0,1323,0,-1075,-0,880,0,-724,-0,595,0,-489,-0,401,0,-327,-0,264,0,-213,-0,
169,0,-134,-0,104,0,-80,-0,61,0,-45,-0,33,0,-24,-0,17,0,-11,-0,8,0,-5,-0,3,0,-2,-0,1,0,-0, 0 };
/* 95 tap Halfband designed with: round(2^16 * halfgen4(0.9/4,24)) (center tap tweaked to 32767) */
static int16_t hb95_coeffs[] = {
-4,0,8,-0,-14,0,23,-0,-36,0,52,-0,-75,0,104,-0,-140,0,186,-0,-243,0,314,-0,-400,0,505,-0,-634,0,793,-0,
-993,0,1247,-0,-1585,0,2056,-0,-2773,0,4022,-0,-6862,0,20830,32767,20830,0,-6862,-0,4022,0,-2773,-0,2056,0,-1585,-0,1247,0,-993,-0,
793,0,-634,-0,505,0,-400,-0,314,0,-243,-0,186,0,-140,-0,104,0,-75,-0,52,0,-36,-0,23,0,-14,-0,8,0,-4,0};
/* 63 tap Halfband designed with: round(2^16 * halfgen4(0.9/4,16)) (center tap tweaked to 32767) */
static int16_t hb63_coeffs[] = {
-58,0,83,-0,-127,0,185,-0,-262,0,361,-0,-488,0,648,-0,-853,0,1117,-0,-1466,0,1954,-0,-2689,0,3960,-0,-6825,0,20818,32767,
20818,0,-6825,-0,3960,0,-2689,-0,1954,0,-1466,-0,1117,0,-853,-0,648,0,-488,-0,361,0,-262,-0,185,0,-127,-0,83,0,-58,0};
/* 47 tap Halfband designed with: round(2^16 * halfgen4(0.85/4,12)) (center tap tweaked to 32767) */
static int16_t hb47_coeffs[] = {
-50,0,98,-0,-181,0,307,-0,-489,0,747,-0,-1109,0,1628,-0,-2413,0,3750,-0,-6693,0,20773,32767,20773,0,-6693,-0,3750,0,-2413,-0,
1628,0,-1109,-0,747,0,-489,-0,307,0,-181,-0,98,0,-50,0};
#endif // INCLUDED_AD9361_FILTER_TAPS_HPP

View File

@ -0,0 +1,95 @@
//
// Copyright 2014 Ettus Research LLC
//
#ifndef INCLUDED_AD9361_GAIN_TABLES_HPP
#define INCLUDED_AD9361_GAIN_TABLES_HPP
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}};
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}};
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}};
#endif /* INCLUDED_AD9361_GAIN_TABLES_HPP */

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,64 @@
//
// Copyright 2014 Ettus Research LLC
//
#ifndef INCLUDED_AD9361_PLATFORM_H
#define INCLUDED_AD9361_PLATFORM_H
#include <stdint.h>
#include "ad9361_device.h"
#ifdef __cplusplus
extern "C" {
#endif
/*!
* Get chip class from handle
*/
ad9361_device_t* get_ad9361_device(uint64_t handle);
/*!
* Write a register in the AD9361 space
*/
void write_ad9361_reg(ad9361_device_t* device, uint32_t reg, uint8_t val);
/*!
* Read a register from the AD9361 space
*/
uint8_t read_ad9361_reg(ad9361_device_t* device, uint32_t reg);
/*!
* Millisecond sleep
*/
void ad9361_msleep(const uint32_t millis);
/*!
* Pack a double into 2 uint32s
*/
void ad9361_double_pack(const double input, uint32_t output[2]);
/*!
* Unpack 2 uint32s into a double
*/
double ad9361_double_unpack(const uint32_t input[2]);
/*!
* Compute the square root of val
*/
double ad9361_sqrt(double val);
/*!
* Compute the floor of val
*/
int ad9361_floor_to_int(double val);
/*!
* Compute the ceil of val
*/
int ad9361_ceil_to_int(double val);
#ifdef __cplusplus
}
#endif
#endif /* INCLUDED_AD9361_PLATFORM_H */

View File

@ -0,0 +1,135 @@
//
// Copyright 2014 Ettus Research LLC
//
#ifndef INCLUDED_AD9361_SYNTH_LUT_HPP
#define INCLUDED_AD9361_SYNTH_LUT_HPP
double vco_index[53] = {12605000000, 12245000000, 11906000000, 11588000000,
11288000000, 11007000000, 10742000000, 10492000000,
10258000000, 10036000000, 9827800000, 9631100000,
9445300000, 9269800000, 9103600000, 8946300000,
8797000000, 8655300000, 8520600000, 8392300000,
8269900000, 8153100000, 8041400000, 7934400000,
7831800000, 7733200000, 7638400000, 7547100000,
7459000000, 7374000000, 7291900000, 7212400000,
7135500000, 7061000000, 6988700000, 6918600000,
6850600000, 6784600000, 6720500000, 6658200000,
6597800000, 6539200000, 6482300000, 6427000000,
6373400000, 6321400000, 6270900000, 6222000000,
6174500000, 6128400000, 6083600000, 6040100000,
5997700000};
int synth_cal_lut[53][12] = { {10, 0, 4, 0, 15, 8, 8, 13, 4, 13, 15, 9},
{10, 0, 4, 0, 15, 8, 9, 13, 4, 13, 15, 9},
{10, 0, 4, 0, 15, 8, 10, 13, 4, 13, 15, 9},
{10, 0, 4, 0, 15, 8, 11, 13, 4, 13, 15, 9},
{10, 0, 4, 0, 15, 8, 11, 13, 4, 13, 15, 9},
{10, 0, 4, 0, 14, 8, 12, 13, 4, 13, 15, 9},
{10, 0, 4, 0, 14, 8, 13, 13, 4, 13, 15, 9},
{10, 0, 5, 1, 14, 9, 13, 13, 4, 13, 15, 9},
{10, 0, 5, 1, 14, 9, 14, 13, 4, 13, 15, 9},
{10, 0, 5, 1, 14, 9, 15, 13, 4, 13, 15, 9},
{10, 0, 5, 1, 14, 9, 15, 13, 4, 13, 15, 9},
{10, 0, 5, 1, 13, 9, 16, 13, 4, 13, 15, 9},
{10, 0, 5, 1, 13, 9, 17, 13, 4, 13, 15, 9},
{10, 0, 5, 1, 13, 9, 18, 13, 4, 13, 15, 9},
{10, 0, 5, 1, 13, 9, 18, 13, 4, 13, 15, 9},
{10, 0, 5, 1, 13, 9, 19, 13, 4, 13, 15, 9},
{10, 1, 6, 1, 15, 11, 14, 13, 4, 13, 15, 9},
{10, 1, 6, 1, 15, 11, 14, 13, 4, 13, 15, 9},
{10, 1, 6, 1, 15, 11, 15, 13, 4, 13, 15, 9},
{10, 1, 6, 1, 15, 11, 15, 13, 4, 13, 15, 9},
{10, 1, 6, 1, 15, 11, 16, 13, 4, 13, 15, 9},
{10, 1, 6, 1, 15, 11, 16, 13, 4, 13, 15, 9},
{10, 1, 6, 1, 15, 11, 17, 13, 4, 13, 15, 9},
{10, 1, 6, 1, 15, 11, 17, 13, 4, 13, 15, 9},
{10, 1, 6, 1, 15, 11, 18, 13, 4, 13, 15, 9},
{10, 1, 6, 1, 15, 11, 18, 13, 4, 13, 15, 9},
{10, 1, 6, 1, 15, 11, 19, 13, 4, 13, 15, 9},
{10, 1, 6, 1, 15, 11, 19, 13, 4, 13, 15, 9},
{10, 1, 6, 1, 15, 11, 20, 13, 4, 13, 15, 9},
{10, 1, 7, 2, 15, 12, 20, 13, 4, 13, 15, 9},
{10, 1, 7, 2, 15, 12, 21, 13, 4, 13, 15, 9},
{10, 1, 7, 2, 15, 12, 21, 13, 4, 13, 15, 9},
{10, 1, 7, 2, 15, 14, 22, 13, 4, 13, 15, 9},
{10, 1, 7, 2, 15, 14, 22, 13, 4, 13, 15, 9},
{10, 1, 7, 2, 15, 14, 23, 13, 4, 13, 15, 9},
{10, 1, 7, 2, 15, 14, 23, 13, 4, 13, 15, 9},
{10, 1, 7, 2, 15, 14, 24, 13, 4, 13, 15, 9},
{10, 1, 7, 2, 15, 14, 24, 13, 4, 13, 15, 9},
{10, 1, 7, 2, 15, 14, 25, 13, 4, 13, 15, 9},
{10, 1, 7, 2, 15, 14, 25, 13, 4, 13, 15, 9},
{10, 1, 7, 2, 15, 14, 26, 13, 4, 13, 15, 9},
{10, 1, 7, 2, 15, 14, 26, 13, 4, 13, 15, 9},
{10, 1, 7, 2, 15, 14, 27, 13, 4, 13, 15, 9},
{10, 1, 7, 2, 15, 14, 27, 13, 4, 13, 15, 9},
{10, 3, 7, 3, 15, 12, 18, 13, 4, 13, 15, 9},
{10, 3, 7, 3, 15, 12, 18, 13, 4, 13, 15, 9},
{10, 3, 7, 3, 15, 12, 18, 13, 4, 13, 15, 9},
{10, 3, 7, 3, 15, 12, 19, 13, 4, 13, 15, 9},
{10, 3, 7, 3, 15, 12, 19, 13, 4, 13, 15, 9},
{10, 3, 7, 3, 15, 12, 19, 13, 4, 13, 15, 9},
{10, 3, 7, 3, 15, 12, 19, 13, 4, 13, 15, 9},
{10, 3, 7, 3, 15, 12, 20, 13, 4, 13, 15, 9},
{10, 3, 7, 3, 15, 12, 20, 13, 4, 13, 15, 9}};
#if 0 /* This is the table for a 40MHz RFPLL Reference */
int synth_cal_lut[53][12] = { {10, 0, 4, 0, 15, 8, 8, 12, 3, 14, 15, 11},
{10, 0, 4, 0, 15, 8, 9, 12, 3, 14, 15, 11},
{10, 0, 4, 0, 15, 8, 9, 12, 3, 14, 15, 11},
{10, 0, 4, 0, 15, 8, 10, 12, 3, 14, 15, 11},
{10, 0, 4, 0, 15, 8, 11, 12, 3, 14, 15, 11},
{10, 0, 4, 0, 15, 8, 11, 12, 3, 14, 15, 11},
{10, 0, 4, 0, 14, 8, 12, 12, 3, 14, 15, 11},
{10, 0, 5, 1, 14, 9, 13, 12, 3, 14, 15, 11},
{10, 0, 5, 1, 14, 9, 13, 12, 3, 14, 15, 11},
{10, 0, 5, 1, 14, 9, 14, 12, 3, 14, 15, 11},
{10, 0, 5, 1, 14, 9, 15, 12, 3, 14, 15, 11},
{10, 0, 5, 1, 14, 9, 15, 12, 3, 14, 15, 11},
{10, 0, 5, 1, 14, 9, 16, 12, 3, 14, 15, 11},
{10, 0, 5, 1, 14, 9, 17, 12, 3, 14, 15, 11},
{10, 0, 5, 1, 14, 9, 17, 12, 3, 14, 15, 11},
{10, 0, 5, 1, 14, 9, 18, 12, 3, 14, 15, 11},
{10, 1, 6, 1, 15, 11, 13, 12, 3, 14, 15, 11},
{10, 1, 6, 1, 15, 11, 14, 12, 3, 14, 15, 11},
{10, 1, 6, 1, 15, 11, 14, 12, 3, 14, 15, 11},
{10, 1, 6, 1, 15, 11, 15, 12, 3, 14, 15, 11},
{10, 1, 6, 1, 15, 11, 15, 12, 3, 14, 15, 11},
{10, 1, 6, 1, 15, 11, 16, 12, 3, 14, 15, 11},
{10, 1, 6, 1, 15, 11, 16, 12, 3, 14, 15, 11},
{10, 1, 6, 1, 15, 11, 17, 12, 3, 14, 15, 11},
{10, 1, 6, 1, 15, 11, 17, 12, 3, 14, 15, 11},
{10, 1, 6, 1, 15, 11, 17, 12, 3, 14, 15, 11},
{10, 1, 6, 1, 15, 11, 18, 12, 3, 14, 15, 11},
{10, 1, 6, 1, 15, 11, 18, 12, 3, 14, 15, 11},
{10, 1, 6, 1, 15, 11, 19, 12, 3, 14, 15, 11},
{10, 1, 7, 2, 15, 12, 19, 12, 3, 14, 15, 11},
{10, 1, 7, 2, 15, 12, 20, 12, 3, 14, 15, 11},
{10, 1, 7, 2, 15, 12, 20, 12, 3, 14, 15, 11},
{10, 1, 7, 2, 15, 14, 21, 12, 3, 14, 15, 11},
{10, 1, 7, 2, 15, 14, 21, 12, 3, 14, 15, 11},
{10, 1, 7, 2, 15, 14, 22, 12, 3, 14, 15, 11},
{10, 1, 7, 2, 15, 14, 22, 12, 3, 14, 15, 11},
{10, 1, 7, 2, 15, 14, 23, 12, 3, 14, 15, 11},
{10, 1, 7, 2, 15, 14, 23, 12, 3, 14, 15, 11},
{10, 1, 7, 2, 15, 14, 24, 12, 3, 14, 15, 11},
{10, 1, 7, 2, 15, 14, 24, 12, 3, 14, 15, 11},
{10, 1, 7, 2, 15, 14, 25, 12, 3, 14, 15, 11},
{10, 1, 7, 2, 15, 14, 25, 12, 3, 14, 15, 11},
{10, 1, 7, 2, 15, 14, 26, 12, 3, 14, 15, 11},
{10, 1, 7, 2, 15, 14, 26, 12, 3, 14, 15, 11},
{10, 3, 7, 3, 15, 12, 17, 12, 3, 14, 15, 11},
{10, 3, 7, 3, 15, 12, 17, 12, 3, 14, 15, 11},
{10, 3, 7, 3, 15, 12, 17, 12, 3, 14, 15, 11},
{10, 3, 7, 3, 15, 12, 18, 12, 3, 14, 15, 11},
{10, 3, 7, 3, 15, 12, 18, 12, 3, 14, 15, 11},
{10, 3, 7, 3, 15, 12, 18, 12, 3, 14, 15, 11},
{10, 3, 7, 3, 15, 12, 18, 12, 3, 14, 15, 11},
{10, 3, 7, 3, 15, 12, 19, 12, 3, 14, 15, 11},
{10, 3, 7, 3, 15, 12, 19, 12, 3, 14, 15, 11} };
#endif
#endif /* INCLUDED_AD9361_SYNTH_LUT_HPP */

View File

@ -1,18 +1,5 @@
//
// Copyright 2013 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
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
// Copyright 2014 Ettus Research LLC
//
#ifndef INCLUDED_AD9361_TRANSACTION_H
@ -25,8 +12,8 @@ extern "C" {
#endif
//various constants
#define AD9361_TRANSACTION_VERSION 0x4
#define AD9361_DISPATCH_PACKET_SIZE 64
#define AD9361_TRANSACTION_VERSION 0x5
#define AD9361_DISPATCH_PACKET_SIZE 64
//action types
#define AD9361_ACTION_ECHO 0
@ -41,28 +28,6 @@ extern "C" {
#define AD9361_ACTION_SET_CLOCK_RATE 9
#define AD9361_ACTION_SET_ACTIVE_CHAINS 10
typedef union
{
double d;
uint32_t x[2];
} ad9361_double_union_t;
static inline void ad9361_double_pack(const double input, uint32_t output[2])
{
ad9361_double_union_t p = {};
p.d = input;
output[0] = p.x[0];
output[1] = p.x[1];
}
static inline double ad9361_double_unpack(const uint32_t input[2])
{
ad9361_double_union_t p = {};
p.x[0] = input[0];
p.x[1] = input[1];
return p.d;
}
typedef struct
{
//version is expected to be AD9361_TRANSACTION_VERSION
@ -72,6 +37,9 @@ typedef struct
//sequence number - increment every call for sanity
uint32_t sequence;
//location info for the ad9361 chip class
uint64_t handle;
//action tells us what to do, see AD9361_ACTION_*
uint32_t action;

View File

@ -0,0 +1,86 @@
//
// Copyright 2014 Ettus Research LLC
//
#include <uhd/utils/msg.hpp>
#include <cmath>
#include <cstdlib>
#include <cstring>
#include <stdint.h>
#include <ad9361_platform.h>
#include "ad9361_ctrl.hpp"
#include <stdio.h>
#include <boost/date_time/posix_time/posix_time.hpp>
#include <boost/thread/thread.hpp>
//If the platform for the AD9361 driver is UHD (host) then the handle is simply
//a pointer to a device class instance
ad9361_device_t* get_ad9361_device(uint64_t handle)
{
return reinterpret_cast<ad9361_device_t*>(reinterpret_cast<void*>(handle));
}
uint8_t read_ad9361_reg(ad9361_device_t* device, uint32_t reg)
{
if (device && device->io_iface) {
//If the platform for the AD9361 driver is UHD (host) then the io_iface is
//a pointer to a ad9361_io implementation
ad9361_io* io_iface = reinterpret_cast<ad9361_io*>(device->io_iface);
return io_iface->peek8(reg);
} else {
return 0;
}
}
void write_ad9361_reg(ad9361_device_t* device, uint32_t reg, uint8_t val)
{
if (device && device->io_iface) {
//If the platform for the AD9361 driver is UHD (host) then the io_iface is
//a pointer to a ad9361_io implementation
ad9361_io* io_iface = reinterpret_cast<ad9361_io*>(device->io_iface);
io_iface->poke8(reg, val);
}
}
typedef union
{
double d;
uint32_t x[2];
} ad9361_double_union_t;
void ad9361_double_pack(const double input, uint32_t output[2])
{
ad9361_double_union_t p = {};
p.d = input;
output[0] = p.x[0];
output[1] = p.x[1];
}
double ad9361_double_unpack(const uint32_t input[2])
{
ad9361_double_union_t p = {};
p.x[0] = input[0];
p.x[1] = input[1];
return p.d;
}
double ad9361_sqrt(double val)
{
return std::sqrt(val);
}
void ad9361_msleep(const uint32_t millis)
{
boost::this_thread::sleep(boost::posix_time::milliseconds(millis));
}
int ad9361_floor_to_int(double val)
{
return static_cast<int>(std::floor(val));
}
int ad9361_ceil_to_int(double val)
{
return static_cast<int>(std::ceil(val));
}

View File

@ -1,5 +1,5 @@
#
# Copyright 2010-2014 Ettus Research LLC
# Copyright 2010-2013 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
@ -62,22 +62,11 @@ IF(ENABLE_USB)
)
INCLUDE_DIRECTORIES(${LIBUSB_INCLUDE_DIRS})
# Additional include directories for b2xx_fx3_utils
INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/../lib/usrp/b200 ${CMAKE_CURRENT_SOURCE_DIR}/../lib/usrp/common)
INCLUDE_DIRECTORIES(
${CMAKE_CURRENT_SOURCE_DIR}/../lib/usrp/b200
${CMAKE_CURRENT_SOURCE_DIR}/../lib/usrp/common
${CMAKE_CURRENT_SOURCE_DIR}/../lib/usrp/common/ad9361_driver)
ENDIF(ENABLE_USB)
IF(ENABLE_OCTOCLOCK)
LIST(APPEND util_share_sources
octoclock_burn_eeprom.cpp
)
SET(octoclock_burner_sources
octoclock_firmware_burner.cpp
ihexcvt.cpp
)
ADD_EXECUTABLE(octoclock_firmware_burner ${octoclock_burner_sources})
TARGET_LINK_LIBRARIES(octoclock_firmware_burner uhd ${Boost_LIBRARIES})
UHD_INSTALL(TARGETS octoclock_firmware_burner RUNTIME DESTINATION ${RUNTIME_DIR} COMPONENT utilities)
ENDIF(ENABLE_OCTOCLOCK)
IF(LINUX AND ENABLE_USB)
UHD_INSTALL(FILES