diff options
author | Mark Meserve <mark.meserve@ni.com> | 2017-03-23 14:49:42 -0700 |
---|---|---|
committer | Martin Braun <martin.braun@ettus.com> | 2017-12-22 15:03:44 -0800 |
commit | bc4d1bf0ca341a72a7d7f6b2168aa3d2e936aabf (patch) | |
tree | 5af9a631efc95c2a1e94e58aa1a86b84e2c91712 /mpm/lib/mykonos | |
parent | 1a4348038d0eb57d53475074dca49e8192aeb2d7 (diff) | |
download | uhd-bc4d1bf0ca341a72a7d7f6b2168aa3d2e936aabf.tar.gz uhd-bc4d1bf0ca341a72a7d7f6b2168aa3d2e936aabf.tar.bz2 uhd-bc4d1bf0ca341a72a7d7f6b2168aa3d2e936aabf.zip |
mpm: Rearchitecture of AD9371 code to use ctrl/device paradigm
Diffstat (limited to 'mpm/lib/mykonos')
23 files changed, 1219 insertions, 2694 deletions
diff --git a/mpm/lib/mykonos/CMakeLists.txt b/mpm/lib/mykonos/CMakeLists.txt index 03b3ef102..182058405 100644 --- a/mpm/lib/mykonos/CMakeLists.txt +++ b/mpm/lib/mykonos/CMakeLists.txt @@ -32,7 +32,6 @@ SET(mykonos_sources ) ADD_SUBDIRECTORY(adi) -ADD_SUBDIRECTORY(adi_sample) ADD_SUBDIRECTORY(config) USRP_PERIPHS_ADD_OBJECT(mykonos ${mykonos_sources}) diff --git a/mpm/lib/mykonos/ad937x_ctrl.cpp b/mpm/lib/mykonos/ad937x_ctrl.cpp index b4ff38139..a5cd842f5 100644 --- a/mpm/lib/mykonos/ad937x_ctrl.cpp +++ b/mpm/lib/mykonos/ad937x_ctrl.cpp @@ -1,15 +1,31 @@ -#include "adi/mykonos.h" +// +// Copyright 2017 Ettus Research (National Instruments) +// +// 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 "ad937x_ctrl.hpp" #include "ad937x_device.hpp" +#include "ad937x_ctrl.hpp" +#include "adi/mykonos.h" + #include <sstream> +#include <set> #include <functional> -#include <iostream> -#include <cmath> uhd::meta_range_t ad937x_ctrl::get_rf_freq_range(void) { - return uhd::meta_range_t(300e6, 6e9); + return uhd::meta_range_t(ad937x_device::MIN_FREQ, ad937x_device::MAX_FREQ); } uhd::meta_range_t ad937x_ctrl::get_bw_filter_range(void) @@ -18,7 +34,7 @@ uhd::meta_range_t ad937x_ctrl::get_bw_filter_range(void) return uhd::meta_range_t(0, 1); } -std::vector<double> ad937x_ctrl::get_clock_rates(void) +std::set<double> ad937x_ctrl::get_clock_rates(void) { // TODO: fix return { 125e6 }; @@ -30,16 +46,16 @@ uhd::meta_range_t ad937x_ctrl::get_gain_range(const std::string &which) switch (dir) { case uhd::direction_t::RX_DIRECTION: - return uhd::meta_range_t(0, 30, 0.5); + return uhd::meta_range_t(ad937x_device::MIN_RX_GAIN, ad937x_device::MAX_RX_GAIN, ad937x_device::RX_GAIN_STEP); case uhd::direction_t::TX_DIRECTION: - return uhd::meta_range_t(0, 41.95, 0.05); + return uhd::meta_range_t(ad937x_device::MIN_TX_GAIN, ad937x_device::MAX_TX_GAIN, ad937x_device::TX_GAIN_STEP); default: - throw uhd::runtime_error("ad937x_ctrl got an invalid channel string."); + UHD_THROW_INVALID_CODE_PATH(); return uhd::meta_range_t(); } } -std::vector<size_t> ad937x_ctrl::_get_valid_fir_lengths(const std::string& which) +std::set<size_t> ad937x_ctrl::_get_valid_fir_lengths(const std::string& which) { auto dir = _get_direction_from_antenna(which); switch (dir) @@ -49,8 +65,8 @@ std::vector<size_t> ad937x_ctrl::_get_valid_fir_lengths(const std::string& which case uhd::direction_t::TX_DIRECTION: return { 16, 32, 48, 64, 80, 96 }; default: - throw uhd::runtime_error("ad937x_ctrl got an invalid channel string."); - return std::vector<size_t>(); + UHD_THROW_INVALID_CODE_PATH(); + return std::set<size_t>(); } } @@ -87,30 +103,27 @@ ad937x_device::chain_t ad937x_ctrl::_get_chain_from_antenna(const std::string& a class ad937x_ctrl_impl : public ad937x_ctrl { public: - // change to uhd::spi_iface - static sptr make(spi_lock::sptr spi_l, mpm::spi_iface::sptr iface); - - ad937x_ctrl_impl(spi_lock::sptr spi_l, mpm::spi_iface::sptr iface) : + ad937x_ctrl_impl(spi_lock::sptr spi_l, uhd::spi_iface::sptr iface) : spi_l(spi_l), - iface(iface) + device(iface) { } virtual uint8_t get_product_id() { - std::lock_guard<spi_lock>(*spi_l); + std::lock_guard<spi_lock> lock(*spi_l); return device.get_product_id(); } virtual uint8_t get_device_rev() { - std::lock_guard<spi_lock>(*spi_l); + std::lock_guard<spi_lock> lock(*spi_l); return device.get_device_rev(); } virtual std::string get_api_version() { - std::lock_guard<spi_lock>(*spi_l); + std::lock_guard<spi_lock> lock(*spi_l); auto api = device.get_api_version(); std::ostringstream ss; ss << api.silicon_ver << "." @@ -122,7 +135,7 @@ public: virtual std::string get_arm_version() { - std::lock_guard<spi_lock>(*spi_l); + std::lock_guard<spi_lock> lock(*spi_l); auto arm = device.get_arm_version(); std::ostringstream ss; ss << arm.major_ver << "." @@ -131,27 +144,19 @@ public: return ss.str(); } - virtual double set_bw_filter(const std::string &which, const double value) + virtual double set_bw_filter(const std::string &which, double value) { // TODO implement return double(); } - virtual double set_gain(const std::string &which, const double value) + virtual double set_gain(const std::string &which, double value) { auto dir = _get_direction_from_antenna(which); auto chain = _get_chain_from_antenna(which); - return device.set_gain(dir, chain, value); - } - virtual void set_agc(const std::string &which, const bool enable) - { - auto dir = _get_direction_from_antenna(which); - if (dir != uhd::direction_t::RX_DIRECTION) - { - throw uhd::runtime_error("ad937x_ctrl::set_agc was called on a non-RX channel"); - } - return device.set_agc(dir, enable); + std::lock_guard<spi_lock> lock(*spi_l); + return device.set_gain(dir, chain, value); } virtual void set_agc_mode(const std::string &which, const std::string &mode) @@ -159,7 +164,7 @@ public: auto dir = _get_direction_from_antenna(which); if (dir != uhd::direction_t::RX_DIRECTION) { - throw uhd::runtime_error("ad937x_ctrl::set_agc was called on a non-RX channel"); + throw uhd::runtime_error("set_agc not valid for non-rx channels"); } ad937x_device::gain_mode_t gain_mode; @@ -174,392 +179,89 @@ public: gain_mode = ad937x_device::gain_mode_t::HYBRID; } else { - throw uhd::runtime_error("ad937x_ctrl::set_agc_mode was called on a non-RX channel"); + throw uhd::runtime_error("invalid agc mode"); } + std::lock_guard<spi_lock> lock(*spi_l); device.set_agc_mode(dir, gain_mode); } - virtual double set_clock_rate(const double value) + virtual double set_clock_rate(double value) { auto rates = get_clock_rates(); - auto coerced_value = value; - if (std::find(rates.begin(), rates.end(), value) == rates.end()) + if (std::find(rates.cbegin(), rates.cend(), value) == rates.end()) { - coerced_value = rates[0]; + value = *(rates.cbegin()); } - return device.set_clock_rate(coerced_value); + std::lock_guard<spi_lock> lock(*spi_l); + return device.set_clock_rate(value); } - virtual void enable_channel(const std::string &which, const bool enable) + virtual void enable_channel(const std::string &which, bool enable) { auto dir = _get_direction_from_antenna(which); auto chain = _get_chain_from_antenna(which); + + std::lock_guard<spi_lock> lock(*spi_l); return device.enable_channel(dir, chain, enable); } - virtual double set_freq(const std::string &which, const double value) + virtual double set_freq(const std::string &which, double value) { auto dir = _get_direction_from_antenna(which); auto clipped_value = get_rf_freq_range().clip(value); + + std::lock_guard<spi_lock> lock(*spi_l); return device.tune(dir, clipped_value); } virtual double get_freq(const std::string &which) { auto dir = _get_direction_from_antenna(which); + + std::lock_guard<spi_lock> lock(*spi_l); return device.get_freq(dir); } virtual void set_fir(const std::string &which, int8_t gain, const std::vector<int16_t> & fir) { + auto dir = _get_direction_from_antenna(which); + auto chain = _get_chain_from_antenna(which); + auto lengths = _get_valid_fir_lengths(which); if (std::find(lengths.begin(), lengths.end(), fir.size()) == lengths.end()) { - throw uhd::value_error("ad937x_ctrl::set_fir got filter of invalid length"); + throw uhd::value_error("invalid filter length"); } - ad937x_fir(gain, fir); - - } - virtual std::vector<int16_t> get_fir(const std::string &which) = 0; - - virtual int16_t get_temperature() = 0; - -private: - ad937x_device device; - spi_lock::sptr spi_l; - mpm::spi_iface::sptr iface; -}; - -const double ad937x_ctrl_impl::MIN_FREQ = 300e6; -const double ad937x_ctrl_impl::MAX_FREQ = 6e9; - -/* -ad937x_ctrl::sptr ad937x_ctrl_impl::make( - spi_lock::sptr spi_l, - mpm::spi_iface::sptr iface) -{ - return std::make_shared<ad937x_ctrl_impl>(spi_l, iface); -} - - -void ad937x_ctrl::initialize() -{ - //headlessinit(mykonos_config.device); - // TODO: finish initialization - { - std::lock_guard<spi_lock> lock(*spi_l); - call_api_function(std::bind(MYKONOS_initialize, mykonos_config.device)); - } - get_product_id(); -} - -ad937x_ctrl::ad937x_ctrl( - spi_lock::sptr spi_l, - mpm::spi_iface::sptr iface) : - spi_l(spi_l), - iface(iface) -{ - mpm_sps.spi_iface = iface.get(); - - //TODO assert iface->get_chip_select() is 1-8 - mpm_sps.spi_settings.chipSelectIndex = static_cast<uint8_t>(iface->get_chip_select()); - mpm_sps.spi_settings.writeBitPolarity = 1; - mpm_sps.spi_settings.longInstructionWord = 1; // set to 1 by initialize - mpm_sps.spi_settings.MSBFirst = - (iface->get_endianness() == mpm::spi_iface::spi_endianness_t::LSB_FIRST) ? 0 : 1; - mpm_sps.spi_settings.CPHA = 0; // set to 0 by initialize - mpm_sps.spi_settings.CPOL = 0; // set to 0 by initialize - mpm_sps.spi_settings.enSpiStreaming = 1; - mpm_sps.spi_settings.autoIncAddrUp = 1; - mpm_sps.spi_settings.fourWireMode = - (iface->get_wire_mode() == mpm::spi_iface::spi_wire_mode_t::THREE_WIRE_MODE) ? 0 : 1; - mpm_sps.spi_settings.spiClkFreq_Hz = 25000000; - - initialize(); -} - -// helper function to unify error handling -// bind is bad, but maybe this is justifiable -void ad937x_ctrl::call_api_function(std::function<mykonosErr_t()> func) -{ - auto error = func(); - if (error != MYKONOS_ERR_OK) - { - std::cout << getMykonosErrorMessage(error); - // TODO: make UHD exception - //throw std::exception(getMykonosErrorMessage(error)); - } -} - -uint8_t ad937x_ctrl::get_product_id() -{ - std::lock_guard<spi_lock> lock(*spi_l); - uint8_t id; - call_api_function(std::bind(MYKONOS_getProductId, mykonos_config.device, &id)); - return id; -} - -double ad937x_ctrl::set_clock_rate(const double req_rate) -{ - auto rate = static_cast<decltype(mykonos_config.device->clocks->deviceClock_kHz)>(req_rate / 1000); - mykonos_config.device->clocks->deviceClock_kHz = rate; - { - std::lock_guard<spi_lock> lock(*spi_l); - call_api_function(std::bind(MYKONOS_initDigitalClocks, mykonos_config.device)); - } - return static_cast<decltype(set_clock_rate(0))>(rate); -} - -void ad937x_ctrl::_set_active_tx_chains(bool tx1, bool tx2) -{ - decltype(mykonos_config.device->tx->txChannels) newTxChannel; - if (tx1 && tx2) - { - newTxChannel = TX1_TX2; - } - else if (tx1) { - newTxChannel = TX1; - } - else if (tx2) { - newTxChannel = TX2; - } - else { - newTxChannel = TXOFF; - } - mykonos_config.device->tx->txChannels = newTxChannel; -} - -void ad937x_ctrl::_set_active_rx_chains(bool rx1, bool rx2) -{ - decltype(mykonos_config.device->rx->rxChannels) newRxChannel; - if (rx1 && rx2) - { - newRxChannel = RX1_RX2; - } - else if (rx1) { - newRxChannel = RX1; - } - else if (rx2) { - newRxChannel = RX2; - } - else { - newRxChannel = RXOFF; - } - mykonos_config.device->rx->rxChannels = newRxChannel; -} - -void ad937x_ctrl::set_active_chains(direction_t direction, bool channel1, bool channel2) -{ - switch (direction) - { - case TX: _set_active_tx_chains(channel1, channel2); break; - case RX: _set_active_rx_chains(channel1, channel2); break; - default: - // TODO: bad code path exception - throw std::exception(); - } - // TODO: make this apply the setting -} - -double ad937x_ctrl::tune(direction_t direction, const double value) -{ - // I'm not really sure why we set the PLL value in the config AND as a function parameter - // but here it is - - mykonosRfPllName_t pll; - uint64_t integer_value = static_cast<uint64_t>(value); - switch (direction) - { - case TX: - pll = TX_PLL; - mykonos_config.device->tx->txPllLoFrequency_Hz = integer_value; - break; - case RX: - pll = RX_PLL; - mykonos_config.device->rx->rxPllLoFrequency_Hz = integer_value; - break; - default: - // TODO: bad code path exception - throw std::exception(); - } - - { - std::lock_guard<spi_lock> lock(*spi_l); - call_api_function(std::bind(MYKONOS_setRfPllFrequency, mykonos_config.device, pll, integer_value)); - } - - // TODO: coercion here causes extra device accesses, when the formula is provided on pg 119 of the user guide - // Furthermore, because coerced is returned as an integer, it's not even accurate - uint64_t coerced_pll; - { std::lock_guard<spi_lock> lock(*spi_l); - call_api_function(std::bind(MYKONOS_getRfPllFrequency, mykonos_config.device, pll, &coerced_pll)); + device.set_fir(dir, chain, gain, fir); } - return static_cast<double>(coerced_pll); -} -double ad937x_ctrl::get_freq(direction_t direction) -{ - mykonosRfPllName_t pll; - switch (direction) + std::vector<int16_t> get_fir(const std::string &which, int8_t &gain) { - case TX: pll = TX_PLL; break; - case RX: pll = RX_PLL; break; - default: - // TODO: bad code path exception - throw std::exception(); - } + auto dir = _get_direction_from_antenna(which); + auto chain = _get_chain_from_antenna(which); - // TODO: coercion here causes extra device accesses, when the formula is provided on pg 119 of the user guide - // Furthermore, because coerced is returned as an integer, it's not even accurate - uint64_t coerced_pll; - { std::lock_guard<spi_lock> lock(*spi_l); - call_api_function(std::bind(MYKONOS_getRfPllFrequency, mykonos_config.device, pll, &coerced_pll)); + return device.get_fir(dir, chain, gain); } - return static_cast<double>(coerced_pll); - return double(); -} - -// RX Gain values are table entries given in mykonos_user.h -// An array of gain values is programmed at initialization, which the API will then use for its gain values -// In general, Gain Value = (255 - Gain Table Index) -uint8_t ad937x_ctrl::_convert_rx_gain(double inGain, double &coercedGain) -{ - // TODO: use uhd::meta_range? - const static double min_gain = 0; - const static double max_gain = 30; - const static double gain_step = 0.5; - coercedGain = inGain; - if (coercedGain < min_gain) + virtual int16_t get_temperature() { - coercedGain = min_gain; - } - if (coercedGain > max_gain) - { - coercedGain = max_gain; - } - - // round to nearest step - coercedGain = std::round(coercedGain * (1.0 / gain_step)) / (1.0 / gain_step); - - // gain should be a value 0-60, add 195 to make 195-255 - return static_cast<uint8_t>((coercedGain * 2) + 195); -} - -// TX gain is completely different from RX gain for no good reason so deal with it -// TX is set as attenuation using a value from 0-41950 mdB -// Only increments of 50 mdB are valid -uint16_t ad937x_ctrl::_convert_tx_gain(double inGain, double &coercedGain) -{ - // TODO: use uhd::meta_range? - const static double min_gain = 0; - const static double max_gain = 41.95; - const static double gain_step = 0.05; - - coercedGain = inGain; - if (coercedGain < min_gain) - { - coercedGain = min_gain; - } - if (coercedGain > max_gain) - { - coercedGain = max_gain; - } - - coercedGain = std::round(coercedGain * (1.0 / gain_step)) / (1.0 / gain_step); - - // attenuation is inverted and in mdB not dB - return static_cast<uint16_t>((max_gain - (coercedGain)) * 1000); -} - - -double ad937x_ctrl::set_gain(direction_t direction, chain_t chain, const double value) -{ - double coerced_value; - switch (direction) - { - case TX: - { - uint16_t attenuation = _convert_tx_gain(value, coerced_value); - std::function<mykonosErr_t(mykonosDevice_t*, uint16_t)> func; - switch (chain) - { - case CHAIN_1: - func = MYKONOS_setTx1Attenuation; - break; - case CHAIN_2: - func = MYKONOS_setTx2Attenuation; - break; - default: - // TODO: bad code path exception - throw std::exception(); - } std::lock_guard<spi_lock> lock(*spi_l); - call_api_function(std::bind(func, mykonos_config.device, attenuation)); - break; + return device.get_temperature(); } - case RX: - { - uint8_t gain = _convert_rx_gain(value, coerced_value); - std::function<mykonosErr_t(mykonosDevice_t*, uint8_t)> func; - switch (chain) - { - case CHAIN_1: - func = MYKONOS_setRx1ManualGain; - break; - case CHAIN_2: - func = MYKONOS_setRx2ManualGain; - break; - default: - // TODO: bad code path exception - throw std::exception(); - } - std::lock_guard<spi_lock> lock(*spi_l); - call_api_function(std::bind(func, mykonos_config.device, gain)); - break; - } - default: - // TODO: bad code path exception - throw std::exception(); - } - return coerced_value; -} + +private: + ad937x_device device; + spi_lock::sptr spi_l; +}; -double ad937x_ctrl::set_agc_mode(direction_t direction, chain_t chain, gain_mode_t mode) +ad937x_ctrl::sptr ad937x_ctrl::make(spi_lock::sptr spi_l, uhd::spi_iface::sptr iface) { - std::lock_guard<spi_lock> lock(*spi_l); - switch (direction) - { - case RX: - switch (mode) - { - case GAIN_MODE_MANUAL: - call_api_function(std::bind(MYKONOS_resetRxAgc, mykonos_config.device)); - break; - case GAIN_MODE_SLOW_AGC: - case GAIN_MODE_FAST_AGC: - // TODO: differentiate these - call_api_function(std::bind(MYKONOS_setupRxAgc, mykonos_config.device)); - break; - default: - // TODO: bad code path exception - throw std::exception(); - } - default: - // TODO: bad code path exception - throw std::exception(); - } - return double(); + return std::make_shared<ad937x_ctrl_impl>(spi_l, iface); } -ad937x_ctrl::sptr ad937x_ctrl::make(spi_lock::sptr spi_l, mpm::spi_iface::sptr iface) -{ - return std::make_shared<ad937x_ctrl>(spi_l, iface); -} -*/ diff --git a/mpm/lib/mykonos/ad937x_ctrl.hpp b/mpm/lib/mykonos/ad937x_ctrl.hpp index 6d36bdf05..213a146b4 100644 --- a/mpm/lib/mykonos/ad937x_ctrl.hpp +++ b/mpm/lib/mykonos/ad937x_ctrl.hpp @@ -1,41 +1,46 @@ +// +// Copyright 2017 Ettus Research (National Instruments) +// +// 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/>. +// + #pragma once +#include "ad937x_device.hpp" +#include "../spi/spi_lock.h" + // TODO: fix path of UHD includes #include <../../host/include/uhd/types/direction.hpp> #include <../../host/include/uhd/types/ranges.hpp> #include <../../host/include/uhd/exception.hpp> +#include <../../host/include/uhd/types/serial.hpp> -#include "config/ad937x_fir.h" -#include "adi/t_mykonos.h" -#include "../spi/spi_lock.h" -#include "../spi/spi_config.h" -#include <mpm/spi_iface.hpp> -#include <mpm/spi/adi_ctrl.hpp> #include <boost/noncopyable.hpp> +#include <memory> #include <functional> - -struct ad937x_api_version_t { - uint32_t silicon_ver; - uint32_t major_ver; - uint32_t minor_ver; - uint32_t build_ver; -}; - -struct ad937x_arm_version_t { - uint32_t major_ver; - uint32_t minor_ver; - uint32_t rc_ver; -}; +#include <set> class ad937x_ctrl : public boost::noncopyable { public: typedef std::shared_ptr<ad937x_ctrl> sptr; + static sptr make(spi_lock::sptr spi_l, uhd::spi_iface::sptr iface); virtual ~ad937x_ctrl(void) {}; static uhd::meta_range_t get_rf_freq_range(void); static uhd::meta_range_t get_bw_filter_range(void); - static std::vector<double> get_clock_rates(void); + static std::set<double> get_clock_rates(void); static uhd::meta_range_t get_gain_range(const std::string &which); virtual uint8_t get_product_id() = 0; @@ -43,20 +48,19 @@ public: virtual std::string get_api_version() = 0; virtual std::string get_arm_version() = 0; - virtual double set_bw_filter(const std::string &which, const double value) = 0; - virtual double set_gain(const std::string &which, const double value) = 0; + virtual double set_bw_filter(const std::string &which, double value) = 0; + virtual double set_gain(const std::string &which, double value) = 0; - virtual void set_agc(const std::string &which, const bool enable) = 0; virtual void set_agc_mode(const std::string &which, const std::string &mode) = 0; - virtual double set_clock_rate(const double value) = 0; - virtual void enable_channel(const std::string &which, const bool enable) = 0; + virtual double set_clock_rate(double value) = 0; + virtual void enable_channel(const std::string &which, bool enable) = 0; - virtual double set_freq(const std::string &which, const double value) = 0; + virtual double set_freq(const std::string &which, double value) = 0; virtual double get_freq(const std::string &which) = 0; - virtual void set_fir(const std::string &which, const std::vector<int16_t> & fir) = 0; - virtual std::vector<int16_t> get_fir(const std::string &which) = 0; + virtual void set_fir(const std::string &which, int8_t gain, const std::vector<int16_t> & fir) = 0; + virtual std::vector<int16_t> get_fir(const std::string &which, int8_t &gain) = 0; virtual int16_t get_temperature() = 0; @@ -64,5 +68,5 @@ protected: static uhd::direction_t _get_direction_from_antenna(const std::string& antenna); static ad937x_device::chain_t _get_chain_from_antenna(const std::string& antenna); - static std::vector<size_t> _get_valid_fir_lengths(const std::string& which); + static std::set<size_t> _get_valid_fir_lengths(const std::string& which); };
\ No newline at end of file diff --git a/mpm/lib/mykonos/ad937x_device.cpp b/mpm/lib/mykonos/ad937x_device.cpp index 305ef2965..62725f219 100644 --- a/mpm/lib/mykonos/ad937x_device.cpp +++ b/mpm/lib/mykonos/ad937x_device.cpp @@ -1,58 +1,90 @@ -#include "adi/mykonos.h" +// +// Copyright 2017 Ettus Research (National Instruments) +// +// 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 "ad937x_device.hpp" +#include "adi/mykonos.h" +#include "adi/mykonos_gpio.h" + #include <functional> #include <iostream> -#include <cmath> - -/* -ad937x_ctrl::sptr ad937x_ctrl_impl::make( - spi_lock::sptr spi_l, - mpm::spi_iface::sptr iface) -{ - return std::make_shared<ad937x_ctrl_impl>(spi_l, iface); -} - - -void ad937x_ctrl::initialize() -{ - //headlessinit(mykonos_config.device); - // TODO: finish initialization - { - std::lock_guard<spi_lock> lock(*spi_l); - call_api_function(std::bind(MYKONOS_initialize, mykonos_config.device)); - } - get_product_id(); -} -ad937x_ctrl::ad937x_ctrl( - spi_lock::sptr spi_l, - mpm::spi_iface::sptr iface) : - spi_l(spi_l), - iface(iface) -{ - mpm_sps.spi_iface = iface.get(); - - //TODO assert iface->get_chip_select() is 1-8 - mpm_sps.spi_settings.chipSelectIndex = static_cast<uint8_t>(iface->get_chip_select()); - mpm_sps.spi_settings.writeBitPolarity = 1; - mpm_sps.spi_settings.longInstructionWord = 1; // set to 1 by initialize - mpm_sps.spi_settings.MSBFirst = - (iface->get_endianness() == mpm::spi_iface::spi_endianness_t::LSB_FIRST) ? 0 : 1; - mpm_sps.spi_settings.CPHA = 0; // set to 0 by initialize - mpm_sps.spi_settings.CPOL = 0; // set to 0 by initialize - mpm_sps.spi_settings.enSpiStreaming = 1; - mpm_sps.spi_settings.autoIncAddrUp = 1; - mpm_sps.spi_settings.fourWireMode = - (iface->get_wire_mode() == mpm::spi_iface::spi_wire_mode_t::THREE_WIRE_MODE) ? 0 : 1; - mpm_sps.spi_settings.spiClkFreq_Hz = 25000000; - - initialize(); -} +const double ad937x_device::MIN_FREQ = 300e6; +const double ad937x_device::MAX_FREQ = 6e9; +const double ad937x_device::MIN_RX_GAIN = 0.0; +const double ad937x_device::MAX_RX_GAIN = 30.0; +const double ad937x_device::RX_GAIN_STEP = 0.5; +const double ad937x_device::MIN_TX_GAIN = 0.0; +const double ad937x_device::MAX_TX_GAIN = 41.95; +const double ad937x_device::TX_GAIN_STEP = 0.05; + +static const double RX_DEFAULT_FREQ = 1e9; +static const double TX_DEFAULT_FREQ = 1e9; + +// TODO: get the actual device ID +static const uint32_t AD9371_PRODUCT_ID = 0x1F; + +// TODO: move this to whereever we declare the ARM binary +static const size_t ARM_BINARY_SIZE = 98304; + +static const uint32_t INIT_CAL_TIMEOUT_MS = 10000; + +static const uint32_t INIT_CALS = + TX_BB_FILTER | + ADC_TUNER | + TIA_3DB_CORNER | + DC_OFFSET | + TX_ATTENUATION_DELAY | + RX_GAIN_DELAY | + FLASH_CAL | + PATH_DELAY | + TX_LO_LEAKAGE_INTERNAL | +// TX_LO_LEAKAGE_EXTERNAL | + TX_QEC_INIT | + LOOPBACK_RX_LO_DELAY | + LOOPBACK_RX_RX_QEC_INIT | + RX_LO_DELAY | + RX_QEC_INIT | +// DPD_INIT | +// CLGC_INIT | +// VSWR_INIT | + 0; + +static const uint32_t TRACKING_CALS = + TRACK_RX1_QEC | + TRACK_RX2_QEC | + TRACK_ORX1_QEC | + TRACK_ORX2_QEC | +// TRACK_TX1_LOL | +// TRACK_TX2_LOL | + TRACK_TX1_QEC | + TRACK_TX2_QEC | +// TRACK_TX1_DPD | +// TRACK_TX2_DPD | +// TRACK_TX1_CLGC | +// TRACK_TX2_CLGC | +// TRACK_TX1_VSWR | +// TRACK_TX2_VSWR | +// TRACK_ORX1_QEC_SNLO | +// TRACK_ORX2_QEC_SNLO | +// TRACK_SRX_QEC | + 0; // helper function to unify error handling -// bind is bad, but maybe this is justifiable -void ad937x_ctrl::call_api_function(std::function<mykonosErr_t()> func) +void ad937x_device::_call_api_function(std::function<mykonosErr_t()> func) { auto error = func(); if (error != MYKONOS_ERR_OK) @@ -63,272 +95,422 @@ void ad937x_ctrl::call_api_function(std::function<mykonosErr_t()> func) } } -uint8_t ad937x_ctrl::get_product_id() +// helper function to unify error handling, GPIO version +void ad937x_device::_call_gpio_api_function(std::function<mykonosGpioErr_t()> func) { - std::lock_guard<spi_lock> lock(*spi_l); - uint8_t id; - call_api_function(std::bind(MYKONOS_getProductId, mykonos_config.device, &id)); - return id; -} - -double ad937x_ctrl::set_clock_rate(const double req_rate) -{ - auto rate = static_cast<decltype(mykonos_config.device->clocks->deviceClock_kHz)>(req_rate / 1000); - mykonos_config.device->clocks->deviceClock_kHz = rate; + auto error = func(); + if (error != MYKONOS_ERR_GPIO_OK) { - std::lock_guard<spi_lock> lock(*spi_l); - call_api_function(std::bind(MYKONOS_initDigitalClocks, mykonos_config.device)); + std::cout << getGpioMykonosErrorMessage(error); + // TODO: make UHD exception + //throw std::exception(getMykonosErrorMessage(error)); } - return static_cast<decltype(set_clock_rate(0))>(rate); } -void ad937x_ctrl::_set_active_tx_chains(bool tx1, bool tx2) +void ad937x_device::_initialize() { - decltype(mykonos_config.device->tx->txChannels) newTxChannel; - if (tx1 && tx2) + _call_api_function(std::bind(MYKONOS_resetDevice, mykonos_config.device)); + + if (get_product_id() != AD9371_PRODUCT_ID) { - newTxChannel = TX1_TX2; + throw uhd::runtime_error("AD9371 product ID does not match expected ID!"); } - else if (tx1) { - newTxChannel = TX1; + + _call_api_function(std::bind(MYKONOS_initialize, mykonos_config.device)); + + if (!get_pll_lock_status(pll_t::CLK_SYNTH)) + { + throw uhd::runtime_error("AD937x CLK_SYNTH PLL failed to lock in initialize()"); } - else if (tx2) { - newTxChannel = TX2; + + std::vector<uint8_t> binary(98304, 0); + _load_arm(binary); + + tune(uhd::RX_DIRECTION, RX_DEFAULT_FREQ); + tune(uhd::TX_DIRECTION, TX_DEFAULT_FREQ); + + // TODO: wait 200ms or change to polling + if (!get_pll_lock_status(pll_t::RX_SYNTH)) + { + throw uhd::runtime_error("AD937x RX PLL failed to lock in initialize()"); } - else { - newTxChannel = TXOFF; + if (!get_pll_lock_status(pll_t::TX_SYNTH)) + { + throw uhd::runtime_error("AD937x TX PLL failed to lock in initialize()"); } - mykonos_config.device->tx->txChannels = newTxChannel; + + // TODO: ADD GPIO CTRL setup here + + set_gain(uhd::RX_DIRECTION, chain_t::ONE, 0); + set_gain(uhd::RX_DIRECTION, chain_t::TWO, 0); + set_gain(uhd::TX_DIRECTION, chain_t::ONE, 0); + set_gain(uhd::TX_DIRECTION, chain_t::TWO, 0); + + _run_initialization_calibrations(); + + // TODO: do external LO leakage calibration here if hardware supports it + // I don't think we do? + + _start_jesd(); + _enable_tracking_calibrations(); + + // radio is ON! + _call_api_function(std::bind(MYKONOS_radioOn, mykonos_config.device)); + + // TODO: ordering of this doesn't seem right, intuitively, verify this works + _call_api_function(std::bind(MYKONOS_setObsRxPathSource, mykonos_config.device, OBS_RXOFF)); + _call_api_function(std::bind(MYKONOS_setObsRxPathSource, mykonos_config.device, OBS_INTERNALCALS)); } -void ad937x_ctrl::_set_active_rx_chains(bool rx1, bool rx2) +// TODO: review const-ness in this function with respect to ADI API +void ad937x_device::_load_arm(std::vector<uint8_t> & binary) { - decltype(mykonos_config.device->rx->rxChannels) newRxChannel; - if (rx1 && rx2) + _call_api_function(std::bind(MYKONOS_initArm, mykonos_config.device)); + + if (binary.size() == ARM_BINARY_SIZE) { - newRxChannel = RX1_RX2; - } - else if (rx1) { - newRxChannel = RX1; - } - else if (rx2) { - newRxChannel = RX2; - } - else { - newRxChannel = RXOFF; + throw uhd::runtime_error("ad937x_device ARM is not the correct size!"); } - mykonos_config.device->rx->rxChannels = newRxChannel; + + _call_api_function(std::bind(MYKONOS_loadArmFromBinary, mykonos_config.device, &binary[0], binary.size())); } -void ad937x_ctrl::set_active_chains(direction_t direction, bool channel1, bool channel2) +void ad937x_device::_run_initialization_calibrations() { - switch (direction) + _call_api_function(std::bind(MYKONOS_runInitCals, mykonos_config.device, INIT_CALS)); + + uint8_t errorFlag = 0; + uint8_t errorCode = 0; + _call_api_function( + std::bind(MYKONOS_waitInitCals, + mykonos_config.device, + INIT_CAL_TIMEOUT_MS, + &errorFlag, + &errorCode)); + + if ((errorFlag != 0) || (errorCode != 0)) { - case TX: _set_active_tx_chains(channel1, channel2); break; - case RX: _set_active_rx_chains(channel1, channel2); break; - default: - // TODO: bad code path exception - throw std::exception(); + mykonosInitCalStatus_t initCalStatus = { 0 }; + _call_api_function(std::bind(MYKONOS_getInitCalStatus, mykonos_config.device, &initCalStatus)); + + // abort init cals + uint32_t initCalsCompleted = 0; + _call_api_function(std::bind(MYKONOS_abortInitCals, mykonos_config.device, &initCalsCompleted)); + // init cals completed contains mask of cals that did finish + + uint16_t errorWord = 0; + uint16_t statusWord = 0; + _call_api_function(std::bind(MYKONOS_readArmCmdStatus, mykonos_config.device, &errorWord, &statusWord)); + + uint8_t status = 0; + _call_api_function(std::bind(MYKONOS_readArmCmdStatusByte, mykonos_config.device, 2, &status)); } - // TODO: make this apply the setting } -double ad937x_ctrl::tune(direction_t direction, const double value) +void ad937x_device::_start_jesd() +{ + // Stop and/or disable SYSREF + // ensure BBIC JESD is reset and ready to recieve CGS characters + + // prepare to transmit CGS when sysref starts + _call_api_function(std::bind(MYKONOS_enableSysrefToRxFramer, mykonos_config.device, 1)); + + // prepare to transmit CGS when sysref starts + //_call_api_function(std::bind(MYKONOS_enableSysrefToObsRxFramer, mykonos_config.device, 1)); + + // prepare to transmit CGS when sysref starts + _call_api_function(std::bind(MYKONOS_enableSysrefToDeframer, mykonos_config.device, 0)); + + _call_api_function(std::bind(MYKONOS_resetDeframer, mykonos_config.device)); + _call_api_function(std::bind(MYKONOS_enableSysrefToDeframer, mykonos_config.device, 1)); + + // make sure BBIC JESD framer is actively transmitting CGS + // Start SYSREF + + // verify sync code here + // verify links + uint8_t framerStatus = 0; + _call_api_function(std::bind(MYKONOS_readRxFramerStatus, mykonos_config.device, &framerStatus)); + + uint8_t deframerStatus = 0; + _call_api_function(std::bind(MYKONOS_readDeframerStatus, mykonos_config.device, &deframerStatus)); +} + +void ad937x_device::_enable_tracking_calibrations() +{ + _call_api_function(std::bind(MYKONOS_enableTrackingCals, mykonos_config.device, TRACKING_CALS)); +} + +ad937x_device::ad937x_device(uhd::spi_iface::sptr iface) : + full_spi_settings(iface), + mykonos_config(&full_spi_settings.spi_settings) +{ + _initialize(); +} + +uint8_t ad937x_device::get_product_id() +{ + uint8_t id; + _call_api_function(std::bind(MYKONOS_getProductId, mykonos_config.device, &id)); + return id; +} + +uint8_t ad937x_device::get_device_rev() +{ + uint8_t rev; + _call_api_function(std::bind(MYKONOS_getDeviceRev, mykonos_config.device, &rev)); + return rev; +} + +ad937x_device::api_version_t ad937x_device::get_api_version() { - // I'm not really sure why we set the PLL value in the config AND as a function parameter + api_version_t api; + _call_api_function(std::bind(MYKONOS_getApiVersion, + mykonos_config.device, + &api.silicon_ver, + &api.major_ver, + &api.minor_ver, + &api.build_ver)); + return api; +} + +ad937x_device::arm_version_t ad937x_device::get_arm_version() +{ + arm_version_t arm; + _call_api_function(std::bind(MYKONOS_getArmVersion, + mykonos_config.device, + &arm.major_ver, + &arm.minor_ver, + &arm.rc_ver)); + return arm; +} + +double ad937x_device::set_clock_rate(double req_rate) +{ + auto rate = static_cast<uint32_t>(req_rate / 1000.0); + mykonos_config.device->clocks->deviceClock_kHz = rate; + _call_api_function(std::bind(MYKONOS_initDigitalClocks, mykonos_config.device)); + return static_cast<double>(rate); +} + +void ad937x_device::enable_channel(uhd::direction_t direction, chain_t chain, bool enable) +{ + // TODO: + // Turns out the only code in the API that actually sets the channel enable settings + // _initialize(). Need to figure out how to deal with this. +} + +double ad937x_device::tune(uhd::direction_t direction, double value) +{ + // I'm not sure why we set the PLL value in the config AND as a function parameter // but here it is mykonosRfPllName_t pll; uint64_t integer_value = static_cast<uint64_t>(value); switch (direction) { - case TX: + case uhd::TX_DIRECTION: pll = TX_PLL; mykonos_config.device->tx->txPllLoFrequency_Hz = integer_value; break; - case RX: + case uhd::RX_DIRECTION: pll = RX_PLL; mykonos_config.device->rx->rxPllLoFrequency_Hz = integer_value; break; default: - // TODO: bad code path exception - throw std::exception(); + UHD_THROW_INVALID_CODE_PATH(); } - { - std::lock_guard<spi_lock> lock(*spi_l); - call_api_function(std::bind(MYKONOS_setRfPllFrequency, mykonos_config.device, pll, integer_value)); - } + _call_api_function(std::bind(MYKONOS_setRfPllFrequency, mykonos_config.device, pll, integer_value)); // TODO: coercion here causes extra device accesses, when the formula is provided on pg 119 of the user guide // Furthermore, because coerced is returned as an integer, it's not even accurate uint64_t coerced_pll; - { - std::lock_guard<spi_lock> lock(*spi_l); - call_api_function(std::bind(MYKONOS_getRfPllFrequency, mykonos_config.device, pll, &coerced_pll)); - } + _call_api_function(std::bind(MYKONOS_getRfPllFrequency, mykonos_config.device, pll, &coerced_pll)); return static_cast<double>(coerced_pll); } -double ad937x_ctrl::get_freq(direction_t direction) +double ad937x_device::get_freq(uhd::direction_t direction) { mykonosRfPllName_t pll; switch (direction) { - case TX: pll = TX_PLL; break; - case RX: pll = RX_PLL; break; + case uhd::TX_DIRECTION: pll = TX_PLL; break; + case uhd::RX_DIRECTION: pll = RX_PLL; break; default: - // TODO: bad code path exception - throw std::exception(); + UHD_THROW_INVALID_CODE_PATH(); } // TODO: coercion here causes extra device accesses, when the formula is provided on pg 119 of the user guide // Furthermore, because coerced is returned as an integer, it's not even accurate uint64_t coerced_pll; + _call_api_function(std::bind(MYKONOS_getRfPllFrequency, mykonos_config.device, pll, &coerced_pll)); + return static_cast<double>(coerced_pll); +} + +bool ad937x_device::get_pll_lock_status(pll_t pll) +{ + uint8_t pll_status; + _call_api_function(std::bind(MYKONOS_checkPllsLockStatus, mykonos_config.device, &pll_status)); + switch (pll) { - std::lock_guard<spi_lock> lock(*spi_l); - call_api_function(std::bind(MYKONOS_getRfPllFrequency, mykonos_config.device, pll, &coerced_pll)); + case pll_t::CLK_SYNTH: + return (pll_status & 0x01) ? 1 : 0; + case pll_t::RX_SYNTH: + return (pll_status & 0x02) ? 1 : 0; + case pll_t::TX_SYNTH: + return (pll_status & 0x04) ? 1 : 0; + case pll_t::SNIFF_SYNTH: + return (pll_status & 0x08) ? 1 : 0; + case pll_t::CALPLL_SDM: + return (pll_status & 0x10) ? 1 : 0; + default: + UHD_THROW_INVALID_CODE_PATH(); + return false; } - return static_cast<double>(coerced_pll); +} + +double ad937x_device::set_bw_filter(uhd::direction_t direction, chain_t chain, double value) +{ + // TODO: implement return double(); } // RX Gain values are table entries given in mykonos_user.h // An array of gain values is programmed at initialization, which the API will then use for its gain values // In general, Gain Value = (255 - Gain Table Index) -uint8_t ad937x_ctrl::_convert_rx_gain(double inGain, double &coercedGain) +uint8_t ad937x_device::_convert_rx_gain(double gain) { - // TODO: use uhd::meta_range? - const static double min_gain = 0; - const static double max_gain = 30; - const static double gain_step = 0.5; - - coercedGain = inGain; - if (coercedGain < min_gain) - { - coercedGain = min_gain; - } - if (coercedGain > max_gain) - { - coercedGain = max_gain; - } - - // round to nearest step - coercedGain = std::round(coercedGain * (1.0 / gain_step)) / (1.0 / gain_step); - // gain should be a value 0-60, add 195 to make 195-255 - return static_cast<uint8_t>((coercedGain * 2) + 195); + return static_cast<uint8_t>((gain * 2) + 195); } // TX gain is completely different from RX gain for no good reason so deal with it // TX is set as attenuation using a value from 0-41950 mdB // Only increments of 50 mdB are valid -uint16_t ad937x_ctrl::_convert_tx_gain(double inGain, double &coercedGain) +uint16_t ad937x_device::_convert_tx_gain(double gain) { - // TODO: use uhd::meta_range? - const static double min_gain = 0; - const static double max_gain = 41.95; - const static double gain_step = 0.05; - - coercedGain = inGain; - if (coercedGain < min_gain) - { - coercedGain = min_gain; - } - if (coercedGain > max_gain) - { - coercedGain = max_gain; - } - - coercedGain = std::round(coercedGain * (1.0 / gain_step)) / (1.0 / gain_step); - // attenuation is inverted and in mdB not dB - return static_cast<uint16_t>((max_gain - (coercedGain)) * 1000); + return static_cast<uint16_t>((MAX_TX_GAIN - (gain)) * 1e3); } -double ad937x_ctrl::set_gain(direction_t direction, chain_t chain, const double value) +double ad937x_device::set_gain(uhd::direction_t direction, chain_t chain, double value) { double coerced_value; switch (direction) { - case TX: + case uhd::TX_DIRECTION: { - uint16_t attenuation = _convert_tx_gain(value, coerced_value); + uint16_t attenuation = _convert_tx_gain(value); + coerced_value = static_cast<double>(attenuation); + std::function<mykonosErr_t(mykonosDevice_t*, uint16_t)> func; switch (chain) { - case CHAIN_1: + case chain_t::ONE: func = MYKONOS_setTx1Attenuation; break; - case CHAIN_2: + case chain_t::TWO: func = MYKONOS_setTx2Attenuation; break; default: - // TODO: bad code path exception - throw std::exception(); + UHD_THROW_INVALID_CODE_PATH(); } - std::lock_guard<spi_lock> lock(*spi_l); - call_api_function(std::bind(func, mykonos_config.device, attenuation)); + _call_api_function(std::bind(func, mykonos_config.device, attenuation)); break; } - case RX: + case uhd::RX_DIRECTION: { - uint8_t gain = _convert_rx_gain(value, coerced_value); + uint8_t gain = _convert_rx_gain(value); + coerced_value = static_cast<double>(gain); + std::function<mykonosErr_t(mykonosDevice_t*, uint8_t)> func; switch (chain) { - case CHAIN_1: + case chain_t::ONE: func = MYKONOS_setRx1ManualGain; break; - case CHAIN_2: + case chain_t::TWO: func = MYKONOS_setRx2ManualGain; break; default: - // TODO: bad code path exception - throw std::exception(); + UHD_THROW_INVALID_CODE_PATH(); } - std::lock_guard<spi_lock> lock(*spi_l); - call_api_function(std::bind(func, mykonos_config.device, gain)); + _call_api_function(std::bind(func, mykonos_config.device, gain)); break; } default: - // TODO: bad code path exception - throw std::exception(); + UHD_THROW_INVALID_CODE_PATH(); } return coerced_value; } -double ad937x_ctrl::set_agc_mode(direction_t direction, chain_t chain, gain_mode_t mode) +void ad937x_device::set_agc_mode(uhd::direction_t direction, gain_mode_t mode) { - std::lock_guard<spi_lock> lock(*spi_l); switch (direction) { - case RX: + case uhd::RX_DIRECTION: switch (mode) { - case GAIN_MODE_MANUAL: - call_api_function(std::bind(MYKONOS_resetRxAgc, mykonos_config.device)); + case gain_mode_t::MANUAL: + _call_api_function(std::bind(MYKONOS_setRxGainControlMode, mykonos_config.device, MGC)); + break; + case gain_mode_t::AUTOMATIC: + _call_api_function(std::bind(MYKONOS_setRxGainControlMode, mykonos_config.device, AGC)); break; - case GAIN_MODE_SLOW_AGC: - case GAIN_MODE_FAST_AGC: - // TODO: differentiate these - call_api_function(std::bind(MYKONOS_setupRxAgc, mykonos_config.device)); + case gain_mode_t::HYBRID: + _call_api_function(std::bind(MYKONOS_setRxGainControlMode, mykonos_config.device, HYBRID)); break; default: - // TODO: bad code path exception - throw std::exception(); + UHD_THROW_INVALID_CODE_PATH(); } default: - // TODO: bad code path exception - throw std::exception(); + UHD_THROW_INVALID_CODE_PATH(); + } +} + +void ad937x_device::set_fir( + const uhd::direction_t direction, + const chain_t chain, + int8_t gain, + const std::vector<int16_t> & fir) +{ + switch (direction) + { + case uhd::TX_DIRECTION: + mykonos_config.tx_fir_config.set_fir(gain, fir); + break; + case uhd::RX_DIRECTION: + mykonos_config.rx_fir_config.set_fir(gain, fir); + break; + default: + UHD_THROW_INVALID_CODE_PATH(); } - return double(); } -ad937x_ctrl::sptr ad937x_ctrl::make(spi_lock::sptr spi_l, mpm::spi_iface::sptr iface) +std::vector<int16_t> ad937x_device::get_fir( + const uhd::direction_t direction, + const chain_t chain, + int8_t &gain) { - return std::make_shared<ad937x_ctrl>(spi_l, iface); + switch (direction) + { + case uhd::TX_DIRECTION: + return mykonos_config.tx_fir_config.get_fir(gain); + case uhd::RX_DIRECTION: + return mykonos_config.rx_fir_config.get_fir(gain); + default: + UHD_THROW_INVALID_CODE_PATH(); + } } -*/ + +int16_t ad937x_device::get_temperature() +{ + // TODO: deal with the status.tempValid flag + mykonosTempSensorStatus_t status; + _call_gpio_api_function(std::bind(MYKONOS_readTempSensor, mykonos_config.device, &status)); + return status.tempCode; +} + diff --git a/mpm/lib/mykonos/ad937x_device.hpp b/mpm/lib/mykonos/ad937x_device.hpp index c2d159be9..52d25abba 100644 --- a/mpm/lib/mykonos/ad937x_device.hpp +++ b/mpm/lib/mykonos/ad937x_device.hpp @@ -1,92 +1,103 @@ +// +// Copyright 2017 Ettus Research (National Instruments) +// +// 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/>. +// + #pragma once +#include "config/ad937x_config_t.hpp" +#include "config/ad937x_fir.hpp" +#include "adi/t_mykonos.h" +#include "adi/t_mykonos_gpio.h" +#include "mpm/spi/adi_ctrl.hpp" + // TODO: fix path of UHD includes #include <../../host/include/uhd/types/direction.hpp> #include <../../host/include/uhd/types/ranges.hpp> #include <../../host/include/uhd/exception.hpp> -#include "config/ad937x_config_t.hpp" -#include "config/ad937x_fir.h" -#include "adi/t_mykonos.h" -#include "../spi/spi_lock.h" -#include "../spi/spi_config.h" -#include <mpm/spi_iface.hpp> -#include <mpm/spi/adi_ctrl.hpp> #include <boost/noncopyable.hpp> +#include <mutex> +#include <memory> #include <functional> -struct ad937x_api_version_t { - uint32_t silicon_ver; - uint32_t major_ver; - uint32_t minor_ver; - uint32_t build_ver; -}; - -struct ad937x_arm_version_t { - uint32_t major_ver; - uint32_t minor_ver; - uint32_t rc_ver; -}; - class ad937x_device : public boost::noncopyable { public: + struct api_version_t { + uint32_t silicon_ver; + uint32_t major_ver; + uint32_t minor_ver; + uint32_t build_ver; + }; + + struct arm_version_t { + uint8_t major_ver; + uint8_t minor_ver; + uint8_t rc_ver; + }; + enum class gain_mode_t { MANUAL, AUTOMATIC, HYBRID }; enum class chain_t { ONE, TWO }; + enum class pll_t {CLK_SYNTH, RX_SYNTH, TX_SYNTH, SNIFF_SYNTH, CALPLL_SDM}; typedef std::shared_ptr<ad937x_device> sptr; - virtual ~ad937x_device(void) {}; - - static uhd::meta_range_t get_rf_freq_range(void); - static uhd::meta_range_t get_bw_filter_range(void); - static std::vector<double> get_clock_rates(void); + ad937x_device(uhd::spi_iface::sptr iface); - uhd::meta_range_t get_gain_range(uhd::direction_t direction, chain_t chain); + uint8_t get_product_id(); + uint8_t get_device_rev(); + api_version_t get_api_version(); + arm_version_t get_arm_version(); - uint8_t get_product_id() = 0; - uint8_t get_device_rev() = 0; - ad937x_api_version_t get_api_version() = 0; - ad937x_arm_version_t get_arm_version() = 0; + double set_bw_filter(uhd::direction_t direction, chain_t chain, double value); + double set_gain(uhd::direction_t direction, chain_t chain, double value); + void set_agc_mode(uhd::direction_t direction, gain_mode_t mode); + double set_clock_rate(double value); + void enable_channel(uhd::direction_t direction, chain_t chain, bool enable); + double tune(uhd::direction_t direction, double value); + double get_freq(uhd::direction_t direction); - double set_bw_filter(const uhd::direction_t direction, const chain_t chain, const double value) = 0; - double set_gain(const uhd::direction_t direction, const chain_t chain, const double value) = 0; + bool get_pll_lock_status(pll_t pll); - void set_agc(const uhd::direction_t direction, const bool enable) = 0; - void set_agc_mode(const uhd::direction_t direction, const gain_mode_t mode) = 0; + void set_fir(uhd::direction_t direction, chain_t chain, int8_t gain, const std::vector<int16_t> & fir); + std::vector<int16_t> get_fir(uhd::direction_t direction, chain_t chain, int8_t &gain); - double set_clock_rate(const double value) = 0; - void enable_channel(const uhd::direction_t direction, const chain_t chain, const bool enable) = 0; + int16_t get_temperature(); - double tune(const uhd::direction_t direction, const double value) = 0; - double get_freq(const uhd::direction_t direction) = 0; - - void set_fir(const uhd::direction_t direction, const chain_t chain, const ad937x_fir & fir) = 0; - ad937x_fir get_fir(const uhd::direction_t direction, const chain_t chain) = 0; - - int16_t get_temperature() = 0; - -private: const static double MIN_FREQ; const static double MAX_FREQ; + const static double MIN_RX_GAIN; + const static double MAX_RX_GAIN; + const static double RX_GAIN_STEP; + const static double MIN_TX_GAIN; + const static double MAX_TX_GAIN; + const static double TX_GAIN_STEP; - virtual void initialize() = 0; - - spi_lock::sptr spi_l; - mpm::spi_iface::sptr iface; - mpm_spiSettings_t mpm_sps; +private: + void _initialize(); + void _load_arm(std::vector<uint8_t> & binary); + void _run_initialization_calibrations(); + void _start_jesd(); + void _enable_tracking_calibrations(); + ad9371_spiSettings_t full_spi_settings; ad937x_config_t mykonos_config; - void call_api_function(std::function<mykonosErr_t()> func); - - static uint8_t _convert_rx_gain(double inGain, double &coercedGain); - static uint16_t _convert_tx_gain(double inGain, double &coercedGain); - - void _set_active_tx_chains(bool tx1, bool tx2); - void _set_active_rx_chains(bool rx1, bool rx2); - - const static spi_device_settings_t spi_device_settings; -}; + void _call_api_function(std::function<mykonosErr_t()> func); + void _call_gpio_api_function(std::function<mykonosGpioErr_t()> func); -const double ad937x_ctrl::MIN_FREQ = 300e6; -const double ad937x_ctrl::MAX_FREQ = 6e9;
\ No newline at end of file + static uint8_t _convert_rx_gain(double gain); + static uint16_t _convert_tx_gain(double gain); +};
\ No newline at end of file diff --git a/mpm/lib/mykonos/adi/CMakeLists.txt b/mpm/lib/mykonos/adi/CMakeLists.txt index 596344eb8..b54a604b9 100644 --- a/mpm/lib/mykonos/adi/CMakeLists.txt +++ b/mpm/lib/mykonos/adi/CMakeLists.txt @@ -2,5 +2,4 @@ MYKONOS_APPEND_SOURCES( ${CMAKE_CURRENT_SOURCE_DIR}/mykonos.c ${CMAKE_CURRENT_SOURCE_DIR}/mykonos_gpio.c ${CMAKE_CURRENT_SOURCE_DIR}/mykonos_user.c - ${CMAKE_CURRENT_SOURCE_DIR}/mykonosMmap.c ) diff --git a/mpm/lib/mykonos/adi/common.h b/mpm/lib/mykonos/adi/common.h index f39f20ce1..5268b2a8b 100644 --- a/mpm/lib/mykonos/adi/common.h +++ b/mpm/lib/mykonos/adi/common.h @@ -91,9 +91,9 @@ commonErr_t CMB_SPIReadField (spiSettings_t *spiSettings, uint16_t addr, uint8_t /* platform timer functions */ commonErr_t CMB_wait_ms(uint32_t time_ms); commonErr_t CMB_wait_us(uint32_t time_us); -commonErr_t CMB_setTimeout_ms(uint32_t timeOut_ms); -commonErr_t CMB_setTimeout_us(uint32_t timeOut_us); -commonErr_t CMB_hasTimeoutExpired(); +commonErr_t CMB_setTimeout_ms(spiSettings_t *spiSettings, uint32_t timeOut_ms); +commonErr_t CMB_setTimeout_us(spiSettings_t *spiSettings, uint32_t timeOut_us); +commonErr_t CMB_hasTimeoutExpired(spiSettings_t *spiSettings); /* platform logging functions */ commonErr_t CMB_openLog(const char *filename); diff --git a/mpm/lib/mykonos/adi/mykonos.c b/mpm/lib/mykonos/adi/mykonos.c index 4688388ff..f27a03800 100644 --- a/mpm/lib/mykonos/adi/mykonos.c +++ b/mpm/lib/mykonos/adi/mykonos.c @@ -1702,7 +1702,7 @@ mykonosErr_t MYKONOS_waitForEvent(mykonosDevice_t *device, waitEvent_t waitEvent return MYKONOS_ERR_WAITFOREVENT_INV_PARM; } - CMB_setTimeout_us(timeout_us); /* timeout after desired time */ + CMB_setTimeout_us(device->spiSettings, timeout_us); /* timeout after desired time */ do { @@ -1720,7 +1720,7 @@ mykonosErr_t MYKONOS_waitForEvent(mykonosDevice_t *device, waitEvent_t waitEvent } #endif - if (CMB_hasTimeoutExpired() > 0) + if (CMB_hasTimeoutExpired(device->spiSettings) > 0) { CMB_writeToLog(ADIHAL_LOG_WARNING, device->spiSettings->chipSelectIndex, errCode, getMykonosErrorMessage(errCode)); return errCode; @@ -13155,14 +13155,14 @@ mykonosErr_t MYKONOS_verifyArmChecksum(mykonosDevice_t *device) buildTimeChecksum = (((uint32_t)buildData[3] << 24) | ((uint32_t)buildData[2] << 16) | ((uint32_t)buildData[1] << 8) | (uint32_t)buildData[0]); /* using 200 msec timeout for exit out of while loop [maximum checksum calculation time = 5 ms] */ - CMB_setTimeout_ms(200); + CMB_setTimeout_ms(device->spiSettings, 200); /* determining calculated checksum */ do { MYKONOS_readArmMem(device, MYKONOS_ADDR_ARM_CALC_CHKSUM_ADDR, calcData, CHECKSUM_BYTES, 0); calculatedChecksum = (((uint32_t)calcData[3] << 24) | ((uint32_t)calcData[2] << 16) | ((uint32_t)calcData[1] << 8) | (uint32_t)calcData[0]); - } while ((!calculatedChecksum) && (!CMB_hasTimeoutExpired())); + } while ((!calculatedChecksum) && (!CMB_hasTimeoutExpired(device->spiSettings))); /* performing consistency check */ if (buildTimeChecksum == calculatedChecksum) @@ -13204,7 +13204,7 @@ mykonosErr_t MYKONOS_checkArmState(mykonosDevice_t *device, mykonosArmState_t ar CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_checkArmState()\n"); #endif - CMB_setTimeout_ms(timeoutMs); + CMB_setTimeout_ms(device->spiSettings, timeoutMs); do { @@ -13220,7 +13220,7 @@ mykonosErr_t MYKONOS_checkArmState(mykonosDevice_t *device, mykonosArmState_t ar break; } - if (CMB_hasTimeoutExpired()) + if (CMB_hasTimeoutExpired(device->spiSettings)) { CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_WAITARMCSTATE_TIMEOUT, getMykonosErrorMessage(MYKONOS_ERR_WAITARMCSTATE_TIMEOUT)); @@ -15602,13 +15602,13 @@ mykonosErr_t MYKONOS_sendArmCommand(mykonosDevice_t *device, uint8_t opCode, uin } /* setting a 2 sec timeout for mailbox busy bit to be clear (can't send an arm mailbox command until mailbox is ready) */ - CMB_setTimeout_ms(2000); + CMB_setTimeout_ms(device->spiSettings, 2000); do { CMB_SPIReadField(device->spiSettings, MYKONOS_ADDR_ARM_CMD, &armCommandBusy, 0x80, 7); - if (CMB_hasTimeoutExpired()) + if (CMB_hasTimeoutExpired(device->spiSettings)) { CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_TIMEDOUT_ARMMAILBOXBUSY, getMykonosErrorMessage(MYKONOS_ERR_TIMEDOUT_ARMMAILBOXBUSY)); @@ -15795,7 +15795,7 @@ mykonosErr_t MYKONOS_waitArmCmdStatus(mykonosDevice_t *device, uint8_t opCode, u } /* start wait */ - CMB_setTimeout_ms(timeoutMs); + CMB_setTimeout_ms(device->spiSettings, timeoutMs); do { @@ -15809,7 +15809,7 @@ mykonosErr_t MYKONOS_waitArmCmdStatus(mykonosDevice_t *device, uint8_t opCode, u return MYKONOS_ERR_ARMCMDSTATUS_ARMERROR; } - if (CMB_hasTimeoutExpired()) + if (CMB_hasTimeoutExpired(device->spiSettings)) { return MYKONOS_ERR_WAITARMCMDSTATUS_TIMEOUT; } diff --git a/mpm/lib/mykonos/adi/mykonosMmap.c b/mpm/lib/mykonos/adi/mykonosMmap.c deleted file mode 100644 index f88cbb3a3..000000000 --- a/mpm/lib/mykonos/adi/mykonosMmap.c +++ /dev/null @@ -1,129 +0,0 @@ -/** - * \file mykonosMmap.c - * \brief Contains the Mykonos memory mapping - * - * Mykonos API version: 1.3.1.3534 - */ - -#include <stdint.h> -uint8_t mykonosMmap [] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x13,0x03,0x03,0x13,0x13,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01, - 0x00,0xE4,0xE4,0x00,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xA5,0xA5,0x05,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x01,0x00,0xE4,0xE4,0x00,0x00,0x00,0x1F,0x00,0x14,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x9F,0xE0,0x20,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0xF5,0x8F,0x0F,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; -/*!< Mykonos memory map */ diff --git a/mpm/lib/mykonos/adi_ctrl.cpp b/mpm/lib/mykonos/adi_ctrl.cpp index d25c2b188..305e4f711 100644 --- a/mpm/lib/mykonos/adi_ctrl.cpp +++ b/mpm/lib/mykonos/adi_ctrl.cpp @@ -15,123 +15,181 @@ // along with this program. If not, see <http://www.gnu.org/licenses/>. // + #include "adi/common.h" #include <mpm/spi/adi_ctrl.hpp> -#include <mpm/spi_iface.hpp> + +// TODO: fix path of UHD includes +#include <../../host/include/uhd/exception.hpp> #include <iostream> -//#include <boost/format.hpp> +#include <chrono> +#include <thread> -#define CMB_TRACE_FUNCTIONS 0 +ad9371_spiSettings_t::ad9371_spiSettings_t(uhd::spi_iface::sptr uhd_iface) : + spi_iface(uhd_iface) +{ + spi_settings.chipSelectIndex = 0; // set later + spi_settings.writeBitPolarity = 1; // unused + spi_settings.longInstructionWord = 1; + spi_settings.MSBFirst = 1; + spi_settings.CPHA = 0; + spi_settings.CPOL = 0; + spi_settings.enSpiStreaming = 0; // unused + spi_settings.autoIncAddrUp = 0; // unused + spi_settings.fourWireMode = 1; // unused + spi_settings.spiClkFreq_Hz = 250000000; // currently unused +} -#if CMB_TRACE_FUNCTIONS == 1 -#define CMB_TRACE_FUNCTION std::cout << __FUNCTION__ << std::endl; -#else -#define CMB_TRACE_FUNCTION -#endif +uhd::spi_config_t::edge_t _get_edge(const spiSettings_t & sps) +{ + return (sps.CPOL ^ sps.CPHA) ? uhd::spi_config_t::EDGE_FALL : uhd::spi_config_t::EDGE_RISE; +} +// TODO: change // not implemented to meaningful errors -/* close hardware pointers */ +// close hardware pointers commonErr_t CMB_closeHardware(void) { - CMB_TRACE_FUNCTION; - return COMMONERR_OK; + // not implemented + return COMMONERR_FAILED; } -/* GPIO function */ +// GPIO function commonErr_t CMB_setGPIO(uint32_t GPIO) { - CMB_TRACE_FUNCTION; - return COMMONERR_OK; + // not implemented + return COMMONERR_FAILED; } -/* hardware reset function */ +// hardware reset function commonErr_t CMB_hardReset(uint8_t spiChipSelectIndex) { - CMB_TRACE_FUNCTION; - //std::cout << "Hard reset chip select " << spiChipSelectIndex << std::endl; + // TODO: implement return COMMONERR_OK; } -/* SPI read/write functions */ +// +// SPI read/write functions +// -/* allows the platform HAL to work with devices with various SPI settings */ +// allows the platform HAL to work with devices with various SPI settings commonErr_t CMB_setSPIOptions(spiSettings_t *spiSettings) { - CMB_TRACE_FUNCTION; + // not implemented return COMMONERR_OK; } -/* value of 0 deasserts all chip selects */ +// value of 0 deasserts all chip selects commonErr_t CMB_setSPIChannel(uint16_t chipSelectIndex) { - CMB_TRACE_FUNCTION; + // not implemented return COMMONERR_OK; } -/* single SPI byte write function */ +// single SPI byte write function commonErr_t CMB_SPIWriteByte(spiSettings_t *spiSettings, uint16_t addr, uint8_t data) { - mpm_spiSettings_t *mpm_spi = mpm_spiSettings_t::make(spiSettings); + // TODO: crash and burn for these errors? + if (spiSettings == nullptr || spiSettings->MSBFirst == 0) return COMMONERR_FAILED; + + ad9371_spiSettings_t *mpm_spi = ad9371_spiSettings_t::make(spiSettings); + uhd::spi_config_t config(_get_edge(*spiSettings)); + uint32_t data_word = (0) | (addr << 8) | (data); try { - mpm_spi->spi_iface->write_byte(addr, data); + mpm_spi->spi_iface->write_spi(spiSettings->chipSelectIndex, config, data_word, 24); return COMMONERR_OK; } catch (const std::exception &e) { - /* ... error handling ... */ + // ... error handling ... } return COMMONERR_FAILED; } commonErr_t CMB_SPIWriteBytes(spiSettings_t *spiSettings, uint16_t *addr, uint8_t *data, uint32_t count) { - mpm_spiSettings_t *mpm_spi = mpm_spiSettings_t::make(spiSettings); + // TODO: crash and burn for these errors? + if (spiSettings == nullptr || + addr == nullptr || + data == nullptr || + spiSettings->MSBFirst == 0) + { + return COMMONERR_FAILED; + } + + ad9371_spiSettings_t *mpm_spi = ad9371_spiSettings_t::make(spiSettings); + uhd::spi_config_t config(_get_edge(*spiSettings)); try { - mpm_spi->spi_iface->write_bytes(addr, data, count); + for (size_t i = 0; i < count; ++i) + { + uint32_t data_word = (0) | (addr[i] << 8) | (data[i]); + mpm_spi->spi_iface->write_spi(spiSettings->chipSelectIndex, config, data_word, 24); + } return COMMONERR_OK; } catch (const std::exception &e) { - /* ... error handling ... */ + // ... error handling ... } return COMMONERR_FAILED; } -/* single SPI byte read function */ +// single SPI byte read function commonErr_t CMB_SPIReadByte (spiSettings_t *spiSettings, uint16_t addr, uint8_t *readdata) { - mpm_spiSettings_t *mpm_spi = mpm_spiSettings_t::make(spiSettings); + if (spiSettings == nullptr || + readdata == nullptr || + spiSettings->MSBFirst == 0) + { + return COMMONERR_FAILED; + } + + ad9371_spiSettings_t *mpm_spi = ad9371_spiSettings_t::make(spiSettings); + uhd::spi_config_t config(_get_edge(*spiSettings)); + uint32_t data_word = (0) | (addr << 8); + try { - *readdata = mpm_spi->spi_iface->read_byte(addr); + *readdata = static_cast<uint8_t>( + mpm_spi->spi_iface->read_spi(spiSettings->chipSelectIndex, config, data_word, 24)); return COMMONERR_OK; } catch (const std::exception &e) { - /* ... error handling ... */ + // ... error handling ... } return COMMONERR_FAILED; } -/* write a field in a single register */ +// write a field in a single register commonErr_t CMB_SPIWriteField( spiSettings_t *spiSettings, uint16_t addr, uint8_t field_val, uint8_t mask, uint8_t start_bit ) { - mpm_spiSettings_t *mpm_spi = mpm_spiSettings_t::make(spiSettings); + ad9371_spiSettings_t *mpm_spi = ad9371_spiSettings_t::make(spiSettings); + uhd::spi_config_t config(_get_edge(*spiSettings)); + uint32_t read_word = (0) | (addr << 8); + try { - mpm_spi->spi_iface->write_field(addr, field_val, mask, start_bit); + uint32_t current_value = mpm_spi->spi_iface->read_spi(spiSettings->chipSelectIndex, config, read_word, 24); + uint8_t new_value = static_cast<uint8_t>((current_value & ~mask) | (field_val << start_bit)); + uint32_t write_word = (0) | (addr << 8) | new_value; + mpm_spi->spi_iface->write_spi(spiSettings->chipSelectIndex, config, write_word, 24); return COMMONERR_OK; } catch (const std::exception &e) { - /* ... error handling ... */ + // ... error handling ... } return COMMONERR_FAILED; } -/* read a field in a single register */ +// read a field in a single register commonErr_t CMB_SPIReadField( spiSettings_t *spiSettings, uint16_t addr, uint8_t *field_val, uint8_t mask, uint8_t start_bit ) { - mpm_spiSettings_t *mpm_spi = mpm_spiSettings_t::make(spiSettings); + ad9371_spiSettings_t *mpm_spi = ad9371_spiSettings_t::make(spiSettings); + uhd::spi_config_t config(_get_edge(*spiSettings)); + uint32_t read_word = (0) | (addr << 8); + try { - *field_val = mpm_spi->spi_iface->read_field(addr, mask, start_bit); + uint32_t value = mpm_spi->spi_iface->read_spi(spiSettings->chipSelectIndex, config, read_word, 24); + *field_val = static_cast<uint8_t>((value & mask) >> start_bit); return COMMONERR_OK; } catch (const std::exception &e) { /* ... error handling ... */ @@ -139,77 +197,89 @@ commonErr_t CMB_SPIReadField( return COMMONERR_FAILED; } -/* platform timer functions */ +// platform timer functions + commonErr_t CMB_wait_ms(uint32_t time_ms) { - CMB_TRACE_FUNCTION; + std::this_thread::sleep_for(std::chrono::milliseconds(time_ms)); return COMMONERR_OK; } commonErr_t CMB_wait_us(uint32_t time_us) { - CMB_TRACE_FUNCTION; + std::this_thread::sleep_for(std::chrono::microseconds(time_us)); return COMMONERR_OK; } -commonErr_t CMB_setTimeout_ms(uint32_t timeOut_ms) + +commonErr_t CMB_setTimeout_ms(spiSettings_t *spiSettings, uint32_t timeOut_ms) { - CMB_TRACE_FUNCTION; + ad9371_spiSettings_t *mpm_spi = ad9371_spiSettings_t::make(spiSettings); + mpm_spi->timeout_start = std::chrono::steady_clock::now(); + mpm_spi->timeout_duration = std::chrono::milliseconds(timeOut_ms); return COMMONERR_OK; } -commonErr_t CMB_setTimeout_us(uint32_t timeOut_us) +commonErr_t CMB_setTimeout_us(spiSettings_t *spiSettings, uint32_t timeOut_us) { - CMB_TRACE_FUNCTION; + ad9371_spiSettings_t *mpm_spi = ad9371_spiSettings_t::make(spiSettings); + mpm_spi->timeout_start = std::chrono::steady_clock::now(); + mpm_spi->timeout_duration = std::chrono::microseconds(timeOut_us); return COMMONERR_OK; } -commonErr_t CMB_hasTimeoutExpired() +commonErr_t CMB_hasTimeoutExpired(spiSettings_t *spiSettings) { - CMB_TRACE_FUNCTION; - return COMMONERR_FAILED; + ad9371_spiSettings_t *mpm_spi = ad9371_spiSettings_t::make(spiSettings); + auto current_time = std::chrono::steady_clock::now(); + if ((std::chrono::steady_clock::now() - mpm_spi->timeout_start) > mpm_spi->timeout_duration) + { + return COMMONERR_FAILED; + } + else { + return COMMONERR_OK; + } } -/* platform logging functions */ +// platform logging functions commonErr_t CMB_openLog(const char *filename) { - CMB_TRACE_FUNCTION; - return COMMONERR_OK; + // not implemented + return COMMONERR_FAILED; } commonErr_t CMB_closeLog(void) { - CMB_TRACE_FUNCTION; - return COMMONERR_OK; + // not implemented + return COMMONERR_FAILED; } commonErr_t CMB_writeToLog(ADI_LOGLEVEL level, uint8_t deviceIndex, uint32_t errorCode, const char *comment) { - CMB_TRACE_FUNCTION; std::cout << level << " " << errorCode << " " << comment << std::endl; return COMMONERR_OK; } commonErr_t CMB_flushLog(void) { - CMB_TRACE_FUNCTION; - return COMMONERR_OK; + // not implemented + return COMMONERR_FAILED; } /* platform FPGA AXI register read/write functions */ commonErr_t CMB_regRead(uint32_t offset, uint32_t *data) { - CMB_TRACE_FUNCTION; - return COMMONERR_OK; + // not implemented + return COMMONERR_FAILED; } commonErr_t CMB_regWrite(uint32_t offset, uint32_t data) { - CMB_TRACE_FUNCTION; - return COMMONERR_OK; + // not implemented + return COMMONERR_FAILED; } /* platform DDR3 memory read/write functions */ commonErr_t CMB_memRead(uint32_t offset, uint32_t *data, uint32_t len) { - CMB_TRACE_FUNCTION; - return COMMONERR_OK; + // not implemented + return COMMONERR_FAILED; } commonErr_t CMB_memWrite(uint32_t offset, uint32_t *data, uint32_t len) { - CMB_TRACE_FUNCTION; - return COMMONERR_OK; + // not implemented + return COMMONERR_FAILED; } diff --git a/mpm/lib/mykonos/adi_sample/CMakeLists.txt b/mpm/lib/mykonos/adi_sample/CMakeLists.txt deleted file mode 100644 index e00c31032..000000000 --- a/mpm/lib/mykonos/adi_sample/CMakeLists.txt +++ /dev/null @@ -1,4 +0,0 @@ -MYKONOS_APPEND_SOURCES( - ${CMAKE_CURRENT_SOURCE_DIR}/headless.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/mykonos_static_config.c -) diff --git a/mpm/lib/mykonos/adi_sample/headless.c b/mpm/lib/mykonos/adi_sample/headless.c deleted file mode 100644 index 9fedc9338..000000000 --- a/mpm/lib/mykonos/adi_sample/headless.c +++ /dev/null @@ -1,528 +0,0 @@ -/** - * \file headless.c - * - * \brief Contains example code for user integration with their application - * - * All data structures required for operation have been initialized with values which reflect - * these settings: - * - * Device Clock: - * 125MHz - * - * Profiles: - * Rx 100MHz, IQrate 125MSPS, Dec5 - * Tx 20/100MHz, IQrate 125MSPS, Dec5 - * ORX 100MHz, IQrate 125MSPS, Dec5 - * SRx 20MHz, IQrate 31.25MSPS, Dec5 - * - */ - -#include <stdlib.h> -#include "headless.h" -#include "t_mykonos.h" -#include "mykonos.h" -#include "mykonos_gpio.h" -#include "mykonos_config.h" -//#include "mykonos_static_config.h" - -/****< Action: Insert rest of required Includes Here >***/ - -int oldmain() -{ - const char* errorString; - uint8_t mcsStatus = 0; - uint8_t pllLockStatus = 0; - uint8_t binary[98304] = {0}; /*** < Action: binary should contain ARM binary file as array > ***/ - uint32_t count = sizeof(binary); - uint8_t errorFlag = 0; - uint8_t errorCode = 0; - uint32_t initCalsCompleted = 0; - uint16_t errorWord = 0; - uint16_t statusWord = 0; - uint8_t status = 0; - mykonosInitCalStatus_t initCalStatus = {0}; - - uint8_t deframerStatus = 0; - uint8_t obsFramerStatus = 0; - uint8_t framerStatus = 0; - uint32_t initCalMask = TX_BB_FILTER | ADC_TUNER | TIA_3DB_CORNER | DC_OFFSET | - TX_ATTENUATION_DELAY | RX_GAIN_DELAY | FLASH_CAL | - PATH_DELAY | TX_LO_LEAKAGE_INTERNAL | TX_QEC_INIT | - LOOPBACK_RX_LO_DELAY | LOOPBACK_RX_RX_QEC_INIT | - RX_LO_DELAY | RX_QEC_INIT; - - uint32_t trackingCalMask = TRACK_RX1_QEC | - TRACK_RX2_QEC | - TRACK_TX1_QEC | - TRACK_TX2_QEC | - TRACK_ORX1_QEC| - TRACK_ORX2_QEC; - - mykonosErr_t mykError = MYKONOS_ERR_OK; - mykonosGpioErr_t mykGpioErr = MYKONOS_ERR_GPIO_OK; - - /* Allocating memory for the errorString */ - errorString = (const char*) malloc(sizeof(char) * 200); - - /*** < Action: Insert System Clock(s) Initialization Code Here > ***/ - - /*** < Action: Insert BBIC Initialization Code Here > ***/ - - /*************************************************************************/ - /***** Mykonos Initialization Sequence *****/ - /*************************************************************************/ - - // TODO: change to unique ptr - mykonos_config config(); - mykonosDevice_t *mykDevice = &config.device; - - - /*** < Action: Toggle RESETB pin on Mykonos device > ***/ - if ((mykError = MYKONOS_resetDevice(&mykDevice)) != MYKONOS_ERR_OK) - { - /*** < Info: errorString will contain log error string in order to debug failure > ***/ - errorString = getMykonosErrorMessage(mykError); - } - - if ((mykError = MYKONOS_initialize(&mykDevice)) != MYKONOS_ERR_OK) - { - /*** < Info: errorString will contain log error string in order to debug failure > ***/ - errorString = getMykonosErrorMessage(mykError); - } - - /*************************************************************************/ - /***** Mykonos CLKPLL Status Check *****/ - /*************************************************************************/ - if ((mykError = MYKONOS_checkPllsLockStatus(&mykDevice, &pllLockStatus)) != MYKONOS_ERR_OK) - { - /*** < Info: errorString will contain log error string in order to debug failure > ***/ - errorString = getMykonosErrorMessage(mykError); - } - - if (pllLockStatus & 0x01) - { - /*** < User: code here for actions once CLKPLL locked > ***/ - } - else - { - /*** < User: code here here for actions since CLKPLL not locked - * ensure lock before proceeding - > ***/ - } - - /*************************************************************************/ - /***** Mykonos Perform MultiChip Sync *****/ - /*************************************************************************/ - if ((mykError = MYKONOS_enableMultichipSync(&mykDevice, 1, &mcsStatus)) != MYKONOS_ERR_OK) - { - /*** < Info: errorString will contain log error string in order to debug failure > ***/ - errorString = getMykonosErrorMessage(mykError); - } - - - /*** < Action: minimum 3 SYSREF pulses from Clock Device has to be produced - * for MulticChip Sync > ***/ - - /*************************************************************************/ - /***** Mykonos Verify MultiChip Sync *****/ - /*************************************************************************/ - if ((mykError = MYKONOS_enableMultichipSync(&mykDevice, 0, &mcsStatus)) != MYKONOS_ERR_OK) - { - /*** < Info: errorString will contain log error string in order to debug failure > ***/ - errorString = getMykonosErrorMessage(mykError); - } - - if ((mcsStatus & 0x0B) == 0x0B) - { - /*** < Info: MCS successful > ***/ - /*** < Action: extra User code > ***/ - } - else - { - /*** < Info: MCS failed > ***/ - /*** < Action: ensure MCS before proceeding > ***/ - } - - /*************************************************************************/ - /***** Mykonos Load ARM file *****/ - /*************************************************************************/ - if (pllLockStatus & 0x01) - { - if ((mykError = MYKONOS_initArm(&mykDevice)) != MYKONOS_ERR_OK) - { - /*** < Info: errorString will contain log error string in order to debug failure > ***/ - errorString = getMykonosErrorMessage(mykError); - } - - /*** < Action: User must load ARM binary byte array into variable binary[98304] before calling next command > ***/ - if ((mykError = MYKONOS_loadArmFromBinary(&mykDevice, &binary[0], count)) != MYKONOS_ERR_OK) - { - /*** < Info: errorString will contain log error string in order to debug why - * ARM did not load properly - check binary and device settings > ***/ - /*** < Action: User code > ***/ - errorString = getMykonosErrorMessage(mykError); - } - - } - else - { - /*** < Action: check settings for proper CLKPLL lock > ***/ - } - - /*************************************************************************/ - /***** Mykonos Set RF PLL Frequencies *****/ - /*************************************************************************/ - if ((mykError = MYKONOS_setRfPllFrequency(&mykDevice, RX_PLL, mykDevice.rx->rxPllLoFrequency_Hz)) != MYKONOS_ERR_OK) - { - /*** < Info: errorString will contain log error string in order to debug failure > ***/ - errorString = getMykonosErrorMessage(mykError); - } - - if ((mykError = MYKONOS_setRfPllFrequency(&mykDevice, TX_PLL, mykDevice.tx->txPllLoFrequency_Hz)) != MYKONOS_ERR_OK) - { - /*** < Info: errorString will contain log error string in order to debug failure > ***/ - errorString = getMykonosErrorMessage(mykError); - } - - if ((mykError = MYKONOS_setRfPllFrequency(&mykDevice, SNIFFER_PLL, mykDevice.obsRx->snifferPllLoFrequency_Hz)) != MYKONOS_ERR_OK) - { - /*** < Info: errorString will contain log error string in order to debug failure > ***/ - errorString = getMykonosErrorMessage(mykError); - } - - /*** < Action: wait 200ms for PLLs to lock > ***/ - - if ((mykError = MYKONOS_checkPllsLockStatus(&mykDevice, &pllLockStatus)) != MYKONOS_ERR_OK) - { - /*** < Info: errorString will contain log error string in order to debug failure > ***/ - errorString = getMykonosErrorMessage(mykError); - } - - if ((pllLockStatus & 0x0F) == 0x0F) - { - /*** < Info: All PLLs locked > ***/ - } - else - { - /*** < Info: PLLs not locked > ***/ - /*** < Action: Ensure lock before proceeding - User code here > ***/ - } - - /*************************************************************************/ - /***** Mykonos Set GPIOs *****/ - /*************************************************************************/ - if ((mykGpioErr = MYKONOS_setRx1GainCtrlPin(&mykDevice, 0, 0, 0, 0, 0)) != MYKONOS_ERR_GPIO_OK) - { - /*** < Info: errorString will contain log error string in order to debug failure > ***/ - errorString = getGpioMykonosErrorMessage(mykGpioErr); - } - - if ((mykGpioErr = MYKONOS_setRx2GainCtrlPin(&mykDevice, 0, 0, 0, 0, 0)) != MYKONOS_ERR_GPIO_OK) - { - /*** < Info: errorString will contain log error string in order to debug failure > ***/ - errorString = getGpioMykonosErrorMessage(mykGpioErr); - } - - if ((mykGpioErr = MYKONOS_setTx1AttenCtrlPin(&mykDevice, 0, 0, 0, 0, 0)) != MYKONOS_ERR_GPIO_OK) - { - /*** < Info: errorString will contain log error string in order to debug failure > ***/ - errorString = getGpioMykonosErrorMessage(mykGpioErr); - } - - if ((mykGpioErr = MYKONOS_setTx2AttenCtrlPin(&mykDevice, 0, 0, 0, 0)) != MYKONOS_ERR_GPIO_OK) - { - /*** < Info: errorString will contain log error string in order to debug failure > ***/ - errorString = getGpioMykonosErrorMessage(mykGpioErr); - } - - if ((mykGpioErr = MYKONOS_setupGpio(&mykDevice)) != MYKONOS_ERR_GPIO_OK) - { - /*** < Info: errorString will contain log error string in order to debug failure > ***/ - errorString = getGpioMykonosErrorMessage(mykGpioErr); - } - - /*************************************************************************/ - /***** Mykonos Set manual gains values *****/ - /*************************************************************************/ - if ((mykError = MYKONOS_setRx1ManualGain(&mykDevice, 255)) != MYKONOS_ERR_OK) - { - /*** < Info: errorString will contain log error string in order to debug failure > ***/ - errorString = getMykonosErrorMessage(mykError); - } - - if ((mykError = MYKONOS_setRx2ManualGain(&mykDevice, 255)) != MYKONOS_ERR_OK) - { - /*** < Info: errorString will contain log error string in order to debug failure > ***/ - errorString = getMykonosErrorMessage(mykError); - } - - if ((mykError = MYKONOS_setObsRxManualGain(&mykDevice, OBS_RX1_TXLO, 255)) != MYKONOS_ERR_OK) - { - /*** < Info: errorString will contain log error string in order to debug failure > ***/ - errorString = getMykonosErrorMessage(mykError); - } - - if ((mykError = MYKONOS_setObsRxManualGain(&mykDevice, OBS_RX2_TXLO, 255)) != MYKONOS_ERR_OK) - { - /*** < Info: errorString will contain log error string in order to debug failure > ***/ - errorString = getMykonosErrorMessage(mykError); - } - - if ((mykError = MYKONOS_setObsRxManualGain(&mykDevice, OBS_SNIFFER_A, 255)) != MYKONOS_ERR_OK) - { - /*** < Info: errorString will contain log error string in order to debug failure > ***/ - errorString = getMykonosErrorMessage(mykError); - } - - if ((mykError = MYKONOS_setObsRxManualGain(&mykDevice, OBS_SNIFFER_B, 255)) != MYKONOS_ERR_OK) - { - /*** < Info: errorString will contain log error string in order to debug failure > ***/ - errorString = getMykonosErrorMessage(mykError); - } - if ((mykError = MYKONOS_setObsRxManualGain(&mykDevice, OBS_SNIFFER_C, 255)) != MYKONOS_ERR_OK) - { - /*** < Info: errorString will contain log error string in order to debug failure > ***/ - errorString = getMykonosErrorMessage(mykError); - } - - /*************************************************************************/ - /***** Mykonos Initialize attenuations *****/ - /*************************************************************************/ - if ((mykError = MYKONOS_setTx1Attenuation(&mykDevice, 0)) != MYKONOS_ERR_OK) - { - /*** < Info: errorString will contain log error string in order to debug failure > ***/ - errorString = getMykonosErrorMessage(mykError); - } - - if ((mykError = MYKONOS_setTx2Attenuation(&mykDevice, 0)) != MYKONOS_ERR_OK) - { - /*** < Info: errorString will contain log error string in order to debug failure > ***/ - errorString = getMykonosErrorMessage(mykError); - } - - /*************************************************************************/ - /***** Mykonos ARM Initialization Calibrations *****/ - /*************************************************************************/ - - if ((mykError = MYKONOS_runInitCals(&mykDevice, (initCalMask & ~TX_LO_LEAKAGE_EXTERNAL))) != MYKONOS_ERR_OK) - { - /*** < Info: errorString will contain log error string in order to debug failure > ***/ - errorString = getMykonosErrorMessage(mykError); - } - - if ((mykError = MYKONOS_waitInitCals(&mykDevice, 60000, &errorFlag, &errorCode)) != MYKONOS_ERR_OK) - { - /*** < Info: errorString will contain log error string in order to debug failure > ***/ - errorString = getMykonosErrorMessage(mykError); - } - - if ((errorFlag != 0) || (errorCode != 0)) - { - if ((mykError = MYKONOS_getInitCalStatus(&mykDevice, &initCalStatus)) != MYKONOS_ERR_OK) - { - /*** < Info: errorString will contain log error string in order to debug failure > ***/ - errorString = getMykonosErrorMessage(mykError); - } - - /*** < Info: abort init cals > ***/ - if ((mykError = MYKONOS_abortInitCals(&mykDevice, &initCalsCompleted)) != MYKONOS_ERR_OK) - { - /*** < Info: errorString will contain log error string in order to debug failure > ***/ - errorString = getMykonosErrorMessage(mykError); - } - if (initCalsCompleted) - { - /*** < Info: which calls had completed, per the mask > ***/ - } - - if ((mykError = MYKONOS_readArmCmdStatus(&mykDevice, &errorWord, &statusWord)) != MYKONOS_ERR_OK) - { - /*** < Info: errorString will contain log error string in order to debug failure > ***/ - errorString = getMykonosErrorMessage(mykError); - } - - if ((mykError = MYKONOS_readArmCmdStatusByte(&mykDevice, 2, &status)) != MYKONOS_ERR_OK) - { - /*** < Info: errorString will contain log error string in order to debug why failed > ***/ - errorString = getMykonosErrorMessage(mykError); - } - if (status != 0) - { - /*** < Info: Arm Mailbox Status Error errorWord > ***/ - /*** < Info: Pending Flag per opcode statusWord, this follows the mask > ***/ - } - } - else - { - /*** < Info: Calibrations completed successfully > ***/ - } - - /*************************************************************************/ - /***** Mykonos ARM Initialization External LOL Calibrations with PA *****/ - /*************************************************************************/ - /*** < Action: Please ensure PA is enabled operational at this time > ***/ - if (initCalMask & TX_LO_LEAKAGE_EXTERNAL) - { - if ((mykError = MYKONOS_runInitCals(&mykDevice, TX_LO_LEAKAGE_EXTERNAL)) != MYKONOS_ERR_OK) - { - /*** < Info: errorString will contain log error string in order to debug failure > ***/ - errorString = getMykonosErrorMessage(mykError); - } - if ((mykError = MYKONOS_waitInitCals(&mykDevice, 60000, &errorFlag, &errorCode)) != MYKONOS_ERR_OK) - { - /*** < Info: errorString will contain log error string in order to debug failure > ***/ - errorString = getMykonosErrorMessage(mykError); - } - if ((errorFlag != 0) || (errorCode != 0)) - { - if ((mykError = MYKONOS_getInitCalStatus(&mykDevice, &initCalStatus)) != MYKONOS_ERR_OK) - { - /*** < Info: errorString will contain log error string in order to debug failure > ***/ - errorString = getMykonosErrorMessage(mykError); - } - - /*** < Info: abort init cals > ***/ - if ((mykError = MYKONOS_abortInitCals(&mykDevice, &initCalsCompleted)) != MYKONOS_ERR_OK) - { - /*** < Info: errorString will contain log error string in order to debug failure > ***/ - errorString = getMykonosErrorMessage(mykError); - } - if (initCalsCompleted) - { - /*** < Info: which calls had completed, per the mask > ***/ - } - - if ((mykError = MYKONOS_readArmCmdStatus(&mykDevice, &errorWord, &statusWord)) != MYKONOS_ERR_OK) - { - /*** < Info: errorString will contain log error string in order to debug failure > ***/ - errorString = getMykonosErrorMessage(mykError); - } - - if ((mykError = MYKONOS_readArmCmdStatusByte(&mykDevice, 2, &status)) != MYKONOS_ERR_OK) - { - /*** < Info: errorString will contain log error string in order to debug failure > ***/ - errorString = getMykonosErrorMessage(mykError); - } - if (status != 0) - { - /*** < Info: Arm Mailbox Status Error errorWord > ***/ - /*** < Info: Pending Flag per opcode statusWord, this follows the mask > ***/ - } - } - else - { - /*** < Info: Calibrations completed successfully > ***/ - } - } - - /*************************************************************************/ - /***** SYSTEM JESD bring up procedure *****/ - /*************************************************************************/ - /*** < Action: Make sure SYSREF is stopped/disabled > ***/ - /*** < Action: Make sure BBIC JESD is reset and ready to recieve CGS chars> ***/ - - if ((mykError = MYKONOS_enableSysrefToRxFramer(&mykDevice, 1)) != MYKONOS_ERR_OK) - { - /*** < Info: errorString will contain log error string in order to debug failure > ***/ - errorString = getMykonosErrorMessage(mykError); - } - /*** < Info: Mykonos is waiting for sysref in order to start - * transmitting CGS from the RxFramer> ***/ - - if ((mykError = MYKONOS_enableSysrefToObsRxFramer(&mykDevice, 1)) != MYKONOS_ERR_OK) - { - /*** < Info: errorString will contain log error string in order to debug failure > ***/ - errorString = getMykonosErrorMessage(mykError); - } - /*** < Info: Mykonos is waiting for sysref in order to start - * transmitting CGS from the ObsRxFramer> ***/ - - /*** < User: Make sure SYSREF is stopped/disabled > ***/ - if ((mykError = MYKONOS_enableSysrefToDeframer(&mykDevice, 0)) != MYKONOS_ERR_OK) - { - /*** < Info: errorString will contain log error string in order to debug failure > ***/ - errorString = getMykonosErrorMessage(mykError); - } - - if ((mykError = MYKONOS_resetDeframer(&mykDevice)) != MYKONOS_ERR_OK) - { - /*** < Info: errorString will contain log error string in order to debug failure > ***/ - errorString = getMykonosErrorMessage(mykError); - } - - /*** < User: make sure BBIC JESD framer is actively transmitting CGS> ***/ - if ((mykError = MYKONOS_enableSysrefToDeframer(&mykDevice, 1)) != MYKONOS_ERR_OK) - { - /*** < Info: errorString will contain log error string in order to debug failure > ***/ - errorString = getMykonosErrorMessage(mykError); - } - - /*************************************************************************/ - /***** Enable SYSREF to Mykonos and BBIC *****/ - /*************************************************************************/ - /*** < Action: Sends SYSREF Here > ***/ - - /*** < Info: Mykonos is actively transmitting CGS from the RxFramer> ***/ - - /*** < Info: Mykonos is actively transmitting CGS from the ObsRxFramer> ***/ - - /*** < Action: Insert User: BBIC JESD Sync Verification Code Here > ***/ - - /*************************************************************************/ - /***** Check Mykonos Framer Status *****/ - /*************************************************************************/ - if ((mykError = MYKONOS_readRxFramerStatus(&mykDevice, &framerStatus)) != MYKONOS_ERR_OK) - { - /*** < Info: errorString will contain log error string in order to debug failure > ***/ - errorString = getMykonosErrorMessage(mykError); - } - if ((mykError = MYKONOS_readOrxFramerStatus(&mykDevice, &obsFramerStatus)) != MYKONOS_ERR_OK) - { - /*** < Info: errorString will contain log error string in order to debug failure > ***/ - errorString = getMykonosErrorMessage(mykError); - } - - /*************************************************************************/ - /***** Check Mykonos Deframer Status *****/ - /*************************************************************************/ - if ((mykError = MYKONOS_readDeframerStatus(&mykDevice, &deframerStatus)) != MYKONOS_ERR_OK) - { - /*** < Info: errorString will contain log error string in order to debug failure > ***/ - errorString = getMykonosErrorMessage(mykError); - } - - /*** < Action: When links have been verified, proceed > ***/ - - /*************************************************************************/ - /***** Mykonos enable tracking calibrations *****/ - /*************************************************************************/ - if ((mykError = MYKONOS_enableTrackingCals(&mykDevice, trackingCalMask)) != MYKONOS_ERR_OK) - { - /*** < Info: errorString will contain log error string in order to debug why enableTrackingCals failed > ***/ - errorString = getMykonosErrorMessage(mykError); - } - - /*** < Info: Allow Rx1/2 QEC tracking and Tx1/2 QEC tracking to run when in the radioOn state - * Tx calibrations will only run if radioOn and the obsRx path is set to OBS_INTERNAL_CALS > ***/ - - /*** < Info: Function to turn radio on, Enables transmitters and receivers - * that were setup during MYKONOS_initialize() > ***/ - if ((mykError = MYKONOS_radioOn(&mykDevice)) != MYKONOS_ERR_OK) - { - /*** < Info: errorString will contain log error string in order to debug failure > ***/ - errorString = getMykonosErrorMessage(mykError); - } - - /*** < Info: Allow TxQEC to run when User: is not actively using ORx receive path > ***/ - if ((mykError = MYKONOS_setObsRxPathSource(&mykDevice, OBS_RXOFF)) != MYKONOS_ERR_OK) - { - /*** < Info: errorString will contain log error string in order to debug failure > ***/ - errorString = getMykonosErrorMessage(mykError); - } - if ((mykError = MYKONOS_setObsRxPathSource(&mykDevice, OBS_INTERNALCALS)) != MYKONOS_ERR_OK) - { - /*** < Info: errorString will contain log error string in order to debug failure > ***/ - errorString = getMykonosErrorMessage(mykError); - } - - return 0; -}
\ No newline at end of file diff --git a/mpm/lib/mykonos/adi_sample/headless.cpp b/mpm/lib/mykonos/adi_sample/headless.cpp deleted file mode 100644 index 93f079cc2..000000000 --- a/mpm/lib/mykonos/adi_sample/headless.cpp +++ /dev/null @@ -1,312 +0,0 @@ -/** - * \file headless.c - * - * \brief Contains example code for user integration with their application - * - * All data structures required for operation have been initialized with values which reflect - * these settings: - * - * Device Clock: - * 125MHz - * - * Profiles: - * Rx 100MHz, IQrate 125MSPS, Dec5 - * Tx 20/100MHz, IQrate 125MSPS, Dec5 - * ORX 100MHz, IQrate 125MSPS, Dec5 - * SRx 20MHz, IQrate 31.25MSPS, Dec5 - * - */ - -#include <stdlib.h> -#include <iostream> -#include "headless.h" -#include "../adi/t_mykonos.h" -#include "../adi/mykonos.h" -#include "../adi/mykonos_gpio.h" -#include "../config/mykonos_default_config.h" -//#include "mykonos_static_config.h" - -#include <functional> - -// dumb function to make the error reporting reusable within this file -void call_mykonos_api(std::function<mykonosErr_t()> f) -{ - auto error = f(); - if (error != MYKONOS_ERR_OK) - { - // TODO: make this an exception and stop normal processing - // in the mean time, print an error and continue happily on - std::cout << getMykonosErrorMessage(error) << std::endl; - } -} - -int headlessinit(mykonosDevice_t *mykDevice) -{ - uint32_t initCalMask = TX_BB_FILTER | ADC_TUNER | TIA_3DB_CORNER | DC_OFFSET | - TX_ATTENUATION_DELAY | RX_GAIN_DELAY | FLASH_CAL | - PATH_DELAY | TX_LO_LEAKAGE_INTERNAL | TX_QEC_INIT | - LOOPBACK_RX_LO_DELAY | LOOPBACK_RX_RX_QEC_INIT | - RX_LO_DELAY | RX_QEC_INIT; - - uint32_t trackingCalMask = TRACK_RX1_QEC | - TRACK_RX2_QEC | - TRACK_TX1_QEC | - TRACK_TX2_QEC | - TRACK_ORX1_QEC| - TRACK_ORX2_QEC; - - /*** < Action: Insert System Clock(s) Initialization Code Here > ***/ - - /*** < Action: Insert BBIC Initialization Code Here > ***/ - - /*************************************************************************/ - /***** Mykonos Initialization Sequence *****/ - /*************************************************************************/ - - /*** < Action: Toggle RESETB pin on Mykonos device > ***/ - call_mykonos_api(std::bind(MYKONOS_resetDevice, mykDevice)); - call_mykonos_api(std::bind(MYKONOS_initialize, mykDevice)); - - /*************************************************************************/ - /***** Mykonos CLKPLL Status Check *****/ - /*************************************************************************/ - - // change logic to timeout/wait for PLL lock - { - uint8_t pllLockStatus = 0; - call_mykonos_api(std::bind(MYKONOS_checkPllsLockStatus, mykDevice, &pllLockStatus)); - - if (pllLockStatus & 0x01) - { - /*** < User: code here for actions once CLKPLL locked > ***/ - } - else - { - /*** < User: code here here for actions since CLKPLL not locked - * ensure lock before proceeding - > ***/ - } - } - - // Multichip sync was here - - /*************************************************************************/ - /***** Mykonos Load ARM file *****/ - /*************************************************************************/ - - // deleted check for PLL lock here, do not advance until PLL is locked - - call_mykonos_api(std::bind(MYKONOS_initArm, mykDevice)); - { - // TODO: Add code for loading ARM binary here - uint8_t binary[98304] = { 0 }; - uint32_t count = sizeof(binary); - call_mykonos_api(std::bind(MYKONOS_loadArmFromBinary, mykDevice, &binary[0], count)); - } - - /*************************************************************************/ - /***** Mykonos Set RF PLL Frequencies *****/ - /*************************************************************************/ - - call_mykonos_api(std::bind(MYKONOS_setRfPllFrequency, mykDevice, RX_PLL, mykDevice->rx->rxPllLoFrequency_Hz)); - call_mykonos_api(std::bind(MYKONOS_setRfPllFrequency, mykDevice, TX_PLL, mykDevice->tx->txPllLoFrequency_Hz)); - call_mykonos_api(std::bind(MYKONOS_setRfPllFrequency, mykDevice, SNIFFER_PLL, mykDevice->obsRx->snifferPllLoFrequency_Hz)); - - /*** < Action: wait 200ms for PLLs to lock > ***/ - - // change logic to wait for rest of PLLs to lock - { - uint8_t pllLockStatus = 0; - call_mykonos_api(std::bind(MYKONOS_checkPllsLockStatus, mykDevice, &pllLockStatus)); - - if ((pllLockStatus & 0x0F) == 0x0F) - { - /*** < Info: All PLLs locked > ***/ - } - else - { - /*** < Info: PLLs not locked > ***/ - /*** < Action: Ensure lock before proceeding - User code here > ***/ - } - } - - // GPIO Ctrl set up was here - - /*************************************************************************/ - /***** Mykonos Set manual gains values *****/ - /*************************************************************************/ - - call_mykonos_api(std::bind(MYKONOS_setRx1ManualGain, mykDevice, 255)); - call_mykonos_api(std::bind(MYKONOS_setRx2ManualGain, mykDevice, 255)); - - // setting gain of obs and sniffer channels was here - - /*************************************************************************/ - /***** Mykonos Initialize attenuations *****/ - /*************************************************************************/ - - call_mykonos_api(std::bind(MYKONOS_setTx1Attenuation, mykDevice, 0)); - call_mykonos_api(std::bind(MYKONOS_setTx2Attenuation, mykDevice, 0)); - - /*************************************************************************/ - /***** Mykonos ARM Initialization Calibrations *****/ - /*************************************************************************/ - - call_mykonos_api(std::bind(MYKONOS_runInitCals, mykDevice, (initCalMask & ~TX_LO_LEAKAGE_EXTERNAL))); - - { - uint8_t errorFlag = 0; - uint8_t errorCode = 0; - call_mykonos_api(std::bind(MYKONOS_waitInitCals, mykDevice, 60000, &errorFlag, &errorCode)); - - if ((errorFlag != 0) || (errorCode != 0)) - { - mykonosInitCalStatus_t initCalStatus = { 0 }; - call_mykonos_api(std::bind(MYKONOS_getInitCalStatus, mykDevice, &initCalStatus)); - - /*** < Info: abort init cals > ***/ - uint32_t initCalsCompleted = 0; - call_mykonos_api(std::bind(MYKONOS_abortInitCals, mykDevice, &initCalsCompleted)); - if (initCalsCompleted) - { - /*** < Info: which calls had completed, per the mask > ***/ - } - - uint16_t errorWord = 0; - uint16_t statusWord = 0; - call_mykonos_api(std::bind(MYKONOS_readArmCmdStatus, mykDevice, &errorWord, &statusWord)); - - uint8_t status = 0; - call_mykonos_api(std::bind(MYKONOS_readArmCmdStatusByte, mykDevice, 2, &status)); - - if (status != 0) - { - /*** < Info: Arm Mailbox Status Error errorWord > ***/ - /*** < Info: Pending Flag per opcode statusWord, this follows the mask > ***/ - } - } - else - { - /*** < Info: Calibrations completed successfully > ***/ - } - } - - /*************************************************************************/ - /***** Mykonos ARM Initialization External LOL Calibrations with PA *****/ - /*************************************************************************/ - /*** < Action: Please ensure PA is enabled operational at this time > ***/ - if (initCalMask & TX_LO_LEAKAGE_EXTERNAL) - { - call_mykonos_api(std::bind(MYKONOS_runInitCals, mykDevice, TX_LO_LEAKAGE_EXTERNAL)); - - uint8_t errorFlag = 0; - uint8_t errorCode = 0; - call_mykonos_api(std::bind(MYKONOS_waitInitCals, mykDevice, 60000, &errorFlag, &errorCode)); - - if ((errorFlag != 0) || (errorCode != 0)) - { - mykonosInitCalStatus_t initCalStatus = { 0 }; - call_mykonos_api(std::bind(MYKONOS_getInitCalStatus, mykDevice, &initCalStatus)); - - /*** < Info: abort init cals > ***/ - uint32_t initCalsCompleted = 0; - call_mykonos_api(std::bind(MYKONOS_abortInitCals, mykDevice, &initCalsCompleted)); - if (initCalsCompleted) - { - /*** < Info: which calls had completed, per the mask > ***/ - } - - uint16_t errorWord = 0; - uint16_t statusWord = 0; - call_mykonos_api(std::bind(MYKONOS_readArmCmdStatus, mykDevice, &errorWord, &statusWord)); - - uint8_t status = 0; - call_mykonos_api(std::bind(MYKONOS_readArmCmdStatusByte, mykDevice, 2, &status)); - if (status != 0) - { - /*** < Info: Arm Mailbox Status Error errorWord > ***/ - /*** < Info: Pending Flag per opcode statusWord, this follows the mask > ***/ - } - } - else - { - /*** < Info: Calibrations completed successfully > ***/ - } - } - - /*************************************************************************/ - /***** SYSTEM JESD bring up procedure *****/ - /*************************************************************************/ - /*** < Action: Make sure SYSREF is stopped/disabled > ***/ - /*** < Action: Make sure BBIC JESD is reset and ready to recieve CGS chars> ***/ - - call_mykonos_api(std::bind(MYKONOS_enableSysrefToRxFramer, mykDevice, 1)); - - /*** < Info: Mykonos is waiting for sysref in order to start - * transmitting CGS from the RxFramer> ***/ - - call_mykonos_api(std::bind(MYKONOS_enableSysrefToObsRxFramer, mykDevice, 1)); - - /*** < Info: Mykonos is waiting for sysref in order to start - * transmitting CGS from the ObsRxFramer> ***/ - - /*** < User: Make sure SYSREF is stopped/disabled > ***/ - call_mykonos_api(std::bind(MYKONOS_enableSysrefToDeframer, mykDevice, 0)); - - call_mykonos_api(std::bind(MYKONOS_resetDeframer, mykDevice)); - call_mykonos_api(std::bind(MYKONOS_enableSysrefToDeframer, mykDevice, 1)); - - /*** < User: make sure BBIC JESD framer is actively transmitting CGS> ***/ - - /*************************************************************************/ - /***** Enable SYSREF to Mykonos and BBIC *****/ - /*************************************************************************/ - /*** < Action: Sends SYSREF Here > ***/ - - /*** < Info: Mykonos is actively transmitting CGS from the RxFramer> ***/ - - /*** < Info: Mykonos is actively transmitting CGS from the ObsRxFramer> ***/ - - /*** < Action: Insert User: BBIC JESD Sync Verification Code Here > ***/ - - /*************************************************************************/ - /***** Check Mykonos Framer Status *****/ - /*************************************************************************/ - { - uint8_t framerStatus = 0; - call_mykonos_api(std::bind(MYKONOS_readRxFramerStatus, mykDevice, &framerStatus)); - } - - { - uint8_t obsFramerStatus = 0; - call_mykonos_api(std::bind(MYKONOS_readOrxFramerStatus, mykDevice, &obsFramerStatus)); - } - - /*************************************************************************/ - /***** Check Mykonos Deframer Status *****/ - /*************************************************************************/ - - { - uint8_t deframerStatus = 0; - call_mykonos_api(std::bind(MYKONOS_readDeframerStatus, mykDevice, &deframerStatus)); - } - /*** < Action: When links have been verified, proceed > ***/ - - /*************************************************************************/ - /***** Mykonos enable tracking calibrations *****/ - /*************************************************************************/ - - call_mykonos_api(std::bind(MYKONOS_enableTrackingCals, mykDevice, trackingCalMask)); - - /*** < Info: Allow Rx1/2 QEC tracking and Tx1/2 QEC tracking to run when in the radioOn state - * Tx calibrations will only run if radioOn and the obsRx path is set to OBS_INTERNAL_CALS > ***/ - - /*** < Info: Function to turn radio on, Enables transmitters and receivers - * that were setup during MYKONOS_initialize() > ***/ - - call_mykonos_api(std::bind(MYKONOS_radioOn, mykDevice)); - /*** < Info: Allow TxQEC to run when User: is not actively using ORx receive path > ***/ - call_mykonos_api(std::bind(MYKONOS_setObsRxPathSource, mykDevice, OBS_RXOFF)); - call_mykonos_api(std::bind(MYKONOS_setObsRxPathSource, mykDevice, OBS_INTERNALCALS)); - - return 0; -} diff --git a/mpm/lib/mykonos/adi_sample/headless.h b/mpm/lib/mykonos/adi_sample/headless.h deleted file mode 100644 index abdfb65bf..000000000 --- a/mpm/lib/mykonos/adi_sample/headless.h +++ /dev/null @@ -1,10 +0,0 @@ -/** - * \file headless.h - * - * \brief Contains definitions for headless.c -*/ -#pragma once - -#include "mykonos_static_config.h" - -int headlessinit(mykonosDevice_t *mykDevice); diff --git a/mpm/lib/mykonos/adi_sample/mykonos_static_config.c b/mpm/lib/mykonos/adi_sample/mykonos_static_config.c deleted file mode 100644 index 1a70963aa..000000000 --- a/mpm/lib/mykonos/adi_sample/mykonos_static_config.c +++ /dev/null @@ -1,516 +0,0 @@ -/** - * \brief Contains init setting structure declarations for the _instance API - * - * The top level structure mykonosDevice_t mykDevice uses keyword - * extern to allow the application layer main() to have visibility - * to these settings. - * - * All data structures required for operation have been initialized with values which reflect these settings: - * - * Device Clock: - * 125MHz - * - * Profiles: - * Rx 100MHz, IQrate 125MSPS, Dec5 - * Tx 20/100MHz, IQrate 125MSPS, Dec5 - * ORX 100MHz, IQrate 125MSPS, Dec5 - * SRx 20MHz, IQrate 31.25MSPS, Dec5 - * - */ - -#include "mykonos_static_config.h" -#include "../adi/t_mykonos_gpio.h" -#include <stddef.h> - -static int16_t txFirCoefs[] = {-94,-26,282,177,-438,-368,756,732,-1170,-1337,1758,2479,-2648,-5088,4064,16760,16759,4110,-4881,-2247,2888,1917,-1440,-1296,745,828,-358,-474,164,298,-16,-94}; - -static mykonosFir_t txFir = -{ - 6, /* Filter gain in dB*/ - 32, /* Number of coefficients in the FIR filter*/ - &txFirCoefs[0] /* A pointer to an array of filter coefficients*/ -}; - -static int16_t rxFirCoefs[] = {-20,6,66,22,-128,-54,240,126,-402,-248,634,444,-956,-756,1400,1244,-2028,-2050,2978,3538,-4646,-7046,9536,30880,30880,9536,-7046,-4646,3538,2978,-2050,-2028,1244,1400,-756,-956,444,634,-248,-402,126,240,-54,-128,22,66,6,-20}; - -static mykonosFir_t rxFir = -{ - -6, /* Filter gain in dB*/ - 48, /* Number of coefficients in the FIR filter*/ - &rxFirCoefs[0] /* A pointer to an array of filter coefficients*/ -}; - -static int16_t obsrxFirCoefs[] = {-14,-19,44,41,-89,-95,175,178,-303,-317,499,527,-779,-843,1184,1317,-1781,-2059,2760,3350,-4962,-7433,9822,32154,32154,9822,-7433,-4962,3350,2760,-2059,-1781,1317,1184,-843,-779,527,499,-317,-303,178,175,-95,-89,41,44,-19,-14}; -static mykonosFir_t obsrxFir = -{ - -6, /* Filter gain in dB*/ - 48, /* Number of coefficients in the FIR filter*/ - &obsrxFirCoefs[0]/* A pointer to an array of filter coefficients*/ -}; - -static int16_t snifferFirCoefs[] = {-1,-5,-14,-23,-16,24,92,137,80,-120,-378,-471,-174,507,1174,1183,98,-1771,-3216,-2641,942,7027,13533,17738,17738,13533,7027,942,-2641,-3216,-1771,98,1183,1174,507,-174,-471,-378,-120,80,137,92,24,-16,-23,-14,-5,-1}; -static mykonosFir_t snifferRxFir= -{ - -6, /* Filter gain in dB*/ - 48, /* Number of coefficients in the FIR filter*/ - &snifferFirCoefs[0]/* A pointer to an array of filter coefficients*/ -}; - -static mykonosJesd204bFramerConfig_t rxFramer = -{ - 0, /* JESD204B Configuration Bank ID -extension to Device ID (Valid 0..15)*/ - 0, /* JESD204B Configuration Device ID - link identification number. (Valid 0..255)*/ - 0, /* JESD204B Configuration starting Lane ID. If more than one lane used, each lane will increment from the Lane0 ID. (Valid 0..31)*/ - 4, /* number of ADCs (0, 2, or 4) - 2 ADCs per receive chain*/ - 32, /* number of frames in a multiframe (default=32), F*K must be a multiple of 4. (F=2*M/numberOfLanes)*/ - 1, /* scrambling off if framerScramble= 0, if framerScramble>0 scramble is enabled.*/ - 1, /* 0=use internal SYSREF, 1= use external SYSREF*/ - 0x0F, /* serializerLanesEnabled - bit per lane, [0] = Lane0 enabled, [1] = Lane1 enabled*/ - 0xE4, /* serializerLaneCrossbar*/ - 22, /* serializerAmplitude - default 22 (valid (0-31)*/ - 4, /* preEmphasis - < default 4 (valid 0 - 7)*/ - 0, /* invertLanePolarity - default 0 ([0] will invert lane [0], bit1 will invert lane1)*/ - 0, /* lmfcOffset - LMFC_Offset offset value for deterministic latency setting*/ - 0, /* Flag for determining if SYSREF on relink should be set. Where, if > 0 = set, 0 = not set*/ - 0, /* Flag for determining if auto channel select for the xbar should be set. Where, if > 0 = set, '0' = not set*/ - 0, /* Selects SYNCb input source. Where, 0 = use RXSYNCB for this framer, 1 = use OBSRX_SYNCB for this framer*/ - 0, /* Flag for determining if CMOS mode for RX Sync signal is used. Where, if > 0 = CMOS, '0' = LVDS*/ - 0 /* Selects framer bit repeat or oversampling mode for lane rate matching. Where, 0 = bitRepeat mode (changes effective lanerate), 1 = overSample (maintains same lane rate between ObsRx framer and Rx framer and oversamples the ADC samples)*/ -}; - -static mykonosJesd204bFramerConfig_t obsRxFramer = -{ - 0, /* JESD204B Configuration Bank ID -extension to Device ID (Valid 0..15)*/ - 0, /* JESD204B Configuration Device ID - link identification number. (Valid 0..255)*/ - 0, /* JESD204B Configuration starting Lane ID. If more than one lane used, each lane will increment from the Lane0 ID. (Valid 0..31)*/ - 2, /* number of ADCs (0, 2, or 4) - 2 ADCs per receive chain*/ - 32, /* number of frames in a multiframe (default=32), F*K must be a multiple of 4. (F=2*M/numberOfLanes)*/ - 1, /* scrambling off if framerScramble= 0, if framerScramble>0 scramble is enabled.*/ - 1, /* 0=use internal SYSREF, 1= use external SYSREF*/ - 0x00, /* serializerLanesEnabled - bit per lane, [0] = Lane0 enabled, [1] = Lane1 enabled*/ - 0xE4, /* Lane crossbar to map framer lane outputs to physical lanes*/ - 22, /* serializerAmplitude - default 22 (valid (0-31)*/ - 4, /* preEmphasis - < default 4 (valid 0 - 7)*/ - 0, /* invertLanePolarity - default 0 ([0] will invert lane [0], bit1 will invert lane1)*/ - 0, /* lmfcOffset - LMFC_Offset offset value for deterministic latency setting*/ - 0, /* Flag for determining if SYSREF on relink should be set. Where, if > 0 = set, 0 = not set*/ - 0, /* Flag for determining if auto channel select for the xbar should be set. Where, if > 0 = set, '0' = not set*/ - 1, /* Selects SYNCb input source. Where, 0 = use RXSYNCB for this framer, 1 = use OBSRX_SYNCB for this framer*/ - 0, /* Flag for determining if CMOS mode for RX Sync signal is used. Where, if > 0 = CMOS, '0' = LVDS*/ - 1 /* Selects framer bit repeat or oversampling mode for lane rate matching. Where, 0 = bitRepeat mode (changes effective lanerate), 1 = overSample (maintains same lane rate between ObsRx framer and Rx framer and oversamples the ADC samples)*/ -}; - -static mykonosJesd204bDeframerConfig_t deframer = -{ - 0, /* bankId extension to Device ID (Valid 0..15)*/ - 0, /* deviceId link identification number. (Valid 0..255)*/ - 0, /* lane0Id Lane0 ID. (Valid 0..31)*/ - 4, /* M number of DACss (0, 2, or 4) - 2 DACs per transmit chain */ - 32, /* K #frames in a multiframe (default=32), F*K=multiple of 4. (F=2*M/numberOfLanes)*/ - 1, /* scramble scrambling off if scramble= 0.*/ - 1, /* External SYSREF select. 0 = use internal SYSREF, 1 = external SYSREF*/ - 0x0F, /* Deserializer lane select bit field. Where, [0] = Lane0 enabled, [1] = Lane1 enabled, etc */ - 0xE4, /* Lane crossbar to map physical lanes to deframer lane inputs [1:0] = Deframer Input 0 Lane section, [3:2] = Deframer Input 1 lane select, etc */ - 1, /* Equalizer setting. Applied to all deserializer lanes. Range is 0..4*/ - 0, /* PN inversion per each lane. bit[0] = 1 Invert PN of Lane 0, bit[1] = Invert PN of Lane 1, etc).*/ - 0, /* LMFC_Offset offset value to adjust deterministic latency. Range is 0..31*/ - 0, /* Flag for determining if SYSREF on relink should be set. Where, if > 0 = set, '0' = not set*/ - 0, /* Flag for determining if auto channel select for the xbar should be set. Where, if > 0 = set, '0' = not set*/ - 0 /* Flag for determining if CMOS mode for TX Sync signal is used. Where, if > 0 = CMOS, '0' = LVDS*/ -}; - -static mykonosRxGainControl_t rxGainControl = -{ - MGC, /* Current Rx gain control mode setting*/ - 255, /* Rx1 Gain Index, can be used in different ways for manual and AGC gain control*/ - 255, /* Rx2 Gain Index, can be used in different ways for manual and AGC gain control*/ - 255, /* Max gain index for the currently loaded Rx1 Gain table*/ - 195, /* Min gain index for the currently loaded Rx1 Gain table*/ - 255, /* Max gain index for the currently loaded Rx2 Gain table*/ - 195, /* Min gain index for the currently loaded Rx2 Gain table*/ - 0, /* Stores Rx1 RSSI value read back from the Mykonos*/ - 0 /* Stores Rx2 RSSI value read back from the Mykonos*/ -}; - -static mykonosORxGainControl_t orxGainControl = -{ - MGC, /* Current ORx gain control mode setting*/ - 255, /* ORx1 Gain Index, can be used in different ways for manual and AGC gain control*/ - 255, /* ORx2 Gain Index, can be used in different ways for manual and AGC gain control*/ - 255, /* Max gain index for the currently loaded ORx Gain table*/ - 237 /* Min gain index for the currently loaded ORx Gain table*/ -}; - -static mykonosSnifferGainControl_t snifferGainControl = -{ - MGC, /* Current Sniffer gain control mode setting*/ - 255, /* Current Sniffer gain index. Can be used differently for MANUAL Gain control/AGC*/ - 255, /* Max gain index for the currently loaded Sniffer Gain table*/ - 203 /* Min gain index for the currently loaded Sniffer Gain table*/ -}; - -static mykonosPeakDetAgcCfg_t rxPeakAgc = -{ - 0x00, /* apdHighThresh: */ - 0x00, /* apdLowThresh */ - 0x00, /* hb2HighThresh */ - 0x00, /* hb2LowThresh */ - 0x00, /* hb2VeryLowThresh */ - 0x00, /* apdHighThreshExceededCnt */ - 0x00, /* apdLowThreshExceededCnt */ - 0x00, /* hb2HighThreshExceededCnt */ - 0x00, /* hb2LowThreshExceededCnt */ - 0x00, /* hb2VeryLowThreshExceededCnt */ - 0x0, /* apdHighGainStepAttack */ - 0x0, /* apdLowGainStepRecovery */ - 0x0, /* hb2HighGainStepAttack */ - 0x0, /* hb2LowGainStepRecovery */ - 0x0, /* hb2VeryLowGainStepRecovery */ - 0x0, /* apdFastAttack */ - 0x0, /* hb2FastAttack */ - 0x0, /* hb2OverloadDetectEnable */ - 0x0, /* hb2OverloadDurationCnt */ - 0x0 /* hb2OverloadThreshCnt */ -}; - -static mykonosPowerMeasAgcCfg_t rxPwrAgc = -{ - 0x00, /* pmdUpperHighThresh */ - 0x00, /* pmdUpperLowThresh */ - 0x00, /* pmdLowerHighThresh */ - 0x00, /* pmdLowerLowThresh */ - 0x0, /* pmdUpperHighGainStepAttack */ - 0x0, /* pmdUpperLowGainStepAttack */ - 0x0, /* pmdLowerHighGainStepRecovery */ - 0x0, /* pmdLowerLowGainStepRecovery */ - 0x00, /* pmdMeasDuration */ - 0x00 /* pmdMeasConfig */ -}; - -static mykonosAgcCfg_t rxAgcConfig = -{ - 0, /* agcRx1MaxGainIndex */ - 0, /* agcRx1MinGainIndex */ - 0, /* agcRx2MaxGainIndex */ - 0, /* agcRx2MinGainIndex: */ - 0, /* agcObsRxMaxGainIndex */ - 0, /* agcObsRxMinGainIndex */ - 0, /* agcObsRxSelect */ - 0, /* agcPeakThresholdMode */ - 0, /* agcLowThsPreventGainIncrease */ - 0, /* agcGainUpdateCounter */ - 0, /* agcSlowLoopSettlingDelay */ - 0, /* agcPeakWaitTime */ - 0, /* agcResetOnRxEnable */ - 0, /* agcEnableSyncPulseForGainCounter */ - &rxPeakAgc, - &rxPwrAgc -}; - -static mykonosPeakDetAgcCfg_t obsRxPeakAgc = -{ - 0x00, /* apdHighThresh: */ - 0x00, /* apdLowThresh */ - 0x00, /* hb2HighThresh */ - 0x00, /* hb2LowThresh */ - 0x00, /* hb2VeryLowThresh */ - 0x00, /* apdHighThreshExceededCnt */ - 0x00, /* apdLowThreshExceededCnt */ - 0x00, /* hb2HighThreshExceededCnt */ - 0x00, /* hb2LowThreshExceededCnt */ - 0x00, /* hb2VeryLowThreshExceededCnt */ - 0x0, /* apdHighGainStepAttack */ - 0x0, /* apdLowGainStepRecovery */ - 0x0, /* hb2HighGainStepAttack */ - 0x0, /* hb2LowGainStepRecovery */ - 0x0, /* hb2VeryLowGainStepRecovery */ - 0x0, /* apdFastAttack */ - 0x0, /* hb2FastAttack */ - 0x0, /* hb2OverloadDetectEnable */ - 0x0, /* hb2OverloadDurationCnt */ - 0x0 /* hb2OverloadThreshCnt */ -}; - -static mykonosPowerMeasAgcCfg_t obsRxPwrAgc = -{ - 0x00, /* pmdUpperHighThresh */ - 0x00, /* pmdUpperLowThresh */ - 0x00, /* pmdLowerHighThresh */ - 0x00, /* pmdLowerLowThresh */ - 0x0, /* pmdUpperHighGainStepAttack */ - 0x0, /* pmdUpperLowGainStepAttack */ - 0x0, /* pmdLowerHighGainStepRecovery */ - 0x0, /* pmdLowerLowGainStepRecovery */ - 0x00, /* pmdMeasDuration */ - 0x00 /* pmdMeasConfig */ -}; - -static mykonosAgcCfg_t obsRxAgcConfig = -{ - 0, /* agcRx1MaxGainIndex */ - 0, /* agcRx1MinGainIndex */ - 0, /* agcRx2MaxGainIndex */ - 0, /* agcRx2MinGainIndex: */ - 0, /* agcObsRxMaxGainIndex */ - 0, /* agcObsRxMinGainIndex */ - 0, /* agcObsRxSelect */ - 0, /* agcPeakThresholdMode */ - 0, /* agcLowThsPreventGainIncrease */ - 0, /* agcGainUpdateCounter */ - 0, /* agcSlowLoopSettlingDelay */ - 0, /* agcPeakWaitTime */ - 0, /* agcResetOnRxEnable */ - 0, /* agcEnableSyncPulseForGainCounter */ - &obsRxPeakAgc, - &obsRxPwrAgc -}; - - -static mykonosRxProfile_t rxProfile = -{/* Rx 100MHz, IQrate 125MSPS, Dec5 */ - 1, /* The divider used to generate the ADC clock*/ - &rxFir, /* Pointer to Rx FIR filter structure*/ - 2, /* Rx FIR decimation (1,2,4)*/ - 5, /* Decimation of Dec5 or Dec4 filter (5,4)*/ - 1, /* If set, and DEC5 filter used, will use a higher rejection DEC5 FIR filter (1=Enabled, 0=Disabled)*/ - 1, /* RX Half band 1 decimation (1 or 2)*/ - 125000, /* Rx IQ data rate in kHz*/ - 100000000, /* The Rx RF passband bandwidth for the profile*/ - 102000, /* Rx BBF 3dB corner in kHz*/ - NULL /* pointer to custom ADC profile*/ -}; - -static mykonosRxProfile_t orxProfile = -{/* ORX 100MHz, IQrate 125MSPS, Dec5 */ - 1, /* The divider used to generate the ADC clock*/ - &obsrxFir, /* Pointer to Rx FIR filter structure or NULL*/ - 2, /* Rx FIR decimation (1,2,4)*/ - 5, /* Decimation of Dec5 or Dec4 filter (5,4)*/ - 0, /* If set, and DEC5 filter used, will use a higher rejection DEC5 FIR filter (1=Enabled, 0=Disabled)*/ - 1, /* RX Half band 1 decimation (1 or 2)*/ - 125000, /* Rx IQ data rate in kHz*/ - 100000000, /* The Rx RF passband bandwidth for the profile*/ - 102000, /* Rx BBF 3dB corner in kHz*/ - NULL /* pointer to custom ADC profile*/ -}; - - -static mykonosRxProfile_t snifferProfile = -{ /* SRx 20MHz, IQrate 31.25MSPS, Dec5 */ - 1, /* The divider used to generate the ADC clock*/ - &snifferRxFir, /* Pointer to Rx FIR filter structure or NULL*/ - 4, /* Rx FIR decimation (1,2,4)*/ - 5, /* Decimation of Dec5 or Dec4 filter (5,4)*/ - 0, /* If set, and DEC5 filter used, will use a higher rejection DEC5 FIR filter (1=Enabled, 0=Disabled)*/ - 2, /* RX Half band 1 decimation (1 or 2)*/ - 31250, /* Rx IQ data rate in kHz*/ - 20000000, /* The Rx RF passband bandwidth for the profile*/ - 100000, /* Rx BBF 3dB corner in kHz*/ - NULL /* pointer to custom ADC profile*/ -}; - - - -static mykonosTxProfile_t txProfile = -{ /* Tx 20/100MHz, IQrate 125MSPS, Dec5 */ - DACDIV_2p5, /* The divider used to generate the DAC clock*/ - &txFir, /* Pointer to Tx FIR filter structure*/ - 2, /* The Tx digital FIR filter interpolation (1,2,4)*/ - 2, /* Tx Halfband1 filter interpolation (1,2)*/ - 1, /* Tx Halfband2 filter interpolation (1,2)*/ - 1, /* TxInputHbInterpolation (1,2)*/ - 125000, /* Tx IQ data rate in kHz*/ - 20000000, /* Primary Signal BW*/ - 102000000, /* The Tx RF passband bandwidth for the profile*/ - 722000, /* The DAC filter 3dB corner in kHz*/ - 51000, /* Tx BBF 3dB corner in kHz*/ - 0 /* Enable DPD, only valid for AD9373*/ -}; - -static mykonosDigClocks_t mykonosClocks = -{ - 125000, /* CLKPLL and device reference clock frequency in kHz*/ - 10000000, /* CLKPLL VCO frequency in kHz*/ - VCODIV_2, /* CLKPLL VCO divider*/ - 4 /* CLKPLL high speed clock divider*/ -}; - -static mykonosRxSettings_t rxSettings = -{ - &rxProfile, /* Rx datapath profile, 3dB corner frequencies, and digital filter enables*/ - &rxFramer, /* Rx JESD204b framer configuration structure*/ - &rxGainControl, /* Rx Gain control settings structure*/ - &rxAgcConfig, /* Rx AGC control settings structure*/ - 3, /* The desired Rx Channels to enable during initialization*/ - 0, /* Internal LO = 0, external LO*2 = 1*/ - 2550000000U, /* Rx PLL LO Frequency (internal or external LO)*/ - 0 /* Flag to choose if complex baseband or real IF data are selected for Rx and ObsRx paths. Where, if > 0 = real IF data, '0' = zero IF (IQ) data*/ -}; - -static mykonosDpdConfig_t dpdConfig = -{ - 5, /* 1/2^(damping + 8) fraction of power `forgotten' per sample (default: `1/8192' = 5, valid 0 to 15), 0 = infinite damping*/ - 1, /* number of weights to use for int8_cpx weights weights member of this structure (default = 1)*/ - 2, /* DPD model version: one of four different generalized polynomial models: 0 = same as R0 silicon, 1-3 are new and the best one depends on the PA (default: 2)*/ - 1, /* 1 = Update saved model whenever peak Tx digital RMS is within 1dB of historical peak Tx RMS*/ - 20, /* Determines how much weight the loaded prior model has on DPD modeling (Valid 0 - 32, default 20)*/ - 0, /* Default off = 0, 1=enables automatic outlier removal during DPD modeling */ - 512, /* Number of samples to capture (default: 512, valid 64-32768)*/ - 4096, /* threshold for sample in AM-AM plot outside of 1:1 line to be thrown out. (default: 50% = 8192/2, valid 8192 to 1)*/ - 0, /* 16th of an ORx sample (16=1sample), (default 0, valid -64 to 64)*/ - 255, /* Default 255 (-30dBFs=(20Log10(value/8192)), (valid range 1 to 8191)*/ - {{64,0},{0,0},{0,0}}/* DPD model error weighting (real/imag valid from -128 to 127)*/ -}; - -static mykonosClgcConfig_t clgcConfig = -{ - -2000, /* (value = 100 * dB (valid range -32768 to 32767) - total gain and attenuation from Mykonos Tx1 output to ORx1 input in (dB * 100)*/ - -2000, /* (value = 100 * dB (valid range -32768 to 32767) - total gain and attenuation from Mykonos Tx2 output to ORx2 input in (dB * 100)*/ - 0, /* (valid range 0 - 40dB), no default, depends on PA, Protects PA by making sure Tx1Atten is not reduced below the limit*/ - 0, /* (valid range 0 - 40dB), no default, depends on PA, Protects PA by making sure Tx2Atten is not reduced below the limit*/ - 75, /* valid range 1-100, default 75*/ - 75, /* valid range 1-100, default 45*/ - 0, /* 0= allow CLGC to run, but Tx1Atten will not be updated. User can still read back power measurements. 1=CLGC runs, and Tx1Atten automatically updated*/ - 0, /* 0= allow CLGC to run, but Tx2Atten will not be updated. User can still read back power measurements. 1=CLGC runs, and Tx2Atten automatically updated*/ - 0, /* 16th of an ORx sample (16=1sample), (default 0, valid -64 to 64)*/ - 255 /* Default 255 (-30dBFs=(20Log10(value/8192)), (valid range 1 to 8191)*/ -}; - -static mykonosVswrConfig_t vswrConfig = -{ - 0, /* 16th of an ORx sample (16=1sample), (default 0, valid -64 to 64)*/ - 255, /* Default 255 (-30dBFs=(20Log10(value/8192)), (valid range 1 to 8191)*/ - 0, /* 3p3V GPIO pin to use to control VSWR switch for Tx1 (valid 0-11) (output from Mykonos)*/ - 1, /* 3p3V GPIO pin to use to control VSWR switch for Tx2 (valid 0-11) (output from Mykonos)*/ - 0, /* 3p3v GPIO pin polarity for forward path of Tx1, opposite used for reflection path (1 = high level, 0 = low level)*/ - 0, /* 3p3v GPIO pin polarity for forward path of Tx2, opposite used for reflection path (1 = high level, 0 = low level)*/ - 1, /* Delay for Tx1 after flipping the VSWR switch until measurement is made. In ms resolution*/ - 1 /* Delay for Tx2 after flipping the VSWR switch until measurement is made. In ms resolution*/ -}; - -static mykonosTxSettings_t txSettings = -{ - &txProfile, /* Tx datapath profile, 3dB corner frequencies, and digital filter enables*/ - &deframer, /* Mykonos JESD204b deframer config for the Tx data path*/ - TX1_TX2, /* The desired Tx channels to enable during initialization*/ - 0, /* Internal LO=0, external LO*2 if =1*/ - 2500000000U, /* Tx PLL LO frequency (internal or external LO)*/ - TXATTEN_0P05_DB,/* Initial and current Tx1 Attenuation*/ - 10000, /* Initial and current Tx1 Attenuation mdB*/ - 10000, /* Initial and current Tx2 Attenuation mdB*/ - NULL, /* DPD,CLGC,VSWR settings. Only valid for AD9373 device, set pointer to NULL otherwise*/ - NULL, /* CLGC Config Structure. Only valid for AD9373 device, set pointer to NULL otherwise*/ - NULL /* VSWR Config Structure. Only valid for AD9373 device, set pointer to NULL otherwise*/ -}; - - -static mykonosObsRxSettings_t obsRxSettings = -{ - &orxProfile, /* ORx datapath profile, 3dB corner frequencies, and digital filter enables*/ - &orxGainControl,/* ObsRx gain control settings structure*/ - &obsRxAgcConfig,/* ORx AGC control settings structure*/ - &snifferProfile,/* Sniffer datapath profile, 3dB corner frequencies, and digital filter enables*/ - &snifferGainControl,/* SnRx gain control settings structure*/ - &obsRxFramer, /* ObsRx JESD204b framer configuration structure */ - (MYK_ORX1_ORX2 | MYK_SNRXA_B_C),/* obsRxChannel */ - OBSLO_TX_PLL, /* (obsRxLoSource) The Obs Rx mixer can use the Tx Synth(TX_PLL) or Sniffer Synth (SNIFFER_PLL) */ - 2600000000U, /* SnRx PLL LO frequency in Hz */ - 0, /* Flag to choose if complex baseband or real IF data are selected for Rx and ObsRx paths. Where if > 0 = real IF data, '0' = complex data*/ - NULL, /* Custom Loopback ADC profile to set the bandwidth of the ADC response */ - OBS_RXOFF /* Default ObsRx channel to enter when radioOn called */ -}; - -static mykonosArmGpioConfig_t armGpio = -{ - 0, // useRx2EnablePin; /*!< 0= RX1_ENABLE controls RX1 and RX2, 1 = separate RX1_ENABLE/RX2_ENABLE pins */ - 0, // useTx2EnablePin; /*!< 0= TX1_ENABLE controls TX1 and TX2, 1 = separate TX1_ENABLE/TX2_ENABLE pins */ - 0, // txRxPinMode; /*!< 0= ARM command mode, 1 = Pin mode to power up Tx/Rx chains */ - 0, // orxPinMode; /*!< 0= ARM command mode, 1 = Pin mode to power up ObsRx receiver*/ - - /*Mykonos ARM input GPIO pins -- Only valid if orxPinMode = 1 */ - 0, // orxTriggerPin; /*!< Select desired GPIO pin (valid 4-15) */ - 0, // orxMode2Pin; /*!< Select desired GPIO pin (valid 0-18) */ - 0, // orxMode1Pin; /*!< Select desired GPIO pin (valid 0-18) */ - 0, // orxMode0Pin; /*!< Select desired GPIO pin (valid 0-18) */ - - /* Mykonos ARM output GPIO pins -- always available, even when pin mode not enabled*/ - 0, // rx1EnableAck; /*!< Select desired GPIO pin (0-15), [4] = Output Enable */ - 0, // rx2EnableAck; /*!< Select desired GPIO pin (0-15), [4] = Output Enable */ - 0, // tx1EnableAck; /*!< Select desired GPIO pin (0-15), [4] = Output Enable */ - 0, // tx2EnableAck; /*!< Select desired GPIO pin (0-15), [4] = Output Enable */ - 0, // orx1EnableAck; /*!< Select desired GPIO pin (0-15), [4] = Output Enable */ - 0, // orx2EnableAck; /*!< Select desired GPIO pin (0-15), [4] = Output Enable */ - 0, // srxEnableAck; /*!< Select desired GPIO pin (0-15), [4] = Output Enable */ - 0 // txObsSelect; /*!< Select desired GPIO pin (0-15), [4] = Output Enable */ - /* When 2Tx are used with only 1 ORx input, this GPIO tells the BBIC which Tx channel is */ - /* active for calibrations, so BBIC can route correct RF Tx path into the single ORx input*/ -}; - -static mykonosGpio3v3_t gpio3v3 = -{ - 0, /*!< Oe per pin, 1=output, 0 = input */ - GPIO3V3_BITBANG_MODE, /*!< Mode for GPIO3V3[3:0] */ - GPIO3V3_BITBANG_MODE, /*!< Mode for GPIO3V3[7:4] */ - GPIO3V3_BITBANG_MODE, /*!< Mode for GPIO3V3[11:8] */ -}; - -static mykonosGpioLowVoltage_t gpio = -{ - 0,/* Oe per pin, 1=output, 0 = input */ - GPIO_MONITOR_MODE,/* Mode for GPIO[3:0] */ - GPIO_MONITOR_MODE,/* Mode for GPIO[7:4] */ - GPIO_MONITOR_MODE,/* Mode for GPIO[11:8] */ - GPIO_MONITOR_MODE,/* Mode for GPIO[15:12] */ - GPIO_MONITOR_MODE,/* Mode for GPIO[18:16] */ -}; - -static mykonosAuxIo_t mykonosAuxIo = -{ - 0, //auxDacEnableMask uint16_t - {0,0,0,0,0,0,0,0,0,0}, //AuxDacValue uint16[10] - {0,0,0,0,0,0,0,0,0,0}, //AuxDacSlope uint8[10] - {0,0,0,0,0,0,0,0,0,0}, //AuxDacVref uint8[10] - &gpio3v3, //pointer to gpio3v3 struct - &gpio, //pointer to gpio1v8 struct - &armGpio -}; - -static spiSettings_t mykSpiSettings = -{ - 1, /* chip select index - valid 1~8 */ - 0, /* the level of the write bit of a SPI write instruction word, value is inverted for SPI read operation */ - 1, /* 1 = 16-bit instruction word, 0 = 8-bit instruction word */ - 1, /* 1 = MSBFirst, 0 = LSBFirst */ - 0, /* clock phase, sets which clock edge the data updates (valid 0 or 1) */ - 0, /* clock polarity 0 = clock starts low, 1 = clock starts high */ - 0, /* Not implemented in ADIs platform layer. SW feature to improve SPI throughput */ - 1, /* Not implemented in ADIs platform layer. For SPI Streaming, set address increment direction. 1= next addr = addr+1, 0:addr=addr-1 */ - 1 /* 1: Use 4-wire SPI, 0: 3-wire SPI (SDIO pin is bidirectional). NOTE: ADI's FPGA platform always uses 4-wire mode */ -}; - -static mykonosTempSensorConfig_t tempSensor = -{ - 7, /* 3-bit value that controls the AuxADC decimation factor when used for temp sensor calculations; AuxADC_decimation = 256 * 2^tempDecimation*/ - 67, /* 8-bit offset that gets added to temp sensor code internally*/ - 1, /* this bit overrides the factory-calibrated fuse offset and uses the value stored in the offset member*/ - 15, /* 4-bit code with a resolution of 1°C/LSB, each time a temperature measurement is performed, the device compares the current temperature against the previous value.*/ -}; - -static mykonosTempSensorStatus_t tempStatus = -{ - 0, /* 16-bit signed temperature value (in deg C) that is read back*/ - 0, /* If the absolute value of the difference is greater than the value in temperature configuration tempWindow, the windowExceeded flag is set.*/ - 0, /* when windowExceeded member gets set, this bit is set to 1 if current value is greater than previous value, else reset*/ - 0, /* when the reading is complete and a valid temperature value stored in tempCode.*/ -}; - -mykonosDevice_t mykDevice = -{ - &mykSpiSettings, /* SPI settings data structure pointer */ - &rxSettings, /* Rx settings data structure pointer */ - &txSettings, /* Tx settings data structure pointer */ - &obsRxSettings, /* ObsRx settings data structure pointer */ - &mykonosAuxIo, /* Auxiliary IO settings data structure pointer */ - &mykonosClocks, /* Holds settings for CLKPLL and reference clock */ - 0 /* Mykonos initialize function uses this as an output to remember which profile data structure pointers are valid */ -}; diff --git a/mpm/lib/mykonos/adi_sample/mykonos_static_config.h b/mpm/lib/mykonos/adi_sample/mykonos_static_config.h deleted file mode 100644 index 8b919fe5b..000000000 --- a/mpm/lib/mykonos/adi_sample/mykonos_static_config.h +++ /dev/null @@ -1,18 +0,0 @@ -/** - * \file myk_init.h - * - * \brief Contains structure definitions for myk_init.c - * - * The top level structure mykonosDevice_t mykDevice uses keyword - * extern to allow the application layer main() to have visibility - * to these settings. - */ - -#ifndef MYK_INIT_H_ -#define MYK_INIT_H_ - -#include "../adi/t_mykonos.h" - -extern mykonosDevice_t mykDevice; - -#endif diff --git a/mpm/lib/mykonos/config/ad937x_config_t.cpp b/mpm/lib/mykonos/config/ad937x_config_t.cpp index 5cfe6351e..23d32a558 100644 --- a/mpm/lib/mykonos/config/ad937x_config_t.cpp +++ b/mpm/lib/mykonos/config/ad937x_config_t.cpp @@ -1,8 +1,27 @@ -#include "ad937x_config_t.h" -#include "mykonos_default_config.h" - -ad937x_config_t::ad937x_config_t() +// +// Copyright 2017 Ettus Research (National Instruments) +// +// 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 "ad937x_config_t.hpp" +#include "ad937x_default_config.hpp" + +ad937x_config_t::ad937x_config_t(spiSettings_t* sps) { + _device.spiSettings = sps; + _assign_default_configuration(); _init_pointers(); } @@ -59,33 +78,38 @@ void ad937x_config_t::_init_pointers() _device.clocks = &_clocks; _rx.rxProfile = &_rxProfile; - _rxProfile.rxFir = _rx_fir_config.getFir(); _rx.framer = &_framer; _rx.rxGainCtrl = &_rxGainCtrl; _rx.rxAgcCtrl = &_rxAgcCtrl; + _rxProfile.rxFir = rx_fir_config.fir; + _rxProfile.customAdcProfile = nullptr; _rxAgcCtrl.peakAgc = &_rxPeakAgc; _rxAgcCtrl.powerAgc = &_rxPowerAgc; _tx.txProfile = &_txProfile; - _txProfile.txFir = _tx_fir_config.getFir(); + _txProfile.txFir = tx_fir_config.fir; _tx.deframer = &_deframer; // AD9373 - //_tx.dpdConfig = &_dpdConfig; - //_tx.clgcConfig = &_clgcConfig; - //_tx.vswrConfig = &_vswrConfig; + _tx.dpdConfig = nullptr; + _tx.clgcConfig = nullptr; + _tx.vswrConfig = nullptr; + // TODO: ideally we set none of this information and leave the profile as nullptr + // Check that the API supports this _obsRx.orxProfile = &_orxProfile; - _orxProfile.rxFir = _orx_fir_config.getFir(); _obsRx.orxGainCtrl = &_orxGainCtrl; _obsRx.orxAgcCtrl = &_orxAgcCtrl; + _orxProfile.rxFir = _orx_fir_config.fir; + _orxProfile.customAdcProfile = nullptr; _orxAgcCtrl.peakAgc = &_orxPeakAgc; _orxAgcCtrl.powerAgc = &_orxPowerAgc; _obsRx.snifferProfile = &_snifferProfile; - _snifferProfile.rxFir = _sniffer_rx_fir_config.getFir(); + _snifferProfile.rxFir = _sniffer_rx_fir_config.fir; _obsRx.snifferGainCtrl = &_snifferGainCtrl; // sniffer has no AGC ctrl, so leave as null + _obsRx.orxAgcCtrl = nullptr; _obsRx.framer = &_orxFramer; _auxIo.gpio3v3 = &_gpio3v3; @@ -95,16 +119,10 @@ void ad937x_config_t::_init_pointers() void ad937x_config_t::_assign_firs() { - // TODO: In general, storing just these pointers could lead to Bad Stuff - // Consider if it would be helpful to enforce some pointer safety here - // (if that's even possible with the C API) - _rx_fir_config = { -6,{ 48, 0 } }; - _rxProfile.rxFir = _rx_fir_config.getFir(); - _tx_fir_config = { 6,{ 32, 0 } }; - _txProfile.txFir = _tx_fir_config.getFir(); - _orx_fir_config = { -6, { 48, 0 } }; - _orxProfile.rxFir = _orx_fir_config.getFir(); - _sniffer_rx_fir_config = { -6, { 48, 0 } }; - _snifferProfile.rxFir = _sniffer_rx_fir_config.getFir(); + // TODO: get default filters here + tx_fir_config.set_fir(6, { 32, 0 }); + rx_fir_config.set_fir( -6,{ 48, 0 }); + _orx_fir_config.set_fir( -6, { 48, 0 }); + _sniffer_rx_fir_config.set_fir( -6, { 48, 0 }); } diff --git a/mpm/lib/mykonos/config/ad937x_config_t.hpp b/mpm/lib/mykonos/config/ad937x_config_t.hpp index 5375e0867..1d8072244 100644 --- a/mpm/lib/mykonos/config/ad937x_config_t.hpp +++ b/mpm/lib/mykonos/config/ad937x_config_t.hpp @@ -1,21 +1,43 @@ +// +// Copyright 2017 Ettus Research (National Instruments) +// +// 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/>. +// + #pragma once #include "../adi/t_mykonos.h" -#include "ad937x_fir.h" +#include "ad937x_fir.hpp" #include <boost/noncopyable.hpp> // This class exists so that the entire mykonos config can be allocated and managed together -class ad937x_device : public boost::noncopyable +class ad937x_config_t : public boost::noncopyable { // The top level device struct contains all other structs, so everything is technically "public" // a user could technically modify the pointers in the structs, but we have no way of preventing that public: - ad937x_device(); + ad937x_config_t(spiSettings_t* sps); mykonosDevice_t * const device = &_device; + ad937x_fir rx_fir_config; + ad937x_fir tx_fir_config; private: mykonosDevice_t _device; + ad937x_fir _orx_fir_config; + ad937x_fir _sniffer_rx_fir_config; + // in general, this organization stinks // TODO: group and make more sense of these fields and pointers spiSettings_t _spiSettings; @@ -24,35 +46,26 @@ private: mykonosObsRxSettings_t _obsRx; mykonosAuxIo_t _auxIo; mykonosDigClocks_t _clocks; - - ad937x_fir _rx_fir_config; + mykonosRxProfile_t _rxProfile; - std::vector<uint16_t> _customRxAdcProfile; mykonosJesd204bFramerConfig_t _framer; mykonosRxGainControl_t _rxGainCtrl; mykonosAgcCfg_t _rxAgcCtrl; mykonosPeakDetAgcCfg_t _rxPeakAgc; mykonosPowerMeasAgcCfg_t _rxPowerAgc; - - ad937x_fir _tx_fir_config; + mykonosTxProfile_t _txProfile; mykonosJesd204bDeframerConfig_t _deframer; - mykonosDpdConfig_t _dpdConfig; - mykonosClgcConfig_t _clgcConfig; - mykonosVswrConfig_t _vswrConfig; - - ad937x_fir _orx_fir_config; + mykonosRxProfile_t _orxProfile; mykonosORxGainControl_t _orxGainCtrl; mykonosAgcCfg_t _orxAgcCtrl; mykonosPeakDetAgcCfg_t _orxPeakAgc; mykonosPowerMeasAgcCfg_t _orxPowerAgc; - - ad937x_fir _sniffer_rx_fir_config; + mykonosRxProfile_t _snifferProfile; mykonosSnifferGainControl_t _snifferGainCtrl; mykonosJesd204bFramerConfig_t _orxFramer; - std::vector<uint16_t> _customORxAdcProfile; mykonosGpio3v3_t _gpio3v3; mykonosGpioLowVoltage_t _gpio; diff --git a/mpm/lib/mykonos/config/ad937x_default_config.hpp b/mpm/lib/mykonos/config/ad937x_default_config.hpp new file mode 100644 index 000000000..6cdbeacfe --- /dev/null +++ b/mpm/lib/mykonos/config/ad937x_default_config.hpp @@ -0,0 +1,376 @@ +// +// Copyright 2017 Ettus Research (National Instruments) +// +// 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 "../adi/t_mykonos.h" + +// This file is more or less the static config provided by a run of the eval software +// except all pointers have been changed to nullptr +// Hopefully this helps the compiler use these as purely constants +// The pointers should be filled in if these data structures are to be actually used with the API + +static const mykonosRxSettings_t DEFAULT_RX_SETTINGS = +{ + nullptr, // Rx datapath profile, 3dB corner frequencies, and digital filter enables + nullptr, // Rx JESD204b framer configuration structure + nullptr, // Rx Gain control settings structure + nullptr, // Rx AGC control settings structure + RX1_RX2, // The desired Rx Channels to enable during initialization + 0, // Internal LO = 0, external LO*2 = 1 + 3500000000U, // Rx PLL LO Frequency (internal or external LO) + 0 // Flag to choose if complex baseband or real IF data are selected for Rx and ObsRx paths. Where, if > 0 = real IF data, '0' = zero IF (IQ) data +}; + +static const mykonosRxProfile_t DEFAULT_RX_PROFILE = +{ // Rx 100MHz, IQrate 122.88MHz, Dec5 + 1, // The divider used to generate the ADC clock + nullptr, // Pointer to Rx FIR filter structure + 2, // Rx FIR decimation (1,2,4) + 5, // Decimation of Dec5 or Dec4 filter (5,4) + 1, // If set, and DEC5 filter used, will use a higher rejection DEC5 FIR filter (1=Enabled, 0=Disabled) + 1, // RX Half band 1 decimation (1 or 2) + 122880, // Rx IQ data rate in kHz + 100000000, // The Rx RF passband bandwidth for the profile + 100000, // Rx BBF 3dB corner in kHz + NULL // pointer to custom ADC profile +}; + +static const mykonosJesd204bFramerConfig_t DEFAULT_FRAMER = +{ + 0, // JESD204B Configuration Bank ID -extension to Device ID (Valid 0..15) + 0, // JESD204B Configuration Device ID - link identification number. (Valid 0..255) + 0, // JESD204B Configuration starting Lane ID. If more than one lane used, each lane will increment from the Lane0 ID. (Valid 0..31) + 4, // number of ADCs (0, 2, or 4) - 2 ADCs per receive chain + 32, // number of frames in a multiframe (default=32), F*K must be a multiple of 4. (F=2*M/numberOfLanes) + 1, // scrambling off if framerScramble= 0, if framerScramble>0 scramble is enabled. + 1, // 0=use internal SYSREF, 1= use external SYSREF + 0x0F, // serializerLanesEnabled - bit per lane, [0] = Lane0 enabled, [1] = Lane1 enabled + 0xE4, // serializerLaneCrossbar + 26, // serializerAmplitude - default 22 (valid (0-31) + 0, // preEmphasis - < default 4 (valid 0 - 7) + 0, // invertLanePolarity - default 0 ([0] will invert lane [0], bit1 will invert lane1) + 0, // lmfcOffset - LMFC offset value for deterministic latency setting + 0, // Flag for determining if SYSREF on relink should be set. Where, if > 0 = set, 0 = not set + 0, // Flag for determining if auto channel select for the xbar should be set. Where, if > 0 = set, '0' = not set + 0, // Selects SYNCb input source. Where, 0 = use RXSYNCB for this framer, 1 = use OBSRX_SYNCB for this framer + 0, // Flag for determining if CMOS mode for RX Sync signal is used. Where, if > 0 = CMOS, '0' = LVDS + 0 // Selects framer bit repeat or oversampling mode for lane rate matching. Where, 0 = bitRepeat mode (changes effective lanerate), 1 = overSample (maintains same lane rate between ObsRx framer and Rx framer and oversamples the ADC samples) +}; + +static const mykonosRxGainControl_t DEFAULT_RX_GAIN = +{ + MGC, // Current Rx gain control mode setting + 255, // Rx1 Gain Index, can be used in different ways for manual and AGC gain control + 255, // Rx2 Gain Index, can be used in different ways for manual and AGC gain control + 255, // Max gain index for the currently loaded Rx1 Gain table + 195, // Min gain index for the currently loaded Rx1 Gain table + 255, // Max gain index for the currently loaded Rx2 Gain table + 195, // Min gain index for the currently loaded Rx2 Gain table + 0, // Stores Rx1 RSSI value read back from the Mykonos + 0 // Stores Rx2 RSSI value read back from the Mykonos +}; + +static const mykonosPeakDetAgcCfg_t DEFAULT_RX_PEAK_AGC = +{ + 0x1F, // apdHighThresh: + 0x16, // apdLowThresh + 0xB5, // hb2HighThresh + 0x80, // hb2LowThresh + 0x40, // hb2VeryLowThresh + 0x06, // apdHighThreshExceededCnt + 0x04, // apdLowThreshExceededCnt + 0x06, // hb2HighThreshExceededCnt + 0x04, // hb2LowThreshExceededCnt + 0x04, // hb2VeryLowThreshExceededCnt + 0x4, // apdHighGainStepAttack + 0x2, // apdLowGainStepRecovery + 0x4, // hb2HighGainStepAttack + 0x2, // hb2LowGainStepRecovery + 0x4, // hb2VeryLowGainStepRecovery + 0x1, // apdFastAttack + 0x1, // hb2FastAttack + 0x1, // hb2OverloadDetectEnable + 0x1, // hb2OverloadDurationCnt + 0x1 // hb2OverloadThreshCnt +}; + +static const mykonosPowerMeasAgcCfg_t DEFAULT_RX_POWER_AGC = +{ + 0x01, // pmdUpperHighThresh + 0x03, // pmdUpperLowThresh + 0x0C, // pmdLowerHighThresh + 0x04, // pmdLowerLowThresh + 0x4, // pmdUpperHighGainStepAttack + 0x2, // pmdUpperLowGainStepAttack + 0x2, // pmdLowerHighGainStepRecovery + 0x4, // pmdLowerLowGainStepRecovery + 0x08, // pmdMeasDuration + 0x02 // pmdMeasConfig +}; + +static const mykonosAgcCfg_t DEFAULT_RX_AGC_CTRL = +{ + 255, // AGC peak wait time + 195, // agcRx1MinGainIndex + 255, // agcRx2MaxGainIndex + 195, // agcRx2MinGainIndex: + 255, // agcObsRxMaxGainIndex + 203, // agcObsRxMinGainIndex + 1, // agcObsRxSelect + 1, // agcPeakThresholdMode + 1, // agcLowThsPreventGainIncrease + 30720, // agcGainUpdateCounter + 3, // agcSlowLoopSettlingDelay + 2, // agcPeakWaitTime + 0, // agcResetOnRxEnable + 0, // agcEnableSyncPulseForGainCounter + nullptr,// *peakAgc + nullptr // *powerAgc +}; + +static const mykonosTxSettings_t DEFAULT_TX_SETTINGS = +{ + nullptr, // Tx datapath profile, 3dB corner frequencies, and digital filter enables + nullptr, // Mykonos JESD204b deframer config for the Tx data path + TX1_TX2, // The desired Tx channels to enable during initialization + 0, // Internal LO=0, external LO*2 if =1 + 3500000000U, // Tx PLL LO frequency (internal or external LO) + TXATTEN_0P05_DB,// Initial and current Tx1 Attenuation + 10000, // Initial and current Tx1 Attenuation mdB + 10000, // Initial and current Tx2 Attenuation mdB + nullptr, // DPD,CLGC,VSWR settings. Only valid for AD9373 device, set pointer to NULL otherwise + nullptr, // CLGC Config Structure. Only valid for AD9373 device, set pointer to NULL otherwise + nullptr // VSWR Config Structure. Only valid for AD9373 device, set pointer to NULL otherwise +}; + +static const mykonosTxProfile_t DEFAULT_TX_PROFILE = +{ // Tx 20/100MHz, IQrate 122.88MHz, Dec5 + DACDIV_2p5, // The divider used to generate the DAC clock + nullptr, // Pointer to Tx FIR filter structure + 2, // The Tx digital FIR filter interpolation (1,2,4) + 2, // Tx Halfband1 filter interpolation (1,2) + 1, // Tx Halfband2 filter interpolation (1,2) + 1, // TxInputHbInterpolation (1,2) + 122880, // Tx IQ data rate in kHz + 20000000, // Primary Signal BW + 100000000, // The Tx RF passband bandwidth for the profile + 710539, // The DAC filter 3dB corner in kHz + 50000, // Tx BBF 3dB corner in kHz + 0 // Enable DPD, only valid for AD9373 +}; + +static const mykonosJesd204bDeframerConfig_t DEFAULT_DEFRAMER = +{ + 0, // bankId extension to Device ID (Valid 0..15) + 0, // deviceId link identification number. (Valid 0..255) + 0, // lane0Id Lane0 ID. (Valid 0..31) + 4, // M number of DACss (0, 2, or 4) - 2 DACs per transmit chain + 32, // K #frames in a multiframe (default=32), F*K=multiple of 4. (F=2*M/numberOfLanes) + 0, // Scrambling off if scramble = 0, if framerScramble > 0 scrambling is enabled + 1, // External SYSREF select. 0 = use internal SYSREF, 1 = external SYSREF + 0x0F, // Deserializer lane select bit field. Where, [0] = Lane0 enabled, [1] = Lane1 enabled, etc + 0xE4, // Lane crossbar to map physical lanes to deframer lane inputs [1:0] = Deframer Input 0 Lane section, [3:2] = Deframer Input 1 lane select, etc + 1, // Equalizer setting. Applied to all deserializer lanes. Range is 0..4 + 0, // PN inversion per each lane. bit[0] = 1 Invert PN of Lane 0, bit[1] = Invert PN of Lane 1, etc). + 0, // LMFC offset value to adjust deterministic latency. Range is 0..31 + 0, // Flag for determining if SYSREF on relink should be set. Where, if > 0 = set, '0' = not set + 0, // Flag for determining if auto channel select for the xbar should be set. Where, if > 0 = set, '0' = not set + 0 // Flag for determining if CMOS mode for TX Sync signal is used. Where, if > 0 = CMOS, '0' = LVDS +}; + +static const mykonosObsRxSettings_t DEFAULT_ORX_SETTINGS = +{ + nullptr, // ORx datapath profile, 3dB corner frequencies, and digital filter enables + nullptr, // ObsRx gain control settings structure + nullptr, // ORx AGC control settings structure + nullptr, // Sniffer datapath profile, 3dB corner frequencies, and digital filter enables + nullptr, // SnRx gain control settings structure + nullptr, // ObsRx JESD204b framer configuration structure + MYK_OBS_RXOFF, // obsRxChannel + OBSLO_TX_PLL, // (obsRxLoSource) The Obs Rx mixer can use the Tx Synth(TX_PLL) or Sniffer Synth (SNIFFER_PLL) + 2600000000U, // SnRx PLL LO frequency in Hz + 0, // Flag to choose if complex baseband or real IF data are selected for Rx and ObsRx paths. Where if > 0 = real IF data, '0' = complex data + nullptr, // Custom Loopback ADC profile to set the bandwidth of the ADC response + OBS_RXOFF // Default ObsRx channel to enter when radioOn called +}; + +static const mykonosJesd204bFramerConfig_t DEFAULT_ORX_FRAMER = +{ + 0, // JESD204B Configuration Bank ID -extension to Device ID (Valid 0..15) + 0, // JESD204B Configuration Device ID - link identification number. (Valid 0..255) + 0, // JESD204B Configuration starting Lane ID. If more than one lane used, each lane will increment from the Lane0 ID. (Valid 0..31) + 2, // number of ADCs (0, 2, or 4) - 2 ADCs per receive chain + 32, // number of frames in a multiframe (default=32), F*K must be a multiple of 4. (F=2*M/numberOfLanes) + 1, // scrambling off if framerScramble= 0, if framerScramble>0 scramble is enabled. + 1, // 0=use internal SYSREF, 1= use external SYSREF + 0x00, // serializerLanesEnabled - bit per lane, [0] = Lane0 enabled, [1] = Lane1 enabled + 0xE4, // Lane crossbar to map framer lane outputs to physical lanes + 22, // serializerAmplitude - default 22 (valid (0-31) + 4, // preEmphasis - < default 4 (valid 0 - 7) + 0, // invertLanePolarity - default 0 ([0] will invert lane [0], bit1 will invert lane1) + 0, // lmfcOffset - LMFC_Offset offset value for deterministic latency setting + 0, // Flag for determining if SYSREF on relink should be set. Where, if > 0 = set, 0 = not set + 0, // Flag for determining if auto channel select for the xbar should be set. Where, if > 0 = set, '0' = not set + 1, // Selects SYNCb input source. Where, 0 = use RXSYNCB for this framer, 1 = use OBSRX_SYNCB for this framer + 0, // Flag for determining if CMOS mode for RX Sync signal is used. Where, if > 0 = CMOS, '0' = LVDS + 1 // Selects framer bit repeat or oversampling mode for lane rate matching. Where, 0 = bitRepeat mode (changes effective lanerate), 1 = overSample (maintains same lane rate between ObsRx framer and Rx framer and oversamples the ADC samples) +}; + +static const mykonosORxGainControl_t DEFAULT_ORX_GAIN = +{ + MGC, // Current ORx gain control mode setting + 255, // ORx1 Gain Index, can be used in different ways for manual and AGC gain control + 255, // ORx2 Gain Index, can be used in different ways for manual and AGC gain control + 255, // Max gain index for the currently loaded ORx Gain table + 237 // Min gain index for the currently loaded ORx Gain table +}; + +static const mykonosAgcCfg_t DEFAULT_ORX_AGC_CTRL = +{ + 0, // agcRx1MaxGainIndex + 0, // agcRx1MinGainIndex + 0, // agcRx2MaxGainIndex + 0, // agcRx2MinGainIndex: + 0, // agcObsRxMaxGainIndex + 0, // agcObsRxMinGainIndex + 0, // agcObsRxSelect + 0, // agcPeakThresholdMode + 0, // agcLowThsPreventGainIncrease + 0, // agcGainUpdateCounter + 0, // agcSlowLoopSettlingDelay + 0, // agcPeakWaitTime + 0, // agcResetOnRxEnable + 0, // agcEnableSyncPulseForGainCounter + nullptr,// *peakAgc + nullptr // *powerAgc +}; + +static const mykonosPeakDetAgcCfg_t DEFAULT_ORX_PEAK_AGC = +{ + 0, // apdHighThresh: + 0, // apdLowThresh + 0, // hb2HighThresh + 0, // hb2LowThresh + 0, // hb2VeryLowThresh + 0, // apdHighThreshExceededCnt + 0, // apdLowThreshExceededCnt + 0, // hb2HighThreshExceededCnt + 0, // hb2LowThreshExceededCnt + 0, // hb2VeryLowThreshExceededCnt + 0, // apdHighGainStepAttack + 0, // apdLowGainStepRecovery + 0, // hb2HighGainStepAttack + 0, // hb2LowGainStepRecovery + 0, // hb2VeryLowGainStepRecovery + 0, // apdFastAttack + 0, // hb2FastAttack + 0, // hb2OverloadDetectEnable + 0, // hb2OverloadDurationCnt + 0 // hb2OverloadThreshCnt +}; + +static const mykonosPowerMeasAgcCfg_t DEFAULT_ORX_POWER_AGC = +{ + 0, // pmdUpperHighThresh + 0, // pmdUpperLowThresh + 0, // pmdLowerHighThresh + 0, // pmdLowerLowThresh + 0, // pmdUpperHighGainStepAttack + 0, // pmdUpperLowGainStepAttack + 0, // pmdLowerHighGainStepRecovery + 0, // pmdLowerLowGainStepRecovery + 0, // pmdMeasDuration + 0, // pmdMeasConfig +}; + +static const mykonosRxProfile_t DEFAULT_ORX_PROFILE = +{// ORX 100MHz, IQrate 125MSPS, Dec5 + 1, // The divider used to generate the ADC clock + nullptr, // Pointer to Rx FIR filter structure or NULL + 2, // Rx FIR decimation (1,2,4) + 5, // Decimation of Dec5 or Dec4 filter (5,4) + 0, // If set, and DEC5 filter used, will use a higher rejection DEC5 FIR filter (1=Enabled, 0=Disabled) + 1, // RX Half band 1 decimation (1 or 2) + 125000, // Rx IQ data rate in kHz + 100000000, // The Rx RF passband bandwidth for the profile + 102000, // Rx BBF 3dB corner in kHz + nullptr // pointer to custom ADC profile +}; + +static const mykonosArmGpioConfig_t DEFAULT_ARM_GPIO = +{ + 0, // useRx2EnablePin; //!< 0= RX1_ENABLE controls RX1 and RX2, 1 = separate RX1_ENABLE/RX2_ENABLE pins + 0, // useTx2EnablePin; //!< 0= TX1_ENABLE controls TX1 and TX2, 1 = separate TX1_ENABLE/TX2_ENABLE pins + 0, // txRxPinMode; //!< 0= ARM command mode, 1 = Pin mode to power up Tx/Rx chains + 0, // orxPinMode; //!< 0= ARM command mode, 1 = Pin mode to power up ObsRx receiver + + //Mykonos ARM input GPIO pins -- Only valid if orxPinMode = 1 + 0, // orxTriggerPin; //!< Select desired GPIO pin (valid 4-15) + 0, // orxMode2Pin; //!< Select desired GPIO pin (valid 0-18) + 0, // orxMode1Pin; //!< Select desired GPIO pin (valid 0-18) + 0, // orxMode0Pin; //!< Select desired GPIO pin (valid 0-18) + + // Mykonos ARM output GPIO pins -- always available, even when pin mode not enabled + 0, // rx1EnableAck; //!< Select desired GPIO pin (0-15), [4] = Output Enable + 0, // rx2EnableAck; //!< Select desired GPIO pin (0-15), [4] = Output Enable + 0, // tx1EnableAck; //!< Select desired GPIO pin (0-15), [4] = Output Enable + 0, // tx2EnableAck; //!< Select desired GPIO pin (0-15), [4] = Output Enable + 0, // orx1EnableAck; //!< Select desired GPIO pin (0-15), [4] = Output Enable + 0, // orx2EnableAck; //!< Select desired GPIO pin (0-15), [4] = Output Enable + 0, // srxEnableAck; //!< Select desired GPIO pin (0-15), [4] = Output Enable + 0 // txObsSelect; //!< Select desired GPIO pin (0-15), [4] = Output Enable + // When 2Tx are used with only 1 ORx input, this GPIO tells the BBIC which Tx channel is + // active for calibrations, so BBIC can route correct RF Tx path into the single ORx input +}; + +static const mykonosGpio3v3_t DEFAULT_GPIO_3V3 = +{ + 0, //!< Oe per pin, 1=output, 0 = input + GPIO3V3_BITBANG_MODE, //!< Mode for GPIO3V3[3:0] + GPIO3V3_BITBANG_MODE, //!< Mode for GPIO3V3[7:4] + GPIO3V3_BITBANG_MODE, //!< Mode for GPIO3V3[11:8] +}; + +static const mykonosGpioLowVoltage_t DEFAULT_GPIO = +{ + 0, // Oe per pin, 1=output, 0 = input + GPIO_MONITOR_MODE, // Mode for GPIO[3:0] + GPIO_MONITOR_MODE, // Mode for GPIO[7:4] + GPIO_MONITOR_MODE, // Mode for GPIO[11:8] + GPIO_MONITOR_MODE, // Mode for GPIO[15:12] + GPIO_MONITOR_MODE, // Mode for GPIO[18:16] +}; + +static const mykonosAuxIo_t DEFAULT_AUX_IO = +{ + 0, // auxDacEnable uint16_t + { 0,0,0,0,0,0,0,0,0,0 }, // auxDacValue uint16[10] + { 0,0,0,0,0,0,0,0,0,0 }, // auxDacSlope uint8[10] + { 0,0,0,0,0,0,0,0,0,0 }, // auxDacVref uint8[10] + nullptr, // *mykonosGpio3v3_t + nullptr, // *mykonosGpioLowVoltage_t + nullptr // *mykonosArmGpioConfig_t +}; + +static const mykonosDigClocks_t DEFAULT_CLOCKS = +{ + 122880, // CLKPLL and device reference clock frequency in kHz + 9830400, // CLKPLL VCO frequency in kHz + VCODIV_2, // CLKPLL VCO divider + 4 // CLKPLL high speed clock divider +}; + + diff --git a/mpm/lib/mykonos/config/ad937x_fir.cpp b/mpm/lib/mykonos/config/ad937x_fir.cpp index a9ede3318..b62227163 100644 --- a/mpm/lib/mykonos/config/ad937x_fir.cpp +++ b/mpm/lib/mykonos/config/ad937x_fir.cpp @@ -1,37 +1,51 @@ -#include "ad937x_fir.h" -#include <limits> +// +// Copyright 2017 Ettus Research (National Instruments) +// +// 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/>. +// -ad937x_fir::ad937x_fir(int8_t gain, const std::vector<int16_t>& coefficients) -{ - - _set_gain(gain); -} +#include "ad937x_fir.hpp" -ad937x_fir::ad937x_fir(int8_t gain, std::vector<int16_t>&& coefficients) +ad937x_fir::ad937x_fir() : + ad937x_fir(0, { 1, 0 }) { - set_coefficients(std::move(coefficients)); - _set_gain(gain); -} -mykonosFir_t* ad937x_fir::getFir() -{ - return &(_fir); } -void ad937x_fir::set_coefficients(std::vector<int16_t>&& coefficients) +ad937x_fir::ad937x_fir(int8_t gain, const std::vector<int16_t>& coefficients) : + // These two constructors will be run in the order they are declared in the class definition + // see C++ standard 12.6.2 section 13.3 + _fir_coefficients(coefficients), + _fir({gain, + static_cast<uint8_t>(_fir_coefficients.size()), + _fir_coefficients.data()}) { - if (coefficients.size() < std::numeric_limits<decltype(mykonosFir_t().numFirCoefs)>::max() || - coefficients.size() > 0) - { - // TODO: exception - } - fir_coefficients = std::move(coefficients); - _fir.numFirCoefs = static_cast<uint8_t>(fir_coefficients.size()); - _fir.coefs = &fir_coefficients[0]; + } -void ad937x_fir::_set_gain(int8_t gain) +// ad937x_fir.fir should not be accessed during this operation +void ad937x_fir::set_fir(int8_t gain, const std::vector<int16_t>& coefficients) { _fir.gain_dB = gain; + + _fir_coefficients = coefficients; + _fir.coefs = _fir_coefficients.data(); + _fir.numFirCoefs = static_cast<uint8_t>(_fir_coefficients.size()); } +std::vector<int16_t> ad937x_fir::get_fir(int8_t &gain) +{ + gain = _fir.gain_dB; + return _fir_coefficients; +} diff --git a/mpm/lib/mykonos/config/ad937x_fir.h b/mpm/lib/mykonos/config/ad937x_fir.h deleted file mode 100644 index ff277ef26..000000000 --- a/mpm/lib/mykonos/config/ad937x_fir.h +++ /dev/null @@ -1,22 +0,0 @@ -#pragma once - -#include <vector> -#include "../adi/t_mykonos.h" - -// wraps FIR allocation -class ad937x_fir -{ - // these should be const, but can't be because of C API - // - mykonosFir_t _fir; - std::vector<int16_t> fir_coefficients; - - void ad937x_fir::_set_gain(int8_t gain); -public: - ad937x_fir(int8_t gain, const std::vector<int16_t>& coefficients); - ad937x_fir(int8_t gain, std::vector<int16_t>&& coefficients); - - mykonosFir_t* getFir(); -}; - - diff --git a/mpm/lib/mykonos/config/ad937x_fir.hpp b/mpm/lib/mykonos/config/ad937x_fir.hpp new file mode 100644 index 000000000..f243f0f47 --- /dev/null +++ b/mpm/lib/mykonos/config/ad937x_fir.hpp @@ -0,0 +1,35 @@ +// +// Copyright 2017 Ettus Research (National Instruments) +// +// 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/>. +// + +#pragma once + +#include "../adi/t_mykonos.h" +#include <vector> + +// wraps FIR allocation and provides a fixed mykonosFir_t pointer +class ad937x_fir +{ + std::vector<int16_t> _fir_coefficients; + mykonosFir_t _fir; +public: + mykonosFir_t* const fir = &_fir; + ad937x_fir(); + ad937x_fir(int8_t gain, const std::vector<int16_t>& coefficients); + + void set_fir(int8_t gain, const std::vector<int16_t>& coefficients); + std::vector<int16_t> get_fir(int8_t &gain); +}; diff --git a/mpm/lib/mykonos/config/mykonos_default_config.h b/mpm/lib/mykonos/config/mykonos_default_config.h deleted file mode 100644 index a5ed4fe6c..000000000 --- a/mpm/lib/mykonos/config/mykonos_default_config.h +++ /dev/null @@ -1,359 +0,0 @@ -#include "../adi/t_mykonos.h" - -// This file is more or less the static config provided by a run of the eval software -// except all pointers have been changed to NULL -// Hopefully this helps the compiler use these as purely constants -// The pointers should be filled in if these data structures are to be actually used with the API - -static const mykonosRxSettings_t DEFAULT_RX_SETTINGS = -{ - NULL, /* Rx datapath profile, 3dB corner frequencies, and digital filter enables*/ - NULL, /* Rx JESD204b framer configuration structure*/ - NULL, /* Rx Gain control settings structure*/ - NULL, /* Rx AGC control settings structure*/ - RX1_RX2, /* The desired Rx Channels to enable during initialization*/ - 0, /* Internal LO = 0, external LO*2 = 1*/ - 3500000000U, /* Rx PLL LO Frequency (internal or external LO)*/ - 0 /* Flag to choose if complex baseband or real IF data are selected for Rx and ObsRx paths. Where, if > 0 = real IF data, '0' = zero IF (IQ) data*/ -}; - -static const mykonosRxProfile_t DEFAULT_RX_PROFILE = -{/* Rx 100MHz, IQrate 122.88MHz, Dec5 */ - 1, /* The divider used to generate the ADC clock*/ - NULL, /* Pointer to Rx FIR filter structure*/ - 2, /* Rx FIR decimation (1,2,4)*/ - 5, /* Decimation of Dec5 or Dec4 filter (5,4)*/ - 1, /* If set, and DEC5 filter used, will use a higher rejection DEC5 FIR filter (1=Enabled, 0=Disabled)*/ - 1, /* RX Half band 1 decimation (1 or 2)*/ - 122880, /* Rx IQ data rate in kHz*/ - 100000000, /* The Rx RF passband bandwidth for the profile*/ - 100000, /* Rx BBF 3dB corner in kHz*/ - NULL /* pointer to custom ADC profile*/ -}; - -static const mykonosJesd204bFramerConfig_t DEFAULT_FRAMER = -{ - 0, /* JESD204B Configuration Bank ID -extension to Device ID (Valid 0..15)*/ - 0, /* JESD204B Configuration Device ID - link identification number. (Valid 0..255)*/ - 0, /* JESD204B Configuration starting Lane ID. If more than one lane used, each lane will increment from the Lane0 ID. (Valid 0..31)*/ - 4, /* number of ADCs (0, 2, or 4) - 2 ADCs per receive chain*/ - 32, /* number of frames in a multiframe (default=32), F*K must be a multiple of 4. (F=2*M/numberOfLanes)*/ - 1, /* scrambling off if framerScramble= 0, if framerScramble>0 scramble is enabled.*/ - 1, /* 0=use internal SYSREF, 1= use external SYSREF*/ - 0x0F, /* serializerLanesEnabled - bit per lane, [0] = Lane0 enabled, [1] = Lane1 enabled*/ - 0xE4, /* serializerLaneCrossbar*/ - 26, /* serializerAmplitude - default 22 (valid (0-31)*/ - 0, /* preEmphasis - < default 4 (valid 0 - 7)*/ - 0, /* invertLanePolarity - default 0 ([0] will invert lane [0], bit1 will invert lane1)*/ - 0, /* lmfcOffset - LMFC offset value for deterministic latency setting*/ - 0, /* Flag for determining if SYSREF on relink should be set. Where, if > 0 = set, 0 = not set*/ - 0, /* Flag for determining if auto channel select for the xbar should be set. Where, if > 0 = set, '0' = not set*/ - 0, /* Selects SYNCb input source. Where, 0 = use RXSYNCB for this framer, 1 = use OBSRX_SYNCB for this framer*/ - 0, /* Flag for determining if CMOS mode for RX Sync signal is used. Where, if > 0 = CMOS, '0' = LVDS*/ - 0 /* Selects framer bit repeat or oversampling mode for lane rate matching. Where, 0 = bitRepeat mode (changes effective lanerate), 1 = overSample (maintains same lane rate between ObsRx framer and Rx framer and oversamples the ADC samples)*/ -}; - -static const mykonosRxGainControl_t DEFAULT_RX_GAIN = -{ - MGC, /* Current Rx gain control mode setting*/ - 255, /* Rx1 Gain Index, can be used in different ways for manual and AGC gain control*/ - 255, /* Rx2 Gain Index, can be used in different ways for manual and AGC gain control*/ - 255, /* Max gain index for the currently loaded Rx1 Gain table*/ - 195, /* Min gain index for the currently loaded Rx1 Gain table*/ - 255, /* Max gain index for the currently loaded Rx2 Gain table*/ - 195, /* Min gain index for the currently loaded Rx2 Gain table*/ - 0, /* Stores Rx1 RSSI value read back from the Mykonos*/ - 0 /* Stores Rx2 RSSI value read back from the Mykonos*/ -}; - -static const mykonosPeakDetAgcCfg_t DEFAULT_RX_PEAK_AGC = -{ - 0x1F, /* apdHighThresh: */ - 0x16, /* apdLowThresh */ - 0xB5, /* hb2HighThresh */ - 0x80, /* hb2LowThresh */ - 0x40, /* hb2VeryLowThresh */ - 0x06, /* apdHighThreshExceededCnt */ - 0x04, /* apdLowThreshExceededCnt */ - 0x06, /* hb2HighThreshExceededCnt */ - 0x04, /* hb2LowThreshExceededCnt */ - 0x04, /* hb2VeryLowThreshExceededCnt */ - 0x4, /* apdHighGainStepAttack */ - 0x2, /* apdLowGainStepRecovery */ - 0x4, /* hb2HighGainStepAttack */ - 0x2, /* hb2LowGainStepRecovery */ - 0x4, /* hb2VeryLowGainStepRecovery */ - 0x1, /* apdFastAttack */ - 0x1, /* hb2FastAttack */ - 0x1, /* hb2OverloadDetectEnable */ - 0x1, /* hb2OverloadDurationCnt */ - 0x1 /* hb2OverloadThreshCnt */ -}; - -static const mykonosPowerMeasAgcCfg_t DEFAULT_RX_POWER_AGC = -{ - 0x01, /* pmdUpperHighThresh */ - 0x03, /* pmdUpperLowThresh */ - 0x0C, /* pmdLowerHighThresh */ - 0x04, /* pmdLowerLowThresh */ - 0x4, /* pmdUpperHighGainStepAttack */ - 0x2, /* pmdUpperLowGainStepAttack */ - 0x2, /* pmdLowerHighGainStepRecovery */ - 0x4, /* pmdLowerLowGainStepRecovery */ - 0x08, /* pmdMeasDuration */ - 0x02 /* pmdMeasConfig */ -}; - -static const mykonosAgcCfg_t DEFAULT_RX_AGC_CTRL = -{ - 255, /* AGC peak wait time */ - 195, /* agcRx1MinGainIndex */ - 255, /* agcRx2MaxGainIndex */ - 195, /* agcRx2MinGainIndex: */ - 255, /* agcObsRxMaxGainIndex */ - 203, /* agcObsRxMinGainIndex */ - 1, /* agcObsRxSelect */ - 1, /* agcPeakThresholdMode */ - 1, /* agcLowThsPreventGainIncrease */ - 30720, /* agcGainUpdateCounter */ - 3, /* agcSlowLoopSettlingDelay */ - 2, /* agcPeakWaitTime */ - 0, /* agcResetOnRxEnable */ - 0, /* agcEnableSyncPulseForGainCounter */ - NULL, - NULL -}; - -static const mykonosTxSettings_t DEFAULT_TX_SETTINGS = -{ - NULL, /* Tx datapath profile, 3dB corner frequencies, and digital filter enables*/ - NULL, /* Mykonos JESD204b deframer config for the Tx data path*/ - TX1_TX2, /* The desired Tx channels to enable during initialization*/ - 0, /* Internal LO=0, external LO*2 if =1*/ - 3500000000U, /* Tx PLL LO frequency (internal or external LO)*/ - TXATTEN_0P05_DB,/* Initial and current Tx1 Attenuation*/ - 10000, /* Initial and current Tx1 Attenuation mdB*/ - 10000, /* Initial and current Tx2 Attenuation mdB*/ - NULL, /* DPD,CLGC,VSWR settings. Only valid for AD9373 device, set pointer to NULL otherwise*/ - NULL, /* CLGC Config Structure. Only valid for AD9373 device, set pointer to NULL otherwise*/ - NULL /* VSWR Config Structure. Only valid for AD9373 device, set pointer to NULL otherwise*/ -}; - -static const mykonosTxProfile_t DEFAULT_TX_PROFILE = -{ /* Tx 20/100MHz, IQrate 122.88MHz, Dec5 */ - DACDIV_2p5, /* The divider used to generate the DAC clock*/ - NULL, /* Pointer to Tx FIR filter structure*/ - 2, /* The Tx digital FIR filter interpolation (1,2,4)*/ - 2, /* Tx Halfband1 filter interpolation (1,2)*/ - 1, /* Tx Halfband2 filter interpolation (1,2)*/ - 1, /* TxInputHbInterpolation (1,2)*/ - 122880, /* Tx IQ data rate in kHz*/ - 20000000, /* Primary Signal BW*/ - 100000000, /* The Tx RF passband bandwidth for the profile*/ - 710539, /* The DAC filter 3dB corner in kHz*/ - 50000, /* Tx BBF 3dB corner in kHz*/ - 0 /* Enable DPD, only valid for AD9373*/ -}; - -static const mykonosJesd204bDeframerConfig_t DEFAULT_DEFRAMER = -{ - 0, /* bankId extension to Device ID (Valid 0..15)*/ - 0, /* deviceId link identification number. (Valid 0..255)*/ - 0, /* lane0Id Lane0 ID. (Valid 0..31)*/ - 4, /* M number of DACss (0, 2, or 4) - 2 DACs per transmit chain */ - 32, /* K #frames in a multiframe (default=32), F*K=multiple of 4. (F=2*M/numberOfLanes)*/ - 0, /* Scrambling off if scramble = 0, if framerScramble > 0 scrambling is enabled*/ - 1, /* External SYSREF select. 0 = use internal SYSREF, 1 = external SYSREF*/ - 0x0F, /* Deserializer lane select bit field. Where, [0] = Lane0 enabled, [1] = Lane1 enabled, etc */ - 0xE4, /* Lane crossbar to map physical lanes to deframer lane inputs [1:0] = Deframer Input 0 Lane section, [3:2] = Deframer Input 1 lane select, etc */ - 1, /* Equalizer setting. Applied to all deserializer lanes. Range is 0..4*/ - 0, /* PN inversion per each lane. bit[0] = 1 Invert PN of Lane 0, bit[1] = Invert PN of Lane 1, etc).*/ - 0, /* LMFC offset value to adjust deterministic latency. Range is 0..31*/ - 0, /* Flag for determining if SYSREF on relink should be set. Where, if > 0 = set, '0' = not set*/ - 0, /* Flag for determining if auto channel select for the xbar should be set. Where, if > 0 = set, '0' = not set*/ - 0 /* Flag for determining if CMOS mode for TX Sync signal is used. Where, if > 0 = CMOS, '0' = LVDS*/ -}; - -static const mykonosObsRxSettings_t DEFAULT_ORX_SETTINGS = -{ - NULL, /* ORx datapath profile, 3dB corner frequencies, and digital filter enables*/ - NULL, /* ObsRx gain control settings structure*/ - NULL, /* ORx AGC control settings structure*/ - NULL, /* Sniffer datapath profile, 3dB corner frequencies, and digital filter enables*/ - NULL, /* SnRx gain control settings structure*/ - NULL, /* ObsRx JESD204b framer configuration structure */ - MYK_OBS_RXOFF, /* obsRxChannel */ - OBSLO_TX_PLL, /* (obsRxLoSource) The Obs Rx mixer can use the Tx Synth(TX_PLL) or Sniffer Synth (SNIFFER_PLL) */ - 2600000000U, /* SnRx PLL LO frequency in Hz */ - 0, /* Flag to choose if complex baseband or real IF data are selected for Rx and ObsRx paths. Where if > 0 = real IF data, '0' = complex data*/ - NULL, /* Custom Loopback ADC profile to set the bandwidth of the ADC response */ - OBS_RXOFF /* Default ObsRx channel to enter when radioOn called */ -}; - -static const mykonosJesd204bFramerConfig_t DEFAULT_ORX_FRAMER = -{ - 0, /* JESD204B Configuration Bank ID -extension to Device ID (Valid 0..15)*/ - 0, /* JESD204B Configuration Device ID - link identification number. (Valid 0..255)*/ - 0, /* JESD204B Configuration starting Lane ID. If more than one lane used, each lane will increment from the Lane0 ID. (Valid 0..31)*/ - 2, /* number of ADCs (0, 2, or 4) - 2 ADCs per receive chain*/ - 32, /* number of frames in a multiframe (default=32), F*K must be a multiple of 4. (F=2*M/numberOfLanes)*/ - 1, /* scrambling off if framerScramble= 0, if framerScramble>0 scramble is enabled.*/ - 1, /* 0=use internal SYSREF, 1= use external SYSREF*/ - 0x00, /* serializerLanesEnabled - bit per lane, [0] = Lane0 enabled, [1] = Lane1 enabled*/ - 0xE4, /* Lane crossbar to map framer lane outputs to physical lanes*/ - 22, /* serializerAmplitude - default 22 (valid (0-31)*/ - 4, /* preEmphasis - < default 4 (valid 0 - 7)*/ - 0, /* invertLanePolarity - default 0 ([0] will invert lane [0], bit1 will invert lane1)*/ - 0, /* lmfcOffset - LMFC_Offset offset value for deterministic latency setting*/ - 0, /* Flag for determining if SYSREF on relink should be set. Where, if > 0 = set, 0 = not set*/ - 0, /* Flag for determining if auto channel select for the xbar should be set. Where, if > 0 = set, '0' = not set*/ - 1, /* Selects SYNCb input source. Where, 0 = use RXSYNCB for this framer, 1 = use OBSRX_SYNCB for this framer*/ - 0, /* Flag for determining if CMOS mode for RX Sync signal is used. Where, if > 0 = CMOS, '0' = LVDS*/ - 1 /* Selects framer bit repeat or oversampling mode for lane rate matching. Where, 0 = bitRepeat mode (changes effective lanerate), 1 = overSample (maintains same lane rate between ObsRx framer and Rx framer and oversamples the ADC samples)*/ -}; - -static const mykonosORxGainControl_t DEFAULT_ORX_GAIN = -{ - MGC, /* Current ORx gain control mode setting*/ - 255, /* ORx1 Gain Index, can be used in different ways for manual and AGC gain control*/ - 255, /* ORx2 Gain Index, can be used in different ways for manual and AGC gain control*/ - 255, /* Max gain index for the currently loaded ORx Gain table*/ - 237 /* Min gain index for the currently loaded ORx Gain table*/ -}; - -static const mykonosAgcCfg_t DEFAULT_ORX_AGC_CTRL = -{ - 0, /* agcRx1MaxGainIndex */ - 0, /* agcRx1MinGainIndex */ - 0, /* agcRx2MaxGainIndex */ - 0, /* agcRx2MinGainIndex: */ - 0, /* agcObsRxMaxGainIndex */ - 0, /* agcObsRxMinGainIndex */ - 0, /* agcObsRxSelect */ - 0, /* agcPeakThresholdMode */ - 0, /* agcLowThsPreventGainIncrease */ - 0, /* agcGainUpdateCounter */ - 0, /* agcSlowLoopSettlingDelay */ - 0, /* agcPeakWaitTime */ - 0, /* agcResetOnRxEnable */ - 0, /* agcEnableSyncPulseForGainCounter */ - NULL, - NULL -}; - -static const mykonosPeakDetAgcCfg_t DEFAULT_ORX_PEAK_AGC = -{ - 0x00, /* apdHighThresh: */ - 0x00, /* apdLowThresh */ - 0x00, /* hb2HighThresh */ - 0x00, /* hb2LowThresh */ - 0x00, /* hb2VeryLowThresh */ - 0x00, /* apdHighThreshExceededCnt */ - 0x00, /* apdLowThreshExceededCnt */ - 0x00, /* hb2HighThreshExceededCnt */ - 0x00, /* hb2LowThreshExceededCnt */ - 0x00, /* hb2VeryLowThreshExceededCnt */ - 0x0, /* apdHighGainStepAttack */ - 0x0, /* apdLowGainStepRecovery */ - 0x0, /* hb2HighGainStepAttack */ - 0x0, /* hb2LowGainStepRecovery */ - 0x0, /* hb2VeryLowGainStepRecovery */ - 0x0, /* apdFastAttack */ - 0x0, /* hb2FastAttack */ - 0x0, /* hb2OverloadDetectEnable */ - 0x0, /* hb2OverloadDurationCnt */ - 0x0 /* hb2OverloadThreshCnt */ -}; - -static const mykonosPowerMeasAgcCfg_t DEFAULT_ORX_POWER_AGC = -{ - 0x00, /* pmdUpperHighThresh */ - 0x00, /* pmdUpperLowThresh */ - 0x00, /* pmdLowerHighThresh */ - 0x00, /* pmdLowerLowThresh */ - 0x0, /* pmdUpperHighGainStepAttack */ - 0x0, /* pmdUpperLowGainStepAttack */ - 0x0, /* pmdLowerHighGainStepRecovery */ - 0x0, /* pmdLowerLowGainStepRecovery */ - 0x00, /* pmdMeasDuration */ - 0x00 /* pmdMeasConfig */ -}; - -static const mykonosRxProfile_t DEFAULT_ORX_PROFILE = -{/* ORX 100MHz, IQrate 125MSPS, Dec5 */ - 1, /* The divider used to generate the ADC clock*/ - NULL, /* Pointer to Rx FIR filter structure or NULL*/ - 2, /* Rx FIR decimation (1,2,4)*/ - 5, /* Decimation of Dec5 or Dec4 filter (5,4)*/ - 0, /* If set, and DEC5 filter used, will use a higher rejection DEC5 FIR filter (1=Enabled, 0=Disabled)*/ - 1, /* RX Half band 1 decimation (1 or 2)*/ - 125000, /* Rx IQ data rate in kHz*/ - 100000000, /* The Rx RF passband bandwidth for the profile*/ - 102000, /* Rx BBF 3dB corner in kHz*/ - NULL /* pointer to custom ADC profile*/ -}; - -static const mykonosArmGpioConfig_t DEFAULT_ARM_GPIO = -{ - 0, // useRx2EnablePin; /*!< 0= RX1_ENABLE controls RX1 and RX2, 1 = separate RX1_ENABLE/RX2_ENABLE pins */ - 0, // useTx2EnablePin; /*!< 0= TX1_ENABLE controls TX1 and TX2, 1 = separate TX1_ENABLE/TX2_ENABLE pins */ - 0, // txRxPinMode; /*!< 0= ARM command mode, 1 = Pin mode to power up Tx/Rx chains */ - 0, // orxPinMode; /*!< 0= ARM command mode, 1 = Pin mode to power up ObsRx receiver*/ - - /*Mykonos ARM input GPIO pins -- Only valid if orxPinMode = 1 */ - 0, // orxTriggerPin; /*!< Select desired GPIO pin (valid 4-15) */ - 0, // orxMode2Pin; /*!< Select desired GPIO pin (valid 0-18) */ - 0, // orxMode1Pin; /*!< Select desired GPIO pin (valid 0-18) */ - 0, // orxMode0Pin; /*!< Select desired GPIO pin (valid 0-18) */ - - /* Mykonos ARM output GPIO pins -- always available, even when pin mode not enabled*/ - 0, // rx1EnableAck; /*!< Select desired GPIO pin (0-15), [4] = Output Enable */ - 0, // rx2EnableAck; /*!< Select desired GPIO pin (0-15), [4] = Output Enable */ - 0, // tx1EnableAck; /*!< Select desired GPIO pin (0-15), [4] = Output Enable */ - 0, // tx2EnableAck; /*!< Select desired GPIO pin (0-15), [4] = Output Enable */ - 0, // orx1EnableAck; /*!< Select desired GPIO pin (0-15), [4] = Output Enable */ - 0, // orx2EnableAck; /*!< Select desired GPIO pin (0-15), [4] = Output Enable */ - 0, // srxEnableAck; /*!< Select desired GPIO pin (0-15), [4] = Output Enable */ - 0 // txObsSelect; /*!< Select desired GPIO pin (0-15), [4] = Output Enable */ - /* When 2Tx are used with only 1 ORx input, this GPIO tells the BBIC which Tx channel is */ - /* active for calibrations, so BBIC can route correct RF Tx path into the single ORx input*/ -}; - -static const mykonosGpio3v3_t DEFAULT_GPIO_3V3 = -{ - 0, /*!< Oe per pin, 1=output, 0 = input */ - GPIO3V3_BITBANG_MODE, /*!< Mode for GPIO3V3[3:0] */ - GPIO3V3_BITBANG_MODE, /*!< Mode for GPIO3V3[7:4] */ - GPIO3V3_BITBANG_MODE, /*!< Mode for GPIO3V3[11:8] */ -}; - -static const mykonosGpioLowVoltage_t DEFAULT_GPIO = -{ - 0,/* Oe per pin, 1=output, 0 = input */ - GPIO_MONITOR_MODE,/* Mode for GPIO[3:0] */ - GPIO_MONITOR_MODE,/* Mode for GPIO[7:4] */ - GPIO_MONITOR_MODE,/* Mode for GPIO[11:8] */ - GPIO_MONITOR_MODE,/* Mode for GPIO[15:12] */ - GPIO_MONITOR_MODE,/* Mode for GPIO[18:16] */ -}; - -static const mykonosAuxIo_t DEFAULT_AUX_IO = -{ - 0, //auxDacEnableMask uint16_t - { 0,0,0,0,0,0,0,0,0,0 }, //AuxDacValue uint16[10] - { 0,0,0,0,0,0,0,0,0,0 }, //AuxDacSlope uint8[10] - { 0,0,0,0,0,0,0,0,0,0 }, //AuxDacVref uint8[10] - NULL, //pointer to gpio3v3 struct - NULL, //pointer to gpio1v8 struct - NULL -}; - -static const mykonosDigClocks_t DEFAULT_CLOCKS = -{ - 122880, /* CLKPLL and device reference clock frequency in kHz*/ - 9830400, /* CLKPLL VCO frequency in kHz*/ - VCODIV_2, /* CLKPLL VCO divider*/ - 4 /* CLKPLL high speed clock divider*/ -}; - - |