summaryrefslogtreecommitdiffstats
path: root/host/include
diff options
context:
space:
mode:
authorJosh Blum <josh@joshknows.com>2010-07-07 02:23:38 +0000
committerJosh Blum <josh@joshknows.com>2010-07-07 02:23:38 +0000
commitf2e9d3ed0941dc5738149dd82d1eac158bdf0a0f (patch)
tree82a350987e32cd329ab5fe56b6dd9fbfef08230f /host/include
parent998fee6ef064f1d53a61dd0eec79276d1e85291e (diff)
parent5c2cccfe8c4a9c6c912a4d18dc1e7a6f84c79609 (diff)
downloaduhd-f2e9d3ed0941dc5738149dd82d1eac158bdf0a0f.tar.gz
uhd-f2e9d3ed0941dc5738149dd82d1eac158bdf0a0f.tar.bz2
uhd-f2e9d3ed0941dc5738149dd82d1eac158bdf0a0f.zip
Merge branch 'master' of ettus.sourcerepo.com:ettus/uhdpriv into usrp_e
Conflicts: host/examples/rx_timed_samples.cpp
Diffstat (limited to 'host/include')
-rw-r--r--host/include/uhd/CMakeLists.txt1
-rw-r--r--host/include/uhd/config.hpp11
-rw-r--r--host/include/uhd/device.hpp59
-rw-r--r--host/include/uhd/device.ipp79
-rw-r--r--host/include/uhd/transport/CMakeLists.txt4
-rw-r--r--host/include/uhd/transport/alignment_buffer.hpp84
-rw-r--r--host/include/uhd/transport/alignment_buffer.ipp140
-rw-r--r--host/include/uhd/transport/bounded_buffer.hpp82
-rw-r--r--host/include/uhd/transport/bounded_buffer.ipp112
-rw-r--r--host/include/uhd/transport/vrt.hpp115
-rw-r--r--host/include/uhd/transport/vrt_if_packet.hpp99
-rw-r--r--host/include/uhd/transport/zero_copy.hpp8
-rw-r--r--host/include/uhd/types/metadata.hpp14
-rw-r--r--host/include/uhd/types/time_spec.hpp86
-rw-r--r--host/include/uhd/usrp/CMakeLists.txt3
-rw-r--r--host/include/uhd/usrp/dboard_id.hpp2
-rw-r--r--host/include/uhd/usrp/mboard_props.hpp2
-rw-r--r--host/include/uhd/usrp/mimo_usrp.hpp171
-rw-r--r--host/include/uhd/usrp/simple_usrp.hpp22
-rw-r--r--host/include/uhd/usrp/usrp2.hpp62
-rw-r--r--host/include/uhd/utils/CMakeLists.txt1
-rw-r--r--host/include/uhd/utils/algorithm.hpp29
-rw-r--r--host/include/uhd/utils/byteswap.hpp82
-rw-r--r--host/include/uhd/utils/byteswap.ipp120
24 files changed, 932 insertions, 456 deletions
diff --git a/host/include/uhd/CMakeLists.txt b/host/include/uhd/CMakeLists.txt
index d63062032..c0339dbd3 100644
--- a/host/include/uhd/CMakeLists.txt
+++ b/host/include/uhd/CMakeLists.txt
@@ -24,6 +24,7 @@ ADD_SUBDIRECTORY(utils)
INSTALL(FILES
config.hpp
device.hpp
+ device.ipp
wax.hpp
DESTINATION ${INCLUDE_DIR}/uhd
)
diff --git a/host/include/uhd/config.hpp b/host/include/uhd/config.hpp
index b23a4dc00..013354d33 100644
--- a/host/include/uhd/config.hpp
+++ b/host/include/uhd/config.hpp
@@ -78,7 +78,7 @@
#endif // UHD_DLL
// Define force inline macro
-#ifdef BOOST_MSVC
+#if defined(BOOST_MSVC)
#define UHD_INLINE __forceinline
#elif defined(__GNUG__) && __GNUG__ >= 4
#define UHD_INLINE inline __attribute__((always_inline))
@@ -86,4 +86,13 @@
#define UHD_INLINE inline
#endif
+// Define deprecated attribute macro
+#if defined(BOOST_MSVC)
+ #define UHD_DEPRECATED __declspec(deprecated)
+#elif defined(__GNUG__) && __GNUG__ >= 4
+ #define UHD_DEPRECATED __attribute__ ((deprecated))
+#else
+ #define UHD_DEPRECATED
+#endif
+
#endif /* INCLUDED_UHD_CONFIG_HPP */
diff --git a/host/include/uhd/device.hpp b/host/include/uhd/device.hpp
index d3e9015c4..a0c29f2e6 100644
--- a/host/include/uhd/device.hpp
+++ b/host/include/uhd/device.hpp
@@ -27,6 +27,7 @@
#include <boost/shared_ptr.hpp>
#include <boost/function.hpp>
#include <boost/asio/buffer.hpp>
+#include <vector>
namespace uhd{
@@ -97,7 +98,7 @@ public:
};
/*!
- * Send a buffer containing IF data with its metadata.
+ * Send buffers containing IF data described by the metadata.
*
* Send handles fragmentation as follows:
* If the buffer has more samples than the maximum per packet,
@@ -108,23 +109,42 @@ public:
* Fragmentation only applies in the full buffer send mode.
*
* This is a blocking call and will not return until the number
- * of samples returned have been read out of the buffer.
+ * of samples returned have been read out of each buffer.
*
- * \param buff a buffer pointing to some read-only memory
+ * \param buffs a vector of read-only memory containing IF data
+ * \param nsamps_per_buff the number of samples to send, per buffer
* \param metadata data describing the buffer's contents
* \param io_type the type of data loaded in the buffer
* \param send_mode tells send how to unload the buffer
* \return the number of samples sent
*/
virtual size_t send(
- const boost::asio::const_buffer &buff,
+ const std::vector<const void *> &buffs,
+ size_t nsamps_per_buff,
const tx_metadata_t &metadata,
const io_type_t &io_type,
send_mode_t send_mode
) = 0;
/*!
- * Receive a buffer containing IF data and its metadata.
+ * Convenience wrapper for send that takes a single buffer.
+ */
+ size_t send(
+ const void *buff,
+ size_t nsamps_per_buff,
+ const tx_metadata_t &metadata,
+ const io_type_t &io_type,
+ send_mode_t send_mode
+ );
+
+ //! Deprecated
+ size_t send(
+ const boost::asio::const_buffer &, const tx_metadata_t &,
+ const io_type_t &, send_mode_t send_mode
+ );
+
+ /*!
+ * Receive buffers containing IF data described by the metadata.
*
* Receive handles fragmentation as follows:
* If the buffer has insufficient space to hold all samples
@@ -138,7 +158,7 @@ public:
* See the rx metadata fragment flags and offset fields for details.
*
* This is a blocking call and will not return until the number
- * of samples returned have been written into the buffer.
+ * of samples returned have been written into each buffer.
* However, a call to receive may timeout and return zero samples.
* The timeout duration is decided by the underlying transport layer.
* The caller should assume that the call to receive will not return
@@ -146,23 +166,42 @@ public:
* and that the timeout duration is reasonably tuned for performance.
*
* When using the full buffer recv mode, the metadata only applies
- * to the first packet received and written into the recv buffer.
+ * to the first packet received and written into the recv buffers.
* Use the one packet recv mode to get per packet metadata.
*
- * \param buff the buffer to fill with IF data
+ * \param buffs a vector of writable memory to fill with IF data
+ * \param nsamps_per_buff the size of each buffer in number of samples
* \param metadata data to fill describing the buffer
* \param io_type the type of data to fill into the buffer
* \param recv_mode tells recv how to load the buffer
* \return the number of samples received
*/
virtual size_t recv(
- const boost::asio::mutable_buffer &buff,
+ const std::vector<void *> &buffs,
+ size_t nsamps_per_buff,
rx_metadata_t &metadata,
const io_type_t &io_type,
recv_mode_t recv_mode
) = 0;
/*!
+ * Convenience wrapper for recv that takes a single buffer.
+ */
+ size_t recv(
+ void *buff,
+ size_t nsamps_per_buff,
+ rx_metadata_t &metadata,
+ const io_type_t &io_type,
+ recv_mode_t recv_mode
+ );
+
+ //! Deprecated
+ size_t recv(
+ const boost::asio::mutable_buffer &, rx_metadata_t &,
+ const io_type_t &, recv_mode_t
+ );
+
+ /*!
* Get the maximum number of samples per packet on send.
* \return the number of samples
*/
@@ -178,4 +217,6 @@ public:
} //namespace uhd
+#include <uhd/device.ipp>
+
#endif /* INCLUDED_UHD_DEVICE_HPP */
diff --git a/host/include/uhd/device.ipp b/host/include/uhd/device.ipp
new file mode 100644
index 000000000..c38a2e43e
--- /dev/null
+++ b/host/include/uhd/device.ipp
@@ -0,0 +1,79 @@
+//
+// Copyright 2010 Ettus Research LLC
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see <http://www.gnu.org/licenses/>.
+//
+
+#ifndef INCLUDED_UHD_DEVICE_IPP
+#define INCLUDED_UHD_DEVICE_IPP
+
+namespace uhd{
+
+ UHD_INLINE size_t device::send(
+ const void *buff,
+ size_t nsamps_per_buff,
+ const tx_metadata_t &metadata,
+ const io_type_t &io_type,
+ send_mode_t send_mode
+ ){
+ return this->send(
+ std::vector<const void *>(1, buff),
+ nsamps_per_buff, metadata,
+ io_type, send_mode
+ );
+ }
+
+ UHD_DEPRECATED UHD_INLINE size_t device::send(
+ const boost::asio::const_buffer &buff,
+ const tx_metadata_t &metadata,
+ const io_type_t &io_type,
+ send_mode_t send_mode
+ ){
+ return this->send(
+ boost::asio::buffer_cast<const void *>(buff),
+ boost::asio::buffer_size(buff)/io_type.size,
+ metadata, io_type, send_mode
+ );
+ }
+
+ UHD_INLINE size_t device::recv(
+ void *buff,
+ size_t nsamps_per_buff,
+ rx_metadata_t &metadata,
+ const io_type_t &io_type,
+ recv_mode_t recv_mode
+ ){
+ return this->recv(
+ std::vector<void *>(1, buff),
+ nsamps_per_buff, metadata,
+ io_type, recv_mode
+ );
+ }
+
+ UHD_DEPRECATED UHD_INLINE size_t device::recv(
+ const boost::asio::mutable_buffer &buff,
+ rx_metadata_t &metadata,
+ const io_type_t &io_type,
+ recv_mode_t recv_mode
+ ){
+ return this->recv(
+ boost::asio::buffer_cast<void *>(buff),
+ boost::asio::buffer_size(buff)/io_type.size,
+ metadata, io_type, recv_mode
+ );
+ }
+
+} //namespace uhd
+
+#endif /* INCLUDED_UHD_DEVICE_IPP */
diff --git a/host/include/uhd/transport/CMakeLists.txt b/host/include/uhd/transport/CMakeLists.txt
index 23a4aae94..93e9a6485 100644
--- a/host/include/uhd/transport/CMakeLists.txt
+++ b/host/include/uhd/transport/CMakeLists.txt
@@ -18,12 +18,14 @@
INSTALL(FILES
alignment_buffer.hpp
+ alignment_buffer.ipp
bounded_buffer.hpp
+ bounded_buffer.ipp
convert_types.hpp
if_addrs.hpp
udp_simple.hpp
udp_zero_copy.hpp
- vrt.hpp
+ vrt_if_packet.hpp
zero_copy.hpp
DESTINATION ${INCLUDE_DIR}/uhd/transport
)
diff --git a/host/include/uhd/transport/alignment_buffer.hpp b/host/include/uhd/transport/alignment_buffer.hpp
index dc6ccc3ed..29ba74efc 100644
--- a/host/include/uhd/transport/alignment_buffer.hpp
+++ b/host/include/uhd/transport/alignment_buffer.hpp
@@ -19,16 +19,14 @@
#define INCLUDED_UHD_TRANSPORT_ALIGNMENT_BUFFER_HPP
#include <uhd/config.hpp>
-#include <uhd/transport/bounded_buffer.hpp>
-#include <boost/thread/condition_variable.hpp>
+#include <uhd/transport/bounded_buffer.hpp> //time_duration_t
#include <boost/shared_ptr.hpp>
-#include <utility>
#include <vector>
namespace uhd{ namespace transport{
/*!
- * Imlement a templated alignment buffer:
+ * Implement a templated alignment buffer:
* Used for aligning asynchronously pushed elements with matching ids.
*/
template <typename elem_type, typename seq_type> class alignment_buffer{
@@ -40,9 +38,7 @@ namespace uhd{ namespace transport{
* \param capacity the maximum elements per index
* \param width the number of elements to align
*/
- static sptr make(size_t capacity, size_t width){
- return sptr(new alignment_buffer(capacity, width));
- }
+ static sptr make(size_t capacity, size_t width);
/*!
* Push an element with sequence id into the buffer at index.
@@ -51,13 +47,11 @@ namespace uhd{ namespace transport{
* \param index the buffer index
* \return true if the element fit without popping for space
*/
- UHD_INLINE bool push_with_pop_on_full(
+ virtual bool push_with_pop_on_full(
const elem_type &elem,
const seq_type &seq,
size_t index
- ){
- return _buffs[index]->push_with_pop_on_full(buff_contents_type(elem, seq));
- }
+ ) = 0;
/*!
* Pop an aligned set of elements from this alignment buffer.
@@ -65,70 +59,14 @@ namespace uhd{ namespace transport{
* \param time the timeout time
* \return false when the operation times out
*/
- template <typename elems_type, typename time_type>
- bool pop_elems_with_timed_wait(elems_type &elems, const time_type &time){
- buff_contents_type buff_contents_tmp;
- std::list<size_t> indexes_to_do(_all_indexes);
-
- //do an initial pop to load an initial sequence id
- size_t index = indexes_to_do.front();
- if (not _buffs[index]->pop_with_timed_wait(buff_contents_tmp, time)) return false;
- elems[index] = buff_contents_tmp.first;
- seq_type expected_seq_id = buff_contents_tmp.second;
- indexes_to_do.pop_front();
-
- //get an aligned set of elements from the buffers:
- while(indexes_to_do.size() != 0){
- //pop an element off for this index
- index = indexes_to_do.front();
- if (not _buffs[index]->pop_with_timed_wait(buff_contents_tmp, time)) return false;
-
- //if the sequence id matches:
- // store the popped element into the output,
- // remove this index from the list and continue
- if (buff_contents_tmp.second == expected_seq_id){
- elems[index] = buff_contents_tmp.first;
- indexes_to_do.pop_front();
- continue;
- }
-
- //if the sequence id is older:
- // continue with the same index to try again
- if (buff_contents_tmp.second < expected_seq_id){
- continue;
- }
-
- //if the sequence id is newer:
- // store the popped element into the output,
- // add all other indexes back into the list
- if (buff_contents_tmp.second > expected_seq_id){
- elems[index] = buff_contents_tmp.first;
- expected_seq_id = buff_contents_tmp.second;
- indexes_to_do = _all_indexes;
- indexes_to_do.remove(index);
- continue;
- }
- }
- return true;
- }
-
- private:
- //a vector of bounded buffers for each index
- typedef std::pair<elem_type, seq_type> buff_contents_type;
- typedef bounded_buffer<buff_contents_type> bounded_buffer_type;
- typedef boost::shared_ptr<bounded_buffer_type> bounded_buffer_sptr;
- std::vector<bounded_buffer_sptr> _buffs;
- std::list<size_t> _all_indexes;
-
- //private constructor
- alignment_buffer(size_t capacity, size_t width){
- for (size_t i = 0; i < width; i++){
- _buffs.push_back(bounded_buffer_type::make(capacity));
- _all_indexes.push_back(i);
- }
- }
+ virtual bool pop_elems_with_timed_wait(
+ std::vector<elem_type> &elems,
+ const time_duration_t &time
+ ) = 0;
};
}} //namespace
+#include <uhd/transport/alignment_buffer.ipp>
+
#endif /* INCLUDED_UHD_TRANSPORT_ALIGNMENT_BUFFER_HPP */
diff --git a/host/include/uhd/transport/alignment_buffer.ipp b/host/include/uhd/transport/alignment_buffer.ipp
new file mode 100644
index 000000000..ed7cfd26c
--- /dev/null
+++ b/host/include/uhd/transport/alignment_buffer.ipp
@@ -0,0 +1,140 @@
+//
+// Copyright 2010 Ettus Research LLC
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see <http://www.gnu.org/licenses/>.
+//
+
+#ifndef INCLUDED_UHD_TRANSPORT_ALIGNMENT_BUFFER_IPP
+#define INCLUDED_UHD_TRANSPORT_ALIGNMENT_BUFFER_IPP
+
+#include <uhd/transport/bounded_buffer.hpp>
+#include <boost/thread/condition_variable.hpp>
+#include <utility>
+
+namespace uhd{ namespace transport{ namespace{ /*anon*/
+
+ /*!
+ * Imlement a templated alignment buffer:
+ * Used for aligning asynchronously pushed elements with matching ids.
+ */
+ template <typename elem_type, typename seq_type>
+ class alignment_buffer_impl : public alignment_buffer<elem_type, seq_type>{
+ public:
+
+ alignment_buffer_impl(size_t capacity, size_t width) : _last_seqs(width){
+ for (size_t i = 0; i < width; i++){
+ _buffs.push_back(bounded_buffer<buff_contents_type>::make(capacity));
+ _all_indexes.push_back(i);
+ }
+ _there_was_a_clear = false;
+ }
+
+ UHD_INLINE bool push_with_pop_on_full(
+ const elem_type &elem,
+ const seq_type &seq,
+ size_t index
+ ){
+ //clear the buffer for this index if the seqs are mis-ordered
+ if (seq < _last_seqs[index]){
+ _buffs[index]->clear();
+ _there_was_a_clear = true;
+ } _last_seqs[index] = seq;
+ return _buffs[index]->push_with_pop_on_full(buff_contents_type(elem, seq));
+ }
+
+ UHD_INLINE bool pop_elems_with_timed_wait(
+ std::vector<elem_type> &elems,
+ const time_duration_t &time
+ ){
+ buff_contents_type buff_contents_tmp;
+ std::list<size_t> indexes_to_do(_all_indexes);
+
+ //do an initial pop to load an initial sequence id
+ size_t index = indexes_to_do.front();
+ if (not _buffs[index]->pop_with_timed_wait(buff_contents_tmp, time)) return false;
+ elems[index] = buff_contents_tmp.first;
+ seq_type expected_seq_id = buff_contents_tmp.second;
+ indexes_to_do.pop_front();
+
+ //get an aligned set of elements from the buffers:
+ while(indexes_to_do.size() != 0){
+
+ //respond to a clear by starting from scratch
+ if(_there_was_a_clear){
+ _there_was_a_clear = false;
+ indexes_to_do = _all_indexes;
+ index = indexes_to_do.front();
+ if (not _buffs[index]->pop_with_timed_wait(buff_contents_tmp, time)) return false;
+ elems[index] = buff_contents_tmp.first;
+ expected_seq_id = buff_contents_tmp.second;
+ indexes_to_do.pop_front();
+ }
+
+ //pop an element off for this index
+ index = indexes_to_do.front();
+ if (not _buffs[index]->pop_with_timed_wait(buff_contents_tmp, time)) return false;
+
+ //if the sequence id matches:
+ // store the popped element into the output,
+ // remove this index from the list and continue
+ if (buff_contents_tmp.second == expected_seq_id){
+ elems[index] = buff_contents_tmp.first;
+ indexes_to_do.pop_front();
+ continue;
+ }
+
+ //if the sequence id is older:
+ // continue with the same index to try again
+ if (buff_contents_tmp.second < expected_seq_id){
+ continue;
+ }
+
+ //if the sequence id is newer:
+ // store the popped element into the output,
+ // add all other indexes back into the list
+ if (buff_contents_tmp.second > expected_seq_id){
+ elems[index] = buff_contents_tmp.first;
+ expected_seq_id = buff_contents_tmp.second;
+ indexes_to_do = _all_indexes;
+ indexes_to_do.remove(index);
+ continue;
+ }
+ }
+ return true;
+ }
+
+ private:
+ //a vector of bounded buffers for each index
+ typedef std::pair<elem_type, seq_type> buff_contents_type;
+ std::vector<typename bounded_buffer<buff_contents_type>::sptr> _buffs;
+ std::vector<seq_type> _last_seqs;
+ std::list<size_t> _all_indexes;
+ bool _there_was_a_clear;
+ };
+
+}}} //namespace
+
+namespace uhd{ namespace transport{
+
+ template <typename elem_type, typename seq_type>
+ typename alignment_buffer<elem_type, seq_type>::sptr
+ alignment_buffer<elem_type, seq_type>::make(size_t capacity, size_t width){
+ return typename alignment_buffer<elem_type, seq_type>::sptr(
+ new alignment_buffer_impl<elem_type, seq_type>(capacity, width)
+ );
+ }
+
+}} //namespace
+
+#endif /* INCLUDED_UHD_TRANSPORT_ALIGNMENT_BUFFER_IPP */
diff --git a/host/include/uhd/transport/bounded_buffer.hpp b/host/include/uhd/transport/bounded_buffer.hpp
index baecd6382..d1deece96 100644
--- a/host/include/uhd/transport/bounded_buffer.hpp
+++ b/host/include/uhd/transport/bounded_buffer.hpp
@@ -19,15 +19,16 @@
#define INCLUDED_UHD_TRANSPORT_BOUNDED_BUFFER_HPP
#include <uhd/config.hpp>
-#include <boost/bind.hpp>
#include <boost/shared_ptr.hpp>
-#include <boost/circular_buffer.hpp>
-#include <boost/thread/condition.hpp>
+#include <boost/date_time/posix_time/posix_time_types.hpp>
namespace uhd{ namespace transport{
+ //! typedef for the time duration type for wait operations
+ typedef boost::posix_time::time_duration time_duration_t;
+
/*!
- * Imlement a templated bounded buffer:
+ * Implement a templated bounded buffer:
* Used for passing elements between threads in a producer-consumer model.
* The bounded buffer implemented waits and timed waits with condition variables.
* The pop operation blocks on the bounded_buffer to become non empty.
@@ -41,9 +42,7 @@ namespace uhd{ namespace transport{
* Make a new bounded buffer object.
* \param capacity the bounded_buffer capacity
*/
- static sptr make(size_t capacity){
- return sptr(new bounded_buffer(capacity));
- }
+ static sptr make(size_t capacity);
/*!
* Push a new element into the bounded buffer.
@@ -52,35 +51,14 @@ namespace uhd{ namespace transport{
* \param elem the new element to push
* \return true if the element fit without popping for space
*/
- UHD_INLINE bool push_with_pop_on_full(const elem_type &elem){
- boost::unique_lock<boost::mutex> lock(_mutex);
- if(_buffer.full()){
- _buffer.pop_back();
- _buffer.push_front(elem);
- lock.unlock();
- _empty_cond.notify_one();
- return false;
- }
- else{
- _buffer.push_front(elem);
- lock.unlock();
- _empty_cond.notify_one();
- return true;
- }
- }
+ virtual bool push_with_pop_on_full(const elem_type &elem) = 0;
/*!
* Push a new element into the bounded_buffer.
* Wait until the bounded_buffer becomes non-full.
* \param elem the new element to push
*/
- UHD_INLINE void push_with_wait(const elem_type &elem){
- boost::unique_lock<boost::mutex> lock(_mutex);
- _full_cond.wait(lock, boost::bind(&bounded_buffer<elem_type>::not_full, this));
- _buffer.push_front(elem);
- lock.unlock();
- _empty_cond.notify_one();
- }
+ virtual void push_with_wait(const elem_type &elem) = 0;
/*!
* Push a new element into the bounded_buffer.
@@ -89,28 +67,14 @@ namespace uhd{ namespace transport{
* \param time the timeout time
* \return false when the operation times out
*/
- template<typename time_type> UHD_INLINE
- bool push_with_timed_wait(const elem_type &elem, const time_type &time){
- boost::unique_lock<boost::mutex> lock(_mutex);
- if (not _full_cond.timed_wait(lock, time, boost::bind(&bounded_buffer<elem_type>::not_full, this))) return false;
- _buffer.push_front(elem);
- lock.unlock();
- _empty_cond.notify_one();
- return true;
- }
+ virtual bool push_with_timed_wait(const elem_type &elem, const time_duration_t &time) = 0;
/*!
* Pop an element from the bounded_buffer.
* Wait until the bounded_buffer becomes non-empty.
* \param elem the element reference pop to
*/
- UHD_INLINE void pop_with_wait(elem_type &elem){
- boost::unique_lock<boost::mutex> lock(_mutex);
- _empty_cond.wait(lock, boost::bind(&bounded_buffer<elem_type>::not_empty, this));
- elem = _buffer.back(); _buffer.pop_back();
- lock.unlock();
- _full_cond.notify_one();
- }
+ virtual void pop_with_wait(elem_type &elem) = 0;
/*!
* Pop an element from the bounded_buffer.
@@ -119,28 +83,16 @@ namespace uhd{ namespace transport{
* \param time the timeout time
* \return false when the operation times out
*/
- template<typename time_type> UHD_INLINE
- bool pop_with_timed_wait(elem_type &elem, const time_type &time){
- boost::unique_lock<boost::mutex> lock(_mutex);
- if (not _empty_cond.timed_wait(lock, time, boost::bind(&bounded_buffer<elem_type>::not_empty, this))) return false;
- elem = _buffer.back(); _buffer.pop_back();
- lock.unlock();
- _full_cond.notify_one();
- return true;
- }
-
- private:
- boost::mutex _mutex;
- boost::condition _empty_cond, _full_cond;
- boost::circular_buffer<elem_type> _buffer;
-
- bool not_full(void) const{return not _buffer.full();}
- bool not_empty(void) const{return not _buffer.empty();}
+ virtual bool pop_with_timed_wait(elem_type &elem, const time_duration_t &time) = 0;
- //private constructor
- bounded_buffer(size_t capacity) : _buffer(capacity){}
+ /*!
+ * Clear all elements from the bounded_buffer.
+ */
+ virtual void clear(void) = 0;
};
}} //namespace
+#include <uhd/transport/bounded_buffer.ipp>
+
#endif /* INCLUDED_UHD_TRANSPORT_BOUNDED_BUFFER_HPP */
diff --git a/host/include/uhd/transport/bounded_buffer.ipp b/host/include/uhd/transport/bounded_buffer.ipp
new file mode 100644
index 000000000..e106e229e
--- /dev/null
+++ b/host/include/uhd/transport/bounded_buffer.ipp
@@ -0,0 +1,112 @@
+//
+// Copyright 2010 Ettus Research LLC
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see <http://www.gnu.org/licenses/>.
+//
+
+#ifndef INCLUDED_UHD_TRANSPORT_BOUNDED_BUFFER_IPP
+#define INCLUDED_UHD_TRANSPORT_BOUNDED_BUFFER_IPP
+
+#include <boost/bind.hpp>
+#include <boost/circular_buffer.hpp>
+#include <boost/thread/condition.hpp>
+
+namespace uhd{ namespace transport{ namespace{ /*anon*/
+
+ template <typename elem_type>
+ class bounded_buffer_impl : public bounded_buffer<elem_type>{
+ public:
+
+ bounded_buffer_impl(size_t capacity) : _buffer(capacity){
+ /* NOP */
+ }
+
+ UHD_INLINE bool push_with_pop_on_full(const elem_type &elem){
+ boost::unique_lock<boost::mutex> lock(_mutex);
+ if(_buffer.full()){
+ _buffer.pop_back();
+ _buffer.push_front(elem);
+ lock.unlock();
+ _empty_cond.notify_one();
+ return false;
+ }
+ else{
+ _buffer.push_front(elem);
+ lock.unlock();
+ _empty_cond.notify_one();
+ return true;
+ }
+ }
+
+ UHD_INLINE void push_with_wait(const elem_type &elem){
+ boost::unique_lock<boost::mutex> lock(_mutex);
+ _full_cond.wait(lock, boost::bind(&bounded_buffer_impl<elem_type>::not_full, this));
+ _buffer.push_front(elem);
+ lock.unlock();
+ _empty_cond.notify_one();
+ }
+
+ bool push_with_timed_wait(const elem_type &elem, const time_duration_t &time){
+ boost::unique_lock<boost::mutex> lock(_mutex);
+ if (not _full_cond.timed_wait(lock, time, boost::bind(&bounded_buffer_impl<elem_type>::not_full, this))) return false;
+ _buffer.push_front(elem);
+ lock.unlock();
+ _empty_cond.notify_one();
+ return true;
+ }
+
+ UHD_INLINE void pop_with_wait(elem_type &elem){
+ boost::unique_lock<boost::mutex> lock(_mutex);
+ _empty_cond.wait(lock, boost::bind(&bounded_buffer_impl<elem_type>::not_empty, this));
+ elem = _buffer.back(); _buffer.pop_back();
+ lock.unlock();
+ _full_cond.notify_one();
+ }
+
+ bool pop_with_timed_wait(elem_type &elem, const time_duration_t &time){
+ boost::unique_lock<boost::mutex> lock(_mutex);
+ if (not _empty_cond.timed_wait(lock, time, boost::bind(&bounded_buffer_impl<elem_type>::not_empty, this))) return false;
+ elem = _buffer.back(); _buffer.pop_back();
+ lock.unlock();
+ _full_cond.notify_one();
+ return true;
+ }
+
+ UHD_INLINE void clear(void){
+ boost::unique_lock<boost::mutex> lock(_mutex);
+ while (not_empty()) _buffer.pop_back();
+ lock.unlock();
+ _full_cond.notify_one();
+ }
+
+ private:
+ boost::mutex _mutex;
+ boost::condition _empty_cond, _full_cond;
+ boost::circular_buffer<elem_type> _buffer;
+
+ bool not_full(void) const{return not _buffer.full();}
+ bool not_empty(void) const{return not _buffer.empty();}
+ };
+}}} //namespace
+
+namespace uhd{ namespace transport{
+
+ template <typename elem_type> typename bounded_buffer<elem_type>::sptr
+ bounded_buffer<elem_type>::make(size_t capacity){
+ return typename bounded_buffer<elem_type>::sptr(new bounded_buffer_impl<elem_type>(capacity));
+ }
+
+}} //namespace
+
+#endif /* INCLUDED_UHD_TRANSPORT_BOUNDED_BUFFER_IPP */
diff --git a/host/include/uhd/transport/vrt.hpp b/host/include/uhd/transport/vrt.hpp
deleted file mode 100644
index fb6efc99c..000000000
--- a/host/include/uhd/transport/vrt.hpp
+++ /dev/null
@@ -1,115 +0,0 @@
-//
-// Copyright 2010 Ettus Research LLC
-//
-// This program is free software: you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program. If not, see <http://www.gnu.org/licenses/>.
-//
-
-#ifndef INCLUDED_UHD_TRANSPORT_VRT_HPP
-#define INCLUDED_UHD_TRANSPORT_VRT_HPP
-
-#include <uhd/config.hpp>
-#include <uhd/types/metadata.hpp>
-#include <cstddef>
-
-namespace uhd{ namespace transport{
-
-namespace vrt{
-
- static const size_t max_header_words32 = 5; //hdr+sid+tsi+tsf (no class id supported)
-
- /*!
- * Pack a vrt header from metadata (big endian format).
- * \param metadata the tx metadata with flags and timestamps
- * \param header_buff memory to write the packed vrt header
- * \param num_header_words32 number of words in the vrt header
- * \param num_payload_words32 the length of the payload
- * \param num_packet_words32 the length of the packet
- * \param packet_count the packet count sequence number
- * \param tick_rate ticks per second used in time conversion
- */
- UHD_API void pack_be(
- const tx_metadata_t &metadata, //input
- boost::uint32_t *header_buff, //output
- size_t &num_header_words32, //output
- size_t num_payload_words32, //input
- size_t &num_packet_words32, //output
- size_t packet_count, //input
- double tick_rate //input
- );
-
- /*!
- * Unpack a vrt header to metadata (big endian format).
- * \param metadata the rx metadata with flags and timestamps
- * \param header_buff memory to read the packed vrt header
- * \param num_header_words32 number of words in the vrt header
- * \param num_payload_words32 the length of the payload
- * \param num_packet_words32 the length of the packet
- * \param packet_count the packet count sequence number
- * \param tick_rate ticks per second used in time conversion
- */
- UHD_API void unpack_be(
- rx_metadata_t &metadata, //output
- const boost::uint32_t *header_buff, //input
- size_t &num_header_words32, //output
- size_t &num_payload_words32, //output
- size_t num_packet_words32, //input
- size_t &packet_count, //output
- double tick_rate //input
- );
-
- /*!
- * Pack a vrt header from metadata (little endian format).
- * \param metadata the tx metadata with flags and timestamps
- * \param header_buff memory to write the packed vrt header
- * \param num_header_words32 number of words in the vrt header
- * \param num_payload_words32 the length of the payload
- * \param num_packet_words32 the length of the packet
- * \param packet_count the packet count sequence number
- * \param tick_rate ticks per second used in time conversion
- */
- UHD_API void pack_le(
- const tx_metadata_t &metadata, //input
- boost::uint32_t *header_buff, //output
- size_t &num_header_words32, //output
- size_t num_payload_words32, //input
- size_t &num_packet_words32, //output
- size_t packet_count, //input
- double tick_rate //input
- );
-
- /*!
- * Unpack a vrt header to metadata (little endian format).
- * \param metadata the rx metadata with flags and timestamps
- * \param header_buff memory to read the packed vrt header
- * \param num_header_words32 number of words in the vrt header
- * \param num_payload_words32 the length of the payload
- * \param num_packet_words32 the length of the packet
- * \param packet_count the packet count sequence number
- * \param tick_rate ticks per second used in time conversion
- */
- UHD_API void unpack_le(
- rx_metadata_t &metadata, //output
- const boost::uint32_t *header_buff, //input
- size_t &num_header_words32, //output
- size_t &num_payload_words32, //output
- size_t num_packet_words32, //input
- size_t &packet_count, //output
- double tick_rate //input
- );
-
-} //namespace vrt
-
-}} //namespace
-
-#endif /* INCLUDED_UHD_TRANSPORT_VRT_HPP */
diff --git a/host/include/uhd/transport/vrt_if_packet.hpp b/host/include/uhd/transport/vrt_if_packet.hpp
new file mode 100644
index 000000000..ccefe14ea
--- /dev/null
+++ b/host/include/uhd/transport/vrt_if_packet.hpp
@@ -0,0 +1,99 @@
+//
+// Copyright 2010 Ettus Research LLC
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see <http://www.gnu.org/licenses/>.
+//
+
+#ifndef INCLUDED_UHD_TRANSPORT_VRT_IF_PACKET_HPP
+#define INCLUDED_UHD_TRANSPORT_VRT_IF_PACKET_HPP
+
+#include <uhd/config.hpp>
+#include <boost/cstdint.hpp>
+#include <cstddef> //size_t
+
+namespace uhd{ namespace transport{
+
+namespace vrt{
+
+ //! The maximum number of 32-bit words in a vrt if packet header
+ static const size_t max_if_hdr_words32 = 7; //hdr+sid+cid+tsi+tsf
+
+ /*!
+ * Definition for fields that can be packed into a vrt if header.
+ * The size fields are used for input and output depending upon
+ * the operation used (ie the pack or unpack function call).
+ */
+ struct UHD_API if_packet_info_t{
+ //size fields
+ size_t num_payload_words32; //required in pack, derived in unpack
+ size_t num_header_words32; //derived in pack, derived in unpack
+ size_t num_packet_words32; //derived in pack, required in unpack
+
+ //header fields
+ size_t packet_count;
+ bool sob, eob;
+
+ //optional fields
+ bool has_sid; boost::uint32_t sid;
+ bool has_cid; boost::uint64_t cid;
+ bool has_tsi; boost::uint32_t tsi;
+ bool has_tsf; boost::uint64_t tsf;
+ bool has_tlr; boost::uint32_t tlr;
+ };
+
+ /*!
+ * Pack a vrt header from metadata (big endian format).
+ * \param packet_buff memory to write the packed vrt header
+ * \param if_packet_info the if packet info (read/write)
+ */
+ UHD_API void if_hdr_pack_be(
+ boost::uint32_t *packet_buff,
+ if_packet_info_t &if_packet_info
+ );
+
+ /*!
+ * Unpack a vrt header to metadata (big endian format).
+ * \param packet_buff memory to read the packed vrt header
+ * \param if_packet_info the if packet info (read/write)
+ */
+ UHD_API void if_hdr_unpack_be(
+ const boost::uint32_t *packet_buff,
+ if_packet_info_t &if_packet_info
+ );
+
+ /*!
+ * Pack a vrt header from metadata (little endian format).
+ * \param packet_buff memory to write the packed vrt header
+ * \param if_packet_info the if packet info (read/write)
+ */
+ UHD_API void if_hdr_pack_le(
+ boost::uint32_t *packet_buff,
+ if_packet_info_t &if_packet_info
+ );
+
+ /*!
+ * Unpack a vrt header to metadata (little endian format).
+ * \param packet_buff memory to read the packed vrt header
+ * \param if_packet_info the if packet info (read/write)
+ */
+ UHD_API void if_hdr_unpack_le(
+ const boost::uint32_t *packet_buff,
+ if_packet_info_t &if_packet_info
+ );
+
+} //namespace vrt
+
+}} //namespace
+
+#endif /* INCLUDED_UHD_TRANSPORT_VRT_IF_PACKET_HPP */
diff --git a/host/include/uhd/transport/zero_copy.hpp b/host/include/uhd/transport/zero_copy.hpp
index 2815e3189..da10bfbe2 100644
--- a/host/include/uhd/transport/zero_copy.hpp
+++ b/host/include/uhd/transport/zero_copy.hpp
@@ -47,7 +47,7 @@ namespace uhd{ namespace transport{
* Get the size of the underlying buffer.
* \return the number of bytes
*/
- size_t size(void) const{
+ inline size_t size(void) const{
return boost::asio::buffer_size(this->get());
}
@@ -55,7 +55,7 @@ namespace uhd{ namespace transport{
* Get a pointer to the underlying buffer.
* \return a pointer into memory
*/
- template <class T> T cast(void) const{
+ template <class T> inline T cast(void) const{
return boost::asio::buffer_cast<T>(this->get());
}
@@ -89,7 +89,7 @@ namespace uhd{ namespace transport{
* Get the size of the underlying buffer.
* \return the number of bytes
*/
- size_t size(void) const{
+ inline size_t size(void) const{
return boost::asio::buffer_size(this->get());
}
@@ -97,7 +97,7 @@ namespace uhd{ namespace transport{
* Get a pointer to the underlying buffer.
* \return a pointer into memory
*/
- template <class T> T cast(void) const{
+ template <class T> inline T cast(void) const{
return boost::asio::buffer_cast<T>(this->get());
}
diff --git a/host/include/uhd/types/metadata.hpp b/host/include/uhd/types/metadata.hpp
index 55add71cc..f4c962ff7 100644
--- a/host/include/uhd/types/metadata.hpp
+++ b/host/include/uhd/types/metadata.hpp
@@ -31,13 +31,6 @@ namespace uhd{
*/
struct UHD_API rx_metadata_t{
/*!
- * Stream IDs may be used to identify source DSP units.
- * --Not currently used in any known device implementation.--
- */
- bool has_stream_id;
- boost::uint32_t stream_id;
-
- /*!
* Time specification:
* Set from timestamps on incoming data when provided.
*/
@@ -84,13 +77,6 @@ namespace uhd{
*/
struct UHD_API tx_metadata_t{
/*!
- * Stream IDs may be used to identify destination DSP units.
- * --Not currently used in any known device implementation.--
- */
- bool has_stream_id;
- boost::uint32_t stream_id;
-
- /*!
* Time specification:
* Set has time spec to false to perform a send "now".
* Or, set to true, and fill in time spec for a send "at".
diff --git a/host/include/uhd/types/time_spec.hpp b/host/include/uhd/types/time_spec.hpp
index 25d9e41d0..59b85f4b7 100644
--- a/host/include/uhd/types/time_spec.hpp
+++ b/host/include/uhd/types/time_spec.hpp
@@ -19,58 +19,92 @@
#define INCLUDED_UHD_TYPES_TIME_SPEC_HPP
#include <uhd/config.hpp>
-#include <boost/cstdint.hpp>
+#include <boost/operators.hpp>
+#include <ctime>
namespace uhd{
/*!
- * A time_spec_t holds a seconds and fractional seconds time value.
- * The time_spec_t can be used when setting the time on devices,
- * and for dealing with time stamped samples though the metadata.
- * and for controlling the start of streaming for applicable dsps.
+ * A time_spec_t holds a seconds and a fractional seconds time value.
+ * Depending upon usage, the time_spec_t can represent absolute times,
+ * relative times, or time differences (between absolute times).
*
- * The fractional seconds are represented in units of nanoseconds,
- * which provide a clock-domain independent unit of time storage.
- * The methods "get_ticks" and "set_ticks" can be used to convert
- * the fractional seconds to and from clock-domain specific units.
+ * The time_spec_t provides clock-domain independent time storage,
+ * but can convert fractional seconds to/from clock-domain specific units.
*
- * The nanoseconds count is stored as double precision floating point.
+ * The fractional seconds are stored as double precision floating point.
* This gives the fractional seconds enough precision to unambiguously
* specify a clock-tick/sample-count up to rates of several petahertz.
*/
- struct UHD_API time_spec_t{
+ class UHD_API time_spec_t : boost::additive<time_spec_t>, boost::totally_ordered<time_spec_t>{
+ public:
- //! whole/integer seconds count in seconds
- boost::uint32_t secs;
+ /*!
+ * Create a time_spec_t from a real-valued seconds count.
+ * \param secs the real-valued seconds count (default = 0)
+ */
+ time_spec_t(double secs = 0);
+
+ /*!
+ * Create a time_spec_t from whole and fractional seconds.
+ * \param full_secs the whole/integer seconds count
+ * \param frac_secs the fractional seconds count (default = 0)
+ */
+ time_spec_t(time_t full_secs, double frac_secs = 0);
- //! fractional seconds count in nano-seconds
- double nsecs;
+ /*!
+ * Create a time_spec_t from whole and fractional seconds.
+ * Translation from clock-domain specific units.
+ * \param full_secs the whole/integer seconds count
+ * \param tick_count the fractional seconds tick count
+ * \param tick_rate the number of ticks per second
+ */
+ time_spec_t(time_t full_secs, size_t tick_count, double tick_rate);
/*!
- * Convert the fractional nsecs to clock ticks.
+ * Convert the fractional seconds to clock ticks.
* Translation into clock-domain specific units.
* \param tick_rate the number of ticks per second
* \return the fractional seconds tick count
*/
- boost::uint32_t get_ticks(double tick_rate) const;
+ size_t get_tick_count(double tick_rate) const;
/*!
- * Set the fractional nsecs from clock ticks.
- * Translation from clock-domain specific units.
- * \param ticks the fractional seconds tick count
- * \param tick_rate the number of ticks per second
+ * Get the time as a real-valued seconds count.
+ * Note: If this time_spec_t represents an absolute time,
+ * the precision of the fractional seconds may be lost.
+ * \return the real-valued seconds
*/
- void set_ticks(boost::uint32_t ticks, double tick_rate);
+ double get_real_secs(void) const;
/*!
- * Create a time_spec_t from whole and fractional seconds.
- * \param secs the whole/integer seconds count in seconds (default = 0)
- * \param nsecs the fractional seconds count in nanoseconds (default = 0)
+ * Get the whole/integer part of the time in seconds.
+ * \return the whole/integer seconds
+ */
+ time_t get_full_secs(void) const;
+
+ /*!
+ * Get the fractional part of the time in seconds.
+ * \return the fractional seconds
*/
- time_spec_t(boost::uint32_t secs = 0, double nsecs = 0);
+ double get_frac_secs(void) const;
+
+ //! Implement addable interface
+ time_spec_t &operator+=(const time_spec_t &);
+
+ //! Implement subtractable interface
+ time_spec_t &operator-=(const time_spec_t &);
+ //private time storage details
+ private: time_t _full_secs; double _frac_secs;
};
+ //! Implement equality_comparable interface
+ UHD_API bool operator==(const time_spec_t &, const time_spec_t &);
+
+ //! Implement less_than_comparable interface
+ UHD_API bool operator<(const time_spec_t &, const time_spec_t &);
+
} //namespace uhd
#endif /* INCLUDED_UHD_TYPES_TIME_SPEC_HPP */
diff --git a/host/include/uhd/usrp/CMakeLists.txt b/host/include/uhd/usrp/CMakeLists.txt
index 58aa8588a..6f8c1a2d8 100644
--- a/host/include/uhd/usrp/CMakeLists.txt
+++ b/host/include/uhd/usrp/CMakeLists.txt
@@ -33,7 +33,10 @@ INSTALL(FILES
### utilities ###
tune_helper.hpp
+
+ ### interfaces ###
simple_usrp.hpp
+ mimo_usrp.hpp
DESTINATION ${INCLUDE_DIR}/uhd/usrp
)
diff --git a/host/include/uhd/usrp/dboard_id.hpp b/host/include/uhd/usrp/dboard_id.hpp
index 8b6eaf6bd..4c45e4334 100644
--- a/host/include/uhd/usrp/dboard_id.hpp
+++ b/host/include/uhd/usrp/dboard_id.hpp
@@ -25,7 +25,7 @@
namespace uhd{ namespace usrp{
- class UHD_API dboard_id_t : boost::equality_comparable1<dboard_id_t>{
+ class UHD_API dboard_id_t : boost::equality_comparable<dboard_id_t>{
public:
/*!
* Create a dboard id from an integer.
diff --git a/host/include/uhd/usrp/mboard_props.hpp b/host/include/uhd/usrp/mboard_props.hpp
index 7ff454472..a432ce50c 100644
--- a/host/include/uhd/usrp/mboard_props.hpp
+++ b/host/include/uhd/usrp/mboard_props.hpp
@@ -40,7 +40,7 @@ namespace uhd{ namespace usrp{
MBOARD_PROP_TX_DBOARD = 'v', //ro, wax::obj
MBOARD_PROP_TX_DBOARD_NAMES = 'V', //ro, prop_names_t
MBOARD_PROP_CLOCK_CONFIG = 'C', //rw, clock_config_t
- MBOARD_PROP_TIME_NOW = 't', //wo, time_spec_t
+ MBOARD_PROP_TIME_NOW = 't', //rw, time_spec_t
MBOARD_PROP_TIME_NEXT_PPS = 'T', //wo, time_spec_t
MBOARD_PROP_STREAM_CMD = 's' //wo, stream_cmd_t
};
diff --git a/host/include/uhd/usrp/mimo_usrp.hpp b/host/include/uhd/usrp/mimo_usrp.hpp
new file mode 100644
index 000000000..68a42cad8
--- /dev/null
+++ b/host/include/uhd/usrp/mimo_usrp.hpp
@@ -0,0 +1,171 @@
+//
+// Copyright 2010 Ettus Research LLC
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see <http://www.gnu.org/licenses/>.
+//
+
+#ifndef INCLUDED_UHD_USRP_MIMO_USRP_HPP
+#define INCLUDED_UHD_USRP_MIMO_USRP_HPP
+
+#include <uhd/config.hpp>
+#include <uhd/device.hpp>
+#include <uhd/types/ranges.hpp>
+#include <uhd/types/stream_cmd.hpp>
+#include <uhd/types/clock_config.hpp>
+#include <uhd/types/tune_result.hpp>
+#include <boost/shared_ptr.hpp>
+#include <boost/utility.hpp>
+#include <vector>
+
+namespace uhd{ namespace usrp{
+
+/*!
+ * The MIMO USRP device class:
+ * A mimo usrp facilitates ease-of-use for multi-usrp scenarios.
+ * The wrapper provides convenience functions to control the group
+ * of underlying devices as if they consisted of a single device.
+ */
+class UHD_API mimo_usrp : boost::noncopyable{
+public:
+ typedef boost::shared_ptr<mimo_usrp> sptr;
+
+ /*!
+ * Make a new mimo usrp from the device address.
+ * \param dev_addr the device address
+ * \return a new mimo usrp object
+ */
+ static sptr make(const device_addr_t &dev_addr);
+
+ /*!
+ * Get the underlying device object.
+ * This is needed to get access to the streaming API and properties.
+ * \return the device object within this simple usrp
+ */
+ virtual device::sptr get_device(void) = 0;
+
+ /*!
+ * Get a printable name for this mimo usrp.
+ * \return a printable string
+ */
+ virtual std::string get_pp_string(void) = 0;
+
+ /*!
+ * Get the number of channels in this mimo configuration.
+ * The number of rx channels == the number of tx channels.
+ * \return the number of channels
+ */
+ virtual size_t get_num_channels(void) = 0;
+
+ /*******************************************************************
+ * Misc
+ ******************************************************************/
+ /*!
+ * Gets the current time in the usrp time registers.
+ * \return a timespec representing current usrp time
+ */
+ virtual time_spec_t get_time_now(void) = 0;
+
+ /*!
+ * Set the time registers on the usrp at the next pps tick.
+ * The values will not be latched in until the pulse occurs.
+ * It is recommended that the user sleep(1) after calling to ensure
+ * that the time registers will be in a known state prior to use.
+ * This call works across all mboards in the mimo configuration.
+ *
+ * Note: Because this call sets the time on the "next" pps,
+ * the seconds in the time spec should be current seconds + 1.
+ *
+ * \param time_spec the time to latch into the usrp device
+ */
+ virtual void set_time_next_pps(const time_spec_t &time_spec) = 0;
+
+ /*!
+ * Synchronize the times across all motherboards in this configuration.
+ * Use this method to sync the times when the edge of the PPS is unknown.
+ *
+ * Ex: Host machine is not attached to serial port of GPSDO
+ * and can therefore not query the GPSDO for the PPS edge.
+ *
+ * This is a 3-step process, and will take at most 3 seconds to complete.
+ * Upon completion, the times will be synchronized to the time provided.
+ *
+ * - Step1: set the time at the next pps (potential race condition)
+ * - Step2: wait for the seconds to rollover to catch the pps edge
+ * - Step3: set the time at the next pps (synchronous for all boards)
+ *
+ * \param time_spec the time to latch into the usrp device
+ */
+ virtual void set_time_unknown_pps(const time_spec_t &time_spec) = 0;
+
+ /*!
+ * Issue a stream command to the usrp device.
+ * This tells the usrp to send samples into the host.
+ * See the documentation for stream_cmd_t for more info.
+ * \param stream_cmd the stream command to issue
+ */
+ virtual void issue_stream_cmd(const stream_cmd_t &stream_cmd) = 0;
+
+ /*******************************************************************
+ * RX methods
+ ******************************************************************/
+ virtual void set_rx_rate_all(double rate) = 0;
+ virtual double get_rx_rate_all(void) = 0;
+
+ virtual tune_result_t set_rx_freq(size_t chan, double freq) = 0;
+ virtual tune_result_t set_rx_freq(size_t chan, double freq, double lo_off) = 0;
+ virtual freq_range_t get_rx_freq_range(size_t chan) = 0;
+
+ virtual void set_rx_gain(size_t chan, float gain) = 0;
+ virtual float get_rx_gain(size_t chan) = 0;
+ virtual gain_range_t get_rx_gain_range(size_t chan) = 0;
+
+ virtual void set_rx_antenna(size_t chan, const std::string &ant) = 0;
+ virtual std::string get_rx_antenna(size_t chan) = 0;
+ virtual std::vector<std::string> get_rx_antennas(size_t chan) = 0;
+
+ virtual bool get_rx_lo_locked(size_t chan) = 0;
+
+ /*!
+ * Read the RSSI value from a usrp device.
+ * Or throw if the dboard does not support an RSSI readback.
+ * \param chan which mimo channel 0 to N-1
+ * \return the rssi in dB
+ */
+ virtual float read_rssi(size_t chan) = 0;
+
+ /*******************************************************************
+ * TX methods
+ ******************************************************************/
+ virtual void set_tx_rate_all(double rate) = 0;
+ virtual double get_tx_rate_all(void) = 0;
+
+ virtual tune_result_t set_tx_freq(size_t chan, double freq) = 0;
+ virtual tune_result_t set_tx_freq(size_t chan, double freq, double lo_off) = 0;
+ virtual freq_range_t get_tx_freq_range(size_t chan) = 0;
+
+ virtual void set_tx_gain(size_t chan, float gain) = 0;
+ virtual float get_tx_gain(size_t chan) = 0;
+ virtual gain_range_t get_tx_gain_range(size_t chan) = 0;
+
+ virtual void set_tx_antenna(size_t chan, const std::string &ant) = 0;
+ virtual std::string get_tx_antenna(size_t chan) = 0;
+ virtual std::vector<std::string> get_tx_antennas(size_t chan) = 0;
+
+ virtual bool get_tx_lo_locked(size_t chan) = 0;
+
+};
+
+}}
+
+#endif /* INCLUDED_UHD_USRP_MIMO_USRP_HPP */
diff --git a/host/include/uhd/usrp/simple_usrp.hpp b/host/include/uhd/usrp/simple_usrp.hpp
index 6ba1b90dd..1d9136f08 100644
--- a/host/include/uhd/usrp/simple_usrp.hpp
+++ b/host/include/uhd/usrp/simple_usrp.hpp
@@ -58,12 +58,18 @@ public:
* Get a printable name for this simple usrp.
* \return a printable string
*/
- virtual std::string get_name(void) = 0;
+ virtual std::string get_pp_string(void) = 0;
/*******************************************************************
* Misc
******************************************************************/
/*!
+ * Gets the current time in the usrp time registers.
+ * \return a timespec representing current usrp time
+ */
+ virtual time_spec_t get_time_now(void) = 0;
+
+ /*!
* Sets the time registers on the usrp immediately.
* \param time_spec the time to latch into the usrp device
*/
@@ -98,13 +104,6 @@ public:
*/
virtual void set_clock_config(const clock_config_t &clock_config) = 0;
- /*!
- * Read the RSSI value from a usrp device.
- * Or throw if the dboard does not support an RSSI readback.
- * \return the rssi in dB
- */
- virtual float read_rssi(void) = 0;
-
/*******************************************************************
* RX methods
******************************************************************/
@@ -125,6 +124,13 @@ public:
virtual bool get_rx_lo_locked(void) = 0;
+ /*!
+ * Read the RSSI value from a usrp device.
+ * Or throw if the dboard does not support an RSSI readback.
+ * \return the rssi in dB
+ */
+ virtual float read_rssi(void) = 0;
+
/*******************************************************************
* TX methods
******************************************************************/
diff --git a/host/include/uhd/usrp/usrp2.hpp b/host/include/uhd/usrp/usrp2.hpp
deleted file mode 100644
index 7387e5dd4..000000000
--- a/host/include/uhd/usrp/usrp2.hpp
+++ /dev/null
@@ -1,62 +0,0 @@
-//
-// Copyright 2010 Ettus Research LLC
-//
-// This program is free software: you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program. If not, see <http://www.gnu.org/licenses/>.
-//
-
-#ifndef INCLUDED_UHD_USRP_USRP2_HPP
-#define INCLUDED_UHD_USRP_USRP2_HPP
-
-#include <uhd/config.hpp>
-#include <uhd/device.hpp>
-
-namespace uhd{ namespace usrp{
-
-/*!
- * The usrp2 device class.
- */
-class UHD_API usrp2 : public device{
-public:
- /*!
- * Find usrp2 devices over the ethernet.
- *
- * Recommended key/value pairs for the device hint address:
- * hint["addr"] = address, where address is a resolvable address
- * or ip address, which may or may not be a broadcast address.
- *
- * Other optional device address keys:
- * recv_buff_size: resizes the recv buffer on the data socket
- * send_buff_size: resizes the send buffer on the data socket
- *
- * \param hint a device addr with the usrp2 address filled in
- * \return a vector of device addresses for all usrp2s found
- */
- static device_addrs_t find(const device_addr_t &hint);
-
- /*!
- * Make a usrp2 from a device address.
- *
- * Required key/value pairs for the device address:
- * hint["addr"] = address, where address is a resolvable address
- * or ip address, which must be the specific address of a usrp2.
- *
- * \param addr the device address
- * \return a device sptr to a new usrp2
- */
- static device::sptr make(const device_addr_t &addr);
-};
-
-}} //namespace
-
-#endif /* INCLUDED_UHD_USRP_USRP2_HPP */
diff --git a/host/include/uhd/utils/CMakeLists.txt b/host/include/uhd/utils/CMakeLists.txt
index c98eec639..36f86054a 100644
--- a/host/include/uhd/utils/CMakeLists.txt
+++ b/host/include/uhd/utils/CMakeLists.txt
@@ -19,6 +19,7 @@ INSTALL(FILES
algorithm.hpp
assert.hpp
byteswap.hpp
+ byteswap.ipp
exception.hpp
gain_handler.hpp
pimpl.hpp
diff --git a/host/include/uhd/utils/algorithm.hpp b/host/include/uhd/utils/algorithm.hpp
index 08977a69f..b52edc6b5 100644
--- a/host/include/uhd/utils/algorithm.hpp
+++ b/host/include/uhd/utils/algorithm.hpp
@@ -83,6 +83,35 @@ namespace std{
}
/*!
+ * Count the number of appearances of a value in a range.
+ *
+ * Uses std::count to count the appearances in the range.
+ *
+ * \param range the elements to iterate through
+ * \param value the value to count in the range
+ * \return the number of appearances of the value
+ */
+ template<typename Range, typename T> inline
+ size_t count(const Range &range, const T &value){
+ return std::count(boost::begin(range), boost::end(range), value);
+ }
+
+ /*!
+ * Are the ranges equal (are their elements equivalent)?
+ *
+ * Uses std::equal to search the iterable for an element.
+ *
+ * \param range1 the first range of elements
+ * \param range2 the second range of elements
+ * \return true when the elements are equivalent
+ */
+ template<typename Range> inline
+ bool equal(const Range &range1, const Range &range2){
+ return (boost::size(range1) == boost::size(range2)) and
+ std::equal(boost::begin(range1), boost::end(range1), boost::begin(range2));
+ }
+
+ /*!
* A templated signum implementation.
* \param n the comparable to process
* \return -1 when n negative, +1 when n positive, otherwise 0
diff --git a/host/include/uhd/utils/byteswap.hpp b/host/include/uhd/utils/byteswap.hpp
index dd5dcbc09..9a1871210 100644
--- a/host/include/uhd/utils/byteswap.hpp
+++ b/host/include/uhd/utils/byteswap.hpp
@@ -37,84 +37,14 @@ namespace uhd{
//! perform a byteswap on a 64 bit integer
boost::uint64_t byteswap(boost::uint64_t);
-} //namespace uhd
-
-/***********************************************************************
- * Platform-specific implementation details for byteswap below:
- **********************************************************************/
-#ifdef BOOST_MSVC //http://msdn.microsoft.com/en-us/library/a3140177%28VS.80%29.aspx
- #include <stdlib.h>
-
- UHD_INLINE boost::uint16_t uhd::byteswap(boost::uint16_t x){
- return _byteswap_ushort(x);
- }
-
- UHD_INLINE boost::uint32_t uhd::byteswap(boost::uint32_t x){
- return _byteswap_ulong(x);
- }
-
- UHD_INLINE boost::uint64_t uhd::byteswap(boost::uint64_t x){
- return _byteswap_uint64(x);
- }
-
-#elif defined(__GNUC__) && __GNUC__ >= 4 && __GNUC_MINOR__ >= 2
-
- UHD_INLINE boost::uint16_t uhd::byteswap(boost::uint16_t x){
- return (x>>8) | (x<<8); //DNE return __builtin_bswap16(x);
- }
-
- UHD_INLINE boost::uint32_t uhd::byteswap(boost::uint32_t x){
- return __builtin_bswap32(x);
- }
-
- UHD_INLINE boost::uint64_t uhd::byteswap(boost::uint64_t x){
- return __builtin_bswap64(x);
- }
-
-#elif defined(__FreeBSD__) || defined(__MACOSX__) || defined(__APPLE__)
- #include <libkern/OSByteOrder.h>
+ //! network to host: short, long, or long-long
+ template<typename T> T ntohx(T);
- UHD_INLINE boost::uint16_t uhd::byteswap(boost::uint16_t x){
- return OSSwapInt16(x);
- }
+ //! host to network: short, long, or long-long
+ template<typename T> T htonx(T);
- UHD_INLINE boost::uint32_t uhd::byteswap(boost::uint32_t x){
- return OSSwapInt32(x);
- }
-
- UHD_INLINE boost::uint64_t uhd::byteswap(boost::uint64_t x){
- return OSSwapInt64(x);
- }
-
-#elif defined(linux) || defined(__linux)
- #include <byteswap.h>
-
- UHD_INLINE boost::uint16_t uhd::byteswap(boost::uint16_t x){
- return bswap_16(x);
- }
-
- UHD_INLINE boost::uint32_t uhd::byteswap(boost::uint32_t x){
- return bswap_32(x);
- }
-
- UHD_INLINE boost::uint64_t uhd::byteswap(boost::uint64_t x){
- return bswap_64(x);
- }
-
-#else //http://www.koders.com/c/fidB93B34CD44F0ECF724F1A4EAE3854BA2FE692F59.aspx
-
- UHD_INLINE boost::uint16_t uhd::byteswap(boost::uint16_t x){
- return (x>>8) | (x<<8);
- }
-
- UHD_INLINE boost::uint32_t uhd::byteswap(boost::uint32_t x){
- return (boost::uint32_t(uhd::byteswap(boost::uint16_t(x&0xfffful)))<<16) | (uhd::byteswap(boost::uint16_t(x>>16)));
- }
-
- UHD_INLINE boost::uint64_t uhd::byteswap(boost::uint64_t x){
- return (boost::uint64_t(uhd::byteswap(boost::uint32_t(x&0xffffffffull)))<<32) | (uhd::byteswap(boost::uint32_t(x>>32)));
- }
+} //namespace uhd
-#endif
+#include <uhd/utils/byteswap.ipp>
#endif /* INCLUDED_UHD_UTILS_BYTESWAP_HPP */
diff --git a/host/include/uhd/utils/byteswap.ipp b/host/include/uhd/utils/byteswap.ipp
new file mode 100644
index 000000000..11c82a4ec
--- /dev/null
+++ b/host/include/uhd/utils/byteswap.ipp
@@ -0,0 +1,120 @@
+//
+// Copyright 2010 Ettus Research LLC
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see <http://www.gnu.org/licenses/>.
+//
+
+#ifndef INCLUDED_UHD_UTILS_BYTESWAP_IPP
+#define INCLUDED_UHD_UTILS_BYTESWAP_IPP
+
+/***********************************************************************
+ * Platform-specific implementation details for byteswap below:
+ **********************************************************************/
+#ifdef BOOST_MSVC //http://msdn.microsoft.com/en-us/library/a3140177%28VS.80%29.aspx
+ #include <stdlib.h>
+
+ UHD_INLINE boost::uint16_t uhd::byteswap(boost::uint16_t x){
+ return _byteswap_ushort(x);
+ }
+
+ UHD_INLINE boost::uint32_t uhd::byteswap(boost::uint32_t x){
+ return _byteswap_ulong(x);
+ }
+
+ UHD_INLINE boost::uint64_t uhd::byteswap(boost::uint64_t x){
+ return _byteswap_uint64(x);
+ }
+
+#elif defined(__GNUC__) && __GNUC__ >= 4 && __GNUC_MINOR__ >= 2
+
+ UHD_INLINE boost::uint16_t uhd::byteswap(boost::uint16_t x){
+ return (x>>8) | (x<<8); //DNE return __builtin_bswap16(x);
+ }
+
+ UHD_INLINE boost::uint32_t uhd::byteswap(boost::uint32_t x){
+ return __builtin_bswap32(x);
+ }
+
+ UHD_INLINE boost::uint64_t uhd::byteswap(boost::uint64_t x){
+ return __builtin_bswap64(x);
+ }
+
+#elif defined(__FreeBSD__) || defined(__MACOSX__) || defined(__APPLE__)
+ #include <libkern/OSByteOrder.h>
+
+ UHD_INLINE boost::uint16_t uhd::byteswap(boost::uint16_t x){
+ return OSSwapInt16(x);
+ }
+
+ UHD_INLINE boost::uint32_t uhd::byteswap(boost::uint32_t x){
+ return OSSwapInt32(x);
+ }
+
+ UHD_INLINE boost::uint64_t uhd::byteswap(boost::uint64_t x){
+ return OSSwapInt64(x);
+ }
+
+#elif defined(linux) || defined(__linux)
+ #include <byteswap.h>
+
+ UHD_INLINE boost::uint16_t uhd::byteswap(boost::uint16_t x){
+ return bswap_16(x);
+ }
+
+ UHD_INLINE boost::uint32_t uhd::byteswap(boost::uint32_t x){
+ return bswap_32(x);
+ }
+
+ UHD_INLINE boost::uint64_t uhd::byteswap(boost::uint64_t x){
+ return bswap_64(x);
+ }
+
+#else //http://www.koders.com/c/fidB93B34CD44F0ECF724F1A4EAE3854BA2FE692F59.aspx
+
+ UHD_INLINE boost::uint16_t uhd::byteswap(boost::uint16_t x){
+ return (x>>8) | (x<<8);
+ }
+
+ UHD_INLINE boost::uint32_t uhd::byteswap(boost::uint32_t x){
+ return (boost::uint32_t(uhd::byteswap(boost::uint16_t(x&0xfffful)))<<16) | (uhd::byteswap(boost::uint16_t(x>>16)));
+ }
+
+ UHD_INLINE boost::uint64_t uhd::byteswap(boost::uint64_t x){
+ return (boost::uint64_t(uhd::byteswap(boost::uint32_t(x&0xffffffffull)))<<32) | (uhd::byteswap(boost::uint32_t(x>>32)));
+ }
+
+#endif
+
+/***********************************************************************
+ * Define the templated network to/from host conversions
+ **********************************************************************/
+#include <boost/detail/endian.hpp>
+
+template<typename T> UHD_INLINE T uhd::ntohx(T num){
+ #ifdef BOOST_BIG_ENDIAN
+ return num;
+ #else
+ return uhd::byteswap(num);
+ #endif
+}
+
+template<typename T> UHD_INLINE T uhd::htonx(T num){
+ #ifdef BOOST_BIG_ENDIAN
+ return num;
+ #else
+ return uhd::byteswap(num);
+ #endif
+}
+
+#endif /* INCLUDED_UHD_UTILS_BYTESWAP_IPP */