diff options
Diffstat (limited to 'host/lib/usrp/common')
-rw-r--r-- | host/lib/usrp/common/CMakeLists.txt | 4 | ||||
-rw-r--r-- | host/lib/usrp/common/ad9361_ctrl.cpp | 165 | ||||
-rw-r--r-- | host/lib/usrp/common/ad9361_ctrl.hpp | 127 | ||||
-rw-r--r-- | host/lib/usrp/common/ad9361_transaction.h | 102 | ||||
-rw-r--r-- | host/lib/usrp/common/adf4001_ctrl.cpp | 151 | ||||
-rw-r--r-- | host/lib/usrp/common/adf4001_ctrl.hpp | 142 | ||||
-rw-r--r-- | host/lib/usrp/common/recv_packet_demuxer_3000.hpp | 14 |
7 files changed, 703 insertions, 2 deletions
diff --git a/host/lib/usrp/common/CMakeLists.txt b/host/lib/usrp/common/CMakeLists.txt index fa07e3d1d..1728b63f9 100644 --- a/host/lib/usrp/common/CMakeLists.txt +++ b/host/lib/usrp/common/CMakeLists.txt @@ -1,5 +1,5 @@ # -# Copyright 2011-2012 Ettus Research LLC +# Copyright 2011-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 @@ -29,6 +29,8 @@ ENDIF(ENABLE_USB) INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}) LIBUHD_APPEND_SOURCES( + ${CMAKE_CURRENT_SOURCE_DIR}/adf4001_ctrl.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/ad9361_ctrl.cpp ${CMAKE_CURRENT_SOURCE_DIR}/apply_corrections.cpp ${CMAKE_CURRENT_SOURCE_DIR}/validate_subdev_spec.cpp ${CMAKE_CURRENT_SOURCE_DIR}/recv_packet_demuxer.cpp diff --git a/host/lib/usrp/common/ad9361_ctrl.cpp b/host/lib/usrp/common/ad9361_ctrl.cpp new file mode 100644 index 000000000..ae7cc6f9b --- /dev/null +++ b/host/lib/usrp/common/ad9361_ctrl.cpp @@ -0,0 +1,165 @@ +// +// 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/>. +// + +#include "ad9361_ctrl.hpp" +#include "ad9361_transaction.h" +#include <uhd/exception.hpp> +#include <uhd/types/ranges.hpp> +#include <uhd/utils/msg.hpp> +#include <boost/thread/mutex.hpp> +#include <boost/format.hpp> +#include <cstring> + +using namespace uhd; + +struct ad9361_ctrl_impl : public ad9361_ctrl +{ + ad9361_ctrl_impl(ad9361_ctrl_iface_sptr iface): + _iface(iface), _seq(0) + { + ad9361_transaction_t request; + + request.action = AD9361_ACTION_ECHO; + this->do_transaction(request); + + request.action = AD9361_ACTION_INIT; + this->do_transaction(request); + } + + 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; + + ad9361_double_pack(value, request.value.gain); + const ad9361_transaction_t reply = this->do_transaction(request); + return ad9361_double_unpack(reply.value.gain); + } + + //! set a new clock rate, return the exact value + double set_clock_rate(const double rate) + { + //warning for known trouble rates + if (rate > 56e6) UHD_MSG(warning) << boost::format( + "The requested clock rate %f MHz may cause slow configuration.\n" + "The driver recommends a master clock rate less than %f MHz.\n" + ) % (rate/1e6) % 56.0 << std::endl; + + //clip to known bounds + const meta_range_t clock_rate_range(250e3, 61.44e6); + 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); + } + + //! 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); + } + + //! tune the given frontend, return the exact value + double tune(const std::string &which, const double freq) + { + //clip to known bounds + const meta_range_t freq_range(50e6, 6e9); + 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); + } + + //! 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[64] = {}; + unsigned char out_buff[64] = {}; + + //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->version = AD9361_TRANSACTION_VERSION; + in->sequence = _seq++; + + //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 = 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 do transaction: " + error_msg); + + //return result done! + return *out; + } + + ad9361_ctrl_iface_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) +{ + return sptr(new ad9361_ctrl_impl(iface)); +} diff --git a/host/lib/usrp/common/ad9361_ctrl.hpp b/host/lib/usrp/common/ad9361_ctrl.hpp new file mode 100644 index 000000000..6d79ef3e9 --- /dev/null +++ b/host/lib/usrp/common/ad9361_ctrl.hpp @@ -0,0 +1,127 @@ +// +// 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/>. +// + +#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 <boost/shared_ptr.hpp> +#include <boost/utility.hpp> +#include <boost/function.hpp> +#include <vector> +#include <string> + + +struct ad9361_ctrl_iface_type +{ + virtual void ad9361_transact(const unsigned char in_buff[64], unsigned char out_buff[64]) = 0; +}; +typedef boost::shared_ptr<ad9361_ctrl_iface_type> ad9361_ctrl_iface_sptr; + + +struct ad9361_ctrl_over_zc : ad9361_ctrl_iface_type +{ + ad9361_ctrl_over_zc(uhd::transport::zero_copy_if::sptr xport) + { + _xport = xport; + } + + void ad9361_transact(const unsigned char in_buff[64], unsigned char out_buff[64]) + { + { + uhd::transport::managed_send_buffer::sptr buff = _xport->get_send_buff(10.0); + if (not buff or buff->size() < 64) throw std::runtime_error("ad9361_ctrl_over_zc send timeout"); + std::memcpy(buff->cast<void *>(), in_buff, 64); + buff->commit(64); + } + { + uhd::transport::managed_recv_buffer::sptr buff = _xport->get_recv_buff(10.0); + if (not buff or buff->size() < 64) throw std::runtime_error("ad9361_ctrl_over_zc recv timeout"); + std::memcpy(out_buff, buff->cast<const void *>(), 64); + } + } + + 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); + + //! Get a list of gain names for RX or TX + static std::vector<std::string> get_gain_names(const std::string &/*which*/) + { + return std::vector<std::string>(1, "PGA"); + } + + //! get the gain range for a particular gain element + static uhd::meta_range_t get_gain_range(const std::string &which) + { + if(which[0] == 'R') { + return uhd::meta_range_t(0.0, 73.0, 1.0); + } else { + return uhd::meta_range_t(0.0, 89.75, 0.25); + } + } + + //! get the freq range for the frontend which + static uhd::meta_range_t get_rf_freq_range(void) + { + return uhd::meta_range_t(30e6, 6e9); + } + + //! get the filter range for the frontend which + static uhd::meta_range_t get_bw_filter_range(const std::string &/*which*/) + { + return uhd::meta_range_t(200e3, 56e6); + } + + //! get the filter range for the frontend which + static uhd::meta_range_t get_samp_rate_range(void) + { + return uhd::meta_range_t(220e3, 61.44e6); + } + + //! set the filter bandwidth for the frontend + double set_bw_filter(const std::string &/*which*/, const double /*bw*/) + { + return 56e6; //TODO + } + + //! set the gain for a particular gain element + virtual double set_gain(const std::string &which, const double value) = 0; + + //! set a new clock rate, return the exact value + virtual double set_clock_rate(const double rate) = 0; + + //! set which RX and TX chains/antennas are active + virtual void set_active_chains(bool tx1, bool tx2, bool rx1, bool rx2) = 0; + + //! tune the given frontend, return the exact value + virtual double tune(const std::string &which, const double value) = 0; + + //! turn on/off Catalina's data port loopback + virtual void data_port_loopback(const bool on) = 0; +}; + +#endif /* INCLUDED_AD9361_CTRL_HPP */ diff --git a/host/lib/usrp/common/ad9361_transaction.h b/host/lib/usrp/common/ad9361_transaction.h new file mode 100644 index 000000000..7b41b811f --- /dev/null +++ b/host/lib/usrp/common/ad9361_transaction.h @@ -0,0 +1,102 @@ +// +// 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/>. +// + +#ifndef INCLUDED_AD9361_TRANSACTION_H +#define INCLUDED_AD9361_TRANSACTION_H + +#include <stdint.h> + +#ifdef __cplusplus +extern "C" { +#endif + +//various constants +#define AD9361_TRANSACTION_VERSION 0x4 +#define AD9361_TRANSACTION_MAX_ERROR_MSG 40 + +//action types +#define AD9361_ACTION_ECHO 0 +#define AD9361_ACTION_INIT 1 +#define AD9361_ACTION_SET_RX1_GAIN 2 +#define AD9361_ACTION_SET_TX1_GAIN 3 +#define AD9361_ACTION_SET_RX2_GAIN 4 +#define AD9361_ACTION_SET_TX2_GAIN 5 +#define AD9361_ACTION_SET_RX_FREQ 6 +#define AD9361_ACTION_SET_TX_FREQ 7 +#define AD9361_ACTION_SET_CODEC_LOOP 8 +#define AD9361_ACTION_SET_CLOCK_RATE 9 +#define AD9361_ACTION_SET_ACTIVE_CHAINS 10 + +static inline void ad9361_double_pack(const double input, uint32_t output[2]) +{ + const uint32_t *p = (const uint32_t *)&input; + output[0] = p[0]; + output[1] = p[1]; +} + +static inline double ad9361_double_unpack(const uint32_t input[2]) +{ + double output = 0.0; + uint32_t *p = (uint32_t *)&output; + p[0] = input[0]; + p[1] = input[1]; + return output; +} + +typedef struct +{ + //version is expected to be AD9361_TRANSACTION_VERSION + //check otherwise for compatibility + uint32_t version; + + //sequence number - increment every call for sanity + uint32_t sequence; + + //action tells us what to do, see AD9361_ACTION_* + uint32_t action; + + union + { + //enable mask for chains + uint32_t enable_mask; + + //true to enable codec internal loopback + uint32_t codec_loop; + + //freq holds request LO freq and result from tune + uint32_t freq[2]; + + //gain holds request gain and result from action + uint32_t gain[2]; + + //rate holds request clock rate and result from action + uint32_t rate[2]; + + } value; + + //error message comes back as a reply - + //set to null string for no error \0 + char error_msg[]; + +} ad9361_transaction_t; + + +#ifdef __cplusplus +} +#endif + +#endif /* INCLUDED_AD9361_TRANSACTION_H */ diff --git a/host/lib/usrp/common/adf4001_ctrl.cpp b/host/lib/usrp/common/adf4001_ctrl.cpp new file mode 100644 index 000000000..46171c7ce --- /dev/null +++ b/host/lib/usrp/common/adf4001_ctrl.cpp @@ -0,0 +1,151 @@ +// +// Copyright 2013 Ettus Research LLC +// +// Original ADF4001 driver written by: bistromath +// Mar 1, 2013 +// +// Re-used and re-licensed with permission. +// +// 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/>. +// + +#include "adf4001_ctrl.hpp" + +#include <uhd/utils/msg.hpp> +#include <iostream> +#include <iomanip> + +using namespace uhd; +using namespace uhd::usrp; + +adf4001_regs_t::adf4001_regs_t(void) { + ref_counter = 0; + n = 0; + charge_pump_current_1 = 0; + charge_pump_current_2 = 0; + anti_backlash_width = ANTI_BACKLASH_WIDTH_2_9NS; + lock_detect_precision = LOCK_DETECT_PRECISION_3CYC; + charge_pump_gain = CHARGE_PUMP_GAIN_1; + counter_reset = COUNTER_RESET_NORMAL; + power_down = POWER_DOWN_NORMAL; + muxout = MUXOUT_TRISTATE_OUT; + phase_detector_polarity = PHASE_DETECTOR_POLARITY_NEGATIVE; + charge_pump_mode = CHARGE_PUMP_TRISTATE; + fastlock_mode = FASTLOCK_MODE_DISABLED; + timer_counter_control = TIMEOUT_3CYC; +} + + +boost::uint32_t adf4001_regs_t::get_reg(boost::uint8_t addr) { + boost::uint32_t reg = 0; + switch (addr) { + case 0: + reg |= (boost::uint32_t(ref_counter) & 0x003FFF) << 2; + reg |= (boost::uint32_t(anti_backlash_width) & 0x000003) << 16; + reg |= (boost::uint32_t(lock_detect_precision) & 0x000001) << 20; + break; + case 1: + reg |= (boost::uint32_t(n) & 0x001FFF) << 8; + reg |= (boost::uint32_t(charge_pump_gain) & 0x000001) << 21; + break; + case 2: + reg |= (boost::uint32_t(counter_reset) & 0x000001) << 2; + reg |= (boost::uint32_t(power_down) & 0x000001) << 3; + reg |= (boost::uint32_t(muxout) & 0x000007) << 4; + reg |= (boost::uint32_t(phase_detector_polarity) & 0x000001) << 7; + reg |= (boost::uint32_t(charge_pump_mode) & 0x000001) << 8; + reg |= (boost::uint32_t(fastlock_mode) & 0x000003) << 9; + reg |= (boost::uint32_t(timer_counter_control) & 0x00000F) << 11; + reg |= (boost::uint32_t(charge_pump_current_1) & 0x000007) << 15; + reg |= (boost::uint32_t(charge_pump_current_2) & 0x000007) << 18; + reg |= (boost::uint32_t(power_down) & 0x000002) << 21; + break; + case 3: + reg |= (boost::uint32_t(counter_reset) & 0x000001) << 2; + reg |= (boost::uint32_t(power_down) & 0x000001) << 3; + reg |= (boost::uint32_t(muxout) & 0x000007) << 4; + reg |= (boost::uint32_t(phase_detector_polarity) & 0x000001) << 7; + reg |= (boost::uint32_t(charge_pump_mode) & 0x000001) << 8; + reg |= (boost::uint32_t(fastlock_mode) & 0x000003) << 9; + reg |= (boost::uint32_t(timer_counter_control) & 0x00000F) << 11; + reg |= (boost::uint32_t(charge_pump_current_1) & 0x000007) << 15; + reg |= (boost::uint32_t(charge_pump_current_2) & 0x000007) << 18; + reg |= (boost::uint32_t(power_down) & 0x000002) << 21; + break; + default: + break; + } + + reg |= (boost::uint32_t(addr) & 0x03); + + return reg; +} + + +adf4001_ctrl::adf4001_ctrl(spi_core_3000::sptr _spi, int slaveno): + spi_iface(_spi), + slaveno(slaveno) + { + + spi_config.mosi_edge = spi_config_t::EDGE_RISE; + + //set defaults + adf4001_regs.ref_counter = 1; + adf4001_regs.n = 4; + adf4001_regs.charge_pump_current_1 = 7; + adf4001_regs.charge_pump_current_2 = 7; + adf4001_regs.muxout = adf4001_regs_t::MUXOUT_DLD; + adf4001_regs.counter_reset = adf4001_regs_t::COUNTER_RESET_NORMAL; + adf4001_regs.phase_detector_polarity = adf4001_regs_t::PHASE_DETECTOR_POLARITY_POSITIVE; + adf4001_regs.charge_pump_mode = adf4001_regs_t::CHARGE_PUMP_TRISTATE; + + //everything else should be defaults + + program_regs(); +} + +void adf4001_ctrl::set_lock_to_ext_ref(bool external) { + if(external) { + adf4001_regs.charge_pump_mode = adf4001_regs_t::CHARGE_PUMP_NORMAL; + } else { + adf4001_regs.charge_pump_mode = adf4001_regs_t::CHARGE_PUMP_TRISTATE; + } + + program_regs(); +} + +void adf4001_ctrl::program_regs(void) { + //no control over CE, only LE, therefore we use the initialization latch method + write_reg(3); + boost::this_thread::sleep(boost::posix_time::microseconds(1)); + + //write R counter latch (0) + write_reg(0); + boost::this_thread::sleep(boost::posix_time::microseconds(1)); + + //write N counter latch (1) + write_reg(1); + boost::this_thread::sleep(boost::posix_time::microseconds(1)); +} + + +void adf4001_ctrl::write_reg(boost::uint8_t addr) { + boost::uint32_t reg = adf4001_regs.get_reg(addr); //load the reg data + + spi_iface->transact_spi(slaveno, + spi_config, + reg, + 24, + false); +} diff --git a/host/lib/usrp/common/adf4001_ctrl.hpp b/host/lib/usrp/common/adf4001_ctrl.hpp new file mode 100644 index 000000000..a16cff3fa --- /dev/null +++ b/host/lib/usrp/common/adf4001_ctrl.hpp @@ -0,0 +1,142 @@ +// +// Copyright 2013 Ettus Research LLC +// +// Original ADF4001 driver written by: bistromath +// Mar 1, 2013 +// +// Re-used and re-licensed with permission. +// +// 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/>. +// + +#ifndef INCLUDED_LIBUHD_USRP_COMMON_ADF4001_HPP +#define INCLUDED_LIBUHD_USRP_COMMON_ADF4001_HPP + +#include "spi_core_3000.hpp" +#include <uhd/types/serial.hpp> +#include <boost/cstdint.hpp> +#include <boost/thread/thread.hpp> + +namespace uhd { namespace usrp { + +class adf4001_regs_t { +public: + + /* Function prototypes */ + boost::uint32_t get_reg(boost::uint8_t addr); + adf4001_regs_t(void); + + /* Register values / addresses */ + boost::uint16_t ref_counter; //14 bits + boost::uint16_t n; //13 bits + boost::uint8_t charge_pump_current_1; //3 bits + boost::uint8_t charge_pump_current_2; //3 bits + + enum anti_backlash_width_t { + ANTI_BACKLASH_WIDTH_2_9NS = 0, + ANTI_BACKLASH_WIDTH_1_3NS = 1, + ANTI_BACKLASH_WIDTH_6_0NS = 2, + ANTI_BACKLASH_WIDTH_2_9NS_WAT = 3 + }; + anti_backlash_width_t anti_backlash_width; + + enum lock_detect_precision_t { + LOCK_DETECT_PRECISION_3CYC = 0, + LOCK_DETECT_PRECISION_5CYC = 1 + }; + lock_detect_precision_t lock_detect_precision; + enum charge_pump_gain_t { + CHARGE_PUMP_GAIN_1 = 0, + CHARGE_PUMP_GAIN_2 = 1 + }; + charge_pump_gain_t charge_pump_gain; + enum counter_reset_t { + COUNTER_RESET_NORMAL = 0, + COUNTER_RESET_RESET = 1 + }; + counter_reset_t counter_reset; + enum power_down_t { + POWER_DOWN_NORMAL = 0, + POWER_DOWN_ASYNC = 1, + POWER_DOWN_SYNC = 3 + }; + power_down_t power_down; + enum muxout_t { + MUXOUT_TRISTATE_OUT = 0, + MUXOUT_DLD = 1, + MUXOUT_NDIV = 2, + MUXOUT_AVDD = 3, + MUXOUT_RDIV = 4, + MUXOUT_NCH_OD_ALD = 5, + MUXOUT_SDO = 6, + MUXOUT_GND = 7 + }; + muxout_t muxout; + enum phase_detector_polarity_t { + PHASE_DETECTOR_POLARITY_NEGATIVE = 0, + PHASE_DETECTOR_POLARITY_POSITIVE = 1 + }; + phase_detector_polarity_t phase_detector_polarity; + enum charge_pump_mode_t { + CHARGE_PUMP_NORMAL = 0, + CHARGE_PUMP_TRISTATE = 1 + }; + charge_pump_mode_t charge_pump_mode; + enum fastlock_mode_t { + FASTLOCK_MODE_DISABLED = 0, + FASTLOCK_MODE_1 = 1, + FASTLOCK_MODE_2 = 2 + }; + fastlock_mode_t fastlock_mode; + enum timer_counter_control_t { + TIMEOUT_3CYC = 0, + TIMEOUT_7CYC = 1, + TIMEOUT_11CYC = 2, + TIMEOUT_15CYC = 3, + TIMEOUT_19CYC = 4, + TIMEOUT_23CYC = 5, + TIMEOUT_27CYC = 6, + TIMEOUT_31CYC = 7, + TIMEOUT_35CYC = 8, + TIMEOUT_39CYC = 9, + TIMEOUT_43CYC = 10, + TIMEOUT_47CYC = 11, + TIMEOUT_51CYC = 12, + TIMEOUT_55CYC = 13, + TIMEOUT_59CYC = 14, + TIMEOUT_63CYC = 15, + }; + timer_counter_control_t timer_counter_control; +}; + + +class adf4001_ctrl { +public: + + adf4001_ctrl(spi_core_3000::sptr _spi, int slaveno); + void set_lock_to_ext_ref(bool external); + +private: + spi_core_3000::sptr spi_iface; + int slaveno; + spi_config_t spi_config; + adf4001_regs_t adf4001_regs; + + void program_regs(void); + void write_reg(boost::uint8_t addr); +}; + +}} + +#endif diff --git a/host/lib/usrp/common/recv_packet_demuxer_3000.hpp b/host/lib/usrp/common/recv_packet_demuxer_3000.hpp index 9de3666dd..4fb6c4604 100644 --- a/host/lib/usrp/common/recv_packet_demuxer_3000.hpp +++ b/host/lib/usrp/common/recv_packet_demuxer_3000.hpp @@ -92,7 +92,10 @@ namespace uhd{ namespace usrp{ if (new_sid != sid) { boost::mutex::scoped_lock l(mutex); - _queues[new_sid].push(buff); + if (_queues.count(new_sid) == 0) UHD_MSG(error) + << "recv packet demuxer unexpected sid 0x" << std::hex << new_sid << std::dec + << std::endl; + else _queues[new_sid].push(buff); buff.reset(); } } @@ -102,6 +105,15 @@ namespace uhd{ namespace usrp{ return buff; } + void realloc_sid(const boost::uint32_t sid) + { + boost::mutex::scoped_lock l(mutex); + while(not _queues[sid].empty()) //allocated and clears if already allocated + { + _queues[sid].pop(); + } + } + typedef std::queue<transport::managed_recv_buffer::sptr> queue_type_t; std::map<boost::uint32_t, queue_type_t> _queues; transport::zero_copy_if::sptr _xport; |