diff options
Diffstat (limited to 'host/lib')
-rw-r--r-- | host/lib/CMakeLists.txt | 7 | ||||
-rw-r--r-- | host/lib/cal/CMakeLists.txt | 32 | ||||
-rw-r--r-- | host/lib/cal/interpolation.hpp | 71 | ||||
-rw-r--r-- | host/lib/cal/interpolation.ipp | 199 | ||||
-rw-r--r-- | host/lib/cal/power_container_impl.cpp | 80 | ||||
-rw-r--r-- | host/lib/cal/power_container_impl.hpp | 77 | ||||
-rw-r--r-- | host/lib/rfnoc/block_ctrl_base.cpp | 1 | ||||
-rw-r--r-- | host/lib/rfnoc/ctrl_iface.cpp | 100 | ||||
-rw-r--r-- | host/lib/rfnoc/ctrl_iface.hpp | 12 | ||||
-rw-r--r-- | host/lib/rfnoc/legacy_compat.cpp | 19 | ||||
-rw-r--r-- | host/lib/rfnoc/xports.hpp | 2 | ||||
-rw-r--r-- | host/lib/types/sid.cpp | 10 | ||||
-rw-r--r-- | host/lib/uhd.rc.in | 4 | ||||
-rw-r--r-- | host/lib/usrp/device3/device3_impl.cpp | 8 | ||||
-rw-r--r-- | host/lib/usrp/device3/device3_impl.hpp | 4 | ||||
-rw-r--r-- | host/lib/usrp/device3/device3_io_impl.cpp | 8 | ||||
-rw-r--r-- | host/lib/usrp/mboard_eeprom.cpp | 2 | ||||
-rw-r--r-- | host/lib/usrp/x300/x300_impl.cpp | 75 | ||||
-rw-r--r-- | host/lib/usrp/x300/x300_impl.hpp | 3 | ||||
-rw-r--r-- | host/lib/usrp/x300/x300_radio_ctrl_impl.cpp | 8 | ||||
-rw-r--r-- | host/lib/utils/msg.cpp | 9 |
21 files changed, 572 insertions, 159 deletions
diff --git a/host/lib/CMakeLists.txt b/host/lib/CMakeLists.txt index 0cd89953c..fce1021c1 100644 --- a/host/lib/CMakeLists.txt +++ b/host/lib/CMakeLists.txt @@ -91,6 +91,7 @@ INCLUDE_SUBDIRECTORY(ic_reg_maps) INCLUDE_SUBDIRECTORY(types) INCLUDE_SUBDIRECTORY(convert) INCLUDE_SUBDIRECTORY(rfnoc) +INCLUDE_SUBDIRECTORY(cal) INCLUDE_SUBDIRECTORY(usrp) INCLUDE_SUBDIRECTORY(usrp_clock) INCLUDE_SUBDIRECTORY(utils) @@ -140,10 +141,10 @@ ENDIF(ENABLE_C_API) # Add DLL resource file to Windows build ######################################################################## IF(MSVC) - MATH(EXPR TRIMMED_VERSION_MAJOR_API "${TRIMMED_VERSION_MAJOR} * 1000 + ${TRIMMED_VERSION_API}") - SET(RC_TRIMMED_VERSION_PATCH ${TRIMMED_VERSION_PATCH}) + MATH(EXPR RC_VERSION_MAJOR_API "${UHD_VERSION_MAJOR} * 1000 + ${UHD_VERSION_API}") + SET(RC_VERSION_PATCH ${UHD_VERSION_PATCH}) IF(UHD_VERSION_DEVEL) - SET(RC_TRIMMED_VERSION_PATCH "999") + SET(RC_VERSION_PATCH "999") ENDIF(UHD_VERSION_DEVEL) # Allow a custom .rc template file to be used diff --git a/host/lib/cal/CMakeLists.txt b/host/lib/cal/CMakeLists.txt new file mode 100644 index 000000000..5c616a9da --- /dev/null +++ b/host/lib/cal/CMakeLists.txt @@ -0,0 +1,32 @@ +# +# Copyright 2016 Ettus Research +# +# 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/>. +# + +######################################################################## +# This file included, use CMake directory variables +######################################################################## +INCLUDE(CheckIncludeFileCXX) +MESSAGE(STATUS "") + +######################################################################## +# Convert types generation +######################################################################## +INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}) +INCLUDE_DIRECTORIES(${CMAKE_CURRENT_BINARY_DIR}) + +LIBUHD_APPEND_SOURCES( + ${CMAKE_CURRENT_SOURCE_DIR}/power_container_impl.cpp +) diff --git a/host/lib/cal/interpolation.hpp b/host/lib/cal/interpolation.hpp new file mode 100644 index 000000000..34f084fbd --- /dev/null +++ b/host/lib/cal/interpolation.hpp @@ -0,0 +1,71 @@ +// +// Copyright 2016 Ettus Research +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. +// + +#ifndef INCLUDED_UHD_INTERPOLATION_HPP +#define INCLUDED_UHD_INTERPOLATION_HPP + +#include <uhd/exception.hpp> +#include <boost/format.hpp> +#include <map> +#include <cmath> + +namespace uhd { +namespace cal { + +template<typename in_type, typename out_type> +struct interp +{ +public: + typedef std::vector<in_type> args_t; + typedef std::map<args_t, out_type> container_t; + + /*! + * Nearest neighbor interpolation given a mapping: R^n -> R + * + * 1) search for the nearest point in R^n + * 2) find the nearest output scalars in R + * + * \param data input data container + * \param args input data point + * \returns interpolated output value + */ + const out_type nn_interp(container_t &data, const args_t &args); + + /*! + * Bilinear interpolation given a mapping: R^2 -> R + * + * 1) search for 4 surrounding points in R^2 + * 2) find the output scalars in R + * 3) solve the system of equations given our input mappings + * + * \param data input data container + * \param args input data point + * \returns interpolated output value + */ + const out_type bl_interp(container_t &data, const args_t &args); + +private: + /*! + * Calculate the distance between two points + */ + static in_type calc_dist(const args_t &a, const args_t &b); +}; + +} // namespace cal +} // namespace uhd + +#endif /* INCLUDED_UHD_INTERPOLATION_HPP */ diff --git a/host/lib/cal/interpolation.ipp b/host/lib/cal/interpolation.ipp new file mode 100644 index 000000000..f58b70b68 --- /dev/null +++ b/host/lib/cal/interpolation.ipp @@ -0,0 +1,199 @@ +// +// Copyright 2016 Ettus Research +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. +// + +#ifndef INCLUDED_UHD_INTERPOLATION_IPP +#define INCLUDED_UHD_INTERPOLATION_IPP + +#include "interpolation.hpp" +#include <uhd/utils/msg.hpp> +#include <boost/numeric/ublas/io.hpp> +#include <boost/numeric/ublas/matrix.hpp> +#include <boost/numeric/ublas/lu.hpp> + +using namespace boost::numeric; + +namespace uhd { +namespace cal { + +#define CAL_INTERP_METHOD(return_type, method, args, ...) \ + template<typename in_type, typename out_type> \ + return_type interp<in_type, out_type>::\ + method(args, __VA_ARGS__) + +#define ARGS_T typename interp<in_type, out_type>::args_t +#define CONTAINER_T typename interp<in_type, out_type>::container_t + +CAL_INTERP_METHOD(in_type, calc_dist, const ARGS_T &a, const ARGS_T &b) +{ + in_type dist = 0; + for (size_t i = 0; i < std::min(a.size(), b.size()); i++) + { + dist += std::abs(a[i] - b[i]); + } + return dist; +} + +CAL_INTERP_METHOD(const out_type, nn_interp, CONTAINER_T &data, const ARGS_T &args) +{ + // Check the cache for the output + if (data.find(args) != data.end()) { + return data[args]; + } + + out_type output = 0; + in_type min_dist = 0; + typename container_t::const_iterator citer; + for (citer = data.begin(); citer != data.end(); citer++) + { + in_type dist = calc_dist(citer->first, args); + if (citer == data.begin() || dist < min_dist) { + min_dist = dist; + output = data[citer->first]; + } + } + + return output; +} + +CAL_INTERP_METHOD(const out_type, bl_interp, CONTAINER_T &data, const ARGS_T &args) +{ + if (args.size() != 2) { + throw uhd::assertion_error(str(boost::format( + "Bilinear interpolation expects 2D values. Received %d.") + % args.size() + )); + } + + if (data.size() < 4) { + throw uhd::assertion_error(str(boost::format( + "Bilinear interpolation requires at least 4 input points. Found %d.") + % data.size() + )); + } + + // Locate the nearest 4 points + typedef std::pair<interp<in_type, out_type>::args_t, out_type> cal_pair_t; + typename std::vector<cal_pair_t> nearest; + + // Initialize the resulting pair to something + cal_pair_t pair = *data.begin(); + + for (size_t i = 0; i < 4; i++) { + bool init = true; + in_type min_dist = 0; + typename container_t::const_iterator citer; + for (citer = data.begin(); citer != data.end(); citer++) + { + cal_pair_t temp = *citer; + if (std::find(nearest.begin(), nearest.end(), temp) == nearest.end()) + { + in_type dist = calc_dist(citer->first, args); + if (dist < min_dist || init) + { + min_dist = dist; + pair = temp; + init = false; + } + } + } + // Push back the nearest pair + nearest.push_back(pair); + } + + // + // Since these points are not grid aligned, + // we perform irregular bilinear interpolation. + // This math involves finding our interpolation + // function using lagrange multipliers: + // + // f(x, y) = ax^2 + bxy + cy^2 + dx + ey + f + // + // The solution is to solve the following system: + // + // A x b + // | E X' | | s | - | 0 | + // | X 0 | | l | - | z | + // + // where s is a vector of the above coefficients. + // + typename ublas::matrix<in_type> A(10, 10, 0.0); + + // E + A(0, 0) = 1.0; A(1, 1) = 1.0; A(2, 2) = 1.0; + + in_type x1, x2, x3, x4; + in_type y1, y2, y3, y4; + + x1 = nearest[0].first[0]; y1 = nearest[0].first[1]; + x2 = nearest[1].first[0]; y2 = nearest[1].first[1]; + x3 = nearest[2].first[0]; y3 = nearest[2].first[1]; + x4 = nearest[3].first[0]; y4 = nearest[3].first[1]; + + // X + A(0, 6) = x1*x1; A(1, 6) = x1*y1; A(2, 6) = y1*y1; A(3, 6) = x1; A(4, 6) = y1; A(5, 6) = 1.0; + A(0, 7) = x2*x2; A(1, 7) = x2*y2; A(2, 7) = y2*y2; A(3, 7) = x2; A(4, 7) = y2; A(5, 7) = 1.0; + A(0, 8) = x3*x3; A(1, 8) = x3*y3; A(2, 8) = y3*y3; A(3, 8) = x3; A(4, 8) = y3; A(5, 8) = 1.0; + A(0, 9) = x4*x4; A(1, 9) = x4*y4; A(2, 9) = y4*y4; A(3, 9) = x4; A(4, 9) = y4; A(5, 9) = 1.0; + + // X' + A(6, 0) = x1*x1; A(6, 1) = x1*y1; A(6, 2) = y1*y1; A(6, 3) = x1; A(6, 4) = y1; A(6, 5) = 1.0; + A(7, 0) = x2*x2; A(7, 1) = x2*y2; A(7, 2) = y2*y2; A(7, 3) = x2; A(7, 4) = y2; A(7, 5) = 1.0; + A(8, 0) = x3*x3; A(8, 1) = x3*y3; A(8, 2) = y3*y3; A(8, 3) = x3; A(8, 4) = y3; A(8, 5) = 1.0; + A(9, 0) = x4*x4; A(9, 1) = x4*y4; A(9, 2) = y4*y4; A(9, 3) = x4; A(9, 4) = y4; A(9, 5) = 1.0; + + // z + typename ublas::vector<in_type> b(10, 0.0); + b(6) = nearest[0].second; + b(7) = nearest[1].second; + b(8) = nearest[2].second; + b(9) = nearest[3].second; + + typename ublas::matrix<in_type> A_t = A; + typename ublas::vector<in_type> s = b; + typename ublas::permutation_matrix<in_type> P(A_t.size1()); + + // Use LUP factorization to solve for the coefficients + // We're solving the problem in the form of Ax = b + bool is_singular = ublas::lu_factorize(A_t, P); + + out_type output = 0; + + // Fall back to 1D interpolation if the matrix is singular + if (is_singular) { + // Warn the user that the A matrix is singular + UHD_MSG(warning) << "Bilinear interpolation: singular matrix detected." << std::endl + << "Performing 1D linear interpolation against the nearest measurements." << std::endl + << "Provide calibration data with more measurements" << std::endl; + + output = (b[7] - b[6]) / 2.0; + output += b[6]; + return output; + } + ublas::lu_substitute(A_t, P, s); + + in_type x = args[0]; + in_type y = args[1]; + + // Utilize the solution to calculate the interpolation function + output = s[0]*x*x + s[1]*x*y + s[2]*y*y + s[3]*x + s[4]*y + s[5]; + return output; +} + +} // namespace cal +} // namespace uhd + +#endif /* INCLUDED_UHD_INTERPOLATION_IPP */ diff --git a/host/lib/cal/power_container_impl.cpp b/host/lib/cal/power_container_impl.cpp new file mode 100644 index 000000000..5d07c3b7e --- /dev/null +++ b/host/lib/cal/power_container_impl.cpp @@ -0,0 +1,80 @@ +// +// Copyright 2016 Ettus Research +// +// 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 "power_container_impl.hpp" +#include <uhd/exception.hpp> +#include <boost/format.hpp> + +using namespace uhd; +using namespace uhd::cal; + +power_container::sptr power_container::make() +{ + return power_container::sptr(new power_container_impl()); +} + +power_container_impl::power_container_impl() : + _nargs(0), _mode(interp_mode_t::NEAREST) +{ + /* NOP */ +} + +double power_container_impl::get(const std::vector<double> &args) +{ + this->verify_nargs(args); + switch (_mode) + { + case interp_mode_t::BILINEAR : + return _interpolator.bl_interp(_data, args); + case interp_mode_t::NEAREST : + return _interpolator.nn_interp(_data, args); + default: + return _interpolator.nn_interp(_data, args); + } +} + +void power_container_impl::add(const double output, const std::vector<double> &args) +{ + if (_nargs == 0) + { + _nargs = args.size(); + _mode = _nargs == 2 ? interp_mode_t::BILINEAR : interp_mode_t::NEAREST; + } + this->verify_nargs(args); + _data[args] = output; +} + +void power_container_impl::add_metadata(const power_container::metadata_t &data) +{ + _metadata = data; +} + +const power_container_impl::metadata_t &power_container_impl::get_metadata() +{ + return _metadata; +} + +void power_container_impl::verify_nargs(const std::vector<double> &args) +{ + // Check that the number of arguments expected are correct + if (args.size() != _nargs) { + throw uhd::assertion_error(str(boost::format( + "power_container_impl: Expected %d number of arguments/values instead of %d") + % _nargs % args.size() + )); + } +} diff --git a/host/lib/cal/power_container_impl.hpp b/host/lib/cal/power_container_impl.hpp new file mode 100644 index 000000000..4c2bcab79 --- /dev/null +++ b/host/lib/cal/power_container_impl.hpp @@ -0,0 +1,77 @@ +// +// Copyright 2016 Ettus Research +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. +// + +#ifndef INCLUDED_UHD_CAL_POWER_CONTAINER_IMPL_HPP +#define INCLUDED_UHD_CAL_POWER_CONTAINER_IMPL_HPP + +#include "interpolation.ipp" +#include <uhd/cal/power_container.hpp> + +namespace uhd { +namespace cal { + +enum interp_mode_t +{ + BILINEAR, //! linear interpolation + NEAREST //! nearest neighbor interpolation +}; + +class power_container_impl : public power_container { +public: + typedef std::map<std::vector<double>, double> container_t; + + power_container_impl(); + + double get(const std::vector<double> &args); + const metadata_t &get_metadata(); + + void add(const double output, const std::vector<double> &args); + void add_metadata(const metadata_t &data); + +private: + // Container data to be serialized + size_t _nargs; + metadata_t _metadata; + interp_mode_t _mode; + container_t _data; + + interp<double, double> _interpolator; + + void verify_nargs(const std::vector<double> &args); + +protected: + friend class boost::serialization::access; + + void serialize(iarchive_type & ar, const unsigned int) { + ar & _nargs; + ar & _metadata; + ar & _mode; + ar & _data; + } + + void serialize(oarchive_type & ar, const unsigned int) { + ar & _nargs; + ar & _metadata; + ar & _mode; + ar & _data; + } +}; + +} // namespace cal +} // namespace uhd + +#endif /* INCLUDED_UHD_CAL_POWER_CONTAINER_IMPL_HPP */ diff --git a/host/lib/rfnoc/block_ctrl_base.cpp b/host/lib/rfnoc/block_ctrl_base.cpp index 24dad6b47..4ee577891 100644 --- a/host/lib/rfnoc/block_ctrl_base.cpp +++ b/host/lib/rfnoc/block_ctrl_base.cpp @@ -48,7 +48,6 @@ inline uint32_t _sr_to_addr64(uint32_t reg) { return reg * 8; }; // for peek64 block_ctrl_base::block_ctrl_base( const make_args_t &make_args ) : _tree(make_args.tree), - _transport_is_big_endian(make_args.is_big_endian), _ctrl_ifaces(make_args.ctrl_ifaces), _base_address(make_args.base_address & 0xFFF0) { diff --git a/host/lib/rfnoc/ctrl_iface.cpp b/host/lib/rfnoc/ctrl_iface.cpp index b2ac1778e..8e4474af7 100644 --- a/host/lib/rfnoc/ctrl_iface.cpp +++ b/host/lib/rfnoc/ctrl_iface.cpp @@ -16,7 +16,6 @@ // #include "ctrl_iface.hpp" -#include "async_packet_handler.hpp" #include <uhd/exception.hpp> #include <uhd/utils/msg.hpp> #include <uhd/utils/byteswap.hpp> @@ -37,7 +36,6 @@ using namespace uhd::transport; static const double ACK_TIMEOUT = 2.0; //supposed to be worst case practical timeout static const double MASSIVE_TIMEOUT = 10.0; //for when we wait on a timed command -static const size_t SR_READBACK = 32; ctrl_iface::~ctrl_iface(void){ /* NOP */ @@ -60,13 +58,12 @@ public: _name(name), _seq_out(0), _timeout(ACK_TIMEOUT), - _resp_queue(128/*max response msgs*/), - _resp_queue_size(_resp_xport ? _resp_xport->get_num_recv_frames() : 3), + _resp_queue_size(_resp_xport->get_num_recv_frames()), _rb_address(uhd::rfnoc::SR_READBACK) { - if (resp_xport) { - while (resp_xport->get_recv_buff(0.0)) {} //flush - } + UHD_ASSERT_THROW(_ctrl_xport); + UHD_ASSERT_THROW(_resp_xport); + while (resp_xport->get_recv_buff(0.0)) {} //flush this->set_time(uhd::time_spec_t(0.0)); this->set_tick_rate(1.0); //something possible but bogus } @@ -76,7 +73,6 @@ public: _timeout = ACK_TIMEOUT; //reset timeout to something small UHD_SAFE_CALL( this->peek32(0);//dummy peek with the purpose of ack'ing all packets - _async_task.reset();//now its ok to release the task ) } @@ -196,50 +192,16 @@ private: uint32_t const *pkt = NULL; managed_recv_buffer::sptr buff; - //get buffer from response endpoint - or die in timeout - if (_resp_xport) - { - buff = _resp_xport->get_recv_buff(_timeout); - try - { - UHD_ASSERT_THROW(bool(buff)); - UHD_ASSERT_THROW(buff->size() > 0); - } - catch(const std::exception &ex) - { - throw uhd::io_error(str(boost::format("Block ctrl (%s) no response packet - %s") % _name % ex.what())); - } - pkt = buff->cast<const uint32_t *>(); - packet_info.num_packet_words32 = buff->size()/sizeof(uint32_t); + buff = _resp_xport->get_recv_buff(_timeout); + try { + UHD_ASSERT_THROW(bool(buff)); + UHD_ASSERT_THROW(buff->size() > 0); } - - //get buffer from response endpoint - or die in timeout - else - { - /* - * Couldn't get message with haste. - * Now check both possible queues for messages. - * Messages should come in on _resp_queue, - * but could end up in dump_queue. - * If we don't get a message --> Die in timeout. - */ - double accum_timeout = 0.0; - const double short_timeout = 0.005; // == 5ms - while(not ((_resp_queue.pop_with_haste(resp_buff)) - || (check_dump_queue(resp_buff)) - || (_resp_queue.pop_with_timed_wait(resp_buff, short_timeout)) - )){ - /* - * If a message couldn't be received within a given timeout - * --> throw AssertionError! - */ - accum_timeout += short_timeout; - UHD_ASSERT_THROW(accum_timeout < _timeout); - } - - pkt = resp_buff.data; - packet_info.num_packet_words32 = sizeof(resp_buff)/sizeof(uint32_t); + catch(const std::exception &ex) { + throw uhd::io_error(str(boost::format("Block ctrl (%s) no response packet - %s") % _name % ex.what())); } + pkt = buff->cast<const uint32_t *>(); + packet_info.num_packet_words32 = buff->size()/sizeof(uint32_t); //parse the buffer try @@ -306,48 +268,11 @@ private: return 0; } - /* - * If ctrl_core waits for a message that didn't arrive it can search for it in the dump queue. - * This actually happens during shutdown. - * handle_async_task can't access queue anymore thus it returns the corresponding message. - * msg_task class implements a dump_queue to store such messages. - * With check_dump_queue we can check if a message we are waiting for got stranded there. - * If a message got stuck we get it here and push it onto our own message_queue. - */ - bool check_dump_queue(resp_buff_type& b) { - const size_t min_buff_size = 8; // Same value as in b200_io_impl->handle_async_task - uint32_t recv_sid = (((_sid)<<16)|((_sid)>>16)); - uhd::msg_task::msg_payload_t msg; - do{ - msg = _async_task->get_msg_from_dump_queue(recv_sid); - } - while(msg.size() < min_buff_size && msg.size() != 0); - - if(msg.size() >= min_buff_size) { - memcpy(b.data, &msg.front(), std::min(msg.size(), sizeof(b.data))); - return true; - } - return false; - } - - void push_response(const uint32_t *buff) - { - resp_buff_type resp_buff; - std::memcpy(resp_buff.data, buff, sizeof(resp_buff)); - _resp_queue.push_with_haste(resp_buff); - } - - void hold_task(uhd::msg_task::sptr task) - { - _async_task = task; - } - const vrt::if_packet_info_t::link_type_t _link_type; const vrt::if_packet_info_t::packet_type_t _packet_type; const bool _bige; const uhd::transport::zero_copy_if::sptr _ctrl_xport; const uhd::transport::zero_copy_if::sptr _resp_xport; - uhd::msg_task::sptr _async_task; const uint32_t _sid; const std::string _name; boost::mutex _mutex; @@ -357,7 +282,6 @@ private: double _tick_rate; double _timeout; std::queue<size_t> _outstanding_seqs; - bounded_buffer<resp_buff_type> _resp_queue; const size_t _resp_queue_size; const size_t _rb_address; diff --git a/host/lib/rfnoc/ctrl_iface.hpp b/host/lib/rfnoc/ctrl_iface.hpp index 3690874f9..5e88c3dd6 100644 --- a/host/lib/rfnoc/ctrl_iface.hpp +++ b/host/lib/rfnoc/ctrl_iface.hpp @@ -47,18 +47,6 @@ public: const std::string &name = "0" ); - //! Hold a ref to a task thats feeding push response - virtual void hold_task(uhd::msg_task::sptr task) = 0; - - //! Push a response externall (resp_xport is NULL) - virtual void push_response(const uint32_t *buff) = 0; - - //! Set the command time that will activate - virtual void set_time(const uhd::time_spec_t &time) = 0; - - //! Get the command time that will activate - virtual uhd::time_spec_t get_time(void) = 0; - //! Set the tick rate (converting time into ticks) virtual void set_tick_rate(const double rate) = 0; }; diff --git a/host/lib/rfnoc/legacy_compat.cpp b/host/lib/rfnoc/legacy_compat.cpp index 7acaa898c..4060c62ae 100644 --- a/host/lib/rfnoc/legacy_compat.cpp +++ b/host/lib/rfnoc/legacy_compat.cpp @@ -96,16 +96,6 @@ size_t calc_num_tx_chans_per_radio( ); } -double lambda_const_double(const double d) -{ - return d; -} - -uhd::meta_range_t lambda_const_meta_range(const double start, const double stop, const double step) -{ - return uhd::meta_range_t(start, stop, step); -} - /*! Recreate passed property without bound subscribers. Maintains current property value. */ template <typename T> @@ -114,6 +104,7 @@ static void recreate_property(const uhd::fs_path &path, uhd::property_tree::sptr tree->remove(path); tree->create<T>(path).set(temp); } + /************************************************************************ * Class Definition ***********************************************************************/ @@ -645,10 +636,10 @@ private: // methods ) ; _tree->create<double>(rx_dsp_base_path / "freq/value") - .set_publisher(boost::bind(&lambda_const_double, 0.0)) + .set_publisher([](){ return 0.0; }) ; _tree->create<uhd::meta_range_t>(rx_dsp_base_path / "freq/range") - .set_publisher(boost::bind(&lambda_const_meta_range, 0.0, 0.0, 0.0)) + .set_publisher([](){ return uhd::meta_range_t(0.0, 0.0, 0.0); }) ; } } @@ -678,10 +669,10 @@ private: // methods ) ; _tree->create<double>(tx_dsp_base_path / "freq/value") - .set_publisher(boost::bind(&lambda_const_double, 0.0)) + .set_publisher([](){ return 0.0; }) ; _tree->create<uhd::meta_range_t>(tx_dsp_base_path / "freq/range") - .set_publisher(boost::bind(&lambda_const_meta_range, 0.0, 0.0, 0.0)) + .set_publisher([](){ return uhd::meta_range_t(0.0, 0.0, 0.0); }) ; } } diff --git a/host/lib/rfnoc/xports.hpp b/host/lib/rfnoc/xports.hpp index 98cf71b6d..7bd4f2fc8 100644 --- a/host/lib/rfnoc/xports.hpp +++ b/host/lib/rfnoc/xports.hpp @@ -16,6 +16,7 @@ // #include <uhd/types/sid.hpp> +#include <uhd/types/endianness.hpp> #include <uhd/transport/zero_copy.hpp> namespace uhd { @@ -31,6 +32,7 @@ namespace uhd { size_t send_buff_size; uhd::sid_t send_sid; uhd::sid_t recv_sid; + uhd::endianness_t endianness; }; }; diff --git a/host/lib/types/sid.cpp b/host/lib/types/sid.cpp index b697bd614..40f84a2aa 100644 --- a/host/lib/types/sid.cpp +++ b/host/lib/types/sid.cpp @@ -1,5 +1,5 @@ // -// Copyright 2014 Ettus Research LLC +// Copyright 2014-2016 Ettus Research LLC // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by @@ -15,12 +15,12 @@ // along with this program. If not, see <http://www.gnu.org/licenses/>. // +#include <uhd/types/sid.hpp> +#include <uhd/exception.hpp> +#include <uhd/utils/cast.hpp> #include <boost/format.hpp> #include <boost/regex.hpp> #include <boost/lexical_cast.hpp> -#include <uhd/exception.hpp> -#include <uhd/types/sid.hpp> -#include <uhd/utils/cast.hpp> using namespace uhd; @@ -141,7 +141,7 @@ void sid_t::set_dst_blockport(uint32_t new_blockport) set_sid((_sid & 0xFFFFFFF0) | ((new_blockport & 0xF) << 0)); } -sid_t sid_t::reversed() +sid_t sid_t::reversed() const { return sid_t((get_dst() << 16) | get_src()); } diff --git a/host/lib/uhd.rc.in b/host/lib/uhd.rc.in index 24177a00a..dee6bb8a3 100644 --- a/host/lib/uhd.rc.in +++ b/host/lib/uhd.rc.in @@ -1,8 +1,8 @@ #include <windows.h> VS_VERSION_INFO VERSIONINFO - FILEVERSION @TRIMMED_VERSION_MAJOR_API@,@TRIMMED_VERSION_ABI@,@RC_TRIMMED_VERSION_PATCH@,@UHD_GIT_COUNT@ - PRODUCTVERSION @TRIMMED_VERSION_MAJOR_API@,@TRIMMED_VERSION_ABI@,@RC_TRIMMED_VERSION_PATCH@,@UHD_GIT_COUNT@ + FILEVERSION @RC_VERSION_MAJOR_API@,@UHD_VERSION_ABI@,@RC_VERSION_PATCH@,@UHD_GIT_COUNT@ + PRODUCTVERSION @RC_VERSION_MAJOR_API@,@UHD_VERSION_ABI@,@RC_VERSION_PATCH@,@UHD_GIT_COUNT@ FILEFLAGSMASK 0x3fL #ifndef NDEBUG FILEFLAGS 0x0L diff --git a/host/lib/usrp/device3/device3_impl.cpp b/host/lib/usrp/device3/device3_impl.cpp index 50598a519..28b7bc34b 100644 --- a/host/lib/usrp/device3/device3_impl.cpp +++ b/host/lib/usrp/device3/device3_impl.cpp @@ -105,8 +105,7 @@ void device3_impl::enumerate_rfnoc_blocks( size_t n_blocks, size_t base_port, const uhd::sid_t &base_sid, - uhd::device_addr_t transport_args, - uhd::endianness_t endianness + uhd::device_addr_t transport_args ) { // entries that are already connected to this block uhd::sid_t ctrl_sid = base_sid; @@ -131,7 +130,7 @@ void device3_impl::enumerate_rfnoc_blocks( ); UHD_DEVICE3_LOG() << str(boost::format("Setting up NoC-Shell Control for port #0 (SID: %s)...") % xport.send_sid.to_pp_string_hex()); uhd::rfnoc::ctrl_iface::sptr ctrl = uhd::rfnoc::ctrl_iface::make( - endianness == ENDIANNESS_BIG, + xport.endianness == uhd::ENDIANNESS_BIG, xport.send, xport.recv, xport.send_sid, @@ -160,7 +159,7 @@ void device3_impl::enumerate_rfnoc_blocks( ); UHD_DEVICE3_LOG() << str(boost::format("Setting up NoC-Shell Control for port #%d (SID: %s)...") % port_number % xport1.send_sid.to_pp_string_hex()); uhd::rfnoc::ctrl_iface::sptr ctrl1 = uhd::rfnoc::ctrl_iface::make( - endianness == ENDIANNESS_BIG, + xport1.endianness == uhd::ENDIANNESS_BIG, xport1.send, xport1.recv, xport1.send_sid, @@ -173,7 +172,6 @@ void device3_impl::enumerate_rfnoc_blocks( make_args.base_address = xport.send_sid.get_dst(); make_args.device_index = device_index; make_args.tree = subtree; - make_args.is_big_endian = (endianness == ENDIANNESS_BIG); _rfnoc_block_ctrl.push_back(uhd::rfnoc::block_ctrl_base::make(make_args, noc_id)); } } diff --git a/host/lib/usrp/device3/device3_impl.hpp b/host/lib/usrp/device3/device3_impl.hpp index 117e4af1c..c496b5105 100644 --- a/host/lib/usrp/device3/device3_impl.hpp +++ b/host/lib/usrp/device3/device3_impl.hpp @@ -134,7 +134,6 @@ protected: virtual uhd::device_addr_t get_tx_hints(size_t) { return uhd::device_addr_t(); }; virtual uhd::device_addr_t get_rx_hints(size_t) { return uhd::device_addr_t(); }; - virtual uhd::endianness_t get_transport_endianness(size_t mb_index) = 0; //! Is called after a streamer is generated virtual void post_streamer_hooks(uhd::direction_t) {}; @@ -167,8 +166,7 @@ protected: size_t n_blocks, size_t base_port, const uhd::sid_t &base_sid, - uhd::device_addr_t transport_args, - uhd::endianness_t endianness + uhd::device_addr_t transport_args ); /*********************************************************************** diff --git a/host/lib/usrp/device3/device3_io_impl.cpp b/host/lib/usrp/device3/device3_io_impl.cpp index c1bfd1606..2f2e778c9 100644 --- a/host/lib/usrp/device3/device3_io_impl.cpp +++ b/host/lib/usrp/device3/device3_io_impl.cpp @@ -565,7 +565,7 @@ rx_streamer::sptr device3_impl::get_rx_stream(const stream_args_t &args_) //init some streamer stuff std::string conv_endianness; - if (get_transport_endianness(mb_index) == ENDIANNESS_BIG) { + if (xport.endianness == ENDIANNESS_BIG) { my_streamer->set_vrt_unpacker(&vrt::chdr::if_hdr_unpack_be); conv_endianness = "be"; } else { @@ -618,7 +618,7 @@ rx_streamer::sptr device3_impl::get_rx_stream(const stream_args_t &args_) &handle_rx_flowctrl, xport.send_sid, xport.send, - get_transport_endianness(mb_index), + xport.endianness, fc_cache, _1 ), @@ -755,7 +755,7 @@ tx_streamer::sptr device3_impl::get_tx_stream(const uhd::stream_args_t &args_) //init some streamer stuff std::string conv_endianness; - if (get_transport_endianness(mb_index) == ENDIANNESS_BIG) { + if (xport.endianness == ENDIANNESS_BIG) { my_streamer->set_vrt_packer(&vrt::chdr::if_hdr_pack_be); conv_endianness = "be"; } else { @@ -803,7 +803,7 @@ tx_streamer::sptr device3_impl::get_tx_stream(const uhd::stream_args_t &args_) &handle_tx_async_msgs, fc_cache, xport.recv, - get_transport_endianness(mb_index), + xport.endianness, tick_rate_retriever ) ); diff --git a/host/lib/usrp/mboard_eeprom.cpp b/host/lib/usrp/mboard_eeprom.cpp index 4cf58cd05..0e6cb8574 100644 --- a/host/lib/usrp/mboard_eeprom.cpp +++ b/host/lib/usrp/mboard_eeprom.cpp @@ -600,7 +600,7 @@ template <typename T> static const byte_vector_t to_bytes(const T &item){ } #define sizeof_member(struct_name, member_name) \ - sizeof(reinterpret_cast<struct_name*>(NULL)->member_name) + sizeof(reinterpret_cast<struct_name*>(0)->member_name) static void load_e100(mboard_eeprom_t &mb_eeprom, i2c_iface &iface){ const size_t num_bytes = offsetof(e100_eeprom_map, model); diff --git a/host/lib/usrp/x300/x300_impl.cpp b/host/lib/usrp/x300/x300_impl.cpp index 374247fea..edf254130 100644 --- a/host/lib/usrp/x300/x300_impl.cpp +++ b/host/lib/usrp/x300/x300_impl.cpp @@ -381,7 +381,33 @@ static void x300_load_fw(wb_iface::sptr fw_reg_ctrl, const std::string &file_nam UHD_MSG(status) << " done!" << std::endl; } -x300_impl::x300_impl(const uhd::device_addr_t &dev_addr) +static const std::string thread_final_msg = "Finished multi-threaded initialization\n"; + +static void thread_msg_handler(uhd::msg::type_t type, const std::string &msg) +{ + static boost::mutex msg_mutex; + boost::mutex::scoped_lock lock(msg_mutex); + + typedef std::pair<uhd::msg::type_t, std::string> msg_pair_t; + typedef std::map<boost::thread::id, std::vector<msg_pair_t> > thread_map_t; + + static thread_map_t thread_list; + thread_list[boost::this_thread::get_id()].push_back(msg_pair_t(type, msg)); + + if (msg == thread_final_msg) + { + BOOST_FOREACH(const thread_map_t::value_type &thread_pair, thread_list) + { + BOOST_FOREACH(const msg_pair_t &msg_pair, thread_pair.second) + { + // Forward the message to the default handler + uhd::msg::default_msg_handler(msg_pair.first, msg_pair.second); + } + } + } +} + +x300_impl::x300_impl(const uhd::device_addr_t &dev_addr) : device3_impl() , _sid_framer(0) { @@ -391,10 +417,33 @@ x300_impl::x300_impl(const uhd::device_addr_t &dev_addr) const device_addrs_t device_args = separate_device_addr(dev_addr); _mb.resize(device_args.size()); + + // Serialize the initialization process + if (dev_addr.has_key("serialize_init") or device_args.size() == 1) { + for (size_t i = 0; i < device_args.size(); i++) + { + this->setup_mb(i, device_args[i]); + } + return; + } + + // Setup a custom messenger handler + uhd::msg::handler_t current_handler = uhd::msg::get_handler(); + uhd::msg::register_handler(&thread_msg_handler); + + // Thread the initialization process + boost::thread_group setup_threads; for (size_t i = 0; i < device_args.size(); i++) { - this->setup_mb(i, device_args[i]); + setup_threads.create_thread( + boost::bind(&x300_impl::setup_mb, this, i, device_args[i]) + ); } + setup_threads.join_all(); + + // restore the original message handler + UHD_MSG(status) << thread_final_msg; + uhd::msg::register_handler(current_handler); } void x300_impl::mboard_members_t::discover_eth( @@ -505,6 +554,16 @@ void x300_impl::setup_mb(const size_t mb_i, const uhd::device_addr_t &dev_addr) mboard_members_t &mb = _mb[mb_i]; mb.initialization_done = false; + const std::string thread_id( + boost::lexical_cast<std::string>(boost::this_thread::get_id()) + ); + const std::string thread_msg( + "Thread ID " + thread_id + " for motherboard " + + boost::lexical_cast<std::string>(mb_i) + ); + UHD_MSG(status) << std::endl; + UHD_MSG(status) << thread_msg << std::endl; + std::vector<std::string> eth_addrs; // Not choosing eth0 based on resource might cause user issues std::string eth0_addr = dev_addr.has_key("resource") ? dev_addr["resource"] : dev_addr["addr"]; @@ -886,14 +945,6 @@ void x300_impl::setup_mb(const size_t mb_i, const uhd::device_addr_t &dev_addr) } //////////////////////////////////////////////////////////////////// - //clear router? - //////////////////////////////////////////////////////////////////// - for (size_t i = 0; i < 512; i++) { - mb.zpu_ctrl->poke32(SR_ADDR(SETXB_BASE, i), 0); - } - - - //////////////////////////////////////////////////////////////////// // setup time sources and properties //////////////////////////////////////////////////////////////////// _tree->create<std::string>(mb_path / "time_source" / "value") @@ -950,8 +1001,7 @@ void x300_impl::setup_mb(const size_t mb_i, const uhd::device_addr_t &dev_addr) n_rfnoc_blocks, X300_XB_DST_PCI + 1, /* base port */ uhd::sid_t(X300_SRC_ADDR0, 0, X300_DST_ADDR + mb_i, 0), - dev_addr, - mb.if_pkt_is_big_endian ? ENDIANNESS_BIG : ENDIANNESS_LITTLE + dev_addr ); //////////////// RFNOC ///////////////// @@ -1072,6 +1122,7 @@ uhd::both_xports_t x300_impl::make_transport( zero_copy_xport_params default_buff_args; both_xports_t xports; + xports.endianness = mb.if_pkt_is_big_endian ? ENDIANNESS_BIG : ENDIANNESS_LITTLE; if (mb.xport_path == "nirio") { xports.send_sid = this->allocate_sid(mb, address, X300_SRC_ADDR0, X300_XB_DST_PCI); xports.recv_sid = xports.send_sid.reversed(); diff --git a/host/lib/usrp/x300/x300_impl.hpp b/host/lib/usrp/x300/x300_impl.hpp index 133938daf..d082ab76a 100644 --- a/host/lib/usrp/x300/x300_impl.hpp +++ b/host/lib/usrp/x300/x300_impl.hpp @@ -283,9 +283,6 @@ private: /// More IO stuff uhd::device_addr_t get_tx_hints(size_t mb_index); uhd::device_addr_t get_rx_hints(size_t mb_index); - uhd::endianness_t get_transport_endianness(size_t mb_index) { - return _mb[mb_index].if_pkt_is_big_endian ? uhd::ENDIANNESS_BIG : uhd::ENDIANNESS_LITTLE; - }; void post_streamer_hooks(uhd::direction_t dir); }; diff --git a/host/lib/usrp/x300/x300_radio_ctrl_impl.cpp b/host/lib/usrp/x300/x300_radio_ctrl_impl.cpp index 0e11cb42c..9bf61f998 100644 --- a/host/lib/usrp/x300/x300_radio_ctrl_impl.cpp +++ b/host/lib/usrp/x300/x300_radio_ctrl_impl.cpp @@ -813,8 +813,8 @@ void x300_radio_ctrl_impl::_self_cal_adc_capture_delay(bool print_status) //and count deviations from the expected value _regs->misc_outs_reg.write(radio_regmap_t::misc_outs_reg_t::ADC_CHECKER_ENABLED, 0); _regs->misc_outs_reg.write(radio_regmap_t::misc_outs_reg_t::ADC_CHECKER_ENABLED, 1); - //10ms @ 200MHz = 2 million samples - boost::this_thread::sleep(boost::posix_time::milliseconds(10)); + //5ms @ 200MHz = 1 million samples + boost::this_thread::sleep(boost::posix_time::milliseconds(5)); if (_regs->misc_ins_reg.read(radio_regmap_t::misc_ins_reg_t::ADC_CHECKER0_I_LOCKED)) { err_code += _regs->misc_ins_reg.get(radio_regmap_t::misc_ins_reg_t::ADC_CHECKER0_I_ERROR); } else { @@ -828,8 +828,8 @@ void x300_radio_ctrl_impl::_self_cal_adc_capture_delay(bool print_status) //and count deviations from the expected value _regs->misc_outs_reg.write(radio_regmap_t::misc_outs_reg_t::ADC_CHECKER_ENABLED, 0); _regs->misc_outs_reg.write(radio_regmap_t::misc_outs_reg_t::ADC_CHECKER_ENABLED, 1); - //10ms @ 200MHz = 2 million samples - boost::this_thread::sleep(boost::posix_time::milliseconds(10)); + //5ms @ 200MHz = 1 million samples + boost::this_thread::sleep(boost::posix_time::milliseconds(5)); if (_regs->misc_ins_reg.read(radio_regmap_t::misc_ins_reg_t::ADC_CHECKER0_Q_LOCKED)) { err_code += _regs->misc_ins_reg.get(radio_regmap_t::misc_ins_reg_t::ADC_CHECKER0_Q_ERROR); } else { diff --git a/host/lib/utils/msg.cpp b/host/lib/utils/msg.cpp index 95879a116..d9d2fb66a 100644 --- a/host/lib/utils/msg.cpp +++ b/host/lib/utils/msg.cpp @@ -78,7 +78,12 @@ void uhd::msg::register_handler(const handler_t &handler){ msg_rs().handler = handler; } -static void default_msg_handler(uhd::msg::type_t type, const std::string &msg){ +const uhd::msg::handler_t& uhd::msg::get_handler(){ + boost::mutex::scoped_lock lock(msg_rs().mutex); + return msg_rs().handler; +} + +void uhd::msg::default_msg_handler(uhd::msg::type_t type, const std::string &msg){ static boost::mutex msg_mutex; boost::mutex::scoped_lock lock(msg_mutex); switch(type){ @@ -104,7 +109,7 @@ static void default_msg_handler(uhd::msg::type_t type, const std::string &msg){ } UHD_STATIC_BLOCK(msg_register_default_handler){ - uhd::msg::register_handler(&default_msg_handler); + uhd::msg::register_handler(&uhd::msg::default_msg_handler); } /*********************************************************************** |