diff options
Diffstat (limited to 'host/include')
73 files changed, 6634 insertions, 0 deletions
diff --git a/host/include/CMakeLists.txt b/host/include/CMakeLists.txt new file mode 100644 index 000000000..3f7ca2cb7 --- /dev/null +++ b/host/include/CMakeLists.txt @@ -0,0 +1,19 @@ +# +# 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/>. +# + + +ADD_SUBDIRECTORY(uhd) diff --git a/host/include/uhd/CMakeLists.txt b/host/include/uhd/CMakeLists.txt new file mode 100644 index 000000000..db755511e --- /dev/null +++ b/host/include/uhd/CMakeLists.txt @@ -0,0 +1,32 @@ +# +# Copyright 2010-2011 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/>. +# + + +ADD_SUBDIRECTORY(transport) +ADD_SUBDIRECTORY(types) +ADD_SUBDIRECTORY(usrp) +ADD_SUBDIRECTORY(utils) + +INSTALL(FILES + config.hpp + convert.hpp + device.hpp + exception.hpp + version.hpp + wax.hpp + DESTINATION ${INCLUDE_DIR}/uhd +) diff --git a/host/include/uhd/config.hpp b/host/include/uhd/config.hpp new file mode 100644 index 000000000..1a04680e9 --- /dev/null +++ b/host/include/uhd/config.hpp @@ -0,0 +1,92 @@ +// +// Copyright 2010-2011 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_CONFIG_HPP +#define INCLUDED_UHD_CONFIG_HPP + +#include <boost/config.hpp> + +#ifdef BOOST_MSVC +// suppress warnings +//# pragma warning(push) +//# pragma warning(disable: 4511) // copy constructor can't not be generated +//# pragma warning(disable: 4512) // assignment operator can't not be generated +//# pragma warning(disable: 4100) // unreferenced formal parameter +//# pragma warning(disable: 4996) // <symbol> was declared deprecated +# pragma warning(disable: 4355) // 'this' : used in base member initializer list +//# pragma warning(disable: 4706) // assignment within conditional expression +# pragma warning(disable: 4251) // class 'A<T>' needs to have dll-interface to be used by clients of class 'B' +//# pragma warning(disable: 4127) // conditional expression is constant +//# pragma warning(disable: 4290) // C++ exception specification ignored except to ... +//# pragma warning(disable: 4180) // qualifier applied to function type has no meaning; ignored +# pragma warning(disable: 4275) // non dll-interface class ... used as base for dll-interface class ... +//# pragma warning(disable: 4267) // 'var' : conversion from 'size_t' to 'type', possible loss of data +//# pragma warning(disable: 4511) // 'class' : copy constructor could not be generated +//# pragma warning(disable: 4250) // 'class' : inherits 'method' via dominance +# pragma warning(disable: 4200) // nonstandard extension used : zero-sized array in struct/union + +// define logical operators +#include <ciso646> + +// define ssize_t +#include <cstddef> +typedef ptrdiff_t ssize_t; + +#endif //BOOST_MSVC + +//define cross platform attribute macros +#if defined(BOOST_MSVC) || defined(BOOST_HAS_DECLSPEC) + #define UHD_EXPORT __declspec(dllexport) + #define UHD_IMPORT __declspec(dllimport) + #define UHD_INLINE __forceinline + #define UHD_DEPRECATED __declspec(deprecated) + #define UHD_ALIGNED(x) __declspec(align(x)) +#elif defined(__GNUG__) && __GNUG__ >= 4 + #define UHD_EXPORT __attribute__((visibility("default"))) + #define UHD_IMPORT __attribute__((visibility("default"))) + #define UHD_INLINE inline __attribute__((always_inline)) + #define UHD_DEPRECATED __attribute__((deprecated)) + #define UHD_ALIGNED(x) __attribute__((aligned(x))) +#else + #define UHD_EXPORT + #define UHD_IMPORT + #define UHD_INLINE inline + #define UHD_DEPRECATED + #define UHD_ALIGNED(x) +#endif + +// Define API declaration macro +#ifdef UHD_DLL_EXPORTS + #define UHD_API UHD_EXPORT +#else + #define UHD_API UHD_IMPORT +#endif // UHD_DLL_EXPORTS + +// Platform defines for conditional parts of headers: +// Taken from boost/config/select_platform_config.hpp, +// however, we define macros, not strings for platforms. +#if defined(linux) || defined(__linux) || defined(__linux__) + #define UHD_PLATFORM_LINUX +#elif defined(_WIN32) || defined(__WIN32__) || defined(WIN32) + #define UHD_PLATFORM_WIN32 +#elif defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__) + #define UHD_PLATFORM_MACOS +#elif defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) + #define UHD_PLATFORM_BSD +#endif + +#endif /* INCLUDED_UHD_CONFIG_HPP */ diff --git a/host/include/uhd/convert.hpp b/host/include/uhd/convert.hpp new file mode 100644 index 000000000..8fc2f38db --- /dev/null +++ b/host/include/uhd/convert.hpp @@ -0,0 +1,90 @@ +// +// Copyright 2011 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_CONVERT_HPP +#define INCLUDED_UHD_CONVERT_HPP + +#include <uhd/config.hpp> +#include <uhd/types/io_type.hpp> +#include <uhd/types/otw_type.hpp> +#include <uhd/types/ref_vector.hpp> +#include <boost/function.hpp> +#include <string> + +namespace uhd{ namespace convert{ + + typedef uhd::ref_vector<void *> output_type; + typedef uhd::ref_vector<const void *> input_type; + typedef boost::function<void(const input_type&, const output_type&, size_t)> function_type; + + /*! + * Describe the priority of a converter function. + * A higher priority function takes precedence. + * The general case function are the lowest. + * Next comes the liborc implementations. + * Custom intrinsics implementations are highest. + */ + enum priority_type{ + PRIORITY_GENERAL = 0, + PRIORITY_LIBORC = 1, + PRIORITY_CUSTOM = 2, + PRIORITY_EMPTY = -1, + }; + + /*! + * Register a converter function that converts cpu type to/from otw type. + * \param markup representing the signature + * \param fcn a pointer to the converter + * \param prio the function priority + */ + UHD_API void register_converter( + const std::string &markup, + function_type fcn, + priority_type prio + ); + + /*! + * Get a converter function that converts cpu to otw. + * \param io_type the type of the input samples + * \param otw_type the type of the output samples + * \param num_input_buffs the number of inputs + * \param num_output_buffs the number of outputs + */ + UHD_API const function_type &get_converter_cpu_to_otw( + const io_type_t &io_type, + const otw_type_t &otw_type, + size_t num_input_buffs, + size_t num_output_buffs + ); + + /*! + * Get a converter function that converts otw to cpu. + * \param io_type the type of the input samples + * \param otw_type the type of the output samples + * \param num_input_buffs the number of inputs + * \param num_output_buffs the number of outputs + */ + UHD_API const function_type &get_converter_otw_to_cpu( + const io_type_t &io_type, + const otw_type_t &otw_type, + size_t num_input_buffs, + size_t num_output_buffs + ); + +}} //namespace + +#endif /* INCLUDED_UHD_CONVERT_HPP */ diff --git a/host/include/uhd/device.hpp b/host/include/uhd/device.hpp new file mode 100644 index 000000000..50237472b --- /dev/null +++ b/host/include/uhd/device.hpp @@ -0,0 +1,204 @@ +// +// Copyright 2010-2011 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_HPP +#define INCLUDED_UHD_DEVICE_HPP + +#include <uhd/config.hpp> +#include <uhd/types/device_addr.hpp> +#include <uhd/types/metadata.hpp> +#include <uhd/types/io_type.hpp> +#include <uhd/types/ref_vector.hpp> +#include <uhd/wax.hpp> +#include <boost/utility.hpp> +#include <boost/shared_ptr.hpp> +#include <boost/function.hpp> + +namespace uhd{ + +/*! + * The usrp device interface represents the usrp hardware. + * The api allows for discovery, configuration, and streaming. + */ +class UHD_API device : boost::noncopyable, public wax::obj{ + +public: + typedef boost::shared_ptr<device> sptr; + typedef boost::function<device_addrs_t(const device_addr_t &)> find_t; + typedef boost::function<sptr(const device_addr_t &)> make_t; + + /*! + * Register a device into the discovery and factory system. + * + * \param find a function that discovers devices + * \param make a factory function that makes a device + */ + static void register_device( + const find_t &find, + const make_t &make + ); + + /*! + * \brief Find usrp devices attached to the host. + * + * The hint device address should be used to narrow down the search + * to particular transport types and/or transport arguments. + * + * \param hint a partially (or fully) filled in device address + * \return a vector of device addresses for all usrps on the system + */ + static device_addrs_t find(const device_addr_t &hint); + + /*! + * \brief Create a new usrp device from the device address hint. + * + * The make routine will call find and pick one of the results. + * By default, the first result will be used to create a new device. + * Use the which parameter as an index into the list of results. + * + * \param hint a partially (or fully) filled in device address + * \param which which address to use when multiple are found + * \return a shared pointer to a new device instance + */ + static sptr make(const device_addr_t &hint, size_t which = 0); + + /*! + * Send modes for the device send routine. + */ + enum send_mode_t{ + //! Tells the send routine to send the entire buffer + SEND_MODE_FULL_BUFF = 0, + //! Tells the send routine to return after one packet + SEND_MODE_ONE_PACKET = 1 + }; + + /*! + * Recv modes for the device recv routine. + */ + enum recv_mode_t{ + //! Tells the recv routine to recv the entire buffer + RECV_MODE_FULL_BUFF = 0, + //! Tells the recv routine to return after one packet + RECV_MODE_ONE_PACKET = 1 + }; + + //! Typedef for a pointer to a single, or a collection of send buffers + typedef ref_vector<const void *> send_buffs_type; + + //! Typedef for a pointer to a single, or a collection of recv buffers + typedef ref_vector<void *> recv_buffs_type; + + /*! + * 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, + * the send method will fragment the samples across several packets. + * Send will respect the burst flags when fragmenting to ensure + * that start of burst can only be set on the first fragment and + * that end of burst can only be set on the final fragment. + * 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 each buffer. + * Under a timeout condition, the number of samples returned + * may be less than the number of samples specified. + * + * \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 + * \param timeout the timeout in seconds to wait on a packet + * \return the number of samples sent + */ + virtual size_t send( + const send_buffs_type &buffs, + size_t nsamps_per_buff, + const tx_metadata_t &metadata, + const io_type_t &io_type, + send_mode_t send_mode, + double timeout = 0.1 + ) = 0; + + /*! + * Receive buffers containing IF data described by the metadata. + * + * Receive handles fragmentation as follows: + * If the buffer has insufficient space to hold all samples + * that were received in a single packet over-the-wire, + * then the buffer will be completely filled and the implementation + * will hold a pointer into the remaining portion of the packet. + * Subsequent calls will load from the remainder of the packet, + * and will flag the metadata to show that this is a fragment. + * The next call to receive, after the remainder becomes exahausted, + * will perform an over-the-wire receive as usual. + * 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 each buffer. + * Under a timeout condition, the number of samples returned + * may be less than the number of samples specified. + * + * When using the full buffer recv mode, the metadata only applies + * to the first packet received and written into the recv buffers. + * Use the one packet recv mode to get per packet metadata. + * + * \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 + * \param timeout the timeout in seconds to wait for a packet + * \return the number of samples received or 0 on error + */ + virtual size_t recv( + const recv_buffs_type &buffs, + size_t nsamps_per_buff, + rx_metadata_t &metadata, + const io_type_t &io_type, + recv_mode_t recv_mode, + double timeout = 0.1 + ) = 0; + + /*! + * Get the maximum number of samples per packet on send. + * \return the number of samples + */ + virtual size_t get_max_send_samps_per_packet(void) const = 0; + + /*! + * Get the maximum number of samples per packet on recv. + * \return the number of samples + */ + virtual size_t get_max_recv_samps_per_packet(void) const = 0; + + /*! + * Receive and asynchronous message from the device. + * \param async_metadata the metadata to be filled in + * \param timeout the timeout in seconds to wait for a message + * \return true when the async_metadata is valid, false for timeout + */ + virtual bool recv_async_msg( + async_metadata_t &async_metadata, double timeout = 0.1 + ) = 0; + +}; + +} //namespace uhd + +#endif /* INCLUDED_UHD_DEVICE_HPP */ diff --git a/host/include/uhd/exception.hpp b/host/include/uhd/exception.hpp new file mode 100644 index 000000000..e2a50bf1e --- /dev/null +++ b/host/include/uhd/exception.hpp @@ -0,0 +1,133 @@ +// +// Copyright 2010-2011 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_EXCEPTION_HPP +#define INCLUDED_UHD_UTILS_EXCEPTION_HPP + +#include <uhd/config.hpp> +#include <boost/current_function.hpp> +#include <stdexcept> +#include <string> + +/*! + * Define common exceptions used throughout the code: + * + * - The python built-in exceptions were used as inspiration. + * - Exceptions inherit from std::exception to provide what(). + * - Exceptions inherit from uhd::exception to provide code(). + * + * The code() provides an error code which allows the application + * the option of printing a cryptic error message from the 1990s. + */ +namespace uhd{ + + struct UHD_API exception : std::runtime_error{ + exception(const std::string &what); + virtual unsigned code(void) const = 0; + }; + + struct UHD_API assertion_error : exception{ + assertion_error(const std::string &what); + virtual unsigned code(void) const; + }; + + struct UHD_API lookup_error : exception{ + lookup_error(const std::string &what); + virtual unsigned code(void) const; + }; + + struct UHD_API index_error : lookup_error{ + index_error(const std::string &what); + virtual unsigned code(void) const; + }; + + struct UHD_API key_error : lookup_error{ + key_error(const std::string &what); + virtual unsigned code(void) const; + }; + + struct UHD_API type_error : exception{ + type_error(const std::string &what); + virtual unsigned code(void) const; + }; + + struct UHD_API value_error : exception{ + value_error(const std::string &what); + virtual unsigned code(void) const; + }; + + struct UHD_API runtime_error : exception{ + runtime_error(const std::string &what); + virtual unsigned code(void) const; + }; + + struct UHD_API not_implemented_error : runtime_error{ + not_implemented_error(const std::string &what); + virtual unsigned code(void) const; + }; + + struct UHD_API environment_error : exception{ + environment_error(const std::string &what); + virtual unsigned code(void) const; + }; + + struct UHD_API io_error : environment_error{ + io_error(const std::string &what); + virtual unsigned code(void) const; + }; + + struct UHD_API os_error : environment_error{ + os_error(const std::string &what); + virtual unsigned code(void) const; + }; + + struct UHD_API system_error : exception{ + system_error(const std::string &what); + virtual unsigned code(void) const; + }; + + /*! + * Create a formated string with throw-site information. + * Fills in the function name, file name, and line number. + * \param what the std::exeption message + * \return the formatted exception message + */ + #define UHD_THROW_SITE_INFO(what) std::string( \ + std::string(what) + "\n" + \ + " in " + std::string(BOOST_CURRENT_FUNCTION) + "\n" + \ + " at " + std::string(__FILE__) + ":" + BOOST_STRINGIZE(__LINE__) + "\n" \ + ) + + /*! + * Throws an invalid code path exception with throw-site information. + * Use this macro in places that code execution is not supposed to go. + */ + #define UHD_THROW_INVALID_CODE_PATH() \ + throw uhd::system_error(UHD_THROW_SITE_INFO("invalid code path")) + + /*! + * Assert the result of the code evaluation. + * If the code evaluates to false, throw an assertion error. + * \param code the code that resolved to a boolean + */ + #define UHD_ASSERT_THROW(code) if (not (code)) \ + throw uhd::assertion_error(UHD_THROW_SITE_INFO(#code)); \ + else void(0) + +} //namespace uhd + +#endif /* INCLUDED_UHD_UTILS_EXCEPTION_HPP */ diff --git a/host/include/uhd/transport/CMakeLists.txt b/host/include/uhd/transport/CMakeLists.txt new file mode 100644 index 000000000..14ca82226 --- /dev/null +++ b/host/include/uhd/transport/CMakeLists.txt @@ -0,0 +1,32 @@ +# +# Copyright 2010-2011 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/>. +# + + +INSTALL(FILES + bounded_buffer.hpp + bounded_buffer.ipp + buffer_pool.hpp + if_addrs.hpp + udp_simple.hpp + udp_zero_copy.hpp + usb_control.hpp + usb_zero_copy.hpp + usb_device_handle.hpp + vrt_if_packet.hpp + zero_copy.hpp + DESTINATION ${INCLUDE_DIR}/uhd/transport +) diff --git a/host/include/uhd/transport/bounded_buffer.hpp b/host/include/uhd/transport/bounded_buffer.hpp new file mode 100644 index 000000000..6aa92c2e6 --- /dev/null +++ b/host/include/uhd/transport/bounded_buffer.hpp @@ -0,0 +1,121 @@ +// +// Copyright 2010-2011 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_HPP +#define INCLUDED_UHD_TRANSPORT_BOUNDED_BUFFER_HPP + +#include <uhd/transport/bounded_buffer.ipp> //detail + +namespace uhd{ namespace transport{ + + /*! + * 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. + * The push operation blocks on the bounded_buffer to become non full. + */ + template <typename elem_type> class bounded_buffer{ + public: + + /*! + * Create a new bounded buffer object. + * \param capacity the bounded_buffer capacity + */ + bounded_buffer(size_t capacity): + _detail(capacity) + { + /* NOP */ + } + + /*! + * Push a new element into the bounded buffer immediately. + * The element will not be pushed when the buffer is full. + * \param elem the element reference pop to + * \return false when the buffer is full + */ + bool push_with_haste(const elem_type &elem){ + return _detail.push_with_haste(elem); + } + + /*! + * Push a new element into the bounded buffer. + * If the buffer is full prior to the push, + * make room by poping the oldest element. + * \param elem the new element to push + * \return true if the element fit without popping for space + */ + bool push_with_pop_on_full(const elem_type &elem){ + return _detail.push_with_pop_on_full(elem); + } + + /*! + * Push a new element into the bounded_buffer. + * Wait until the bounded_buffer becomes non-full. + * \param elem the new element to push + */ + void push_with_wait(const elem_type &elem){ + return _detail.push_with_wait(elem); + } + + /*! + * Push a new element into the bounded_buffer. + * Wait until the bounded_buffer becomes non-full or timeout. + * \param elem the new element to push + * \param timeout the timeout in seconds + * \return false when the operation times out + */ + bool push_with_timed_wait(const elem_type &elem, double timeout){ + return _detail.push_with_timed_wait(elem, timeout); + } + + /*! + * Pop an element from the bounded buffer immediately. + * The element will not be popped when the buffer is empty. + * \param elem the element reference pop to + * \return false when the buffer is empty + */ + bool pop_with_haste(elem_type &elem){ + return _detail.pop_with_haste(elem); + } + + /*! + * Pop an element from the bounded_buffer. + * Wait until the bounded_buffer becomes non-empty. + * \param elem the element reference pop to + */ + void pop_with_wait(elem_type &elem){ + return _detail.pop_with_wait(elem); + } + + /*! + * Pop an element from the bounded_buffer. + * Wait until the bounded_buffer becomes non-empty or timeout. + * \param elem the element reference pop to + * \param timeout the timeout in seconds + * \return false when the operation times out + */ + bool pop_with_timed_wait(elem_type &elem, double timeout){ + return _detail.pop_with_timed_wait(elem, timeout); + } + + private: bounded_buffer_detail<elem_type> _detail; + }; + +}} //namespace + +#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..0d393ad64 --- /dev/null +++ b/host/include/uhd/transport/bounded_buffer.ipp @@ -0,0 +1,147 @@ +// +// Copyright 2010-2011 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 <uhd/config.hpp> +#include <boost/bind.hpp> +#include <boost/function.hpp> +#include <boost/circular_buffer.hpp> +#include <boost/thread/condition.hpp> +#include <boost/thread/locks.hpp> + +namespace uhd{ namespace transport{ namespace{ /*anon*/ + + template <typename elem_type> class bounded_buffer_detail{ + public: + + bounded_buffer_detail(size_t capacity): + _buffer(capacity) + { + _not_full_fcn = boost::bind(&bounded_buffer_detail<elem_type>::not_full, this); + _not_empty_fcn = boost::bind(&bounded_buffer_detail<elem_type>::not_empty, this); + } + + UHD_INLINE bool push_with_haste(const elem_type &elem){ + boost::mutex::scoped_lock lock(_mutex); + if (_buffer.full()) return false; + _buffer.push_front(elem); + lock.unlock(); + _empty_cond.notify_one(); + return true; + } + + UHD_INLINE bool push_with_pop_on_full(const elem_type &elem){ + boost::mutex::scoped_lock 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){ + if (this->push_with_haste(elem)) return; + boost::mutex::scoped_lock lock(_mutex); + _full_cond.wait(lock, _not_full_fcn); + _buffer.push_front(elem); + lock.unlock(); + _empty_cond.notify_one(); + } + + UHD_INLINE bool push_with_timed_wait(const elem_type &elem, double timeout){ + if (this->push_with_haste(elem)) return true; + boost::mutex::scoped_lock lock(_mutex); + if (not _full_cond.timed_wait( + lock, to_time_dur(timeout), _not_full_fcn + )) return false; + _buffer.push_front(elem); + lock.unlock(); + _empty_cond.notify_one(); + return true; + } + + UHD_INLINE bool pop_with_haste(elem_type &elem){ + boost::mutex::scoped_lock lock(_mutex); + if (_buffer.empty()) return false; + elem = this->pop_back(); + lock.unlock(); + _full_cond.notify_one(); + return true; + } + + UHD_INLINE void pop_with_wait(elem_type &elem){ + if (this->pop_with_haste(elem)) return; + boost::mutex::scoped_lock lock(_mutex); + _empty_cond.wait(lock, _not_empty_fcn); + elem = this->pop_back(); + lock.unlock(); + _full_cond.notify_one(); + } + + UHD_INLINE bool pop_with_timed_wait(elem_type &elem, double timeout){ + if (this->pop_with_haste(elem)) return true; + boost::mutex::scoped_lock lock(_mutex); + if (not _empty_cond.timed_wait( + lock, to_time_dur(timeout), _not_empty_fcn + )) return false; + elem = this->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();} + + boost::function<bool(void)> _not_full_fcn, _not_empty_fcn; + + /*! + * Three part operation to pop an element: + * 1) assign elem to the back element + * 2) assign the back element to empty + * 3) pop the back to move the counter + */ + UHD_INLINE elem_type pop_back(void){ + elem_type elem = _buffer.back(); + _buffer.back() = elem_type(); + _buffer.pop_back(); + return elem; + } + + static UHD_INLINE boost::posix_time::time_duration to_time_dur(double timeout){ + return boost::posix_time::microseconds(long(timeout*1e6)); + } + + }; +}}} //namespace + +#endif /* INCLUDED_UHD_TRANSPORT_BOUNDED_BUFFER_IPP */ diff --git a/host/include/uhd/transport/buffer_pool.hpp b/host/include/uhd/transport/buffer_pool.hpp new file mode 100644 index 000000000..84a338097 --- /dev/null +++ b/host/include/uhd/transport/buffer_pool.hpp @@ -0,0 +1,59 @@ +// +// Copyright 2011-2011 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_BUFFER_POOL_HPP +#define INCLUDED_UHD_TRANSPORT_BUFFER_POOL_HPP + +#include <uhd/config.hpp> +#include <boost/utility.hpp> +#include <boost/shared_ptr.hpp> + +namespace uhd{ namespace transport{ + + /*! + * A buffer pool manages memory for a homogeneous set of buffers. + * Each buffer is the pool start at a 16-byte alignment boundary. + */ + class UHD_API buffer_pool : boost::noncopyable{ + public: + typedef boost::shared_ptr<buffer_pool> sptr; + typedef void * ptr_type; + + /*! + * Make a new buffer pool. + * \param num_buffs the number of buffers to allocate + * \param buff_size the size of each buffer in bytes + * \param alignment the alignment boundary in bytes + * \return a new buffer pool buff_size X num_buffs + */ + static sptr make( + const size_t num_buffs, + const size_t buff_size, + const size_t alignment = 16 + ); + + //! Get a pointer to the buffer start at the specified index + virtual ptr_type at(const size_t index) const = 0; + + //! Get the number of buffers in this pool + virtual size_t size(void) const = 0; + }; + +}} //namespace + + +#endif /* INCLUDED_UHD_TRANSPORT_BUFFER_POOL_HPP */ diff --git a/host/include/uhd/transport/if_addrs.hpp b/host/include/uhd/transport/if_addrs.hpp new file mode 100644 index 000000000..689aff42c --- /dev/null +++ b/host/include/uhd/transport/if_addrs.hpp @@ -0,0 +1,46 @@ +// +// Copyright 2010-2011 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_IF_ADDRS_HPP +#define INCLUDED_UHD_TRANSPORT_IF_ADDRS_HPP + +#include <uhd/config.hpp> +#include <string> +#include <vector> + +namespace uhd{ namespace transport{ + + /*! + * The address for a network interface. + */ + struct UHD_API if_addrs_t{ + std::string inet; + std::string mask; + std::string bcast; + }; + + /*! + * Get a list of network interface addresses. + * The internal implementation is system-dependent. + * \return a vector of if addrs + */ + UHD_API std::vector<if_addrs_t> get_if_addrs(void); + +}} //namespace + + +#endif /* INCLUDED_UHD_TRANSPORT_IF_ADDRS_HPP */ diff --git a/host/include/uhd/transport/udp_simple.hpp b/host/include/uhd/transport/udp_simple.hpp new file mode 100644 index 000000000..83f895ba9 --- /dev/null +++ b/host/include/uhd/transport/udp_simple.hpp @@ -0,0 +1,84 @@ +// +// 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_UDP_SIMPLE_HPP +#define INCLUDED_UHD_TRANSPORT_UDP_SIMPLE_HPP + +#include <uhd/config.hpp> +#include <boost/asio/buffer.hpp> +#include <boost/utility.hpp> +#include <boost/shared_ptr.hpp> + +namespace uhd{ namespace transport{ + +class UHD_API udp_simple : boost::noncopyable{ +public: + typedef boost::shared_ptr<udp_simple> sptr; + + //! The maximum number of bytes per udp packet. + static const size_t mtu = 1500 - 20 - 8; //default ipv4 mtu - ipv4 header - udp header + + /*! + * Make a new connected udp transport: + * This transport is for sending and receiving + * between this host and a single endpoint. + * The primary usage for this transport will be control transactions. + * The underlying implementation is simple and portable (not fast). + * + * The address will be resolved, it can be a host name or ipv4. + * The port will be resolved, it can be a port type or number. + * + * \param addr a string representing the destination address + * \param port a string representing the destination port + */ + static sptr make_connected(const std::string &addr, const std::string &port); + + /*! + * Make a new broadcasting udp transport: + * This transport can send udp broadcast datagrams + * and receive datagrams from multiple sources. + * The primary usage for this transport will be to discover devices. + * + * The address will be resolved, it can be a host name or ipv4. + * The port will be resolved, it can be a port type or number. + * + * \param addr a string representing the destination address + * \param port a string representing the destination port + */ + static sptr make_broadcast(const std::string &addr, const std::string &port); + + /*! + * Send a single buffer. + * Blocks until the data is sent. + * \param buff single asio buffer + * \return the number of bytes sent + */ + virtual size_t send(const boost::asio::const_buffer &buff) = 0; + + /*! + * Receive into the provided buffer. + * Blocks until data is received or a timeout occurs. + * \param buff a mutable buffer to receive into + * \param timeout the timeout in seconds + * \return the number of bytes received or zero on timeout + */ + virtual size_t recv(const boost::asio::mutable_buffer &buff, double timeout = 0.1) = 0; +}; + +}} //namespace + +#endif /* INCLUDED_UHD_TRANSPORT_UDP_SIMPLE_HPP */ diff --git a/host/include/uhd/transport/udp_zero_copy.hpp b/host/include/uhd/transport/udp_zero_copy.hpp new file mode 100644 index 000000000..bbba97b21 --- /dev/null +++ b/host/include/uhd/transport/udp_zero_copy.hpp @@ -0,0 +1,65 @@ +// +// 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_UDP_ZERO_COPY_HPP +#define INCLUDED_UHD_TRANSPORT_UDP_ZERO_COPY_HPP + +#include <uhd/config.hpp> +#include <uhd/transport/zero_copy.hpp> +#include <uhd/types/device_addr.hpp> +#include <boost/shared_ptr.hpp> + +namespace uhd{ namespace transport{ + +/*! + * A zero copy udp transport provides an efficient way to handle data. + * by avoiding the extra copy when recv() or send() is called on the socket. + * Rather, the zero copy transport gives the caller memory references. + * The caller informs the transport when it is finished with the reference. + * + * On linux systems, the zero copy transport can use a kernel packet ring. + * If no platform specific solution is available, make returns a boost asio + * implementation that wraps the functionality around a standard send/recv calls. + */ +class UHD_API udp_zero_copy : public virtual zero_copy_if{ +public: + typedef boost::shared_ptr<udp_zero_copy> sptr; + + /*! + * Make a new zero copy udp transport: + * This transport is for sending and receiving + * between this host and a single endpoint. + * The primary usage for this transport will be data transactions. + * The underlying implementation is fast and platform specific. + * + * The address will be resolved, it can be a host name or ipv4. + * The port will be resolved, it can be a port type or number. + * + * \param addr a string representing the destination address + * \param port a string representing the destination port + * \param hints optional parameters to pass to the underlying transport + */ + static sptr make( + const std::string &addr, + const std::string &port, + const device_addr_t &hints = device_addr_t() + ); +}; + +}} //namespace + +#endif /* INCLUDED_UHD_TRANSPORT_UDP_ZERO_COPY_HPP */ diff --git a/host/include/uhd/transport/usb_control.hpp b/host/include/uhd/transport/usb_control.hpp new file mode 100644 index 000000000..e6c32f78e --- /dev/null +++ b/host/include/uhd/transport/usb_control.hpp @@ -0,0 +1,65 @@ +// +// 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_USB_CONTROL_HPP +#define INCLUDED_UHD_TRANSPORT_USB_CONTROL_HPP + +#include <uhd/transport/usb_device_handle.hpp> + +namespace uhd { namespace transport { + +class UHD_API usb_control : boost::noncopyable { +public: + typedef boost::shared_ptr<usb_control> sptr; + + /*! + * Create a new usb control transport: + * This transport is for sending and receiving control information from + * the host to device using the Default Control Pipe. + * + * \param handle a device handle that uniquely identifies a USB device + */ + static sptr make(usb_device_handle::sptr handle); + + /*! + * Submit a USB device request: + * Blocks until the request returns + * + * For format and corresponding USB request fields + * see USB Specification Revision 2.0 - 9.3 USB Device Requests + * + * Usage is device specific + * + * \param request_type 1-byte bitmask (bmRequestType) + * \param request 1-byte (bRequest) + * \param value 2-byte (wValue) + * \param index 2-byte (wIndex) + * \param buff buffer to hold send or receive data + * \param length 2-byte (wLength) + * \return number of bytes submitted or error code + */ + virtual ssize_t submit(boost::uint8_t request_type, + boost::uint8_t request, + boost::uint16_t value, + boost::uint16_t index, + unsigned char *buff, + boost::uint16_t length) = 0; +}; + +}} //namespace + +#endif /* INCLUDED_UHD_TRANSPORT_USB_CONTROL_HPP */ diff --git a/host/include/uhd/transport/usb_device_handle.hpp b/host/include/uhd/transport/usb_device_handle.hpp new file mode 100644 index 000000000..6f8d868be --- /dev/null +++ b/host/include/uhd/transport/usb_device_handle.hpp @@ -0,0 +1,73 @@ +// +// 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_USB_DEVICE_HANDLE_HPP +#define INCLUDED_UHD_TRANSPORT_USB_DEVICE_HANDLE_HPP + +#include <uhd/config.hpp> +#include <boost/utility.hpp> +#include <boost/shared_ptr.hpp> +#include <boost/cstdint.hpp> +#include <vector> + +namespace uhd { namespace transport { + +/*! + * Device handle class that represents a USB device + * Used for identifying devices on the USB bus and selecting which device is + * used when creating a USB transport. A minimal subset of USB descriptor + * fields are used. Fields can be found in the USB 2.0 specification Table + * 9-8 (Standard Device Descriptor). In addition to fields of the device + * descriptor, the interface returns the device's USB device address. + * + * Note: The USB 2.0 Standard Device Descriptor contains an index rather then + * a true descriptor serial number string. This interface returns the + * actual string descriptor. + */ +class UHD_API usb_device_handle : boost::noncopyable { +public: + typedef boost::shared_ptr<usb_device_handle> sptr; + + /*! + * Return the device's serial number + * \return a string describing the device's serial number + */ + virtual std::string get_serial() const = 0; + + /*! + * Return the device's Vendor ID (usually assigned by the USB-IF) + * \return a Vendor ID + */ + virtual boost::uint16_t get_vendor_id() const = 0; + + /*! + * Return the device's Product ID (usually assigned by manufacturer) + * \return a Product ID + */ + virtual boost::uint16_t get_product_id() const = 0; + + /*! + * Return a vector of USB devices on this host + * \return a vector of USB device handles that match vid and pid + */ + static std::vector<usb_device_handle::sptr> get_device_list(boost::uint16_t vid, boost::uint16_t pid); + +}; //namespace usb + +}} //namespace + +#endif /* INCLUDED_UHD_TRANSPORT_USB_DEVICE_HANDLE_HPP */ diff --git a/host/include/uhd/transport/usb_zero_copy.hpp b/host/include/uhd/transport/usb_zero_copy.hpp new file mode 100644 index 000000000..b39171fba --- /dev/null +++ b/host/include/uhd/transport/usb_zero_copy.hpp @@ -0,0 +1,63 @@ +// +// 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_USB_ZERO_COPY_HPP +#define INCLUDED_UHD_TRANSPORT_USB_ZERO_COPY_HPP + +#include <uhd/transport/usb_device_handle.hpp> +#include <uhd/transport/zero_copy.hpp> +#include <uhd/types/device_addr.hpp> + +namespace uhd { namespace transport { + +/*! + * A zero copy usb transport provides an efficient way to handle data. + * by avoiding the extra copy when recv() or send() is called on the handle. + * Rather, the zero copy transport gives the caller memory references. + * The caller informs the transport when it is finished with the reference. + * + * On linux systems, the zero copy transport can use a kernel packet ring. + * If no platform specific solution is available, make returns a boost asio + * implementation that wraps functionality around standard send/recv calls. + */ +class UHD_API usb_zero_copy : public virtual zero_copy_if { +public: + typedef boost::shared_ptr<usb_zero_copy> sptr; + + /*! + * Make a new zero copy usb transport: + * This transport is for sending and receiving between the host + * and a pair of USB bulk transfer endpoints. + * The primary usage for this transport is data transactions. + * The underlying implementation may be platform specific. + * + * \param handle a device handle that uniquely identifying the device + * \param recv_endpoint an integer specifiying an IN endpoint number + * \param send_endpoint an integer specifiying an OUT endpoint number + * \param hints optional parameters to pass to the underlying transport + */ + static sptr make( + usb_device_handle::sptr handle, + size_t recv_endpoint, + size_t send_endpoint, + const device_addr_t &hints = device_addr_t() + ); +}; + +}} //namespace + +#endif /* INCLUDED_UHD_TRANSPORT_USB_ZERO_COPY_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..51bd81bb1 --- /dev/null +++ b/host/include/uhd/transport/vrt_if_packet.hpp @@ -0,0 +1,106 @@ +// +// 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{ + //packet type (pack only supports data) + enum packet_type_t { + PACKET_TYPE_DATA = 0x0, + PACKET_TYPE_EXTENSION = 0x1, + PACKET_TYPE_CONTEXT = 0x2 + } packet_type; + + //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 new file mode 100644 index 000000000..092028d09 --- /dev/null +++ b/host/include/uhd/transport/zero_copy.hpp @@ -0,0 +1,157 @@ +// +// Copyright 2010-2011 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_ZERO_COPY_HPP +#define INCLUDED_UHD_TRANSPORT_ZERO_COPY_HPP + +#include <uhd/config.hpp> +#include <boost/utility.hpp> +#include <boost/shared_ptr.hpp> + +namespace uhd{ namespace transport{ + + /*! + * A managed receive buffer: + * Contains a reference to transport-managed memory, + * and a method to release the memory after reading. + */ + class UHD_API managed_recv_buffer{ + public: + typedef boost::shared_ptr<managed_recv_buffer> sptr; + + /*! + * Signal to the transport that we are done with the buffer. + * This should be called to release the buffer to the transport object. + * After calling, the referenced memory should be considered invalid. + */ + virtual void release(void) = 0; + + /*! + * Get a pointer to the underlying buffer. + * \return a pointer into memory + */ + template <class T> inline T cast(void) const{ + return static_cast<T>(this->get_buff()); + } + + /*! + * Get the size of the underlying buffer. + * \return the number of bytes + */ + inline size_t size(void) const{ + return this->get_size(); + } + + private: + virtual const void *get_buff(void) const = 0; + virtual size_t get_size(void) const = 0; + }; + + /*! + * A managed send buffer: + * Contains a reference to transport-managed memory, + * and a method to commit the memory after writing. + */ + class UHD_API managed_send_buffer{ + public: + typedef boost::shared_ptr<managed_send_buffer> sptr; + + /*! + * Signal to the transport that we are done with the buffer. + * This should be called to commit the write to the transport object. + * After calling, the referenced memory should be considered invalid. + * \param num_bytes the number of bytes written into the buffer + */ + virtual void commit(size_t num_bytes) = 0; + + /*! + * Get a pointer to the underlying buffer. + * \return a pointer into memory + */ + template <class T> inline T cast(void) const{ + return static_cast<T>(this->get_buff()); + } + + /*! + * Get the size of the underlying buffer. + * \return the number of bytes + */ + inline size_t size(void) const{ + return this->get_size(); + } + + private: + virtual void *get_buff(void) const = 0; + virtual size_t get_size(void) const = 0; + }; + + /*! + * A zero-copy interface for transport objects. + * Provides a way to get send and receive buffers + * with memory managed by the transport object. + */ + class UHD_API zero_copy_if : boost::noncopyable{ + public: + typedef boost::shared_ptr<zero_copy_if> sptr; + + /*! + * Get a new receive buffer from this transport object. + * \param timeout the timeout to get the buffer in seconds + * \return a managed buffer, or null sptr on timeout/error + */ + virtual managed_recv_buffer::sptr get_recv_buff(double timeout = 0.1) = 0; + + /*! + * Get the number of receive frames: + * The number of simultaneous receive buffers in use. + * \return number of frames + */ + virtual size_t get_num_recv_frames(void) const = 0; + + /*! + * Get the size of a receive frame: + * The maximum capacity of a single receive buffer. + * \return frame size in bytes + */ + virtual size_t get_recv_frame_size(void) const = 0; + + /*! + * Get a new send buffer from this transport object. + * \param timeout the timeout to get the buffer in seconds + * \return a managed buffer, or null sptr on timeout/error + */ + virtual managed_send_buffer::sptr get_send_buff(double timeout = 0.1) = 0; + + /*! + * Get the number of send frames: + * The number of simultaneous send buffers in use. + * \return number of frames + */ + virtual size_t get_num_send_frames(void) const = 0; + + /*! + * Get the size of a send frame: + * The maximum capacity of a single send buffer. + * \return frame size in bytes + */ + virtual size_t get_send_frame_size(void) const = 0; + + }; + +}} //namespace + +#endif /* INCLUDED_UHD_TRANSPORT_ZERO_COPY_HPP */ diff --git a/host/include/uhd/types/CMakeLists.txt b/host/include/uhd/types/CMakeLists.txt new file mode 100644 index 000000000..c856e5568 --- /dev/null +++ b/host/include/uhd/types/CMakeLists.txt @@ -0,0 +1,37 @@ +# +# Copyright 2010-2011 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/>. +# + + +INSTALL(FILES + clock_config.hpp + device_addr.hpp + dict.ipp + dict.hpp + io_type.hpp + mac_addr.hpp + metadata.hpp + otw_type.hpp + ranges.hpp + ref_vector.hpp + sensors.hpp + serial.hpp + stream_cmd.hpp + time_spec.hpp + tune_request.hpp + tune_result.hpp + DESTINATION ${INCLUDE_DIR}/uhd/types +) diff --git a/host/include/uhd/types/clock_config.hpp b/host/include/uhd/types/clock_config.hpp new file mode 100644 index 000000000..a72eb63de --- /dev/null +++ b/host/include/uhd/types/clock_config.hpp @@ -0,0 +1,54 @@ +// +// Copyright 2010-2011 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_TYPES_CLOCK_CONFIG_HPP +#define INCLUDED_UHD_TYPES_CLOCK_CONFIG_HPP + +#include <uhd/config.hpp> + +namespace uhd{ + + /*! + * Clock configuration settings: + * The source for the 10MHz reference clock. + * The source and polarity for the PPS clock. + */ + struct UHD_API clock_config_t{ + //------ simple usage --------// + static clock_config_t external(void); + static clock_config_t internal(void); + + //------ advanced usage --------// + enum ref_source_t { + REF_AUTO = 'a', //automatic (device specific) + REF_INT = 'i', //internal reference + REF_SMA = 's', //external sma port + } ref_source; + enum pps_source_t { + PPS_INT = 'i', //there is no internal + PPS_SMA = 's', //external sma port + } pps_source; + enum pps_polarity_t { + PPS_NEG = 'n', //negative edge + PPS_POS = 'p' //positive edge + } pps_polarity; + clock_config_t(void); + }; + +} //namespace uhd + +#endif /* INCLUDED_UHD_TYPES_CLOCK_CONFIG_HPP */ diff --git a/host/include/uhd/types/device_addr.hpp b/host/include/uhd/types/device_addr.hpp new file mode 100644 index 000000000..2c0841146 --- /dev/null +++ b/host/include/uhd/types/device_addr.hpp @@ -0,0 +1,98 @@ +// +// Copyright 2010-2011 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_TYPES_DEVICE_ADDR_HPP +#define INCLUDED_UHD_TYPES_DEVICE_ADDR_HPP + +#include <uhd/config.hpp> +#include <uhd/types/dict.hpp> +#include <boost/lexical_cast.hpp> +#include <stdexcept> +#include <vector> +#include <string> + +namespace uhd{ + + /*! + * Mapping of key/value pairs for locating devices on the system. + * When left empty, the device discovery routines will search + * all available transports on the system (ethernet, usb...). + * + * To narrow down the discovery process to a particular device, + * specify a transport key/value pair specific to your device. + * - Ex, to find a usrp2: my_dev_addr["addr"] = [resolvable_hostname_or_ip] + * + * The device address can also be used to pass arguments into + * the transport layer control to set (for example) buffer sizes. + * + * An arguments string, is a way to represent a device address + * using a single string with delimiter characters. + * - Ex: addr=192.168.10.2 + * - Ex: addr=192.168.10.2, recv_buff_size=1e6 + */ + class UHD_API device_addr_t : public dict<std::string, std::string>{ + public: + /*! + * Create a device address from an args string. + * \param args the arguments string + */ + device_addr_t(const std::string &args = ""); + + /*! + * Convert a device address into a pretty print string. + * \return a printable string representing the device address + */ + std::string to_pp_string(void) const; + + /*! + * Convert the device address into an args string. + * The args string contains delimiter symbols. + * \return a string with delimiter markup + */ + std::string to_string(void) const; + + /*! + * Lexically cast a parameter to the specified type, + * or use the default value if the key is not found. + * \param key the key as one of the address parameters + * \param def the value to use when key is not present + * \return the casted value as type T or the default + * \throw error when the parameter cannot be casted + */ + template <typename T> T cast(const std::string &key, const T &def) const{ + if (not this->has_key(key)) return def; + try{ + return boost::lexical_cast<T>((*this)[key]); + } + catch(const boost::bad_lexical_cast &){ + throw std::runtime_error("cannot cast " + key + " = " + (*this)[key]); + } + } + }; + + //! A typedef for a vector of device addresses + typedef std::vector<device_addr_t> device_addrs_t; + + //! Separate an indexed device address into a vector of device addresses + UHD_API device_addrs_t separate_device_addr(const device_addr_t &dev_addr); + + //! Combine a vector of device addresses into an indexed device address + UHD_API device_addr_t combine_device_addrs(const device_addrs_t &dev_addrs); + +} //namespace uhd + +#endif /* INCLUDED_UHD_TYPES_DEVICE_ADDR_HPP */ diff --git a/host/include/uhd/types/dict.hpp b/host/include/uhd/types/dict.hpp new file mode 100644 index 000000000..97fa8f09c --- /dev/null +++ b/host/include/uhd/types/dict.hpp @@ -0,0 +1,129 @@ +// +// Copyright 2010-2011 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_TYPES_DICT_HPP +#define INCLUDED_UHD_TYPES_DICT_HPP + +#include <uhd/config.hpp> +#include <vector> +#include <list> + +namespace uhd{ + + /*! + * A templated dictionary class with a python-like interface. + */ + template <typename Key, typename Val> class dict{ + public: + /*! + * Create a new empty dictionary. + */ + dict(void); + + /*! + * Input iterator constructor: + * Makes boost::assign::map_list_of work. + * \param first the begin iterator + * \param last the end iterator + */ + template <typename InputIterator> + dict(InputIterator first, InputIterator last); + + /*! + * Get the number of elements in this dict. + * \return the number of elements + */ + std::size_t size(void) const; + + /*! + * Get a list of the keys in this dict. + * Key order depends on insertion precedence. + * \return vector of keys + */ + std::vector<Key> keys(void) const; + + /*! + * Get a list of the values in this dict. + * Value order depends on insertion precedence. + * \return vector of values + */ + std::vector<Val> vals(void) const; + + /*! + * Does the dictionary contain this key? + * \param key the key to look for + * \return true if found + */ + bool has_key(const Key &key) const; + + /*! + * Get a value in the dict or default. + * \param key the key to look for + * \param other use if key not found + * \return the value or default + */ + const Val &get(const Key &key, const Val &other) const; + + /*! + * Get a value in the dict or throw. + * \param key the key to look for + * \return the value or default + */ + const Val &get(const Key &key) const; + + /*! + * Set a value in the dict at the key. + * \param key the key to set at + * \param val the value to set + */ + void set(const Key &key, const Val &val); + + /*! + * Get a value for the given key if it exists. + * If the key is not found throw an error. + * \param key the key to look for + * \return the value at the key + * \throw an exception when not found + */ + const Val &operator[](const Key &key) const; + + /*! + * Set a value for the given key, however, in reality + * it really returns a reference which can be assigned to. + * \param key the key to set to + * \return a reference to the value + */ + Val &operator[](const Key &key); + + /*! + * Pop an item out of the dictionary. + * \param key the item key + * \return the value of the item + * \throw an exception when not found + */ + Val pop(const Key &key); + + private: + typedef std::pair<Key, Val> pair_t; + std::list<pair_t> _map; //private container + }; + +} //namespace uhd + +#include <uhd/types/dict.ipp> + +#endif /* INCLUDED_UHD_TYPES_DICT_HPP */ diff --git a/host/include/uhd/types/dict.ipp b/host/include/uhd/types/dict.ipp new file mode 100644 index 000000000..5e9cf97ad --- /dev/null +++ b/host/include/uhd/types/dict.ipp @@ -0,0 +1,140 @@ +// +// Copyright 2010-2011 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_TYPES_DICT_IPP +#define INCLUDED_UHD_TYPES_DICT_IPP + +#include <uhd/exception.hpp> +#include <boost/foreach.hpp> +#include <boost/format.hpp> +#include <boost/lexical_cast.hpp> +#include <typeinfo> + +namespace uhd{ + + namespace /*anon*/{ + template<typename Key, typename Val> + struct key_not_found: uhd::key_error{ + key_not_found(const Key &key): uhd::key_error( + str(boost::format( + "key \"%s\" not found in dict(%s, %s)" + ) % boost::lexical_cast<std::string>(key) + % typeid(Key).name() % typeid(Val).name() + ) + ){ + /* NOP */ + } + }; + } // namespace /*anon*/ + + template <typename Key, typename Val> + dict<Key, Val>::dict(void){ + /* NOP */ + } + + template <typename Key, typename Val> template <typename InputIterator> + dict<Key, Val>::dict(InputIterator first, InputIterator last): + _map(first, last) + { + /* NOP */ + } + + template <typename Key, typename Val> + std::size_t dict<Key, Val>::size(void) const{ + return _map.size(); + } + + template <typename Key, typename Val> + std::vector<Key> dict<Key, Val>::keys(void) const{ + std::vector<Key> keys; + BOOST_FOREACH(const pair_t &p, _map){ + keys.push_back(p.first); + } + return keys; + } + + template <typename Key, typename Val> + std::vector<Val> dict<Key, Val>::vals(void) const{ + std::vector<Val> vals; + BOOST_FOREACH(const pair_t &p, _map){ + vals.push_back(p.second); + } + return vals; + } + + template <typename Key, typename Val> + bool dict<Key, Val>::has_key(const Key &key) const{ + BOOST_FOREACH(const pair_t &p, _map){ + if (p.first == key) return true; + } + return false; + } + + template <typename Key, typename Val> + const Val &dict<Key, Val>::get(const Key &key, const Val &other) const{ + BOOST_FOREACH(const pair_t &p, _map){ + if (p.first == key) return p.second; + } + return other; + } + + template <typename Key, typename Val> + const Val &dict<Key, Val>::get(const Key &key) const{ + BOOST_FOREACH(const pair_t &p, _map){ + if (p.first == key) return p.second; + } + throw key_not_found<Key, Val>(key); + } + + template <typename Key, typename Val> + void dict<Key, Val>::set(const Key &key, const Val &val){ + (*this)[key] = val; + } + + template <typename Key, typename Val> + const Val &dict<Key, Val>::operator[](const Key &key) const{ + BOOST_FOREACH(const pair_t &p, _map){ + if (p.first == key) return p.second; + } + throw key_not_found<Key, Val>(key); + } + + template <typename Key, typename Val> + Val &dict<Key, Val>::operator[](const Key &key){ + BOOST_FOREACH(pair_t &p, _map){ + if (p.first == key) return p.second; + } + _map.push_back(std::make_pair(key, Val())); + return _map.back().second; + } + + template <typename Key, typename Val> + Val dict<Key, Val>::pop(const Key &key){ + typename std::list<pair_t>::iterator it; + for (it = _map.begin(); it != _map.end(); it++){ + if (it->first == key){ + Val val = it->second; + _map.erase(it); + return val; + } + } + throw key_not_found<Key, Val>(key); + } + +} //namespace uhd + +#endif /* INCLUDED_UHD_TYPES_DICT_IPP */ diff --git a/host/include/uhd/types/io_type.hpp b/host/include/uhd/types/io_type.hpp new file mode 100644 index 000000000..990d701f9 --- /dev/null +++ b/host/include/uhd/types/io_type.hpp @@ -0,0 +1,76 @@ +// +// Copyright 2010-2011 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_TYPES_IO_TYPE_HPP +#define INCLUDED_UHD_TYPES_IO_TYPE_HPP + +#include <uhd/config.hpp> + +namespace uhd{ + + /*! + * The Input/Output configuration struct: + * Used to specify the IO type with device send/recv. + */ + class UHD_API io_type_t{ + public: + + /*! + * Built in IO types known to the system. + */ + enum tid_t{ + //! Custom type (technically unsupported by implementation) + CUSTOM_TYPE = '?', + //! Complex floating point (64-bit floats) range [-1.0, +1.0] + COMPLEX_FLOAT64 = 'd', + //! Complex floating point (32-bit floats) range [-1.0, +1.0] + COMPLEX_FLOAT32 = 'f', + //! Complex signed integer (16-bit integers) range [-32768, +32767] + COMPLEX_INT16 = 's', + //! Complex signed integer (8-bit integers) range [-128, 127] + COMPLEX_INT8 = 'b' + }; + + /*! + * The size of this io type in bytes. + */ + const size_t size; + + /*! + * The type id of this io type. + * Good for using with switch statements. + */ + const tid_t tid; + + /*! + * Create an io type from a built-in type id. + * \param tid a type id known to the system + */ + io_type_t(tid_t tid); + + /*! + * Create an io type from attributes. + * The tid will be set to custom. + * \param size the size in bytes + */ + io_type_t(size_t size); + + }; + +} //namespace uhd + +#endif /* INCLUDED_UHD_TYPES_IO_TYPE_HPP */ diff --git a/host/include/uhd/types/mac_addr.hpp b/host/include/uhd/types/mac_addr.hpp new file mode 100644 index 000000000..0ced2e734 --- /dev/null +++ b/host/include/uhd/types/mac_addr.hpp @@ -0,0 +1,66 @@ +// +// 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_TYPES_MAC_ADDR_HPP +#define INCLUDED_UHD_TYPES_MAC_ADDR_HPP + +#include <uhd/config.hpp> +#include <uhd/types/serial.hpp> +#include <string> + +namespace uhd{ + + /*! + * Wrapper for an ethernet mac address. + * Provides conversion between string and binary formats. + */ + class UHD_API mac_addr_t{ + public: + /*! + * Create a mac address a byte array. + * \param bytes a vector of bytes + * \return a new mac address + */ + static mac_addr_t from_bytes(const byte_vector_t &bytes); + + /*! + * Create a mac address from a string. + * \param mac_addr_str the string with delimiters + * \return a new mac address + */ + static mac_addr_t from_string(const std::string &mac_addr_str); + + /*! + * Get the byte representation of the mac address. + * \return a vector of bytes + */ + byte_vector_t to_bytes(void) const; + + /*! + * Get the string representation of this mac address. + * \return a string with delimiters + */ + std::string to_string(void) const; + + private: + mac_addr_t(const byte_vector_t &bytes); //private constructor + const byte_vector_t _bytes; //internal representation + }; + +} //namespace uhd + +#endif /* INCLUDED_UHD_TYPES_MAC_ADDR_HPP */ diff --git a/host/include/uhd/types/metadata.hpp b/host/include/uhd/types/metadata.hpp new file mode 100644 index 000000000..f4e084430 --- /dev/null +++ b/host/include/uhd/types/metadata.hpp @@ -0,0 +1,152 @@ +// +// 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_TYPES_METADATA_HPP +#define INCLUDED_UHD_TYPES_METADATA_HPP + +#include <uhd/config.hpp> +#include <uhd/types/time_spec.hpp> + +namespace uhd{ + + /*! + * RX metadata structure for describing sent IF data. + * Includes time specification, fragmentation flags, burst flags, and error codes. + * The receive routines will convert IF data headers into metadata. + */ + struct UHD_API rx_metadata_t{ + //! Has time specification? + bool has_time_spec; + + //! Time of the first sample. + time_spec_t time_spec; + + /*! + * Fragmentation flag: + * Similar to IPv4 fragmentation: http://en.wikipedia.org/wiki/IPv4#Fragmentation_and_reassembly + * More fragments is true when the input buffer has insufficient size to fit + * an entire received packet. More fragments will be false for the last fragment. + */ + bool more_fragments; + + /*! + * Fragmentation offset: + * The fragment offset is the sample number at the start of the receive buffer. + * For non-fragmented receives, the fragment offset should always be zero. + */ + size_t fragment_offset; + + //! Start of burst will be true for the first packet in the chain. + bool start_of_burst; + + //! End of burst will be true for the last packet in the chain. + bool end_of_burst; + + /*! + * The error condition on a receive call. + * + * Note: When an overrun occurs in continuous streaming mode, + * the device will continue to send samples to the host. + * For other streaming modes, streaming will discontinue + * until the user issues a new stream command. + * + * The metadata fields have meaning for the following error codes: + * - none + * - late command + * - broken chain + * - overflow + */ + enum error_code_t { + //! No error associated with this metadata. + ERROR_CODE_NONE = 0x0, + //! No packet received, implementation timed-out. + ERROR_CODE_TIMEOUT = 0x1, + //! A stream command was issued in the past. + ERROR_CODE_LATE_COMMAND = 0x2, + //! Expected another stream command. + ERROR_CODE_BROKEN_CHAIN = 0x4, + //! An internal receive buffer has filled. + ERROR_CODE_OVERFLOW = 0x8, + //! The packet could not be parsed. + ERROR_CODE_BAD_PACKET = 0xf + } error_code; + }; + + /*! + * TX metadata structure for describing received IF data. + * Includes time specification, and start and stop burst flags. + * The send routines will convert the metadata to IF data headers. + */ + struct UHD_API tx_metadata_t{ + /*! + * Has time specification? + * - Set false to send immediately. + * - Set true to send at the time specified by time spec. + */ + bool has_time_spec; + + //! When to send the first sample. + time_spec_t time_spec; + + //! Set start of burst to true for the first packet in the chain. + bool start_of_burst; + + //! Set end of burst to true for the last packet in the chain. + bool end_of_burst; + + /*! + * The default constructor: + * Sets the fields to default values (flags set to false). + */ + tx_metadata_t(void); + }; + + /*! + * Async metadata structure for describing transmit related events. + */ + struct UHD_API async_metadata_t{ + //! The channel number in a mimo configuration + size_t channel; + + //! Has time specification? + bool has_time_spec; + + //! When the async event occurred. + time_spec_t time_spec; + + /*! + * The type of event for a receive async message call. + */ + enum event_code_t { + //! A burst was successfully transmitted. + EVENT_CODE_BURST_ACK = 0x1, + //! An internal send buffer has emptied. + EVENT_CODE_UNDERFLOW = 0x2, + //! Packet loss between host and device. + EVENT_CODE_SEQ_ERROR = 0x4, + //! Packet had time that was late (or too early). + EVENT_CODE_TIME_ERROR = 0x8, + //! Underflow occurred inside a packet. + EVENT_CODE_UNDERFLOW_IN_PACKET = 0x10, + //! Packet loss within a burst. + EVENT_CODE_SEQ_ERROR_IN_BURST = 0x20 + } event_code; + }; + +} //namespace uhd + +#endif /* INCLUDED_UHD_TYPES_METADATA_HPP */ diff --git a/host/include/uhd/types/otw_type.hpp b/host/include/uhd/types/otw_type.hpp new file mode 100644 index 000000000..8e3e65d78 --- /dev/null +++ b/host/include/uhd/types/otw_type.hpp @@ -0,0 +1,69 @@ +// +// 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_TYPES_OTW_TYPE_HPP +#define INCLUDED_UHD_TYPES_OTW_TYPE_HPP + +#include <uhd/config.hpp> + +namespace uhd{ + + /*! + * Description for over-the-wire integers: + * The DSP units in the FPGA deal with signed 16-bit integers. + * The width and shift define the translation between OTW and DSP, + * defined by the following relation: otw_int = dsp_int >> shift + * + * Note: possible combinations of width, shift, and byteorder + * depend on the internals of the FPGA. Not all are supported! + */ + struct UHD_API otw_type_t{ + + /*! + * Width of an over-the-wire integer in bits. + */ + size_t width; //in bits + + /*! + * Shift of an over-the-wire integer in bits. + * otw_int = dsp_int >> shift + * dsp_int = otw_int << shift + */ + size_t shift; //in bits + + /*! + * Constants for byte order (borrowed from numpy's dtype) + */ + enum /*bo_t*/ { + BO_NATIVE = '=', + BO_LITTLE_ENDIAN = '<', + BO_BIG_ENDIAN = '>', + BO_NOT_APPLICABLE = '|' + } byteorder; + + /*! + * Get the sample size of this otw type. + * \return the size of a sample in bytes + */ + size_t get_sample_size(void) const; + + otw_type_t(void); + }; + +} //namespace uhd + +#endif /* INCLUDED_UHD_TYPES_OTW_TYPE_HPP */ diff --git a/host/include/uhd/types/ranges.hpp b/host/include/uhd/types/ranges.hpp new file mode 100644 index 000000000..f0d0e1c0b --- /dev/null +++ b/host/include/uhd/types/ranges.hpp @@ -0,0 +1,120 @@ +// +// Copyright 2010-2011 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_TYPES_RANGES_HPP +#define INCLUDED_UHD_TYPES_RANGES_HPP + +#include <uhd/config.hpp> +#include <uhd/utils/pimpl.hpp> +#include <string> +#include <vector> + +namespace uhd{ + + /*! + * A range object describes a set of discrete values of the form: + * y = start + step*n, where n is an integer between 0 and (stop - start)/step + */ + class UHD_API range_t{ + public: + + /*! + * Create a range from a single value. + * The step size will be taken as zero. + * \param value the only possible value in this range + */ + range_t(double value = 0); + + /*! + * Create a range from a full set of values. + * A step size of zero implies infinite precision. + * \param start the minimum value for this range + * \param stop the maximum value for this range + * \param step the step size for this range + */ + range_t(double start, double stop, double step = 0); + + //! Get the start value for this range. + double start(void) const; + + //! Get the stop value for this range. + double stop(void) const; + + //! Get the step value for this range. + double step(void) const; + + //! Convert this range to a printable string + const std::string to_pp_string(void) const; + + private: UHD_PIMPL_DECL(impl) _impl; + }; + + /*! + * A meta-range object holds a list of individual ranges. + */ + struct UHD_API meta_range_t : std::vector<range_t>{ + + //! A default constructor for an empty meta-range + meta_range_t(void); + + /*! + * Input iterator constructor: + * Makes boost::assign::list_of work. + * \param first the begin iterator + * \param last the end iterator + */ + template <typename InputIterator> + meta_range_t(InputIterator first, InputIterator last): + std::vector<range_t>(first, last){ /* NOP */ } + + /*! + * A convenience constructor for a single range. + * A step size of zero implies infinite precision. + * \param start the minimum value for this range + * \param stop the maximum value for this range + * \param step the step size for this range + */ + meta_range_t(double start, double stop, double step = 0); + + //! Get the overall start value for this meta-range. + double start(void) const; + + //! Get the overall stop value for this meta-range. + double stop(void) const; + + //! Get the overall step value for this meta-range. + double step(void) const; + + /*! + * Clip the target value to a possible range value. + * \param value the value to clip to this range + * \param clip_step if true, clip to steps as well + * \return a value that is in one of the ranges + */ + double clip(double value, bool clip_step = false) const; + + //! Convert this meta-range to a printable string + const std::string to_pp_string(void) const; + + }; + + typedef meta_range_t gain_range_t; + typedef meta_range_t freq_range_t; + +} //namespace uhd + +#endif /* INCLUDED_UHD_TYPES_RANGES_HPP */ diff --git a/host/include/uhd/types/ref_vector.hpp b/host/include/uhd/types/ref_vector.hpp new file mode 100644 index 000000000..bbfb5434d --- /dev/null +++ b/host/include/uhd/types/ref_vector.hpp @@ -0,0 +1,85 @@ +// +// Copyright 2011 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_TYPES_REF_VECTOR_HPP +#define INCLUDED_UHD_TYPES_REF_VECTOR_HPP + +#include <uhd/config.hpp> + +namespace uhd{ + +/*! + * Reference vector: + * - Provides a std::vector-like interface for an array. + * - Statically sized, and does not manage the memory. + */ +template <typename T> class UHD_API ref_vector{ +public: + /*! + * Create a reference vector of size 1 from a pointer. + * Therefore: rv[0] == ptr and rv.size() == 1 + * \param ptr a pointer to a chunk of memory + */ + template <typename Ptr> ref_vector(Ptr *ptr): + _ptr(T(ptr)), _mem(_mem_t(&_ptr)), _size(1) + { + /* NOP */ + } + + /*! + * Create a reference vector from a std::vector container. + * Therefore: rv[n] == vec[n] and rv.size() == vec.size() + * \param vec a const reference to an std::vector + */ + template <typename Vector> ref_vector(const Vector &vec): + _ptr(T()), _mem(_mem_t(&vec.front())), _size(vec.size()) + { + /* NOP */ + } + + /*! + * Create a reference vector from a pointer and a length + * Therefore: rv[n] == mem[n] and rv.size() == len + * \param mem a pointer to an array of pointers + * \param len the length of the array of pointers + */ + ref_vector(const T *mem, size_t len): + _ptr(T()), _mem(_mem_t(mem)), _size(len) + { + /* NOP */ + } + + //! Index operator gets the value of rv[index] + const T &operator[](size_t index) const{ + return _mem[index]; + } + + //! The number of elements in this container + size_t size(void) const{ + return _size; + } + +private: + const T _ptr; + typedef T* _mem_t; + const _mem_t _mem; + const size_t _size; +}; + +} //namespace uhd + +#endif /* INCLUDED_UHD_TYPES_REF_VECTOR_HPP */ diff --git a/host/include/uhd/types/sensors.hpp b/host/include/uhd/types/sensors.hpp new file mode 100644 index 000000000..529e1e3e3 --- /dev/null +++ b/host/include/uhd/types/sensors.hpp @@ -0,0 +1,137 @@ +// +// Copyright 2011 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_TYPES_SENSORS_HPP +#define INCLUDED_UHD_TYPES_SENSORS_HPP + +#include <uhd/config.hpp> +#include <string> + +namespace uhd{ + + /*! + * A sensor value stores a sensor reading as a string with unit and data type. + * The sensor value class can be used in the following way: + * + * sensor_value_t ref_lock_sensor("Reference", my_lock, "unlocked", "locked"); + * std::cout << ref_lock_sensor.to_pp_string() << std::endl; + * //prints Reference: locked + * + * sensor_value_t temp_sensor("Temperature", my_temp, "C"); + * std::cout << temp_sensor.to_pp_string() << std::endl; + * //prints Temperature: 38.5 C + */ + struct UHD_API sensor_value_t{ + + /*! + * Create a sensor value from a boolean. + * \param name the name of the sensor + * \param value the value true or false + * \param utrue the unit string when value is true + * \param ufalse the unit string when value is false + */ + sensor_value_t( + const std::string &name, + bool value, + const std::string &utrue, + const std::string &ufalse + ); + + /*! + * Create a sensor value from an integer. + * \param name the name of the sensor + * \param value the signed integer value + * \param unit the associated unit type + * \param formatter the formatter string + */ + sensor_value_t( + const std::string &name, + signed value, + const std::string &unit, + const std::string &formatter = "%d" + ); + + /*! + * Create a sensor value from a real number. + * \param name the name of the sensor + * \param value the real number value + * \param unit the associated unit type + * \param formatter the formatter string + */ + sensor_value_t( + const std::string &name, + double value, + const std::string &unit, + const std::string &formatter = "%f" + ); + + /*! + * Create a sensor value from a string. + * \param name the name of the sensor + * \param value the real number value + * \param unit the associated unit type + */ + sensor_value_t( + const std::string &name, + const std::string &value, + const std::string &unit + ); + + //! convert the sensor value to a boolean + bool to_bool(void) const; + + //! convert the sensor value to an integer + signed to_int(void) const; + + //! convert the sensor value to real number + double to_real(void) const; + + //! The name of the sensor value + const std::string name; + + /*! + * The sensor value as a string. + * For integer and real number types, this will be the output of the formatter. + * For boolean types, the value will be the string literal "true" or "false". + */ + const std::string value; + + /*! + * The sensor value's unit type. + * For boolean types, this will be the one of the two units + * depending upon the value of the boolean true or false. + */ + const std::string unit; + + //! Enumeration of possible data types in a sensor + enum data_type_t { + BOOLEAN = 'b', + INTEGER = 'i', + REALNUM = 'r', + STRING = 's' + }; + + //! The data type of the value + const data_type_t type; + + //! Convert this sensor value into a printable string + std::string to_pp_string(void) const; + }; + +} //namespace uhd + +#endif /* INCLUDED_UHD_TYPES_SENSORS_HPP */ diff --git a/host/include/uhd/types/serial.hpp b/host/include/uhd/types/serial.hpp new file mode 100644 index 000000000..5c6de162b --- /dev/null +++ b/host/include/uhd/types/serial.hpp @@ -0,0 +1,175 @@ +// +// 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_TYPES_SERIAL_HPP +#define INCLUDED_UHD_TYPES_SERIAL_HPP + +#include <uhd/config.hpp> +#include <boost/cstdint.hpp> +#include <vector> + +namespace uhd{ + + /*! + * Byte vector typedef for passing data in and out of I2C interfaces. + */ + typedef std::vector<boost::uint8_t> byte_vector_t; + + /*! + * The i2c interface class: + * Provides i2c and eeprom functionality. + * A subclass should only have to implement the i2c routines. + * An eeprom implementation comes for free with the interface. + * + * The eeprom routines are implemented on top of i2c. + * The built in eeprom implementation only does single + * byte reads and byte writes over the i2c interface, + * so it should be portable across multiple eeproms. + * Override the eeprom routines if this is not acceptable. + */ + class UHD_API i2c_iface{ + public: + /*! + * Write bytes over the i2c. + * \param addr the address + * \param buf the vector of bytes + */ + virtual void write_i2c( + boost::uint8_t addr, + const byte_vector_t &buf + ) = 0; + + /*! + * Read bytes over the i2c. + * \param addr the address + * \param num_bytes number of bytes to read + * \return a vector of bytes + */ + virtual byte_vector_t read_i2c( + boost::uint8_t addr, + size_t num_bytes + ) = 0; + + /*! + * Write bytes to an eeprom. + * \param addr the address + * \param offset byte offset + * \param buf the vector of bytes + */ + virtual void write_eeprom( + boost::uint8_t addr, + boost::uint8_t offset, + const byte_vector_t &buf + ); + + /*! + * Read bytes from an eeprom. + * \param addr the address + * \param offset byte offset + * \param num_bytes number of bytes to read + * \return a vector of bytes + */ + virtual byte_vector_t read_eeprom( + boost::uint8_t addr, + boost::uint8_t offset, + size_t num_bytes + ); + }; + + /*! + * The SPI configuration struct: + * Used to configure a SPI transaction interface. + */ + struct UHD_API spi_config_t{ + /*! + * The edge type specifies when data is valid + * relative to the edge of the serial clock. + */ + enum edge_t{ + EDGE_RISE = 'r', + EDGE_FALL = 'f' + }; + + //! on what edge is the mosi data valid? + edge_t mosi_edge; + + //! on what edge is the miso data valid? + edge_t miso_edge; + + /*! + * Create a new spi config. + * \param edge the default edge for mosi and miso + */ + spi_config_t(edge_t edge = EDGE_RISE); + }; + + /*! + * The SPI interface class. + * Provides routines to transact SPI and do other useful things which haven't been defined yet. + */ + class UHD_API spi_iface{ + public: + /*! + * Perform a spi transaction. + * \param which_slave the slave device number + * \param config spi config args + * \param data the bits to write + * \param num_bits how many bits in data + * \param readback true to readback a value + * \return spi data if readback set + */ + virtual boost::uint32_t transact_spi( + int which_slave, + const spi_config_t &config, + boost::uint32_t data, + size_t num_bits, + bool readback + ) = 0; + + /*! + * Read from the SPI bus. + * \param which_slave the slave device number + * \param config spi config args + * \param data the bits to write out (be sure to set write bit) + * \param num_bits how many bits in data + * \return spi data + */ + virtual boost::uint32_t read_spi( + int which_slave, + const spi_config_t &config, + boost::uint16_t data, + size_t num_bits + ); + + /*! + * Write to the SPI bus. + * \param which_slave the slave device number + * \param config spi config args + * \param data the bits to write + * \param num_bits how many bits in data + */ + virtual void write_spi( + int which_slave, + const spi_config_t &config, + boost::uint16_t data, + size_t num_bits + ); + }; + +} //namespace uhd + +#endif /* INCLUDED_UHD_TYPES_SERIAL_HPP */ diff --git a/host/include/uhd/types/stream_cmd.hpp b/host/include/uhd/types/stream_cmd.hpp new file mode 100644 index 000000000..41708e2e2 --- /dev/null +++ b/host/include/uhd/types/stream_cmd.hpp @@ -0,0 +1,64 @@ +// +// 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_TYPES_STREAM_CMD_HPP +#define INCLUDED_UHD_TYPES_STREAM_CMD_HPP + +#include <uhd/config.hpp> +#include <uhd/types/time_spec.hpp> + +namespace uhd{ + + /*! + * Command struct for configuration and control of streaming: + * + * A stream command defines how the device sends samples to the host. + * Streaming is controlled by submitting a stream command to the rx dsp. + * Granular control over what the device streams to the host can be + * achieved through submission of multiple (carefully-crafted) commands. + * + * The mode parameter controls how streaming is issued to the device: + * - "Start continuous" tells the device to stream samples indefinitely. + * - "Stop continuous" tells the device to end continuous streaming. + * - "Num samps and done" tells the device to stream num samps and + * to not expect a future stream command for contiguous samples. + * - "Num samps and more" tells the device to stream num samps and + * to expect a future stream command for contiguous samples. + * + * The stream now parameter controls when the stream begins. + * When true, the device will begin streaming ASAP. When false, + * the device will begin streaming at a time specified by time_spec. + */ + struct UHD_API stream_cmd_t{ + + enum stream_mode_t { + STREAM_MODE_START_CONTINUOUS = 'a', + STREAM_MODE_STOP_CONTINUOUS = 'o', + STREAM_MODE_NUM_SAMPS_AND_DONE = 'd', + STREAM_MODE_NUM_SAMPS_AND_MORE = 'm' + } stream_mode; + size_t num_samps; + + bool stream_now; + time_spec_t time_spec; + + stream_cmd_t(const stream_mode_t &stream_mode); + }; + +} //namespace uhd + +#endif /* INCLUDED_UHD_TYPES_STREAM_CMD_HPP */ diff --git a/host/include/uhd/types/time_spec.hpp b/host/include/uhd/types/time_spec.hpp new file mode 100644 index 000000000..2046fbd3f --- /dev/null +++ b/host/include/uhd/types/time_spec.hpp @@ -0,0 +1,117 @@ +// +// 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_TYPES_TIME_SPEC_HPP +#define INCLUDED_UHD_TYPES_TIME_SPEC_HPP + +#include <uhd/config.hpp> +#include <boost/operators.hpp> +#include <ctime> + +namespace uhd{ + + /*! + * 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 time_spec_t provides clock-domain independent time storage, + * but can convert fractional seconds to/from clock-domain specific units. + * + * 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. + */ + class UHD_API time_spec_t : boost::additive<time_spec_t>, boost::totally_ordered<time_spec_t>{ + public: + + /*! + * Get the system time in time_spec_t format. + * Uses the highest precision clock available. + * \return the system time as a time_spec_t + */ + static time_spec_t get_system_time(void); + + /*! + * 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); + + /*! + * 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, long tick_count, double tick_rate); + + /*! + * 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 + */ + long get_tick_count(double tick_rate) const; + + /*! + * 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 + */ + double get_real_secs(void) const; + + /*! + * 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 + */ + 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/types/tune_request.hpp b/host/include/uhd/types/tune_request.hpp new file mode 100644 index 000000000..942b93251 --- /dev/null +++ b/host/include/uhd/types/tune_request.hpp @@ -0,0 +1,95 @@ +// +// 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_TYPES_TUNE_REQUEST_HPP +#define INCLUDED_UHD_TYPES_TUNE_REQUEST_HPP + +#include <uhd/config.hpp> + +namespace uhd{ + + /*! + * A tune request instructs the implementation how to tune the RF chain. + * The policies can be used to select automatic tuning or + * fined control over the daughterboard IF and DSP tuning. + * Not all combinations of policies are applicable. + * Convenience constructors are supplied for most use cases. + */ + struct UHD_API tune_request_t{ + /*! + * Make a new tune request for a particular center frequency. + * Use an automatic policy for the intermediate and DSP frequency + * to tune the chain as close as possible to the target frequency. + * \param target_freq the target frequency in Hz + */ + tune_request_t(double target_freq = 0); + + /*! + * Make a new tune request for a particular center frequency. + * Use a manual policy for the intermediate frequency, + * and an automatic policy for the DSP frequency, + * to tune the chain as close as possible to the target frequency. + * \param target_freq the target frequency in Hz + * \param lo_off the LO offset frequency in Hz + */ + tune_request_t(double target_freq, double lo_off); + + //! Policy options for tunable elements in the RF chain. + enum policy_t { + //! Do not set this argument, use current setting. + POLICY_NONE = 'N', + //! Automatically determine the argument's value. + POLICY_AUTO = 'A', + //! Use the argument's value for the setting. + POLICY_MANUAL = 'M' + }; + + /*! + * The target frequency of the overall chain in Hz. + * Set this even if all policies are set to manual. + */ + double target_freq; + + /*! + * The policy for the intermediate frequency. + * Automatic behavior: the target frequency + default LO offset. + */ + policy_t inter_freq_policy; + + /*! + * The intermediate frequency in Hz. + * Set when the policy is set to manual. + */ + double inter_freq; + + /*! + * The policy for the DSP frequency. + * Automatic behavior: the difference between the target and IF. + */ + policy_t dsp_freq_policy; + + /*! + * The DSP frequency in Hz. + * Set when the policy is set to manual. + */ + double dsp_freq; + + }; + +} //namespace uhd + +#endif /* INCLUDED_UHD_TYPES_TUNE_REQUEST_HPP */ diff --git a/host/include/uhd/types/tune_result.hpp b/host/include/uhd/types/tune_result.hpp new file mode 100644 index 000000000..9eebc161a --- /dev/null +++ b/host/include/uhd/types/tune_result.hpp @@ -0,0 +1,48 @@ +// +// 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_TYPES_TUNE_RESULT_HPP +#define INCLUDED_UHD_TYPES_TUNE_RESULT_HPP + +#include <uhd/config.hpp> +#include <string> + +namespace uhd{ + + /*! + * The tune result struct holds result of a 2-phase tuning: + * The struct hold the result of tuning the dboard as + * the target and actual intermediate frequency. + * The struct hold the result of tuning the DSP as + * the target and actual digital converter frequency. + */ + struct UHD_API tune_result_t{ + double target_inter_freq; + double actual_inter_freq; + double target_dsp_freq; + double actual_dsp_freq; + + /*! + * Create a pretty print string for this tune result struct. + * \return the printable string + */ + std::string to_pp_string(void) const; + }; + +} //namespace uhd + +#endif /* INCLUDED_UHD_TYPES_TUNE_RESULT_HPP */ diff --git a/host/include/uhd/usrp/CMakeLists.txt b/host/include/uhd/usrp/CMakeLists.txt new file mode 100644 index 000000000..59a1302af --- /dev/null +++ b/host/include/uhd/usrp/CMakeLists.txt @@ -0,0 +1,49 @@ +# +# 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/>. +# + + +INSTALL(FILES + #### props headers ### + codec_props.hpp + dboard_props.hpp + device_props.hpp + dsp_props.hpp + mboard_props.hpp + subdev_props.hpp + + #### dboard headers ### + dboard_base.hpp + dboard_eeprom.hpp + dboard_id.hpp + dboard_iface.hpp + dboard_manager.hpp + + ### utilities ### + dsp_utils.hpp + gps_ctrl.hpp + mboard_eeprom.hpp + misc_utils.hpp + subdev_spec.hpp + tune_helper.hpp + + ### interfaces ### + single_usrp.hpp + multi_usrp.hpp + mboard_iface.hpp + + DESTINATION ${INCLUDE_DIR}/uhd/usrp +) diff --git a/host/include/uhd/usrp/codec_props.hpp b/host/include/uhd/usrp/codec_props.hpp new file mode 100644 index 000000000..b0a79e3f6 --- /dev/null +++ b/host/include/uhd/usrp/codec_props.hpp @@ -0,0 +1,42 @@ +// +// Copyright 2010-2011 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_CODEC_PROPS_HPP +#define INCLUDED_UHD_USRP_CODEC_PROPS_HPP + +#include <uhd/utils/props.hpp> + +namespace uhd{ namespace usrp{ + + /*! + * Possible device codec properties: + * A codec is expected to have a rate and gain elements. + * Other properties can be discovered through the others prop. + */ + enum codec_prop_t{ + CODEC_PROP_NAME, //ro, std::string + CODEC_PROP_OTHERS, //ro, prop_names_t + CODEC_PROP_GAIN_I, //rw, double + CODEC_PROP_GAIN_Q , //rw, double + CODEC_PROP_GAIN_RANGE, //ro, gain_range_t + CODEC_PROP_GAIN_NAMES //ro, prop_names_t + }; + + +}} //namespace + +#endif /* INCLUDED_UHD_USRP_CODEC_PROPS_HPP */ diff --git a/host/include/uhd/usrp/dboard_base.hpp b/host/include/uhd/usrp/dboard_base.hpp new file mode 100644 index 000000000..9b75d791f --- /dev/null +++ b/host/include/uhd/usrp/dboard_base.hpp @@ -0,0 +1,117 @@ +// +// 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_DBOARD_BASE_HPP +#define INCLUDED_UHD_USRP_DBOARD_BASE_HPP + +#include <uhd/config.hpp> +#include <uhd/wax.hpp> +#include <uhd/utils/pimpl.hpp> +#include <boost/utility.hpp> +#include <boost/shared_ptr.hpp> +#include <uhd/usrp/dboard_id.hpp> +#include <uhd/usrp/dboard_iface.hpp> + +namespace uhd{ namespace usrp{ + +/*! + * A daughter board dboard_base class for all dboards. + * Only other dboard dboard_base classes should inherit this. + */ +class UHD_API dboard_base : boost::noncopyable{ +public: + typedef boost::shared_ptr<dboard_base> sptr; + /*! + * An opaque type for the dboard constructor args. + * Derived classes should pass the args into the base class, + * but should not deal with the internals of the args. + */ + typedef void * ctor_args_t; + + //structors + dboard_base(ctor_args_t); + virtual ~dboard_base(void); + + //interface + virtual void rx_get(const wax::obj &key, wax::obj &val) = 0; + virtual void rx_set(const wax::obj &key, const wax::obj &val) = 0; + virtual void tx_get(const wax::obj &key, wax::obj &val) = 0; + virtual void tx_set(const wax::obj &key, const wax::obj &val) = 0; + +protected: + std::string get_subdev_name(void); + dboard_iface::sptr get_iface(void); + dboard_id_t get_rx_id(void); + dboard_id_t get_tx_id(void); + +private: + UHD_PIMPL_DECL(impl) _impl; +}; + +/*! + * A xcvr daughter board implements rx and tx methods + * Sub classes for xcvr boards should inherit this. + */ +class UHD_API xcvr_dboard_base : public dboard_base{ +public: + /*! + * Create a new xcvr dboard object, override in subclasses. + */ + xcvr_dboard_base(ctor_args_t); + + virtual ~xcvr_dboard_base(void); +}; + +/*! + * A rx daughter board only implements rx methods. + * Sub classes for rx-only boards should inherit this. + */ +class UHD_API rx_dboard_base : public dboard_base{ +public: + /*! + * Create a new rx dboard object, override in subclasses. + */ + rx_dboard_base(ctor_args_t); + + virtual ~rx_dboard_base(void); + + //override here so the derived classes cannot + void tx_get(const wax::obj &key, wax::obj &val); + void tx_set(const wax::obj &key, const wax::obj &val); +}; + +/*! + * A tx daughter board only implements tx methods. + * Sub classes for rx-only boards should inherit this. + */ +class UHD_API tx_dboard_base : public dboard_base{ +public: + /*! + * Create a new rx dboard object, override in subclasses. + */ + tx_dboard_base(ctor_args_t); + + virtual ~tx_dboard_base(void); + + //override here so the derived classes cannot + void rx_get(const wax::obj &key, wax::obj &val); + void rx_set(const wax::obj &key, const wax::obj &val); +}; + +}} //namespace + +#endif /* INCLUDED_UHD_USRP_DBOARD_BASE_HPP */ diff --git a/host/include/uhd/usrp/dboard_eeprom.hpp b/host/include/uhd/usrp/dboard_eeprom.hpp new file mode 100644 index 000000000..394d71dd6 --- /dev/null +++ b/host/include/uhd/usrp/dboard_eeprom.hpp @@ -0,0 +1,59 @@ +// +// Copyright 2010-2011 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_DBOARD_EEPROM_HPP +#define INCLUDED_UHD_USRP_DBOARD_EEPROM_HPP + +#include <uhd/config.hpp> +#include <uhd/usrp/dboard_id.hpp> +#include <uhd/types/serial.hpp> +#include <string> + +namespace uhd{ namespace usrp{ + +struct UHD_API dboard_eeprom_t{ + + //! The ID for the daughterboard type + dboard_id_t id; + + //! The unique serial number + std::string serial; + + /*! + * Create an empty dboard eeprom struct. + */ + dboard_eeprom_t(void); + + /*! + * Load the object with bytes from the eeprom. + * \param iface the serial interface with i2c + * \param addr the i2c address for the eeprom + */ + void load(i2c_iface &iface, boost::uint8_t addr); + + /*! + * Store the object to bytes in the eeprom. + * \param iface the serial interface with i2c + * \param addr the i2c address for the eeprom + */ + void store(i2c_iface &iface, boost::uint8_t addr); + +}; + +}} //namespace + +#endif /* INCLUDED_UHD_USRP_DBOARD_EEPROM_HPP */ diff --git a/host/include/uhd/usrp/dboard_id.hpp b/host/include/uhd/usrp/dboard_id.hpp new file mode 100644 index 000000000..1fda8182e --- /dev/null +++ b/host/include/uhd/usrp/dboard_id.hpp @@ -0,0 +1,96 @@ +// +// 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_DBOARD_ID_HPP +#define INCLUDED_UHD_USRP_DBOARD_ID_HPP + +#include <uhd/config.hpp> +#include <boost/cstdint.hpp> +#include <boost/operators.hpp> +#include <string> + +namespace uhd{ namespace usrp{ + + class UHD_API dboard_id_t : boost::equality_comparable<dboard_id_t>{ + public: + /*! + * Create a dboard id from an integer. + * \param id the integer representation + */ + dboard_id_t(boost::uint16_t id = 0xffff); + + /*! + * Obtain a dboard id that represents no dboard. + * \return the dboard id with the 0xffff id. + */ + static dboard_id_t none(void); + + /*! + * Create a new dboard id from an integer representation. + * \param uint16 an unsigned 16 bit integer + * \return a new dboard id containing the integer + */ + static dboard_id_t from_uint16(boost::uint16_t uint16); + + /*! + * Get the dboard id represented as an integer. + * \return an unsigned 16 bit integer representation + */ + boost::uint16_t to_uint16(void) const; + + /*! + * Create a new dboard id from a string representation. + * If the string has a 0x prefix, it will be parsed as hex. + * \param string a numeric string, possibly hex + * \return a new dboard id containing the integer + */ + static dboard_id_t from_string(const std::string &string); + + /*! + * Get the dboard id represented as an integer. + * \return a hex string representation with 0x prefix + */ + std::string to_string(void) const; + + /*! + * Get the dboard id represented as a canonical name. + * \return the canonical string representation + */ + std::string to_cname(void) const; + + /*! + * Get the pretty print representation of this dboard id. + * \return a string with the dboard name and id number + */ + std::string to_pp_string(void) const; + + private: + boost::uint16_t _id; //internal representation + }; + + /*! + * Comparator operator overloaded for dboard ids. + * The boost::equality_comparable provides the !=. + * \param lhs the dboard id to the left of the operator + * \param rhs the dboard id to the right of the operator + * \return true when the dboard ids are equal + */ + UHD_API bool operator==(const dboard_id_t &lhs, const dboard_id_t &rhs); + +}} //namespace + +#endif /* INCLUDED_UHD_USRP_DBOARD_ID_HPP */ diff --git a/host/include/uhd/usrp/dboard_iface.hpp b/host/include/uhd/usrp/dboard_iface.hpp new file mode 100644 index 000000000..c5898365d --- /dev/null +++ b/host/include/uhd/usrp/dboard_iface.hpp @@ -0,0 +1,315 @@ +// +// Copyright 2010-2011 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_DBOARD_IFACE_HPP +#define INCLUDED_UHD_USRP_DBOARD_IFACE_HPP + +#include <uhd/config.hpp> +#include <uhd/utils/pimpl.hpp> +#include <uhd/types/serial.hpp> +#include <boost/shared_ptr.hpp> +#include <boost/cstdint.hpp> +#include <string> +#include <vector> + +namespace uhd{ namespace usrp{ + +//! Special properties that differentiate this daughterboard slot +struct UHD_API dboard_iface_special_props_t{ + /*! + * Soft clock divider: + * When a motherboard cannot provided a divided dboard clock, + * it may provided a "soft" divided clock over an FPGA GPIO. + * The implementation must know the type of clock provided. + */ + bool soft_clock_divider; + + /*! + * Mangle i2c addresses: + * When i2c is shared across multiple daugterboard slots, + * the i2c addresses will be mangled on the secondary slot + * to avoid conflicts between slots in the i2c address space. + * The mangling is daguhterboard specific so the implementation + * needs to know whether it should use mangled addresses or not. + */ + bool mangle_i2c_addrs; +}; + +/*! + * The daughter board dboard interface to be subclassed. + * A dboard instance interfaces with the mboard though this api. + * This interface provides i2c, spi, gpio, atr, aux dac/adc access. + * Each mboard should have a specially tailored iface for its dboard. + */ +class UHD_API dboard_iface{ +public: + typedef boost::shared_ptr<dboard_iface> sptr; + typedef dboard_iface_special_props_t special_props_t; + + //! tells the host which unit to use + enum unit_t{ + UNIT_RX = 'r', + UNIT_TX = 't' + }; + + //! possible atr registers + enum atr_reg_t{ + ATR_REG_IDLE = 'i', + ATR_REG_TX_ONLY = 't', + ATR_REG_RX_ONLY = 'r', + ATR_REG_FULL_DUPLEX = 'f' + }; + + //! aux dac selection enums (per unit) + enum aux_dac_t{ + AUX_DAC_A = 'a', + AUX_DAC_B = 'b', + AUX_DAC_C = 'c', + AUX_DAC_D = 'd' + }; + + //! aux adc selection enums (per unit) + enum aux_adc_t{ + AUX_ADC_A = 'a', + AUX_ADC_B = 'b' + }; + + /*! + * Get special properties information for this dboard slot. + * This call helps the dboard code to handle implementation + * differences between different motherboards and dboard slots. + * \return the special properties struct + */ + virtual special_props_t get_special_props(void) = 0; + + /*! + * Write to an aux dac. + * + * \param unit which unit rx or tx + * \param which_dac the dac index 0, 1, 2, 3... + * \param value the value in volts + */ + virtual void write_aux_dac(unit_t unit, aux_dac_t which_dac, double value) = 0; + + /*! + * Read from an aux adc. + * + * \param unit which unit rx or tx + * \param which_adc the adc index 0, 1, 2, 3... + * \return the value in volts + */ + virtual double read_aux_adc(unit_t unit, aux_adc_t which_adc) = 0; + + /*! + * Set a daughterboard output pin control source. + * + * \param unit which unit rx or tx + * \param value 16-bits, 0=GPIO controlled, 1=ATR controlled + * \param mask 16-bits, 0=do not change, 1=change value + */ + virtual void set_pin_ctrl( + unit_t unit, boost::uint16_t value, boost::uint16_t mask = 0xffff + ); + + /*! + * Read back the pin control setting. + * + * \param unit which unit rx or tx + * \return the 16-bit settings value + */ + virtual boost::uint16_t get_pin_ctrl(unit_t unit); + + /*! + * Set a daughterboard ATR register. + * + * \param unit which unit rx or tx + * \param reg which ATR register + * \param value 16-bits, 0=ATR output low, 1=ATR output high + * \param mask 16-bits, 0=do not change, 1=change value + */ + virtual void set_atr_reg( + unit_t unit, atr_reg_t reg, boost::uint16_t value, boost::uint16_t mask = 0xffff + ); + + /*! + * Read back an ATR register setting. + * + * \param unit which unit rx or tx + * \param reg which ATR register + * \return the 16-bit settings value + */ + virtual boost::uint16_t get_atr_reg(unit_t unit, atr_reg_t reg); + + /*! + * Set daughterboard GPIO data direction setting. + * + * \param unit which unit rx or tx + * \param value 16-bits, 0=GPIO input, 1=GPIO output + * \param mask 16-bits, 0=do not change, 1=change value + */ + virtual void set_gpio_ddr( + unit_t unit, boost::uint16_t value, boost::uint16_t mask = 0xffff + ); + + /*! + * Read back the GPIO data direction setting. + * + * \param unit which unit rx or tx + * \return the 16-bit settings value + */ + virtual boost::uint16_t get_gpio_ddr(unit_t unit); + + /*! + * Set daughterboard GPIO pin output setting. + * + * \param unit which unit rx or tx + * \param value 16-bits, 0=GPIO output low, 1=GPIO output high + * \param mask 16-bits, 0=do not change, 1=change value + */ + virtual void set_gpio_out( + unit_t unit, boost::uint16_t value, boost::uint16_t mask = 0xffff + ); + + /*! + * Read back the GPIO pin output setting. + * + * \param unit which unit rx or tx + * \return the 16-bit settings value + */ + virtual boost::uint16_t get_gpio_out(unit_t unit); + + /*! + * Setup the GPIO debug mux. + * + * \param unit which unit rx or tx + * \param which which debug: 0, 1 + */ + virtual void set_gpio_debug(unit_t unit, int which) = 0; + + /*! + * Read daughterboard GPIO pin values. + * + * \param unit which unit rx or tx + * \return the value of the gpio unit + */ + virtual boost::uint16_t read_gpio(unit_t unit) = 0; + + /*! + * Write to an I2C peripheral. + * + * \param addr I2C bus address (7-bits) + * \param bytes the data to write + */ + virtual void write_i2c(boost::uint8_t addr, const byte_vector_t &bytes) = 0; + + /*! + * Read from an I2C peripheral. + * + * \param addr I2C bus address (7-bits) + * \param num_bytes number of bytes to read + * \return the data read if successful, else a zero length string. + */ + virtual byte_vector_t read_i2c(boost::uint8_t addr, size_t num_bytes) = 0; + + /*! + * Write data to SPI bus peripheral. + * + * \param unit which unit, rx or tx + * \param config configuration settings + * \param data the bits to write LSB first + * \param num_bits the number of bits in data + */ + virtual void write_spi( + unit_t unit, + const spi_config_t &config, + boost::uint32_t data, + size_t num_bits + ) = 0; + + /*! + * Read and write data to SPI bus peripheral. + * + * \param unit which unit, rx or tx + * \param config configuration settings + * \param data the bits to write LSB first + * \param num_bits the number of bits in data + * \return the data that was read + */ + virtual boost::uint32_t read_write_spi( + unit_t unit, + const spi_config_t &config, + boost::uint32_t data, + size_t num_bits + ) = 0; + + /*! + * Set the rate of a dboard clock. + * + * \param unit which unit rx or tx + * \param rate the clock rate in Hz + */ + virtual void set_clock_rate(unit_t unit, double rate) = 0; + + /*! + * Get the rate of a dboard clock. + * + * \param unit which unit rx or tx + * \return the clock rate in Hz + */ + virtual double get_clock_rate(unit_t unit) = 0; + + /*! + * Get a list of possible rates for the dboard clock. + * + * \param unit which unit rx or tx + * \return a list of clock rates in Hz + */ + virtual std::vector<double> get_clock_rates(unit_t unit) = 0; + + /*! + * Enable or disable a dboard clock. + * + * \param unit which unit rx or tx + * \param enb true for enabled + */ + virtual void set_clock_enabled(unit_t unit, bool enb) = 0; + + /*! + * Get the rate of the codec. + * For rx, this is the rate the ADC feeds the DSP. + * For tx, this is the rate the DSP feeds the DAC. + * \param unit which unit rx or tx + * \return the codec rate in Hz + */ + virtual double get_codec_rate(unit_t unit) = 0; + +private: + UHD_PIMPL_DECL(impl) _impl; + + virtual void _set_pin_ctrl(unit_t unit, boost::uint16_t value) = 0; + virtual void _set_atr_reg(unit_t unit, atr_reg_t reg, boost::uint16_t value) = 0; + virtual void _set_gpio_ddr(unit_t unit, boost::uint16_t value) = 0; + virtual void _set_gpio_out(unit_t unit, boost::uint16_t value) = 0; + +protected: + dboard_iface(void); + +}; + +}} //namespace + +#endif /* INCLUDED_UHD_USRP_DBOARD_IFACE_HPP */ diff --git a/host/include/uhd/usrp/dboard_manager.hpp b/host/include/uhd/usrp/dboard_manager.hpp new file mode 100644 index 000000000..3c41c65a8 --- /dev/null +++ b/host/include/uhd/usrp/dboard_manager.hpp @@ -0,0 +1,96 @@ +// +// 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_DBOARD_MANAGER_HPP +#define INCLUDED_UHD_USRP_DBOARD_MANAGER_HPP + +#include <uhd/config.hpp> +#include <uhd/utils/props.hpp> +#include <uhd/usrp/dboard_base.hpp> +#include <uhd/usrp/dboard_id.hpp> +#include <boost/utility.hpp> +#include <boost/shared_ptr.hpp> + +namespace uhd{ namespace usrp{ + +/*! + * A daughter board subdev dboard_manager class. + * Create subdev instances for each subdev on a dboard. + * Provide wax::obj access to the subdevs inside. + */ +class UHD_API dboard_manager : boost::noncopyable{ +public: + typedef boost::shared_ptr<dboard_manager> sptr; + + //dboard constructor (each dboard should have a ::make with this signature) + typedef dboard_base::sptr(*dboard_ctor_t)(dboard_base::ctor_args_t); + + /*! + * Register a rx or tx dboard into the system. + * For single subdevice boards, omit subdev_names. + * \param dboard_id the dboard id (rx or tx) + * \param dboard_ctor the dboard constructor function pointer + * \param name the canonical name for the dboard represented + * \param subdev_names the names of the subdevs on this dboard + */ + static void register_dboard( + const dboard_id_t &dboard_id, + dboard_ctor_t dboard_ctor, + const std::string &name, + const prop_names_t &subdev_names = prop_names_t(1, "0") + ); + + /*! + * Register an xcvr dboard into the system. + * For single subdevice boards, omit subdev_names. + * \param rx_dboard_id the rx unit dboard id + * \param tx_dboard_id the tx unit dboard id + * \param dboard_ctor the dboard constructor function pointer + * \param name the canonical name for the dboard represented + * \param subdev_names the names of the subdevs on this dboard + */ + static void register_dboard( + const dboard_id_t &rx_dboard_id, + const dboard_id_t &tx_dboard_id, + dboard_ctor_t dboard_ctor, + const std::string &name, + const prop_names_t &subdev_names = prop_names_t(1, "0") + ); + + /*! + * Make a new dboard manager. + * \param rx_dboard_id the id of the rx dboard + * \param tx_dboard_id the id of the tx dboard + * \param iface the custom dboard interface + * \return an sptr to the new dboard manager + */ + static sptr make( + dboard_id_t rx_dboard_id, + dboard_id_t tx_dboard_id, + dboard_iface::sptr iface + ); + + //dboard manager interface + virtual prop_names_t get_rx_subdev_names(void) = 0; + virtual prop_names_t get_tx_subdev_names(void) = 0; + virtual wax::obj get_rx_subdev(const std::string &subdev_name) = 0; + virtual wax::obj get_tx_subdev(const std::string &subdev_name) = 0; +}; + +}} //namespace + +#endif /* INCLUDED_UHD_USRP_DBOARD_MANAGER_HPP */ diff --git a/host/include/uhd/usrp/dboard_props.hpp b/host/include/uhd/usrp/dboard_props.hpp new file mode 100644 index 000000000..35721ab47 --- /dev/null +++ b/host/include/uhd/usrp/dboard_props.hpp @@ -0,0 +1,42 @@ +// +// Copyright 2010-2011 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_DBOARD_PROPS_HPP +#define INCLUDED_UHD_USRP_DBOARD_PROPS_HPP + +#include <uhd/utils/props.hpp> + +namespace uhd{ namespace usrp{ + + /*! + * Possible device dboard properties: + * A dboard has an id, one or more subdevices, and a codec. + * A dboard is considered to be unidirectional (RX or TX). + */ + enum dboard_prop_t{ + DBOARD_PROP_NAME, //ro, std::string + DBOARD_PROP_SUBDEV, //ro, wax::obj + DBOARD_PROP_SUBDEV_NAMES, //ro, prop_names_t + DBOARD_PROP_DBOARD_EEPROM, //rw, dboard_eeprom_t + DBOARD_PROP_DBOARD_IFACE, //ro, dboard_iface::sptr + DBOARD_PROP_CODEC, //ro, wax::obj + DBOARD_PROP_GAIN_GROUP //ro, gain_group + }; + +}} //namespace + +#endif /* INCLUDED_UHD_USRP_DBOARD_PROPS_HPP */ diff --git a/host/include/uhd/usrp/device_props.hpp b/host/include/uhd/usrp/device_props.hpp new file mode 100644 index 000000000..3c8f7e225 --- /dev/null +++ b/host/include/uhd/usrp/device_props.hpp @@ -0,0 +1,39 @@ +// +// Copyright 2010-2011 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_DEVICE_PROPS_HPP +#define INCLUDED_UHD_USRP_DEVICE_PROPS_HPP + +#include <uhd/utils/props.hpp> + +namespace uhd{ namespace usrp{ + + /*! + * Possible device properties: + * In general, a device will have a single mboard. + * In certain mimo applications, multiple boards + * will be present in the interface for configuration. + */ + enum device_prop_t{ + DEVICE_PROP_NAME, //ro, std::string + DEVICE_PROP_MBOARD, //ro, wax::obj + DEVICE_PROP_MBOARD_NAMES, //ro, prop_names_t + }; + +}} //namespace + +#endif /* INCLUDED_UHD_USRP_DEVICE_PROPS_HPP */ diff --git a/host/include/uhd/usrp/dsp_props.hpp b/host/include/uhd/usrp/dsp_props.hpp new file mode 100644 index 000000000..e68e11deb --- /dev/null +++ b/host/include/uhd/usrp/dsp_props.hpp @@ -0,0 +1,50 @@ +// +// Copyright 2010-2011 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_DSP_PROPS_HPP +#define INCLUDED_UHD_USRP_DSP_PROPS_HPP + +#include <uhd/utils/props.hpp> + +namespace uhd{ namespace usrp{ + + /*! + * Possible device dsp properties: + * A dsp is a black box fpga component found between + * the over-the-wire data and the codec pins. + * + * The host rate can be modified to control resampling. + * Resampling can take the form of decimation, interpolation, + * or more complex fractional resampling techniques. + * As usual, read back the host rate after setting it + * to get the actual rate that was set (implementation dependent). + * + * A dsp can also shift the digital stream in frequency. + * Set the shift property and read it back to get actual shift. + */ + enum dsp_prop_t{ + DSP_PROP_NAME, //ro, std::string + DSP_PROP_OTHERS, //ro, prop_names_t + DSP_PROP_STREAM_CMD, //wo, stream_cmd_t + DSP_PROP_FREQ_SHIFT, //rw, double Hz + DSP_PROP_CODEC_RATE, //ro, double Sps + DSP_PROP_HOST_RATE //rw, double Sps + }; + +}} //namespace + +#endif /* INCLUDED_UHD_USRP_DSP_PROPS_HPP */ diff --git a/host/include/uhd/usrp/dsp_utils.hpp b/host/include/uhd/usrp/dsp_utils.hpp new file mode 100644 index 000000000..5b81ce322 --- /dev/null +++ b/host/include/uhd/usrp/dsp_utils.hpp @@ -0,0 +1,96 @@ +// +// 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_DSP_UTILS_HPP +#define INCLUDED_UHD_USRP_DSP_UTILS_HPP + +#include <uhd/config.hpp> +#include <uhd/types/stream_cmd.hpp> +#include <uhd/usrp/subdev_props.hpp> +#include <boost/cstdint.hpp> + +namespace uhd{ namespace usrp{ + +namespace dsp_type1{ + + /*! + * Calculate the rx mux word from properties. + * \param subdev_conn the subdev connection type + * \return the 32-bit rx mux control word + */ + UHD_API boost::uint32_t calc_rx_mux_word(subdev_conn_t subdev_conn); + + /*! + * Calculate the tx mux word from properties. + * \param subdev_conn the subdev connection type + * \return the 32-bit tx mux control word + */ + UHD_API boost::uint32_t calc_tx_mux_word(subdev_conn_t subdev_conn); + + /*! + * Calculate the cordic word from the frequency and clock rate. + * The frequency will be set to the actual (possible) frequency. + * + * \param freq the requested frequency in Hz + * \param codec_rate the dsp codec rate in Hz + * \return the 32-bit cordic control word + */ + UHD_API boost::uint32_t calc_cordic_word_and_update( + double &freq, double codec_rate + ); + + /*! + * Calculate the CIC filter word from the rate. + * Check if requested decim/interp rate is: + * multiple of 4, enable two halfband filters + * multiple of 2, enable one halfband filter + * handle remainder in CIC + * + * \param rate the requested rate in Sps + * \return the 32-bit cic filter control word + */ + UHD_API boost::uint32_t calc_cic_filter_word(unsigned rate); + + /*! + * Calculate the IQ scale factor word from I and Q components. + * \param i the I component of the scalar + * \param q the Q component of the scalar + * \return the 32-bit scale factor control word + */ + UHD_API boost::uint32_t calc_iq_scale_word( + boost::int16_t i, boost::int16_t q + ); + + /*! + * Calculate the IQ scale factor word from the rate. + * \param rate the requested rate in Sps + * \return the 32-bit scale factor control word + */ + UHD_API boost::uint32_t calc_iq_scale_word(unsigned rate); + + /*! + * Calculate the stream command word from the stream command struct. + * \param stream_cmd the requested stream command with mode, flags, timestamp + * \return the 32-bit stream command word + */ + UHD_API boost::uint32_t calc_stream_cmd_word(const stream_cmd_t &stream_cmd); + +} //namespace dsp_type1 + +}} //namespace + +#endif /* INCLUDED_UHD_USRP_DSP_UTILS_HPP */ diff --git a/host/include/uhd/usrp/gps_ctrl.hpp b/host/include/uhd/usrp/gps_ctrl.hpp new file mode 100644 index 000000000..74f984ee0 --- /dev/null +++ b/host/include/uhd/usrp/gps_ctrl.hpp @@ -0,0 +1,56 @@ +// +// 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_GPS_CTRL_HPP +#define INCLUDED_GPS_CTRL_HPP + +#include <boost/shared_ptr.hpp> +#include <boost/utility.hpp> +#include <boost/function.hpp> +#include <boost/date_time/posix_time/posix_time_types.hpp> + +using namespace boost::posix_time; + +typedef boost::function<void(std::string)> gps_send_fn_t; +typedef boost::function<std::string(void)> gps_recv_fn_t; + +class gps_ctrl : boost::noncopyable{ +public: + typedef boost::shared_ptr<gps_ctrl> sptr; + + /*! + * Make a GPS config for Jackson Labs or generic NMEA GPS devices + */ + static sptr make(gps_send_fn_t, gps_recv_fn_t); + + /*! + * Get the current GPS time and date + * \return current GPS time and date as boost::posix_time::ptime object + */ + virtual ptime get_time(void) = 0; + + /*! + * Tell you if there's a supported GPS connected or not + * \return true if a supported GPS is connected + */ + virtual bool gps_detected(void) = 0; + + //TODO: other fun things you can do with a GPS. + +}; + +#endif /* INCLUDED_GPS_CTRL_HPP */ diff --git a/host/include/uhd/usrp/mboard_eeprom.hpp b/host/include/uhd/usrp/mboard_eeprom.hpp new file mode 100644 index 000000000..52363b95c --- /dev/null +++ b/host/include/uhd/usrp/mboard_eeprom.hpp @@ -0,0 +1,65 @@ +// +// 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_MBOARD_EEPROM_HPP +#define INCLUDED_UHD_USRP_MBOARD_EEPROM_HPP + +#include <uhd/config.hpp> +#include <uhd/types/dict.hpp> +#include <uhd/types/serial.hpp> +#include <string> + +namespace uhd{ namespace usrp{ + + /*! + * The motherboard EEPROM object: + * Knows how to read and write the EEPROM for various USRPs. + * The class inherits from a string, string dictionary. + * Use the dictionary interface to get and set values. + * Commit to the EEPROM to save changed settings. + */ + struct UHD_API mboard_eeprom_t : uhd::dict<std::string, std::string>{ + + //! Possible EEPROM maps types + enum map_type{ + MAP_N100, + MAP_B000, + MAP_E100 + }; + + //! Make a new empty mboard eeprom + mboard_eeprom_t(void); + + /*! + * Make a new mboard EEPROM handler. + * \param iface the interface to i2c + * \param map the map type enum + */ + mboard_eeprom_t(i2c_iface &iface, map_type map); + + /*! + * Write the contents of this object to the EEPROM. + * \param iface the interface to i2c + * \param map the map type enum + */ + void commit(i2c_iface &iface, map_type map); + + }; + +}} //namespace + +#endif /* INCLUDED_UHD_USRP_MBOARD_EEPROM_HPP */ diff --git a/host/include/uhd/usrp/mboard_iface.hpp b/host/include/uhd/usrp/mboard_iface.hpp new file mode 100644 index 000000000..784fbc7c5 --- /dev/null +++ b/host/include/uhd/usrp/mboard_iface.hpp @@ -0,0 +1,85 @@ +// +// Copyright 2010-2011 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_MBOARD_IFACE_HPP +#define INCLUDED_UHD_USRP_MBOARD_IFACE_HPP + +#include <uhd/types/serial.hpp> +#include <uhd/usrp/mboard_eeprom.hpp> +#include <boost/shared_ptr.hpp> +#include <boost/utility.hpp> +#include <boost/cstdint.hpp> +#include <utility> +#include <string> + +namespace uhd{ namespace usrp{ + +/*! + * The mboard interface class: + * Provides a set of functions to implementation layer. + * Including spi, peek, poke, control... + */ +class mboard_iface : public uhd::i2c_iface, public uhd::spi_iface { +public: + typedef boost::shared_ptr<mboard_iface> sptr; + /*! + * Write a register (32 bits) + * \param addr the address + * \param data the 32bit data + */ + virtual void poke32(boost::uint32_t addr, boost::uint32_t data) = 0; + + /*! + * Read a register (32 bits) + * \param addr the address + * \return the 32bit data + */ + virtual boost::uint32_t peek32(boost::uint32_t addr) = 0; + + /*! + * Write a register (16 bits) + * \param addr the address + * \param data the 16bit data + */ + virtual void poke16(boost::uint32_t addr, boost::uint16_t data) = 0; + + /*! + * Read a register (16 bits) + * \param addr the address + * \return the 16bit data + */ + virtual boost::uint16_t peek16(boost::uint32_t addr) = 0; + + /*! + * Write to a serial port. + * \param dev which UART to write to + * \param buf the data to write + */ + virtual void write_uart(boost::uint8_t dev, const std::string &buf) = 0; + + /*! + * Read from a serial port. + * \param dev which UART to read from + * \return the data read from the serial port + */ + virtual std::string read_uart(boost::uint8_t dev) = 0; + +}; + +}} + +#endif //INCLUDED_UHD_USRP_DBOARD_IFACE_HPP diff --git a/host/include/uhd/usrp/mboard_props.hpp b/host/include/uhd/usrp/mboard_props.hpp new file mode 100644 index 000000000..a2580954e --- /dev/null +++ b/host/include/uhd/usrp/mboard_props.hpp @@ -0,0 +1,56 @@ +// +// Copyright 2010-2011 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_MBOARD_PROPS_HPP +#define INCLUDED_UHD_USRP_MBOARD_PROPS_HPP + +#include <uhd/utils/props.hpp> + +namespace uhd{ namespace usrp{ + + /*! + * Possible device mboard properties: + * The general mboard properties are listed below. + * Custom properties can be identified with a string + * and discovered though the others property. + */ + enum mboard_prop_t{ + MBOARD_PROP_NAME, //ro, std::string + MBOARD_PROP_OTHERS, //ro, prop_names_t + MBOARD_PROP_SENSOR, //ro, sensor_value_t + MBOARD_PROP_SENSOR_NAMES, //ro, prop_names_t + MBOARD_PROP_CLOCK_RATE, //rw, double + MBOARD_PROP_RX_DSP, //ro, wax::obj + MBOARD_PROP_RX_DSP_NAMES, //ro, prop_names_t + MBOARD_PROP_TX_DSP, //ro, wax::obj + MBOARD_PROP_TX_DSP_NAMES, //ro, prop_names_t + MBOARD_PROP_RX_DBOARD, //ro, wax::obj + MBOARD_PROP_RX_DBOARD_NAMES, //ro, prop_names_t + MBOARD_PROP_TX_DBOARD, //ro, wax::obj + MBOARD_PROP_TX_DBOARD_NAMES, //ro, prop_names_t + MBOARD_PROP_RX_SUBDEV_SPEC, //rw, subdev_spec_t + MBOARD_PROP_TX_SUBDEV_SPEC, //rw, subdev_spec_t + MBOARD_PROP_CLOCK_CONFIG, //rw, clock_config_t + MBOARD_PROP_TIME_NOW, //rw, time_spec_t + MBOARD_PROP_TIME_PPS, //wo, time_spec_t + MBOARD_PROP_EEPROM_MAP, //wr, mboard_eeprom_t + MBOARD_PROP_IFACE, //ro, mboard_iface::sptr + }; + +}} //namespace + +#endif /* INCLUDED_UHD_USRP_MBOARD_PROPS_HPP */ diff --git a/host/include/uhd/usrp/misc_utils.hpp b/host/include/uhd/usrp/misc_utils.hpp new file mode 100644 index 000000000..37860a1a5 --- /dev/null +++ b/host/include/uhd/usrp/misc_utils.hpp @@ -0,0 +1,71 @@ +// +// 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_MISC_UTILS_HPP +#define INCLUDED_UHD_USRP_MISC_UTILS_HPP + +#include <uhd/config.hpp> +#include <uhd/wax.hpp> +#include <uhd/usrp/dboard_id.hpp> +#include <uhd/usrp/subdev_spec.hpp> +#include <uhd/utils/gain_group.hpp> + +namespace uhd{ namespace usrp{ + + /*! + * Different policies for gain group prioritization. + */ + enum gain_group_policy_t{ + GAIN_GROUP_POLICY_RX = 'R', + GAIN_GROUP_POLICY_TX = 'T' + }; + + /*! + * Create a gain group that represents the subdevice and its codec. + * \param dboard_id the dboard id for this subdevice + * \param subdev the object with subdevice properties + * \param codec the object with codec properties + * \param gain_group_policy the policy to use + */ + UHD_API gain_group::sptr make_gain_group( + const dboard_id_t &dboard_id, + wax::obj subdev, wax::obj codec, + gain_group_policy_t gain_group_policy + ); + + /*! + * Verify the rx subdevice specification. + * If the subdev spec if empty, automatically fill it. + * \param subdev_spec the subdev spec to verify/fill + * \param mboard the motherboard properties object + * \throw exception when the subdev spec is invalid + */ + UHD_API void verify_rx_subdev_spec(subdev_spec_t &subdev_spec, wax::obj mboard); + + /*! + * Verify the tx subdevice specification. + * If the subdev spec if empty, automatically fill it. + * \param subdev_spec the subdev spec to verify/fill + * \param mboard the motherboard properties object + * \throw exception when the subdev spec is invalid + */ + UHD_API void verify_tx_subdev_spec(subdev_spec_t &subdev_spec, wax::obj mboard); + +}} //namespace + +#endif /* INCLUDED_UHD_USRP_MISC_UTILS_HPP */ + diff --git a/host/include/uhd/usrp/multi_usrp.hpp b/host/include/uhd/usrp/multi_usrp.hpp new file mode 100644 index 000000000..b161d1278 --- /dev/null +++ b/host/include/uhd/usrp/multi_usrp.hpp @@ -0,0 +1,654 @@ +// +// Copyright 2010-2011 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_MULTI_USRP_HPP +#define INCLUDED_UHD_USRP_MULTI_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_request.hpp> +#include <uhd/types/tune_result.hpp> +#include <uhd/types/sensors.hpp> +#include <uhd/usrp/subdev_spec.hpp> +#include <uhd/usrp/dboard_iface.hpp> +#include <uhd/usrp/mboard_iface.hpp> +#include <boost/shared_ptr.hpp> +#include <boost/utility.hpp> +#include <vector> + +namespace uhd{ namespace usrp{ + +/*! + * The Multi-USRP device class: + * + * This class facilitates ease-of-use for most use-case scenarios. + * The wrapper provides convenience functions to tune the devices, + * set the dboard gains, antennas, filters, and other properties. + * This class can be used to interface with a single USRP with + * one or more channels, or multiple USRPs in a homogeneous setup. + * All members take an optional parameter for board number or channel number. + * In the single device, single channel case, these parameters can be unspecified. + * + * When using a single device with multiple channels: + * - Channel mapping is determined by the subdevice specifications + * - All channels share a common RX sample rate + * - All channels share a common TX sample rate + * + * When using multiple devices in a configuration: + * - Channel mapping is determined by the device address arguments + * - All boards share a common RX sample rate + * - All boards share a common TX sample rate + * - All boards share a common RX subdevice specification size + * - All boards share a common TX subdevice specification size + * - All boards must have synchronized times (see the set_time_*() calls) + * + * Example to setup channel mapping for multiple devices: + * <pre> + * + * //create a multi_usrp with two boards in the configuration + * device_addr_t dev_addr; + * dev_addr["addr0"] = "192.168.10.2" + * dev_addr["addr1"] = "192.168.10.3"; + * multi_usrp::sptr dev = multi_usrp::make(dev_addr); + * + * //set the board on 10.2 to use the A RX subdevice (RX channel 0) + * dev->set_rx_subdev_spec(":A", 0); + * + * //set the board on 10.3 to use the B RX subdevice (RX channel 1) + * dev->set_rx_subdev_spec(":B", 1); + * + * //set both boards to use the AB TX subdevice (TX channels 0 and 1) + * dev->set_tx_subdev_spec(":AB", multi_usrp::ALL_MBOARDS); + * + * //now that all the channels are mapped, continue with configuration... + * + * </pre> + */ +class UHD_API multi_usrp : boost::noncopyable{ +public: + typedef boost::shared_ptr<multi_usrp> sptr; + + //! A wildcard motherboard index + static const size_t ALL_MBOARDS = size_t(~0); + + //! A wildcard channel index + static const size_t ALL_CHANS = size_t(~0); + + //! A wildcard gain element name + static const std::string ALL_GAINS; + + /*! + * Make a new multi usrp from the device address. + * \param dev_addr the device address + * \return a new single 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 single usrp + */ + virtual device::sptr get_device(void) = 0; + + /******************************************************************* + * Mboard methods + ******************************************************************/ + + /*! + * Set the master clock rate. + * This controls the rate of the clock that feeds the FPGA DSP. + * On some devices, this re-tunes the clock to the specified rate. + * If the specified rate is not available, this method will throw. + * On other devices, this method notifies the software of the rate, + * but requires the the user has made the necessary hardware change. + * \param rate the new master clock rate in Hz + * \param mboard the motherboard index 0 to M-1 + */ + virtual void set_master_clock_rate(double rate, size_t mboard = ALL_MBOARDS) = 0; + + /*! + * Get the master clock rate. + * \param mboard the motherboard index 0 to M-1 + * \return the master clock rate in Hz. + */ + virtual double get_master_clock_rate(size_t mboard = 0) = 0; + + /*! + * Get a printable summary for this USRP configuration. + * \return a printable string + */ + virtual std::string get_pp_string(void) = 0; + + /*! + * Get canonical name for this USRP motherboard. + * \param mboard which motherboard to query + * \return a string representing the name + */ + virtual std::string get_mboard_name(size_t mboard = 0) = 0; + + /*! + * Get the current time in the usrp time registers. + * \param mboard which motherboard to query + * \return a timespec representing current usrp time + */ + virtual time_spec_t get_time_now(size_t mboard = 0) = 0; + + /*! + * Get the time when the last pps pulse occured. + * \param mboard which motherboard to query + * \return a timespec representing the last pps + */ + virtual time_spec_t get_time_last_pps(size_t mboard = 0) = 0; + + /*! + * Sets the time registers on the usrp immediately. + * + * If only one MIMO master is present in your configuration, set_time_now is + * safe to use because the slave's time automatically follows the master's time. + * Otherwise, this call cannot set the time synchronously across multiple devices. + * Please use the set_time_next_pps or set_time_unknown_pps calls with a PPS signal. + * + * \param time_spec the time to latch into the usrp device + * \param mboard the motherboard index 0 to M-1 + */ + virtual void set_time_now(const time_spec_t &time_spec, size_t mboard = ALL_MBOARDS) = 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. + * + * 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 2-step process, and will take at most 2 seconds to complete. + * Upon completion, the times will be synchronized to the time provided. + * + * - Step1: wait for the last pps time to transition to catch the edge + * - Step2: set the time at the next pps (synchronous for all boards) + * + * \param time_spec the time to latch at the next pps after catching the edge + */ + virtual void set_time_unknown_pps(const time_spec_t &time_spec) = 0; + + /*! + * Are the times across all motherboards in this configuration synchronized? + * Checks that all time registers are approximately close but not exact, + * given that the RTT may varying for a control packet transaction. + * \return true when all motherboards time registers are in sync + */ + virtual bool get_time_synchronized(void) = 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. + * + * With multiple devices, the first stream command in a chain of commands + * should have a time spec in the near future and stream_now = false; + * to ensure that the packets can be aligned by their time specs. + * + * \param stream_cmd the stream command to issue + * \param chan the channel index 0 to N-1 + */ + virtual void issue_stream_cmd(const stream_cmd_t &stream_cmd, size_t chan = ALL_CHANS) = 0; + + /*! + * Set the clock configuration for the usrp device. + * This tells the usrp how to get a 10Mhz reference and PPS clock. + * See the documentation for clock_config_t for more info. + * \param clock_config the clock configuration to set + * \param mboard which motherboard to set the config + */ + virtual void set_clock_config(const clock_config_t &clock_config, size_t mboard = ALL_MBOARDS) = 0; + + /*! + * Get the number of USRP motherboards in this configuration. + */ + virtual size_t get_num_mboards(void) = 0; + + /*! + * Get a motherboard sensor value. + * \param name the name of the sensor + * \param mboard the motherboard index 0 to M-1 + * \return a sensor value object + */ + virtual sensor_value_t get_mboard_sensor(const std::string &name, size_t mboard = 0) = 0; + + /*! + * Get a list of possible motherboard sensor names. + * \param mboard the motherboard index 0 to M-1 + * \return a vector of sensor names + */ + virtual std::vector<std::string> get_mboard_sensor_names(size_t mboard = 0) = 0; + + /*! + * Get a handle to the mboard_iface object which controls peripheral access. + * \return a mboard_iface::sptr object + */ + virtual mboard_iface::sptr get_mboard_iface(size_t mboard) = 0; + + /******************************************************************* + * RX methods + ******************************************************************/ + /*! + * Set the RX subdevice specification: + * The subdev spec maps a physical part of a daughter-board to a channel number. + * Set the subdev spec before calling into any methods with a channel number. + * The subdev spec must be the same size across all motherboards. + * \param spec the new subdevice specification + * \param mboard the motherboard index 0 to M-1 + */ + virtual void set_rx_subdev_spec(const uhd::usrp::subdev_spec_t &spec, size_t mboard = ALL_MBOARDS) = 0; + + /*! + * Get the RX subdevice specification. + * \param mboard the motherboard index 0 to M-1 + * \return the subdevice specification in use + */ + virtual uhd::usrp::subdev_spec_t get_rx_subdev_spec(size_t mboard = 0) = 0; + + /*! + * Get the number of RX channels in this configuration. + * This is the number of USRPs times the number of RX channels per board, + * where the number of RX channels per board is homogeneous among all USRPs. + */ + virtual size_t get_rx_num_channels(void) = 0; + + /*! + * Get the name of the RX subdevice. + * \param chan the channel index 0 to N-1 + * \return the subdevice name + */ + virtual std::string get_rx_subdev_name(size_t chan = 0) = 0; + + /*! + * Set the RX sample rate. + * \param rate the rate in Sps + * \param chan the channel index 0 to N-1 + */ + virtual void set_rx_rate(double rate, size_t chan = ALL_CHANS) = 0; + + /*! + * Gets the RX sample rate. + * \param chan the channel index 0 to N-1 + * \return the rate in Sps + */ + virtual double get_rx_rate(size_t chan = 0) = 0; + + /*! + * Set the RX center frequency. + * \param tune_request tune request instructions + * \param chan the channel index 0 to N-1 + * \return a tune result object + */ + virtual tune_result_t set_rx_freq( + const tune_request_t &tune_request, size_t chan = 0 + ) = 0; + + /*! + * Get the RX center frequency. + * \param chan the channel index 0 to N-1 + * \return the frequency in Hz + */ + virtual double get_rx_freq(size_t chan = 0) = 0; + + /*! + * Get the RX center frequency range. + * \param chan the channel index 0 to N-1 + * \return a frequency range object + */ + virtual freq_range_t get_rx_freq_range(size_t chan = 0) = 0; + + /*! + * Set the RX gain value for the specified gain element. + * For an empty name, distribute across all gain elements. + * \param gain the gain in dB + * \param name the name of the gain element + * \param chan the channel index 0 to N-1 + */ + virtual void set_rx_gain(double gain, const std::string &name, size_t chan = 0) = 0; + + //! A convenience wrapper for setting overall RX gain + void set_rx_gain(double gain, size_t chan = 0){ + return this->set_rx_gain(gain, ALL_GAINS, chan); + } + + /*! + * Get the RX gain value for the specified gain element. + * For an empty name, sum across all gain elements. + * \param name the name of the gain element + * \param chan the channel index 0 to N-1 + * \return the gain in dB + */ + virtual double get_rx_gain(const std::string &name, size_t chan = 0) = 0; + + //! A convenience wrapper for getting overall RX gain + double get_rx_gain(size_t chan = 0){ + return this->get_rx_gain(ALL_GAINS, chan); + } + + /*! + * Get the RX gain range for the specified gain element. + * For an empty name, calculate the overall gain range. + * \param name the name of the gain element + * \param chan the channel index 0 to N-1 + * \return a gain range object + */ + virtual gain_range_t get_rx_gain_range(const std::string &name, size_t chan = 0) = 0; + + //! A convenience wrapper for getting overall RX gain range + gain_range_t get_rx_gain_range(size_t chan = 0){ + return this->get_rx_gain_range(ALL_GAINS, chan); + } + + /*! + * Get the names of the gain elements in the RX chain. + * Gain elements are ordered from antenna to FPGA. + * \param chan the channel index 0 to N-1 + * \return a vector of gain element names + */ + virtual std::vector<std::string> get_rx_gain_names(size_t chan = 0) = 0; + + /*! + * Select the RX antenna on the subdevice. + * \param ant the antenna name + * \param chan the channel index 0 to N-1 + */ + virtual void set_rx_antenna(const std::string &ant, size_t chan = 0) = 0; + + /*! + * Get the selected RX antenna on the subdevice. + * \param chan the channel index 0 to N-1 + * \return the antenna name + */ + virtual std::string get_rx_antenna(size_t chan = 0) = 0; + + /*! + * Get a list of possible RX antennas on the subdevice. + * \param chan the channel index 0 to N-1 + * \return a vector of antenna names + */ + virtual std::vector<std::string> get_rx_antennas(size_t chan = 0) = 0; + + /*! + * Get the locked status of the LO on the subdevice. + * \param chan the channel index 0 to N-1 + * \return true for locked + */ + UHD_DEPRECATED bool get_rx_lo_locked(size_t chan = 0){ + return this->get_rx_sensor("lo_locked", chan).to_bool(); + } + + /*! + * Set the RX bandwidth on the subdevice. + * \param bandwidth the bandwidth in Hz + * \param chan the channel index 0 to N-1 + */ + virtual void set_rx_bandwidth(double bandwidth, size_t chan = 0) = 0; + + /*! + * Get the RX bandwidth on the subdevice. + * \param chan the channel index 0 to N-1 + * \return the bandwidth in Hz + */ + virtual double get_rx_bandwidth(size_t chan = 0) = 0; + + /*! + * Read the RSSI value on the RX subdevice. + * \param chan the channel index 0 to N-1 + * \return the rssi in dB + * \throw exception if RSSI readback not supported + */ + UHD_DEPRECATED double read_rssi(size_t chan = 0){ + return this->get_rx_sensor("rssi", chan).to_real(); + } + + /*! + * Get the dboard interface object for the RX subdevice. + * The dboard interface gives access to GPIOs, SPI, I2C, low-speed ADC and DAC. + * Use at your own risk! + * \param chan the channel index 0 to N-1 + * \return the dboard interface sptr + */ + virtual dboard_iface::sptr get_rx_dboard_iface(size_t chan = 0) = 0; + + /*! + * Get an RX subdevice sensor value. + * \param name the name of the sensor + * \param chan the channel index 0 to N-1 + * \return a sensor value object + */ + virtual sensor_value_t get_rx_sensor(const std::string &name, size_t chan = 0) = 0; + + /*! + * Get a list of possible RX subdevice sensor names. + * \param chan the channel index 0 to N-1 + * \return a vector of sensor names + */ + virtual std::vector<std::string> get_rx_sensor_names(size_t chan = 0) = 0; + + /******************************************************************* + * TX methods + ******************************************************************/ + /*! + * Set the TX subdevice specification: + * The subdev spec maps a physical part of a daughter-board to a channel number. + * Set the subdev spec before calling into any methods with a channel number. + * The subdev spec must be the same size across all motherboards. + * \param spec the new subdevice specification + * \param mboard the motherboard index 0 to M-1 + */ + virtual void set_tx_subdev_spec(const uhd::usrp::subdev_spec_t &spec, size_t mboard = ALL_MBOARDS) = 0; + + /*! + * Get the TX subdevice specification. + * \param mboard the motherboard index 0 to M-1 + * \return the subdevice specification in use + */ + virtual uhd::usrp::subdev_spec_t get_tx_subdev_spec(size_t mboard = 0) = 0; + + /*! + * Get the number of TX channels in this configuration. + * This is the number of USRPs times the number of TX channels per board, + * where the number of TX channels per board is homogeneous among all USRPs. + */ + virtual size_t get_tx_num_channels(void) = 0; + + /*! + * Get the name of the TX subdevice. + * \param chan the channel index 0 to N-1 + * \return the subdevice name + */ + virtual std::string get_tx_subdev_name(size_t chan = 0) = 0; + + /*! + * Set the TX sample rate. + * \param rate the rate in Sps + * \param chan the channel index 0 to N-1 + */ + virtual void set_tx_rate(double rate, size_t chan = ALL_CHANS) = 0; + + /*! + * Gets the TX sample rate. + * \param chan the channel index 0 to N-1 + * \return the rate in Sps + */ + virtual double get_tx_rate(size_t chan = 0) = 0; + + /*! + * Set the TX center frequency. + * \param tune_request tune request instructions + * \param chan the channel index 0 to N-1 + * \return a tune result object + */ + virtual tune_result_t set_tx_freq( + const tune_request_t &tune_request, size_t chan = 0 + ) = 0; + + /*! + * Get the TX center frequency. + * \param chan the channel index 0 to N-1 + * \return the frequency in Hz + */ + virtual double get_tx_freq(size_t chan = 0) = 0; + + /*! + * Get the TX center frequency range. + * \param chan the channel index 0 to N-1 + * \return a frequency range object + */ + virtual freq_range_t get_tx_freq_range(size_t chan = 0) = 0; + + /*! + * Set the TX gain value for the specified gain element. + * For an empty name, distribute across all gain elements. + * \param gain the gain in dB + * \param name the name of the gain element + * \param chan the channel index 0 to N-1 + */ + virtual void set_tx_gain(double gain, const std::string &name, size_t chan = 0) = 0; + + //! A convenience wrapper for setting overall TX gain + void set_tx_gain(double gain, size_t chan = 0){ + return this->set_tx_gain(gain, ALL_GAINS, chan); + } + + /*! + * Get the TX gain value for the specified gain element. + * For an empty name, sum across all gain elements. + * \param name the name of the gain element + * \param chan the channel index 0 to N-1 + * \return the gain in dB + */ + virtual double get_tx_gain(const std::string &name, size_t chan = 0) = 0; + + //! A convenience wrapper for getting overall TX gain + double get_tx_gain(size_t chan = 0){ + return this->get_tx_gain(ALL_GAINS, chan); + } + + /*! + * Get the TX gain range for the specified gain element. + * For an empty name, calculate the overall gain range. + * \param name the name of the gain element + * \param chan the channel index 0 to N-1 + * \return a gain range object + */ + virtual gain_range_t get_tx_gain_range(const std::string &name, size_t chan = 0) = 0; + + //! A convenience wrapper for getting overall TX gain range + gain_range_t get_tx_gain_range(size_t chan = 0){ + return this->get_tx_gain_range(ALL_GAINS, chan); + } + + /*! + * Get the names of the gain elements in the TX chain. + * Gain elements are ordered from antenna to FPGA. + * \param chan the channel index 0 to N-1 + * \return a vector of gain element names + */ + virtual std::vector<std::string> get_tx_gain_names(size_t chan = 0) = 0; + + /*! + * Select the TX antenna on the subdevice. + * \param ant the antenna name + * \param chan the channel index 0 to N-1 + */ + virtual void set_tx_antenna(const std::string &ant, size_t chan = 0) = 0; + + /*! + * Get the selected TX antenna on the subdevice. + * \param chan the channel index 0 to N-1 + * \return the antenna name + */ + virtual std::string get_tx_antenna(size_t chan = 0) = 0; + + /*! + * Get a list of possible TX antennas on the subdevice. + * \param chan the channel index 0 to N-1 + * \return a vector of antenna names + */ + virtual std::vector<std::string> get_tx_antennas(size_t chan = 0) = 0; + + /*! + * Get the locked status of the LO on the subdevice. + * \param chan the channel index 0 to N-1 + * \return true for locked + */ + UHD_DEPRECATED bool get_tx_lo_locked(size_t chan = 0){ + return this->get_tx_sensor("lo_locked", chan).to_bool(); + } + + /*! + * Set the TX bandwidth on the subdevice. + * \param bandwidth the bandwidth in Hz + * \param chan the channel index 0 to N-1 + */ + virtual void set_tx_bandwidth(double bandwidth, size_t chan = 0) = 0; + + /*! + * Get the TX bandwidth on the subdevice. + * \param chan the channel index 0 to N-1 + * \return the bandwidth in Hz + */ + virtual double get_tx_bandwidth(size_t chan = 0) = 0; + + /*! + * Get the dboard interface object for the TX subdevice. + * The dboard interface gives access to GPIOs, SPI, I2C, low-speed ADC and DAC. + * Use at your own risk! + * \param chan the channel index 0 to N-1 + * \return the dboard interface sptr + */ + virtual dboard_iface::sptr get_tx_dboard_iface(size_t chan = 0) = 0; + + /*! + * Get an TX subdevice sensor value. + * \param name the name of the sensor + * \param chan the channel index 0 to N-1 + * \return a sensor value object + */ + virtual sensor_value_t get_tx_sensor(const std::string &name, size_t chan = 0) = 0; + + /*! + * Get a list of possible TX subdevice sensor names. + * \param chan the channel index 0 to N-1 + * \return a vector of sensor names + */ + virtual std::vector<std::string> get_tx_sensor_names(size_t chan = 0) = 0; +}; + +}} + +#endif /* INCLUDED_UHD_USRP_MULTI_USRP_HPP */ diff --git a/host/include/uhd/usrp/single_usrp.hpp b/host/include/uhd/usrp/single_usrp.hpp new file mode 100644 index 000000000..0520db162 --- /dev/null +++ b/host/include/uhd/usrp/single_usrp.hpp @@ -0,0 +1,30 @@ +// +// Copyright 2010-2011 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_SINGLE_USRP_HPP +#define INCLUDED_UHD_USRP_SINGLE_USRP_HPP + +#include <uhd/usrp/multi_usrp.hpp> + +namespace uhd{ namespace usrp{ + + //! Multi-USRP is a superset of Single-USRP + typedef multi_usrp single_usrp; + +}} + +#endif /* INCLUDED_UHD_USRP_SINGLE_USRP_HPP */ diff --git a/host/include/uhd/usrp/subdev_props.hpp b/host/include/uhd/usrp/subdev_props.hpp new file mode 100644 index 000000000..40b339703 --- /dev/null +++ b/host/include/uhd/usrp/subdev_props.hpp @@ -0,0 +1,64 @@ +// +// Copyright 2010-2011 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_SUBDEV_PROPS_HPP +#define INCLUDED_UHD_USRP_SUBDEV_PROPS_HPP + +#include <uhd/utils/props.hpp> + +namespace uhd{ namespace usrp{ + + /*! + * Possible subdev connection types: + * + * A complex subdevice is physically connected to both channels, + * which may be connected in one of two ways: IQ or QI (swapped). + * + * A real subdevice is only physically connected one channel, + * either only the I channel or only the Q channel. + */ + enum subdev_conn_t{ + SUBDEV_CONN_COMPLEX_IQ = 'C', + SUBDEV_CONN_COMPLEX_QI = 'c', + SUBDEV_CONN_REAL_I = 'R', + SUBDEV_CONN_REAL_Q = 'r' + }; + + /*! + * Possible device subdev properties + */ + enum subdev_prop_t{ + SUBDEV_PROP_NAME, //ro, std::string + SUBDEV_PROP_OTHERS, //ro, prop_names_t + SUBDEV_PROP_SENSOR, //ro, sensor_value_t + SUBDEV_PROP_SENSOR_NAMES, //ro, prop_names_t + SUBDEV_PROP_GAIN, //rw, double + SUBDEV_PROP_GAIN_RANGE, //ro, gain_range_t + SUBDEV_PROP_GAIN_NAMES, //ro, prop_names_t + SUBDEV_PROP_FREQ, //rw, double + SUBDEV_PROP_FREQ_RANGE, //ro, freq_range_t + SUBDEV_PROP_ANTENNA, //rw, std::string + SUBDEV_PROP_ANTENNA_NAMES, //ro, prop_names_t + SUBDEV_PROP_CONNECTION, //ro, subdev_conn_t + SUBDEV_PROP_ENABLED, //rw, bool + SUBDEV_PROP_USE_LO_OFFSET, //ro, bool + SUBDEV_PROP_BANDWIDTH //rw, double + }; + +}} //namespace + +#endif /* INCLUDED_UHD_USRP_SUBDEV_PROPS_HPP */ diff --git a/host/include/uhd/usrp/subdev_spec.hpp b/host/include/uhd/usrp/subdev_spec.hpp new file mode 100644 index 000000000..b189724c9 --- /dev/null +++ b/host/include/uhd/usrp/subdev_spec.hpp @@ -0,0 +1,96 @@ +// +// 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_SUBDEV_SPEC_HPP +#define INCLUDED_UHD_USRP_SUBDEV_SPEC_HPP + +#include <uhd/config.hpp> +#include <boost/operators.hpp> +#include <vector> +#include <string> + +namespace uhd{ namespace usrp{ + + /*! + * A subdevice specification (daughterboard slot, subdevice) name pairing. + */ + struct UHD_API subdev_spec_pair_t : boost::equality_comparable<subdev_spec_pair_t>{ + //! The daughterboard slot name + std::string db_name; + + //! The subdevice name + std::string sd_name; + + /*! + * Create a new subdevice specification pair from dboard and subdev names. + * \param db_name the name of a daughterboard slot + * \param sd_name the name of a subdevice on that daughterboard + */ + subdev_spec_pair_t( + const std::string &db_name = "", + const std::string &sd_name = "" + ); + }; + + //! overloaded comparison operator for subdev_spec_pair_t + UHD_API bool operator==(const subdev_spec_pair_t &, const subdev_spec_pair_t &); + + /*! + * A list of (daughterboard slot name, subdevice name) pairs: + * + * A subdevice specification represents a list of subdevices on a motherboard. + * The subdevices specified may span across multiple daughterboards; + * Hence the need for a subdevice specification over a simple list of strings. + * Typically, the user will pass a RX or TX subdevice specification into the API, + * and the implementation will infer the channel configuration from the specification. + * + * The subdevice specification can be represented as a markup-string. + * The markup-string is a whitespace separated list of dboard:subdev pairs. + * The first pair represents the subdevice for channel zero, + * the second pair represents the subdevice for channel one, and so on. + * + * Special handling for empty conditions: + * - An empty subdevice specification means: select the first subdevice found in the configuration + * - An empty daughterboard name means: select the only daughterboard slot or error if multiple exist + * - An empty subdevice name means: select the only subdevice on that board or error if multiple exist + */ + class UHD_API subdev_spec_t : public std::vector<subdev_spec_pair_t>{ + public: + + /*! + * Create a subdev specification from a markup string. + * \param markup the markup string + */ + subdev_spec_t(const std::string &markup = ""); + + /*! + * Convert a subdev specification into a pretty print string. + * \return a printable string representing the subdev specification + */ + std::string to_pp_string(void) const; + + /*! + * Convert the subdevice specification into a markup string. + * The markup string contains the delimiter symbols. + * \return a string with delimiter markup + */ + std::string to_string(void) const; + }; + +}} + +#endif /* INCLUDED_UHD_USRP_SUBDEV_SPEC_HPP */ diff --git a/host/include/uhd/usrp/tune_helper.hpp b/host/include/uhd/usrp/tune_helper.hpp new file mode 100644 index 000000000..e97ab0298 --- /dev/null +++ b/host/include/uhd/usrp/tune_helper.hpp @@ -0,0 +1,78 @@ +// +// 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_TUNE_HELPER_HPP +#define INCLUDED_UHD_USRP_TUNE_HELPER_HPP + +#include <uhd/config.hpp> +#include <uhd/wax.hpp> +#include <uhd/types/tune_request.hpp> +#include <uhd/types/tune_result.hpp> + +namespace uhd{ namespace usrp{ + + /*! + * Tune a rx chain to the desired frequency: + * The IF of the subdevice is set as close as possible to + * the given target frequency + the LO offset (when applicable). + * The ddc cordic is setup to bring the IF down to baseband. + * \param subdev the dboard subdevice object with properties + * \param ddc the mboard dsp object with properties + * \param tune_request tune request instructions + * \return a tune result struct + */ + UHD_API tune_result_t tune_rx_subdev_and_dsp( + wax::obj subdev, wax::obj ddc, const tune_request_t &tune_request + ); + + /*! + * Calculate the overall frequency from the combination of dboard IF and DDC shift. + * \param subdev the dboard subdevice object with properties + * \param ddc the mboard dsp object with properties + * \return the overall tune frequency of the system in Hz + */ + UHD_API double derive_freq_from_rx_subdev_and_dsp( + wax::obj subdev, wax::obj ddc + ); + + /*! + * Tune a tx chain to the desired frequency: + * The IF of the subdevice is set as close as possible to + * the given target frequency + the LO offset (when applicable). + * The duc cordic is setup to bring the baseband up to IF. + * \param subdev the dboard subdevice object with properties + * \param duc the mboard dsp object with properties + * \param tune_request tune request instructions + * \return a tune result struct + */ + UHD_API tune_result_t tune_tx_subdev_and_dsp( + wax::obj subdev, wax::obj duc, const tune_request_t &tune_request + ); + + /*! + * Calculate the overall frequency from the combination of dboard IF and DUC shift. + * \param subdev the dboard subdevice object with properties + * \param duc the mboard dsp object with properties + * \return the overall tune frequency of the system in Hz + */ + UHD_API double derive_freq_from_tx_subdev_and_dsp( + wax::obj subdev, wax::obj duc + ); + +}} + +#endif /* INCLUDED_UHD_USRP_TUNE_HELPER_HPP */ diff --git a/host/include/uhd/utils/CMakeLists.txt b/host/include/uhd/utils/CMakeLists.txt new file mode 100644 index 000000000..70f724c2d --- /dev/null +++ b/host/include/uhd/utils/CMakeLists.txt @@ -0,0 +1,34 @@ +# +# Copyright 2010-2011 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/>. +# + +INSTALL(FILES + algorithm.hpp + assert_has.hpp + assert_has.ipp + byteswap.hpp + byteswap.ipp + gain_group.hpp + images.hpp + pimpl.hpp + props.hpp + safe_call.hpp + safe_main.hpp + static.hpp + thread_priority.hpp + warning.hpp + DESTINATION ${INCLUDE_DIR}/uhd/utils +) diff --git a/host/include/uhd/utils/algorithm.hpp b/host/include/uhd/utils/algorithm.hpp new file mode 100644 index 000000000..5598d862b --- /dev/null +++ b/host/include/uhd/utils/algorithm.hpp @@ -0,0 +1,90 @@ +// +// Copyright 2010-2011 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_ALGORITHM_HPP +#define INCLUDED_UHD_UTILS_ALGORITHM_HPP + +#include <algorithm> +#include <boost/range/begin.hpp> +#include <boost/range/end.hpp> + +/*! + * Useful templated functions and classes that I like to pretend are part of stl. + * Many of the range wrapper functions come with recent versions of boost (1.43). + */ +namespace uhd{ + + /*! + * A wrapper around std::sort that takes a range instead of an iterator. + * + * The elements are sorted into ascending order using the less-than operator. + * This wrapper sorts the elements non-destructively into a new range. + * Based on the builtin python function sorted(...) + * + * \param range the range of elements to be sorted + * \return a new range with the elements sorted + */ + template<typename Range> inline Range sorted(const Range &range){ + Range r(range); std::sort(boost::begin(r), boost::end(r)); return r; + } + + /*! + * A wrapper around std::reverse that takes a range instead of an iterator. + * + * The elements are reversed into descending order using the less-than operator. + * This wrapper reverses the elements non-destructively into a new range. + * Based on the builtin python function reversed(...) + * + * \param range the range of elements to be reversed + * \return a new range with the elements reversed + */ + template<typename Range> inline Range reversed(const Range &range){ + Range r(range); std::reverse(boost::begin(r), boost::end(r)); return r; + } + + /*! + * Is the value found within the elements in this range? + * + * Uses std::find to search the iterable for an element. + * + * \param range the elements to search through + * \param value the match to look for in the range + * \return true when the value is found in the range + */ + template<typename Range, typename T> inline + bool has(const Range &range, const T &value){ + return boost::end(range) != std::find(boost::begin(range), boost::end(range), value); + } + + /*! + * A templated clip implementation. + * \param val the value to clip between an upper and lower limit + * \param bound1 the upper or lower bound + * \param bound2 the upper or lower bound + * \return the value clipped at the bounds + */ + template<typename T> inline T clip(const T &val, const T &bound1, const T &bound2){ + const T minimum = std::min(bound1, bound2); + if (val < minimum) return minimum; + const T maximum = std::max(bound1, bound2); + if (val > maximum) return maximum; + return val; + } + +} //namespace uhd + +#endif /* INCLUDED_UHD_UTILS_ALGORITHM_HPP */ diff --git a/host/include/uhd/utils/assert_has.hpp b/host/include/uhd/utils/assert_has.hpp new file mode 100644 index 000000000..eae7652ad --- /dev/null +++ b/host/include/uhd/utils/assert_has.hpp @@ -0,0 +1,47 @@ +// +// Copyright 2010-2011 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_ASSERT_HAS_HPP +#define INCLUDED_UHD_UTILS_ASSERT_HAS_HPP + +#include <uhd/config.hpp> +#include <string> + +namespace uhd{ + + /*! + * Check that an element is found in a container. + * If not, throw a meaningful assertion error. + * The "what" in the error will show what is + * being set and a list of known good values. + * + * \param range a list of possible settings + * \param value an element that may be in the list + * \param what a description of what the value is + * \throw assertion_error when elem not in list + */ + template<typename T, typename Range> void assert_has( + const Range &range, + const T &value, + const std::string &what = "unknown" + ); + +}//namespace uhd + +#include <uhd/utils/assert_has.ipp> + +#endif /* INCLUDED_UHD_UTILS_ASSERT_HAS_HPP */ diff --git a/host/include/uhd/utils/assert_has.ipp b/host/include/uhd/utils/assert_has.ipp new file mode 100644 index 000000000..7b3c88cb7 --- /dev/null +++ b/host/include/uhd/utils/assert_has.ipp @@ -0,0 +1,53 @@ +// +// Copyright 2010-2011 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_ASSERT_HAS_IPP +#define INCLUDED_UHD_UTILS_ASSERT_HAS_IPP + +#include <uhd/utils/algorithm.hpp> +#include <uhd/exception.hpp> +#include <boost/format.hpp> +#include <boost/foreach.hpp> +#include <boost/lexical_cast.hpp> + +namespace uhd{ + + template<typename T, typename Range> UHD_INLINE void assert_has( + const Range &range, + const T &value, + const std::string &what + ){ + if (uhd::has(range, value)) return; + std::string possible_values = ""; + size_t i = 0; + BOOST_FOREACH(const T &v, range){ + if (i++ > 0) possible_values += ", "; + possible_values += boost::lexical_cast<std::string>(v); + } + throw uhd::assertion_error(str(boost::format( + "assertion failed:\n" + " %s is not a valid %s.\n" + " possible values are: [%s].\n" + ) + % boost::lexical_cast<std::string>(value) + % what % possible_values + )); + } + +}//namespace uhd + +#endif /* INCLUDED_UHD_UTILS_ASSERT_HAS_IPP */ diff --git a/host/include/uhd/utils/byteswap.hpp b/host/include/uhd/utils/byteswap.hpp new file mode 100644 index 000000000..9a1871210 --- /dev/null +++ b/host/include/uhd/utils/byteswap.hpp @@ -0,0 +1,50 @@ +// +// 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_HPP +#define INCLUDED_UHD_UTILS_BYTESWAP_HPP + +#include <uhd/config.hpp> +#include <boost/cstdint.hpp> + +/*! \file byteswap.hpp + * Provide fast byteswaping routines for 16, 32, and 64 bit integers, + * by using the system's native routines/intrinsics when available. + */ + +namespace uhd{ + + //! perform a byteswap on a 16 bit integer + boost::uint16_t byteswap(boost::uint16_t); + + //! perform a byteswap on a 32 bit integer + boost::uint32_t byteswap(boost::uint32_t); + + //! perform a byteswap on a 64 bit integer + boost::uint64_t byteswap(boost::uint64_t); + + //! network to host: short, long, or long-long + template<typename T> T ntohx(T); + + //! host to network: short, long, or long-long + template<typename T> T htonx(T); + +} //namespace uhd + +#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..a070a7cf5 --- /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: + **********************************************************************/ +#if defined(UHD_PLATFORM_WIN32) //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(UHD_PLATFORM_MACOS) + #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(UHD_PLATFORM_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 */ diff --git a/host/include/uhd/utils/gain_group.hpp b/host/include/uhd/utils/gain_group.hpp new file mode 100644 index 000000000..7ef7bdcf5 --- /dev/null +++ b/host/include/uhd/utils/gain_group.hpp @@ -0,0 +1,108 @@ +// +// Copyright 2010-2011 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_GAIN_GROUP_HPP +#define INCLUDED_UHD_UTILS_GAIN_GROUP_HPP + +#include <uhd/config.hpp> +#include <uhd/types/ranges.hpp> +#include <boost/shared_ptr.hpp> +#include <boost/function.hpp> +#include <boost/utility.hpp> +#include <vector> +#include <string> + +namespace uhd{ + +/*! + * A set of function to control a gain element. + */ +struct UHD_API gain_fcns_t{ + boost::function<gain_range_t(void)> get_range; + boost::function<double(void)> get_value; + boost::function<void(double)> set_value; +}; + +class UHD_API gain_group : boost::noncopyable{ +public: + typedef boost::shared_ptr<gain_group> sptr; + + /*! + * Get the gain range for the gain element specified by name. + * For an empty name, get the overall gain range for this group. + * Overall step is defined as the minimum step size. + * \param name name of the gain element (optional) + * \return a gain range with overall min, max, step + */ + virtual gain_range_t get_range(const std::string &name = "") = 0; + + /*! + * Get the gain value for the gain element specified by name. + * For an empty name, get the overall gain value for this group. + * \param name name of the gain element (optional) + * \return a gain value of the element or all elements + */ + virtual double get_value(const std::string &name = "") = 0; + + /*! + * Set the gain value for the gain element specified by name. + * For an empty name, set the overall gain value for this group. + * The power will be distributed across individual gain elements. + * The semantics of how to do this are determined by the priority. + * \param gain the gain to set for the lement or across the group + * \param name name of the gain element (optional) + */ + virtual void set_value(double gain, const std::string &name = "") = 0; + + /*! + * Get a list of names of registered gain elements. + * The names are in the order that they were registered. + * \return a vector of gain name strings + */ + virtual const std::vector<std::string> get_names(void) = 0; + + /*! + * Register a set of gain functions into this group: + * + * The name should be a unique and non-empty name. + * Othwerwise, the implementation will rename it. + * + * Priority determines how power will be distributed + * with higher priorities getting the power first, + * and lower priorities getting the remainder power. + * + * \param name the name of the gain element + * \param gain_fcns the set of gain functions + * \param priority the priority of the gain element + */ + virtual void register_fcns( + const std::string &name, + const gain_fcns_t &gain_fcns, + size_t priority = 0 + ) = 0; + + /*! + * Make a new empty gain group. + * \return a gain group object. + */ + static sptr make(void); +}; + +} //namespace uhd + +#endif /* INCLUDED_UHD_UTILS_GAIN_GROUP_HPP */ + diff --git a/host/include/uhd/utils/images.hpp b/host/include/uhd/utils/images.hpp new file mode 100644 index 000000000..8b5a1eedd --- /dev/null +++ b/host/include/uhd/utils/images.hpp @@ -0,0 +1,38 @@ +// +// 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_IMAGES_HPP +#define INCLUDED_UHD_UTILS_IMAGES_HPP + +#include <uhd/config.hpp> +#include <string> + +namespace uhd{ + + /*! + * Search for an image in the system image paths: + * Search compiled-in paths and environment variable paths + * for a specific image file with the provided file name. + * \param image_name the name of the file + * \return the full system path to the file + * \throw exception if the image was not found + */ + UHD_API std::string find_image_path(const std::string &image_name); + +} //namespace uhd + +#endif /* INCLUDED_UHD_UTILS_IMAGES_HPP */ diff --git a/host/include/uhd/utils/pimpl.hpp b/host/include/uhd/utils/pimpl.hpp new file mode 100644 index 000000000..09bf0c0a2 --- /dev/null +++ b/host/include/uhd/utils/pimpl.hpp @@ -0,0 +1,55 @@ +// +// 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_PIMPL_HPP +#define INCLUDED_UHD_UTILS_PIMPL_HPP + +#include <uhd/config.hpp> +#include <boost/shared_ptr.hpp> + +/*! \file pimpl.hpp + * "Pimpl idiom" (pointer to implementation idiom). + * The UHD_PIMPL_* macros simplify code overhead for declaring and making pimpls. + * + * Each pimpl is implemented as a shared pointer to the implementation: + * - The container class will not have to deallocate the pimpl. + * - The container class will use the pimpl as a regular pointer. + * - Usage: _impl->method(arg0, arg1) + * - Usage: _impl->member = value; + * + * \see http://en.wikipedia.org/wiki/Opaque_pointer + */ + +/*! + * Make a declaration for a pimpl in a header file. + * - Usage: UHD_PIMPL_DECL(impl) _impl; + * \param _name the name of the pimpl class + */ +#define UHD_PIMPL_DECL(_name) \ + struct _name; boost::shared_ptr<_name> + +/*! + * Make an instance of a pimpl in a source file. + * - Usage: _impl = UHD_PIMPL_MAKE(impl, ()); + * - Usage: _impl = UHD_PIMPL_MAKE(impl, (a0, a1)); + * \param _name the name of the pimpl class + * \param _args the constructor args for the pimpl + */ +#define UHD_PIMPL_MAKE(_name, _args) \ + boost::shared_ptr<_name>(new _name _args) + +#endif /* INCLUDED_UHD_UTILS_PIMPL_HPP */ diff --git a/host/include/uhd/utils/props.hpp b/host/include/uhd/utils/props.hpp new file mode 100644 index 000000000..81737423a --- /dev/null +++ b/host/include/uhd/utils/props.hpp @@ -0,0 +1,81 @@ +// +// Copyright 2010-2011 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_PROPS_HPP +#define INCLUDED_UHD_UTILS_PROPS_HPP + +#include <uhd/config.hpp> +#include <uhd/wax.hpp> +#include <uhd/exception.hpp> +#include <vector> +#include <string> + +namespace uhd{ + + //! The type for a vector of property names + typedef std::vector<std::string> prop_names_t; + + /*! + * A named prop struct holds a key and a name. + * Allows properties to be sub-sectioned by name. + */ + struct UHD_API named_prop_t{ + const wax::obj key; + const std::string name; + + //! Convert the key to the specified type + template<typename T> inline T as(void){ + return key.as<T>(); + } + + /*! + * Utility function to convert generic key into a named prop. + * If the key was already a named prop, the prop will be split. + * Otherwise, the key will be the key, and the name will be used. + * \param key a reference to the prop object + * \param name a reference to the name object + * \return a named property struct with key and name + */ + static named_prop_t extract( + const wax::obj &key, const std::string &name = "" + ); + + /*! + * Create a new named prop from key and name. + * \param key the property key + * \param name the string name + */ + named_prop_t(const wax::obj &key, const std::string &name); + }; + + /*! + * Throw when getting a not-implemented or write-only property. + * Throw-site information will be included with this error. + */ + #define UHD_THROW_PROP_GET_ERROR() \ + throw uhd::key_error(UHD_THROW_SITE_INFO("cannot get this property")) + + /*! + * Throw when setting a not-implemented or read-only property. + * Throw-site information will be included with this error. + */ + #define UHD_THROW_PROP_SET_ERROR() \ + throw uhd::key_error(UHD_THROW_SITE_INFO("cannot set this property")) + +} //namespace uhd + +#endif /* INCLUDED_UHD_UTILS_PROPS_HPP */ diff --git a/host/include/uhd/utils/safe_call.hpp b/host/include/uhd/utils/safe_call.hpp new file mode 100644 index 000000000..6b2c210af --- /dev/null +++ b/host/include/uhd/utils/safe_call.hpp @@ -0,0 +1,45 @@ +// +// Copyright 2011 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_SAFE_CALL_HPP +#define INCLUDED_UHD_UTILS_SAFE_CALL_HPP + +#include <uhd/config.hpp> +#include <uhd/exception.hpp> +#include <uhd/utils/warning.hpp> + +//! helper macro for safe call to produce warnings +#define _UHD_SAFE_CALL_WARNING(code, what) uhd::warning::post( \ + UHD_THROW_SITE_INFO("Exception caught in safe-call.") + #code + " -> " + what \ +); + +/*! + * A safe-call catches all exceptions thrown by code, + * and creates a verbose warning about the exception. + * Usage: UHD_SAFE_CALL(some_code_to_call();) + * \param code the block of code to call safely + */ +#define UHD_SAFE_CALL(code) \ + try{code} \ + catch(const std::exception &e){ \ + _UHD_SAFE_CALL_WARNING(code, e.what()); \ + } \ + catch(...){ \ + _UHD_SAFE_CALL_WARNING(code, "unknown exception"); \ + } + +#endif /* INCLUDED_UHD_UTILS_SAFE_CALL_HPP */ diff --git a/host/include/uhd/utils/safe_main.hpp b/host/include/uhd/utils/safe_main.hpp new file mode 100644 index 000000000..b682aa540 --- /dev/null +++ b/host/include/uhd/utils/safe_main.hpp @@ -0,0 +1,44 @@ +// +// 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_SAFE_MAIN_HPP +#define INCLUDED_UHD_UTILS_SAFE_MAIN_HPP + +#include <uhd/config.hpp> +#include <iostream> +#include <stdexcept> + +/*! + * Defines a safe wrapper that places a catch-all around main. + * If an exception is thrown, it prints to stderr and returns. + * Usage: int UHD_SAFE_MAIN(int argc, char *argv[]){ main code here } + * \param _argc the declaration for argc + * \param _argv the declaration for argv + */ +#define UHD_SAFE_MAIN(_argc, _argv) _main(int, char*[]); \ +int main(int argc, char *argv[]){ \ + try { \ + return _main(argc, argv); \ + } catch(const std::exception &e) { \ + std::cerr << "Error: " << e.what() << std::endl; \ + } catch(...) { \ + std::cerr << "Error: unknown exception" << std::endl; \ + } \ + return ~0; \ +} int _main(_argc, _argv) + +#endif /* INCLUDED_UHD_UTILS_SAFE_MAIN_HPP */ diff --git a/host/include/uhd/utils/static.hpp b/host/include/uhd/utils/static.hpp new file mode 100644 index 000000000..82cdf36d9 --- /dev/null +++ b/host/include/uhd/utils/static.hpp @@ -0,0 +1,46 @@ +// +// Copyright 2010-2011 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_STATIC_HPP +#define INCLUDED_UHD_UTILS_STATIC_HPP + +#include <uhd/config.hpp> + +/*! + * Defines a function that implements the "construct on first use" idiom + * \param _t the type definition for the instance + * \param _x the name of the defined function + * \return a reference to the lazy instance + */ +#define UHD_SINGLETON_FCN(_t, _x) static _t &_x(){static _t _x; return _x;} + +/*! + * Defines a static code block that will be called before main() + * The static block will catch and print exceptions to std error. + * \param _x the unique name of the fixture (unique per source) + */ +#define UHD_STATIC_BLOCK(_x) \ + void _x(void); \ + static _uhd_static_fixture _x##_fixture(&_x, #_x); \ + void _x(void) + +//! Helper for static block, constructor calls function +struct UHD_API _uhd_static_fixture{ + _uhd_static_fixture(void (*)(void), const char *); +}; + +#endif /* INCLUDED_UHD_UTILS_STATIC_HPP */ diff --git a/host/include/uhd/utils/thread_priority.hpp b/host/include/uhd/utils/thread_priority.hpp new file mode 100644 index 000000000..988fc3012 --- /dev/null +++ b/host/include/uhd/utils/thread_priority.hpp @@ -0,0 +1,58 @@ +// +// 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_THREAD_PRIORITY_HPP +#define INCLUDED_UHD_UTILS_THREAD_PRIORITY_HPP + +#include <uhd/config.hpp> + +namespace uhd{ + + static const float default_thread_priority = float(0.5); + + /*! + * Set the scheduling priority on the current thread. + * + * A new thread or calling process should make this call + * with the defailts this to enable realtime scheduling. + * + * A priority of zero corresponds to normal priority. + * Positive priority values are higher than normal. + * Negative priority values are lower than normal. + * + * \param priority a value between -1 and 1 + * \param realtime true to use realtime mode + * \throw exception on set priority failure + */ + UHD_API void set_thread_priority( + float priority = default_thread_priority, + bool realtime = true + ); + + /*! + * Set the scheduling priority on the current thread. + * Same as set_thread_priority but does not throw on failure. + * \return true on success, false on failure + */ + UHD_API bool set_thread_priority_safe( + float priority = default_thread_priority, + bool realtime = true + ); + +} //namespace uhd + +#endif /* INCLUDED_UHD_UTILS_THREAD_PRIORITY_HPP */ diff --git a/host/include/uhd/utils/warning.hpp b/host/include/uhd/utils/warning.hpp new file mode 100644 index 000000000..a1e3f0d1e --- /dev/null +++ b/host/include/uhd/utils/warning.hpp @@ -0,0 +1,62 @@ +// +// 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_WARNING_HPP +#define INCLUDED_UHD_UTILS_WARNING_HPP + +#include <uhd/config.hpp> +#include <boost/function.hpp> +#include <vector> +#include <string> + +namespace uhd{ namespace warning{ + + //! Callback function type for a message handler + typedef boost::function<void(std::string)> handler_t; + + /*! + * Post a warning message to all registered handlers. + * \param msg the multiline warning message + */ + UHD_API void post(const std::string &msg); + + /*! + * Register a new handler with this name. + * If the name was already registered for this name, + * the old registered handler will be replaced. + * \param name a unique name for this handler + * \param handler the callback handler function + */ + UHD_API void register_handler(const std::string &name, const handler_t &handler); + + /*! + * Unregister a handler for this name. + * \param name a unique name for a registered handler + * \return the handler that was registered + * \throw error when the name was not found in the registry + */ + UHD_API handler_t unregister_handler(const std::string &name); + + /*! + * Get a list of registered handler names. + * \return a vector of unique string names + */ + UHD_API const std::vector<std::string> registry_names(void); + +}} //namespace uhd::warning + +#endif /* INCLUDED_UHD_UTILS_WARNING_HPP */ diff --git a/host/include/uhd/version.hpp b/host/include/uhd/version.hpp new file mode 100644 index 000000000..19d672e65 --- /dev/null +++ b/host/include/uhd/version.hpp @@ -0,0 +1,28 @@ +// +// 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_VERSION_HPP +#define INCLUDED_UHD_VERSION_HPP + +#include <uhd/config.hpp> +#include <string> + +namespace uhd{ + UHD_API std::string get_version_string(void); +} //namespace uhd + +#endif /* INCLUDED_UHD_VERSION_HPP */ diff --git a/host/include/uhd/wax.hpp b/host/include/uhd/wax.hpp new file mode 100644 index 000000000..6fd2b8652 --- /dev/null +++ b/host/include/uhd/wax.hpp @@ -0,0 +1,169 @@ +// +// Copyright 2010-2011 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_WAX_HPP +#define INCLUDED_WAX_HPP + +#include <uhd/config.hpp> +#include <uhd/exception.hpp> +#include <boost/any.hpp> +#include <typeinfo> +#include <string> + +/*! + * WAX - it's a metaphor! + * + * The WAX framework allows an object to have generic/anyobj properties. + * These properties can be addressed through generic/anyobj identifiers. + * + * The WAX object itself is an anytype container much like boost::any. + * To retrieve the value of the appropriate type, use my_obj.as<type>(). + * + * Proprties may be referenced though the [] overloaded operator. + * The [] operator returns a special proxy that allows for assigment. + * Also, the [] operators may be chained as in the folowing examples: + * my_obj[prop1][prop2][prop3] = value; + * value = my_obj[prop1][prop2][prop3].as<type>(); + * + * Property nesting occurs when a WAX object gets another object's link. + * This special link is obtained through a call to my_obj.get_link(). + * + * Note: Do not put a class derived from wax::obj into an stl container. + * MSVC will compile the code, but the binaries will crash at runtime. + * Rather, use pointers or smart pointers to instances of the derived class. + */ + +namespace wax{ + + /*! + * WAX object base class: + * + * A wax obj has two major purposes: + * 1) to act as a polymorphic container, just like boost any + * 2) to provide a nested set/get properties interface + * + * Internally, the polymorphic container is handled by a boost any. + * For properties, a subclass should override the set and get methods. + * For property nesting, wax obj subclasses return special links + * to other wax obj subclasses, and the api handles the magic. + */ + class UHD_API obj{ + public: + + /*! + * Default constructor: + * The contents will be empty. + */ + obj(void); + + /*! + * Copy constructor: + * The contents will be cloned. + * \param o another wax::obj + */ + obj(const obj &o); + + /*! + * Templated any type constructor: + * The contents can be anything. + * Uses the boost::any to handle the magic. + * \param o an object of any type + */ + template<class T> obj(const T &o){ + _contents = o; + } + + /*! + * Destructor. + */ + virtual ~obj(void); + + /*! + * The chaining operator: + * This operator allows access objs with properties. + * A call to the [] operator will return a new proxy obj. + * The proxy object is an obj with special proxy contents. + * Assignment and casting can be used on this special object + * to access the property referenced by the obj key. + * \param key a key to identify a property within this obj + * \return a special wax obj that proxies the obj and key + */ + obj operator[](const obj &key); + + /*! + * The assignment operator: + * This operator allows for assignment of new contents. + * In the special case where this obj contains a proxy, + * the value will be set to the proxy's property reference. + * \param val the new value to assign to the wax obj + * \return a reference to this obj (*this) + */ + obj & operator=(const obj &val); + + /*! + * Get a link in the chain: + * When a wax obj returns another wax obj as part of a get call, + * the return value should be set to the result of this method. + * Doing so will ensure chain-ability of the returned object. + * \return an obj containing a valid link to a wax obj + */ + obj get_link(void) const; + + /*! + * Get the type of the contents of this obj. + * \return a reference to the type_info + */ + const std::type_info & type(void) const; + + /*! + * Cast this obj into the desired type. + * Usage: myobj.as<type>() + * + * \return an object of the desired type + * \throw wax::bad_cast when the cast fails + */ + template<class T> T as(void) const{ + try{ + return boost::any_cast<T>(resolve()); + } + catch(const boost::bad_any_cast &e){ + throw uhd::type_error(std::string("") + "Cannot wax cast " + type().name() + " to " + typeid(T).name() + " " + e.what()); + } + } + + private: + //private interface (override in subclasses) + virtual void get(const obj &, obj &); + virtual void set(const obj &, const obj &); + + /*! + * Resolve the contents of this obj. + * In the case where this obj is a proxy, + * the referenced property will be resolved. + * Otherwise, just get the private contents. + * \return a boost any type with contents + */ + boost::any resolve(void) const; + + //private contents of this obj + boost::any _contents; + + }; + +} //namespace wax + +#endif /* INCLUDED_WAX_HPP */ |