aboutsummaryrefslogtreecommitdiffstats
path: root/host/lib
diff options
context:
space:
mode:
Diffstat (limited to 'host/lib')
-rw-r--r--host/lib/CMakeLists.txt7
-rw-r--r--host/lib/cal/CMakeLists.txt32
-rw-r--r--host/lib/cal/interpolation.hpp71
-rw-r--r--host/lib/cal/interpolation.ipp199
-rw-r--r--host/lib/cal/power_container_impl.cpp80
-rw-r--r--host/lib/cal/power_container_impl.hpp77
-rw-r--r--host/lib/rfnoc/block_ctrl_base.cpp1
-rw-r--r--host/lib/rfnoc/ctrl_iface.cpp100
-rw-r--r--host/lib/rfnoc/ctrl_iface.hpp12
-rw-r--r--host/lib/rfnoc/legacy_compat.cpp19
-rw-r--r--host/lib/rfnoc/xports.hpp2
-rw-r--r--host/lib/types/sid.cpp10
-rw-r--r--host/lib/uhd.rc.in4
-rw-r--r--host/lib/usrp/device3/device3_impl.cpp8
-rw-r--r--host/lib/usrp/device3/device3_impl.hpp4
-rw-r--r--host/lib/usrp/device3/device3_io_impl.cpp8
-rw-r--r--host/lib/usrp/mboard_eeprom.cpp2
-rw-r--r--host/lib/usrp/x300/x300_impl.cpp75
-rw-r--r--host/lib/usrp/x300/x300_impl.hpp3
-rw-r--r--host/lib/usrp/x300/x300_radio_ctrl_impl.cpp8
-rw-r--r--host/lib/utils/msg.cpp9
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);
}
/***********************************************************************