diff options
Diffstat (limited to 'host/include')
70 files changed, 7082 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..1df04d577 --- /dev/null +++ b/host/include/uhd/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/>. +# + + +ADD_SUBDIRECTORY(transport) +ADD_SUBDIRECTORY(types) +ADD_SUBDIRECTORY(usrp) +ADD_SUBDIRECTORY(utils) + +INSTALL(FILES + config.hpp + convert.hpp + deprecated.hpp + device.hpp + device_deprecated.ipp + exception.hpp + property_tree.ipp + property_tree.hpp + stream.hpp + version.hpp + DESTINATION ${INCLUDE_DIR}/uhd + COMPONENT headers +) diff --git a/host/include/uhd/config.hpp b/host/include/uhd/config.hpp new file mode 100644 index 000000000..6fd2932cf --- /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) + #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..c6b005867 --- /dev/null +++ b/host/include/uhd/convert.hpp @@ -0,0 +1,105 @@ +// +// Copyright 2011-2012 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/ref_vector.hpp> +#include <boost/shared_ptr.hpp> +#include <boost/function.hpp> +#include <boost/operators.hpp> +#include <string> + +namespace uhd{ namespace convert{ + + //! A conversion class that implements a conversion from inputs -> outputs. + class converter{ + public: + typedef boost::shared_ptr<converter> sptr; + typedef uhd::ref_vector<void *> output_type; + typedef uhd::ref_vector<const void *> input_type; + + //! Set the scale factor (used in floating point conversions) + virtual void set_scalar(const double) = 0; + + //! The public conversion method to convert inputs -> outputs + UHD_INLINE void conv(const input_type &in, const output_type &out, const size_t num){ + if (num != 0) (*this)(in, out, num); + } + + private: + //! Callable method: input vectors, output vectors, num samples + virtual void operator()(const input_type&, const output_type&, const size_t) = 0; + }; + + //! Conversion factory function typedef + typedef boost::function<converter::sptr(void)> function_type; + + //! Priority of conversion routines + typedef int priority_type; + + //! Identify a conversion routine in the registry + struct id_type : boost::equality_comparable<id_type>{ + std::string input_format; + size_t num_inputs; + std::string output_format; + size_t num_outputs; + std::string to_pp_string(void) const; + }; + + //! Implement equality_comparable interface + UHD_API bool operator==(const id_type &, const id_type &); + + /*! + * Register a converter function. + * \param id identify the conversion + * \param fcn makes a new converter + * \param prio the function priority + */ + UHD_API void register_converter( + const id_type &id, + const function_type &fcn, + const priority_type prio + ); + + /*! + * Get a converter factory function. + * \param id identify the conversion + * \param prio the desired prio or -1 for best + * \return the converter factory function + */ + UHD_API function_type get_converter( + const id_type &id, + const priority_type prio = -1 + ); + + /*! + * Register the size of a particular item. + * \param format the item format + * \param size the size in bytes + */ + UHD_API void register_bytes_per_item( + const std::string &format, const size_t size + ); + + //! Convert an item format to a size in bytes + UHD_API size_t get_bytes_per_item(const std::string &format); + +}} //namespace + +#endif /* INCLUDED_UHD_CONVERT_HPP */ diff --git a/host/include/uhd/deprecated.hpp b/host/include/uhd/deprecated.hpp new file mode 100644 index 000000000..95cce58e9 --- /dev/null +++ b/host/include/uhd/deprecated.hpp @@ -0,0 +1,76 @@ +//---------------------------------------------------------------------- +//-- deprecated interfaces below, to be removed when the API is changed +//---------------------------------------------------------------------- + +// +// 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 = int('='), + BO_LITTLE_ENDIAN = int('<'), + BO_BIG_ENDIAN = int('>'), + BO_NOT_APPLICABLE = int('|') + } 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 */ + +#include <uhd/types/io_type.hpp> //wish it was in here +#include <uhd/types/clock_config.hpp> //wish it was in here diff --git a/host/include/uhd/device.hpp b/host/include/uhd/device.hpp new file mode 100644 index 000000000..89c6332da --- /dev/null +++ b/host/include/uhd/device.hpp @@ -0,0 +1,104 @@ +// +// 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/stream.hpp> +#include <uhd/deprecated.hpp> +#include <uhd/types/device_addr.hpp> +#include <boost/utility.hpp> +#include <boost/shared_ptr.hpp> +#include <boost/function.hpp> + +namespace uhd{ + +class property_tree; //forward declaration + +/*! + * The usrp device interface represents the usrp hardware. + * The api allows for discovery, configuration, and streaming. + */ +class UHD_API device : boost::noncopyable{ + +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); + + //! Make a new receive streamer from the streamer arguments + virtual rx_streamer::sptr get_rx_stream(const stream_args_t &args) = 0; + + //! Make a new transmit streamer from the streamer arguments + virtual tx_streamer::sptr get_tx_stream(const stream_args_t &args) = 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; + + //! Get access to the underlying property structure + virtual boost::shared_ptr<property_tree> get_tree(void) const = 0; + + #include <uhd/device_deprecated.ipp> + +}; + +} //namespace uhd + +#endif /* INCLUDED_UHD_DEVICE_HPP */ diff --git a/host/include/uhd/device_deprecated.ipp b/host/include/uhd/device_deprecated.ipp new file mode 100644 index 000000000..0ee1cd706 --- /dev/null +++ b/host/include/uhd/device_deprecated.ipp @@ -0,0 +1,191 @@ +// +// 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/>. +// + +//this file is included inside device class +//it supports the old send/recv functions +//this was replaced by the streamer API + +#define _lazymin(x, y) (((x) > (y))? (y) : (x)) + +/*! + * 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 + */ +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 +){ + if (_tx_streamer.get() == NULL or _tx_streamer->get_num_channels() != buffs.size() or _send_tid != io_type.tid){ + _send_tid = io_type.tid; + _tx_streamer.reset(); //cleanup possible old one + stream_args_t args; + args.cpu_format = (_send_tid == io_type_t::COMPLEX_FLOAT32)? "fc32" : "sc16"; + args.otw_format = "sc16"; + args.args["noclear"] = "1"; + for (size_t ch = 0; ch < buffs.size(); ch++) + args.channels.push_back(ch); //linear mapping + _tx_streamer = get_tx_stream(args); + } + const size_t nsamps = (send_mode == SEND_MODE_ONE_PACKET)? + _lazymin(nsamps_per_buff, get_max_send_samps_per_packet()) : + nsamps_per_buff; + return _tx_streamer->send(buffs, nsamps, metadata, timeout); +} + +/*! + * 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 + */ +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 +){ + if (_rx_streamer.get() == NULL or _rx_streamer->get_num_channels() != buffs.size() or _recv_tid != io_type.tid){ + _recv_tid = io_type.tid; + _rx_streamer.reset(); //cleanup possible old one + stream_args_t args; + args.cpu_format = (_recv_tid == io_type_t::COMPLEX_FLOAT32)? "fc32" : "sc16"; + args.otw_format = "sc16"; + args.args["noclear"] = "1"; + for (size_t ch = 0; ch < buffs.size(); ch++) + args.channels.push_back(ch); //linear mapping + _rx_streamer = get_rx_stream(args); + } + const size_t nsamps = (recv_mode == RECV_MODE_ONE_PACKET)? + _lazymin(nsamps_per_buff, get_max_recv_samps_per_packet()) : + nsamps_per_buff; + return _rx_streamer->recv(buffs, nsamps, metadata, timeout); +} + +/*! + * Get the maximum number of samples per packet on send. + * \return the number of samples + */ +size_t get_max_send_samps_per_packet(void){ + if (_tx_streamer.get() == NULL){ + stream_args_t args; + args.cpu_format = "fc32"; + args.otw_format = "sc16"; + args.args["noclear"] = "1"; + _tx_streamer = get_tx_stream(args); + _send_tid = io_type_t::COMPLEX_FLOAT32; + } + return _tx_streamer->get_max_num_samps(); +} + +/*! + * Get the maximum number of samples per packet on recv. + * \return the number of samples + */ +size_t get_max_recv_samps_per_packet(void){ + if (_rx_streamer.get() == NULL){ + stream_args_t args; + args.cpu_format = "fc32"; + args.otw_format = "sc16"; + args.args["noclear"] = "1"; + _rx_streamer = get_rx_stream(args); + _recv_tid = io_type_t::COMPLEX_FLOAT32; + } + return _rx_streamer->get_max_num_samps(); +} + +private: + rx_streamer::sptr _rx_streamer; + io_type_t::tid_t _recv_tid; + tx_streamer::sptr _tx_streamer; + io_type_t::tid_t _send_tid; diff --git a/host/include/uhd/exception.hpp b/host/include/uhd/exception.hpp new file mode 100644 index 000000000..c05861788 --- /dev/null +++ b/host/include/uhd/exception.hpp @@ -0,0 +1,166 @@ +// +// 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_EXCEPTION_HPP +#define INCLUDED_UHD_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. + * + * The dynamic_clone() and dynamic_throw() methods allow us to: + * catch an exception by dynamic type (i.e. derived class), save it, + * and later rethrow it, knowing only the static type (i.e. base class), + * and then finally to catch it again using the derived type. + * + * http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2006/n2106.html + */ +namespace uhd{ + + struct UHD_API exception : std::runtime_error{ + exception(const std::string &what); + virtual unsigned code(void) const = 0; + virtual exception *dynamic_clone(void) const = 0; + virtual void dynamic_throw(void) const = 0; + }; + + struct UHD_API assertion_error : exception{ + assertion_error(const std::string &what); + virtual unsigned code(void) const; + virtual assertion_error *dynamic_clone(void) const; + virtual void dynamic_throw(void) const; + }; + + struct UHD_API lookup_error : exception{ + lookup_error(const std::string &what); + virtual unsigned code(void) const; + virtual lookup_error *dynamic_clone(void) const; + virtual void dynamic_throw(void) const; + }; + + struct UHD_API index_error : lookup_error{ + index_error(const std::string &what); + virtual unsigned code(void) const; + virtual index_error *dynamic_clone(void) const; + virtual void dynamic_throw(void) const; + }; + + struct UHD_API key_error : lookup_error{ + key_error(const std::string &what); + virtual unsigned code(void) const; + virtual key_error *dynamic_clone(void) const; + virtual void dynamic_throw(void) const; + }; + + struct UHD_API type_error : exception{ + type_error(const std::string &what); + virtual unsigned code(void) const; + virtual type_error *dynamic_clone(void) const; + virtual void dynamic_throw(void) const; + }; + + struct UHD_API value_error : exception{ + value_error(const std::string &what); + virtual unsigned code(void) const; + virtual value_error *dynamic_clone(void) const; + virtual void dynamic_throw(void) const; + }; + + struct UHD_API runtime_error : exception{ + runtime_error(const std::string &what); + virtual unsigned code(void) const; + virtual runtime_error *dynamic_clone(void) const; + virtual void dynamic_throw(void) const; + }; + + struct UHD_API not_implemented_error : runtime_error{ + not_implemented_error(const std::string &what); + virtual unsigned code(void) const; + virtual not_implemented_error *dynamic_clone(void) const; + virtual void dynamic_throw(void) const; + }; + + struct UHD_API environment_error : exception{ + environment_error(const std::string &what); + virtual unsigned code(void) const; + virtual environment_error *dynamic_clone(void) const; + virtual void dynamic_throw(void) const; + }; + + struct UHD_API io_error : environment_error{ + io_error(const std::string &what); + virtual unsigned code(void) const; + virtual io_error *dynamic_clone(void) const; + virtual void dynamic_throw(void) const; + }; + + struct UHD_API os_error : environment_error{ + os_error(const std::string &what); + virtual unsigned code(void) const; + virtual os_error *dynamic_clone(void) const; + virtual void dynamic_throw(void) const; + }; + + struct UHD_API system_error : exception{ + system_error(const std::string &what); + virtual unsigned code(void) const; + virtual system_error *dynamic_clone(void) const; + virtual void dynamic_throw(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_EXCEPTION_HPP */ diff --git a/host/include/uhd/property_tree.hpp b/host/include/uhd/property_tree.hpp new file mode 100644 index 000000000..47b2c5736 --- /dev/null +++ b/host/include/uhd/property_tree.hpp @@ -0,0 +1,158 @@ +// +// 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_PROPERTY_TREE_HPP +#define INCLUDED_UHD_PROPERTY_TREE_HPP + +#include <uhd/config.hpp> +#include <boost/utility.hpp> +#include <boost/shared_ptr.hpp> +#include <boost/function.hpp> +#include <vector> + +namespace uhd{ + +/*! + * A templated property interface for holding a value + * and registering callbacks when that value changes. + */ +template <typename T> class property : boost::noncopyable{ +public: + typedef boost::function<void(const T &)> subscriber_type; + typedef boost::function<T(void)> publisher_type; + typedef boost::function<T(const T &)> coercer_type; + + /*! + * Register a coercer into the property. + * A coercer is a special subscribes that coerces the value. + * Only one coercer may be registered per property. + * Registering a coercer replaces the previous coercer. + * \param coercer the coercer callback function + * \return a reference to this property for chaining + */ + virtual property<T> &coerce(const coercer_type &coercer) = 0; + + /*! + * Register a publisher into the property. + * A publisher is a special callback the provides the value. + * Publishers are useful for creating read-only properties. + * Only one publisher may be registered per property. + * Registering a publisher replaces the previous publisher. + * \param publisher the publisher callback function + * \return a reference to this property for chaining + */ + virtual property<T> &publish(const publisher_type &publisher) = 0; + + /*! + * Register a subscriber into the property. + * All subscribers are called when the value changes. + * Once a subscriber is registered, it cannot be unregistered. + * \param subscriber the subscriber callback function + * \return a reference to this property for chaining + */ + virtual property<T> &subscribe(const subscriber_type &subscriber) = 0; + + /*! + * Update calls all subscribers w/ the current value. + * \return a reference to this property for chaining + */ + virtual property<T> &update(void) = 0; + + /*! + * Set the new value and call all subscribers. + * The coercer (when provided) is called initially, + * and the coerced value is used to set the subscribers. + * \param value the new value to set on this property + * \return a reference to this property for chaining + */ + virtual property<T> &set(const T &value) = 0; + + /*! + * Get the current value of this property. + * The publisher (when provided) yields the value, + * otherwise an internal shadow is used for the value. + * \return the current value in the property + */ + virtual T get(void) const = 0; + + /*! + * A property is empty if it has never been set. + * A property with a publisher is never empty. + * \return true if the property is empty + */ + virtual bool empty(void) const = 0; +}; + +/*! + * FS Path: A glorified string with path manipulations. + * Inspired by boost filesystem path, but without the dependency. + * + * Notice: we do not declare UHD_API on the whole structure + * because MSVC will do weird things with std::string and linking. + */ +struct fs_path : std::string{ + UHD_API fs_path(void); + UHD_API fs_path(const char *); + UHD_API fs_path(const std::string &); + UHD_API std::string leaf(void) const; + UHD_API fs_path branch_path(void) const; +}; + +UHD_API fs_path operator/(const fs_path &, const fs_path &); + +/*! + * The property tree provides a file system structure for accessing properties. + */ +class UHD_API property_tree : boost::noncopyable{ +public: + typedef boost::shared_ptr<property_tree> sptr; + + //! Create a new + empty property tree + static sptr make(void); + + //! Get a subtree with a new root starting at path + virtual sptr subtree(const fs_path &path) const = 0; + + //! Remove a property or directory (recursive) + virtual void remove(const fs_path &path) = 0; + + //! True if the path exists in the tree + virtual bool exists(const fs_path &path) const = 0; + + //! Get an iterable to all things in the given path + virtual std::vector<std::string> list(const fs_path &path) const = 0; + + //! Create a new property entry in the tree + template <typename T> property<T> &create(const fs_path &path); + + //! Get access to a property in the tree + template <typename T> property<T> &access(const fs_path &path); + +private: + //! Internal create property with wild-card type + virtual void _create(const fs_path &path, const boost::shared_ptr<void> &prop) = 0; + + //! Internal access property with wild-card type + virtual boost::shared_ptr<void> &_access(const fs_path &path) const = 0; + +}; + +} //namespace uhd + +#include <uhd/property_tree.ipp> + +#endif /* INCLUDED_UHD_PROPERTY_TREE_HPP */ diff --git a/host/include/uhd/property_tree.ipp b/host/include/uhd/property_tree.ipp new file mode 100644 index 000000000..85720dc6b --- /dev/null +++ b/host/include/uhd/property_tree.ipp @@ -0,0 +1,95 @@ +// +// 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_PROPERTY_TREE_IPP +#define INCLUDED_UHD_PROPERTY_TREE_IPP + +#include <uhd/exception.hpp> +#include <boost/foreach.hpp> +#include <vector> + +/*********************************************************************** + * Implement templated property impl + **********************************************************************/ +namespace uhd{ namespace /*anon*/{ + +template <typename T> class property_impl : public property<T>{ +public: + + property<T> &coerce(const typename property<T>::coercer_type &coercer){ + _coercer = coercer; + return *this; + } + + property<T> &publish(const typename property<T>::publisher_type &publisher){ + _publisher = publisher; + return *this; + } + + property<T> &subscribe(const typename property<T>::subscriber_type &subscriber){ + _subscribers.push_back(subscriber); + return *this; + } + + property<T> &update(void){ + this->set(this->get()); + return *this; + } + + property<T> &set(const T &value){ + _value = boost::shared_ptr<T>(new T(_coercer.empty()? value : _coercer(value))); + BOOST_FOREACH(typename property<T>::subscriber_type &subscriber, _subscribers){ + subscriber(*_value); //let errors propagate + } + return *this; + } + + T get(void) const{ + if (empty()) throw uhd::runtime_error("Cannot get() on an empty property"); + return _publisher.empty()? *_value : _publisher(); + } + + bool empty(void) const{ + return _publisher.empty() and _value.get() == NULL; + } + +private: + std::vector<typename property<T>::subscriber_type> _subscribers; + typename property<T>::publisher_type _publisher; + typename property<T>::coercer_type _coercer; + boost::shared_ptr<T> _value; +}; + +}} //namespace uhd::/*anon*/ + +/*********************************************************************** + * Implement templated methods for the property tree + **********************************************************************/ +namespace uhd{ + + template <typename T> property<T> &property_tree::create(const fs_path &path){ + this->_create(path, typename boost::shared_ptr<property<T> >(new property_impl<T>())); + return this->access<T>(path); + } + + template <typename T> property<T> &property_tree::access(const fs_path &path){ + return *boost::static_pointer_cast<property<T> >(this->_access(path)); + } + +} //namespace uhd + +#endif /* INCLUDED_UHD_PROPERTY_TREE_IPP */ diff --git a/host/include/uhd/stream.hpp b/host/include/uhd/stream.hpp new file mode 100644 index 000000000..c8ab303ad --- /dev/null +++ b/host/include/uhd/stream.hpp @@ -0,0 +1,224 @@ +// +// Copyright 2011-2012 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_STREAM_HPP +#define INCLUDED_UHD_STREAM_HPP + +#include <uhd/config.hpp> +#include <uhd/types/metadata.hpp> +#include <uhd/types/device_addr.hpp> +#include <uhd/types/ref_vector.hpp> +#include <boost/utility.hpp> +#include <boost/shared_ptr.hpp> +#include <vector> +#include <string> + +namespace uhd{ + +/*! + * A struct of parameters to construct a streamer. + * + * Note: + * Not all combinations of CPU and OTW format have conversion support. + * You may however write and register your own conversion routines. + */ +struct UHD_API stream_args_t{ + + //! Convenience constructor for streamer args + stream_args_t( + const std::string &cpu = "", + const std::string &otw = "" + ){ + cpu_format = cpu; + otw_format = otw; + } + + /*! + * The CPU format is a string that describes the format of host memory. + * Conversions for the following CPU formats have been implemented: + * - fc64 - complex<double> + * - fc32 - complex<float> + * - sc16 - complex<int16_t> + * - sc8 - complex<int8_t> + * + * The following are not implemented, but are listed to demonstrate naming convention: + * - f32 - float + * - f64 - double + * - s16 - int16_t + * - s8 - int8_t + */ + std::string cpu_format; + + /*! + * The OTW format is a string that describes the format over-the-wire. + * The following over-the-wire formats have been implemented: + * - sc16 - Q16 I16 + * - sc8 - Q8_1 I8_1 Q8_0 I8_0 + * + * The following are not implemented, but are listed to demonstrate naming convention: + * - s16 - R16_1 R16_0 + * - s8 - R8_3 R8_2 R8_1 R8_0 + */ + std::string otw_format; + + /*! + * The args parameter is used to pass arbitrary key/value pairs. + * Possible keys used by args (depends on implementation): + * + * - fullscale: specifies the full-scale amplitude when using floats. + * By default, the fullscale amplitude under floating point is 1.0. + * Set the "fullscale" to scale the samples in the host to the + * expected input range and/or output range of your application. + * + * - peak: specifies a fractional sample level to calculate scaling with the sc8 wire format. + * When using sc8 samples over the wire, the device must scale samples + * (both on the host and in the device) to satisfy the dynamic range needs. + * The peak value specifies a fraction of the maximum sample level (1.0 = 100%). + * Set peak to max_sample_level/full_scale_level to ensure optimum dynamic range. + * + * - underflow_policy: how the TX DSP should recover from underflow. + * Possible options are "next_burst" or "next_packet". + * In the "next_burst" mode, the DSP drops incoming packets until a new burst is started. + * In the "next_packet" mode, the DSP starts transmitting again at the next packet. + * + * - spp: (samples per packet) controls the size of RX packets. + * When not specified, the packets are always maximum frame size. + * Users should specify this option to request smaller than default + * packets, probably with the intention of reducing packet latency. + * + * The following are not implemented, but are listed for conceptual purposes: + * - function: magnitude or phase/magnitude + * - units: numeric units like counts or dBm + */ + device_addr_t args; + + /*! + * The channels is a list of channel numbers. + * Leave this blank to default to channel 0. + * Set channels for a multi-channel application. + * Channel mapping depends on the front-end selection. + */ + std::vector<size_t> channels; +}; + +/*! + * The RX streamer is the host interface to receiving samples. + * It represents the layer between the samples on the host + * and samples inside the device's receive DSP processing. + */ +class UHD_API rx_streamer : boost::noncopyable{ +public: + typedef boost::shared_ptr<rx_streamer> sptr; + + //! Get the number of channels associated with this streamer + virtual size_t get_num_channels(void) const = 0; + + //! Get the max number of samples per buffer per packet + virtual size_t get_max_num_samps(void) const = 0; + + //! Typedef for a pointer to a single, or a collection of recv buffers + typedef ref_vector<void *> buffs_type; + + /*! + * Receive buffers containing samples 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. + * + * The one_packet option allows the user to guarantee that + * the call will return after a single packet has been processed. + * This may be useful to maintain packet boundaries in some cases. + * + * \param buffs a vector of writable memory to fill with samples + * \param nsamps_per_buff the size of each buffer in number of samples + * \param metadata data to fill describing the buffer + * \param timeout the timeout in seconds to wait for a packet + * \param one_packet return after the first packet is received + * \return the number of samples received or 0 on error + */ + virtual size_t recv( + const buffs_type &buffs, + const size_t nsamps_per_buff, + rx_metadata_t &metadata, + const double timeout = 0.1, + const bool one_packet = false + ) = 0; +}; + +/*! + * The TX streamer is the host interface to transmitting samples. + * It represents the layer between the samples on the host + * and samples inside the device's transmit DSP processing. + */ +class UHD_API tx_streamer : boost::noncopyable{ +public: + typedef boost::shared_ptr<tx_streamer> sptr; + + //! Get the number of channels associated with this streamer + virtual size_t get_num_channels(void) const = 0; + + //! Get the max number of samples per buffer per packet + virtual size_t get_max_num_samps(void) const = 0; + + //! Typedef for a pointer to a single, or a collection of send buffers + typedef ref_vector<const void *> buffs_type; + + /*! + * Send buffers containing samples described by the metadata. + * + * Send handles fragmentation as follows: + * If the buffer has more items 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. + * + * 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 samples + * \param nsamps_per_buff the number of samples to send, per buffer + * \param metadata data describing the buffer's contents + * \param timeout the timeout in seconds to wait on a packet + * \return the number of samples sent + */ + virtual size_t send( + const buffs_type &buffs, + const size_t nsamps_per_buff, + const tx_metadata_t &metadata, + const double timeout = 0.1 + ) = 0; +}; + +} //namespace uhd + +#endif /* INCLUDED_UHD_STREAM_HPP */ diff --git a/host/include/uhd/transport/CMakeLists.txt b/host/include/uhd/transport/CMakeLists.txt new file mode 100644 index 000000000..bf7497ee7 --- /dev/null +++ b/host/include/uhd/transport/CMakeLists.txt @@ -0,0 +1,33 @@ +# +# 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 + COMPONENT headers +) diff --git a/host/include/uhd/transport/bounded_buffer.hpp b/host/include/uhd/transport/bounded_buffer.hpp new file mode 100644 index 000000000..620a708d0 --- /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 + */ + UHD_INLINE 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 + */ + UHD_INLINE 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 + */ + UHD_INLINE 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 + */ + UHD_INLINE 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 + */ + UHD_INLINE 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 + */ + UHD_INLINE 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 + */ + UHD_INLINE 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..9c24005b7 --- /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/utility.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 : boost::noncopyable{ + 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; + this->pop_back(elem); + 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); + this->pop_back(elem); + 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; + this->pop_back(elem); + 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 void pop_back(elem_type &elem){ + elem = _buffer.back(); + _buffer.back() = elem_type(); + _buffer.pop_back(); + } + + 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..ead3ad4b7 --- /dev/null +++ b/host/include/uhd/transport/udp_simple.hpp @@ -0,0 +1,98 @@ +// +// 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 <uhd/types/serial.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); + + /*! + * Make a UART interface from a UDP transport. + * \param udp the UDP transport object + * \return a new UART interface + */ + static uart_iface::sptr make_uart(sptr udp); + + /*! + * 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; + + /*! + * Get the last IP address as seen by recv(). + * Only use this with the broadcast socket. + */ + virtual std::string get_recv_addr(void) = 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..2af4b3bbe --- /dev/null +++ b/host/include/uhd/transport/usb_control.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_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 + * \param interface the USB interface number for the control transport + */ + static sptr make(usb_device_handle::sptr handle, const size_t interface); + + /*! + * 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..24b709ec9 --- /dev/null +++ b/host/include/uhd/transport/usb_zero_copy.hpp @@ -0,0 +1,86 @@ +// +// 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_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_interface an integer specifiying an IN interface number + * \param recv_endpoint an integer specifiying an IN endpoint number + * \param send_interface an integer specifiying an OUT interface number + * \param send_endpoint an integer specifiying an OUT endpoint number + * \param hints optional parameters to pass to the underlying transport + * \return a new zero copy usb object + */ + static sptr make( + usb_device_handle::sptr handle, + const size_t recv_interface, + const size_t recv_endpoint, + const size_t send_interface, + const size_t send_endpoint, + const device_addr_t &hints = device_addr_t() + ); + + /*! + * Make a wrapper around a zero copy implementation. + * The wrapper performs the following functions: + * - Pad commits to the frame boundary + * - Extract multiple packets on recv + * + * When enable multiple receive packets is set to true, + * the implementation inspects the vita length on transfers, + * and may split a single transfer into multiple managed buffers. + * + * \param usb_zc a usb zero copy interface object + * \param usb_frame_boundary bytes per frame + * \return a new zero copy wrapper object + */ + static sptr make_wrapper( + sptr usb_zc, size_t usb_frame_boundary = 512 + ); +}; + +}} //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..1be480874 --- /dev/null +++ b/host/include/uhd/transport/vrt_if_packet.hpp @@ -0,0 +1,107 @@ +// +// 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_payload_bytes; //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..1dc0e8e26 --- /dev/null +++ b/host/include/uhd/transport/zero_copy.hpp @@ -0,0 +1,164 @@ +// +// Copyright 2010-2012 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> +#include <boost/intrusive_ptr.hpp> +#include <boost/detail/atomic_count.hpp> + +namespace uhd{ namespace transport{ + + //! Simple managed buffer with release interface + class UHD_API managed_buffer{ + public: + managed_buffer(void):_ref_count(0){} + + /*! + * 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; + + /*! + * Use commit() to re-write the length (for use with send buffers). + * \param num_bytes the number of bytes written into the buffer + */ + UHD_INLINE void commit(size_t num_bytes){ + _length = num_bytes; + } + + /*! + * Get a pointer to the underlying buffer. + * \return a pointer into memory + */ + template <class T> UHD_INLINE T cast(void) const{ + return static_cast<T>(_buffer); + } + + /*! + * Get the size of the underlying buffer. + * \return the number of bytes + */ + UHD_INLINE size_t size(void) const{ + return _length; + } + + //! Create smart pointer to a reusable managed buffer + template <typename T> UHD_INLINE boost::intrusive_ptr<T> make( + T *p, void *buffer, size_t length + ){ + _buffer = buffer; + _length = length; + return boost::intrusive_ptr<T>(p); + } + + boost::detail::atomic_count _ref_count; + + protected: + void *_buffer; + size_t _length; + }; + + UHD_INLINE void intrusive_ptr_add_ref(managed_buffer *p){ + ++(p->_ref_count); + } + + UHD_INLINE void intrusive_ptr_release(managed_buffer *p){ + if (--(p->_ref_count) == 0) p->release(); + } + + /*! + * 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 managed_buffer{ + public: + typedef boost::intrusive_ptr<managed_recv_buffer> sptr; + }; + + /*! + * 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 managed_buffer{ + public: + typedef boost::intrusive_ptr<managed_send_buffer> sptr; + }; + + /*! + * 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..0971ca472 --- /dev/null +++ b/host/include/uhd/types/CMakeLists.txt @@ -0,0 +1,38 @@ +# +# 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 + COMPONENT headers +) diff --git a/host/include/uhd/types/clock_config.hpp b/host/include/uhd/types/clock_config.hpp new file mode 100644 index 000000000..27b312245 --- /dev/null +++ b/host/include/uhd/types/clock_config.hpp @@ -0,0 +1,66 @@ +// +// 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{ + + /*! + * The DEPRECATED Clock configuration settings: + * The source for the 10MHz reference clock. + * The source and polarity for the PPS clock. + * + * Deprecated in favor of set time/clock source calls. + * Its still in this file for the sake of gr-uhd swig. + * + * Use the convenience functions external() and internal(), + * unless you have a special purpose and cannot use them. + */ + struct UHD_API clock_config_t{ + //------ simple usage --------// + + //! A convenience function to create an external clock configuration + static clock_config_t external(void); + + //! A convenience function to create an internal clock configuration + static clock_config_t internal(void); + + //------ advanced usage --------// + enum ref_source_t { + REF_AUTO = int('a'), //automatic (device specific) + REF_INT = int('i'), //internal reference + REF_SMA = int('s'), //external sma port + REF_MIMO = int('m'), //reference from mimo cable + } ref_source; + enum pps_source_t { + PPS_INT = int('i'), //there is no internal + PPS_SMA = int('s'), //external sma port + PPS_MIMO = int('m'), //time sync from mimo cable + } pps_source; + enum pps_polarity_t { + PPS_NEG = int('n'), //negative edge + PPS_POS = int('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..967ad7908 --- /dev/null +++ b/host/include/uhd/types/io_type.hpp @@ -0,0 +1,79 @@ +// +// 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 DEPRECATED Input/Output configuration struct: + * Used to specify the IO type with device send/recv. + * + * Deprecated in favor of streamer interface. + * Its still in this file for the sake of gr-uhd swig. + */ + 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 = int('?'), + //! Complex floating point (64-bit floats) range [-1.0, +1.0] + COMPLEX_FLOAT64 = int('d'), + //! Complex floating point (32-bit floats) range [-1.0, +1.0] + COMPLEX_FLOAT32 = int('f'), + //! Complex signed integer (16-bit integers) range [-32768, +32767] + COMPLEX_INT16 = int('s'), + //! Complex signed integer (8-bit integers) range [-128, 127] + COMPLEX_INT8 = int('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..788999900 --- /dev/null +++ b/host/include/uhd/types/metadata.hpp @@ -0,0 +1,163 @@ +// +// Copyright 2010-2012 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> +#include <boost/cstdint.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, + //! Multi-channel alignment failed. + ERROR_CODE_ALIGNMENT = 0xc, + //! 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. + 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, + //! Some kind of custom user payload + EVENT_CODE_USER_PAYLOAD = 0x40 + } event_code; + + /*! + * A special payload populated by custom FPGA fabric. + */ + boost::uint32_t user_payload[4]; + + }; + +} //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..6dc634fc8 --- /dev/null +++ b/host/include/uhd/types/otw_type.hpp @@ -0,0 +1,2 @@ +//The OTW type API has been deprecated in favor of the streamer interface +#include <uhd/deprecated.hpp> diff --git a/host/include/uhd/types/ranges.hpp b/host/include/uhd/types/ranges.hpp new file mode 100644 index 000000000..ac632df93 --- /dev/null +++ b/host/include/uhd/types/ranges.hpp @@ -0,0 +1,119 @@ +// +// Copyright 2010-2012 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 <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: double _start, _stop, _step; + }; + + /*! + * 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..f66822775 --- /dev/null +++ b/host/include/uhd/types/serial.hpp @@ -0,0 +1,202 @@ +// +// 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_SERIAL_HPP +#define INCLUDED_UHD_TYPES_SERIAL_HPP + +#include <uhd/config.hpp> +#include <boost/shared_ptr.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: + typedef boost::shared_ptr<i2c_iface> sptr; + + /*! + * 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: + typedef boost::shared_ptr<spi_iface> sptr; + + /*! + * 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::uint32_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::uint32_t data, + size_t num_bits + ); + }; + + /*! + * UART interface to write and read bytes. + */ + class UHD_API uart_iface{ + public: + typedef boost::shared_ptr<uart_iface> sptr; + + /*! + * Write to a serial port. + * \param buf the data to write + */ + virtual void write_uart(const std::string &buf) = 0; + + /*! + * Read from a serial port. + * Reads until complete line or timeout. + * \param timeout the timeout in seconds + * \return the data read from the serial port + */ + virtual std::string read_uart(double timeout) = 0; + }; + +} //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..3c34c9656 --- /dev/null +++ b/host/include/uhd/types/stream_cmd.hpp @@ -0,0 +1,64 @@ +// +// Copyright 2010-2012 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 = int('a'), + STREAM_MODE_STOP_CONTINUOUS = int('o'), + STREAM_MODE_NUM_SAMPS_AND_DONE = int('d'), + STREAM_MODE_NUM_SAMPS_AND_MORE = int('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..e7d7d5ab4 --- /dev/null +++ b/host/include/uhd/types/time_spec.hpp @@ -0,0 +1,141 @@ +// +// Copyright 2010-2012 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 seconds and fractional ticks. + * 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); + + /*! + * Create a time_spec_t from a 64-bit tick count. + * Translation from clock-domain specific units. + * \param ticks an integer count of ticks + * \param tick_rate the number of ticks per second + */ + static time_spec_t from_ticks(long long ticks, 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; + + /*! + * Convert the time spec into a 64-bit tick count. + * Translation into clock-domain specific units. + * \param tick_rate the number of ticks per second + * \return an integer number of ticks + */ + long long to_ticks(const 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 &); + + UHD_INLINE time_t time_spec_t::get_full_secs(void) const{ + return this->_full_secs; + } + + UHD_INLINE double time_spec_t::get_frac_secs(void) const{ + return this->_frac_secs; + } + +} //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..9c498bfe9 --- /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 RF 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 RF 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 = int('N'), + //! Automatically determine the argument's value. + POLICY_AUTO = int('A'), + //! Use the argument's value for the setting. + POLICY_MANUAL = int('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 RF frequency. + * Automatic behavior: the target frequency + default LO offset. + */ + policy_t rf_freq_policy; + + /*! + * The RF frequency in Hz. + * Set when the policy is set to manual. + */ + double rf_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..e51473085 --- /dev/null +++ b/host/include/uhd/types/tune_result.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_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. + */ + struct UHD_API tune_result_t{ + double target_rf_freq; + double actual_rf_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..d7b936fc2 --- /dev/null +++ b/host/include/uhd/usrp/CMakeLists.txt @@ -0,0 +1,38 @@ +# +# 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 + + #### dboard headers ### + dboard_base.hpp + dboard_eeprom.hpp + dboard_id.hpp + dboard_iface.hpp + dboard_manager.hpp + + ### utilities ### + gps_ctrl.hpp + mboard_eeprom.hpp + subdev_spec.hpp + + ### interfaces ### + multi_usrp.hpp + + DESTINATION ${INCLUDE_DIR}/uhd/usrp + COMPONENT headers +) diff --git a/host/include/uhd/usrp/dboard_base.hpp b/host/include/uhd/usrp/dboard_base.hpp new file mode 100644 index 000000000..31b3643c7 --- /dev/null +++ b/host/include/uhd/usrp/dboard_base.hpp @@ -0,0 +1,98 @@ +// +// 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/property_tree.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); + +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); + property_tree::sptr get_rx_subtree(void); + property_tree::sptr get_tx_subtree(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); +}; + +/*! + * 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); +}; + +/*! + * 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); +}; + +}} //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..93fc5ac7d --- /dev/null +++ b/host/include/uhd/usrp/dboard_eeprom.hpp @@ -0,0 +1,62 @@ +// +// 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; + + //! A hardware revision number + std::string revision; + + /*! + * 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) const; + +}; + +}} //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..6a6a68321 --- /dev/null +++ b/host/include/uhd/usrp/dboard_iface.hpp @@ -0,0 +1,298 @@ +// +// 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 uhd::i2c_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 = int('r'), + UNIT_TX = int('t') + }; + + //! possible atr registers + enum atr_reg_t{ + ATR_REG_IDLE = int('i'), + ATR_REG_TX_ONLY = int('t'), + ATR_REG_RX_ONLY = int('r'), + ATR_REG_FULL_DUPLEX = int('f') + }; + + //! aux dac selection enums (per unit) + enum aux_dac_t{ + AUX_DAC_A = int('a'), + AUX_DAC_B = int('b'), + AUX_DAC_C = int('c'), + AUX_DAC_D = int('d') + }; + + //! aux adc selection enums (per unit) + enum aux_adc_t{ + AUX_ADC_A = int('a'), + AUX_ADC_B = int('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 data to SPI bus peripheral. + * + * \param unit which unit, rx or tx + * \param config configuration settings + * \param data the bits to write MSB 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 MSB 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..d3a3ffb5c --- /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/property_tree.hpp> +#include <uhd/usrp/dboard_base.hpp> +#include <uhd/usrp/dboard_id.hpp> +#include <boost/utility.hpp> +#include <boost/shared_ptr.hpp> +#include <string> +#include <vector> + +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 std::vector<std::string> &subdev_names = std::vector<std::string>(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 std::vector<std::string> &subdev_names = std::vector<std::string>(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 gdboard_id the id of the grand-dboard + * \param iface the custom dboard interface + * \param subtree the subtree to load with props + * \return an sptr to the new dboard manager + */ + static sptr make( + dboard_id_t rx_dboard_id, + dboard_id_t tx_dboard_id, + dboard_id_t gdboard_id, + dboard_iface::sptr iface, + property_tree::sptr subtree + ); +}; + +}} //namespace + +#endif /* INCLUDED_UHD_USRP_DBOARD_MANAGER_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..0c1389d48 --- /dev/null +++ b/host/include/uhd/usrp/gps_ctrl.hpp @@ -0,0 +1,61 @@ +// +// 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_GPS_CTRL_HPP +#define INCLUDED_GPS_CTRL_HPP + +#include <uhd/types/serial.hpp> +#include <uhd/types/sensors.hpp> +#include <boost/shared_ptr.hpp> +#include <boost/utility.hpp> +#include <boost/function.hpp> +#include <vector> + +namespace uhd{ + +class UHD_API 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(uart_iface::sptr uart); + + /*! + * Retrieve the list of sensors this GPS object provides + */ + virtual std::vector<std::string> get_sensors(void) = 0; + + /*! + * Retrieve the named sensor + */ + virtual uhd::sensor_value_t get_sensor(std::string key) = 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. + +}; + +} //namespace uhd + +#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..f064e9956 --- /dev/null +++ b/host/include/uhd/usrp/mboard_eeprom.hpp @@ -0,0 +1,58 @@ +// +// Copyright 2010-2012 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>{ + + //! Make a new empty mboard eeprom + mboard_eeprom_t(void); + + /*! + * Make a new mboard EEPROM handler. + * \param iface the interface to i2c + * \param which which EEPROM map to use + */ + mboard_eeprom_t(i2c_iface &iface, const std::string &which); + + /*! + * Write the contents of this object to the EEPROM. + * \param iface the interface to i2c + * \param which which EEPROM map to use + */ + void commit(i2c_iface &iface, const std::string &which) const; + + }; + +}} //namespace + +#endif /* INCLUDED_UHD_USRP_MBOARD_EEPROM_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..2e83823ba --- /dev/null +++ b/host/include/uhd/usrp/multi_usrp.hpp @@ -0,0 +1,855 @@ +// +// Copyright 2010-2012 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 + +//define API capabilities for compile time detection of new features +#define UHD_USRP_MULTI_USRP_REF_SOURCES_API +#define UHD_USRP_MULTI_USRP_GET_RATES_API +#define UHD_USRP_MULTI_USRP_FRONTEND_CAL_API +#define UHD_USRP_MULTI_USRP_COMMAND_TIME_API +#define UHD_USRP_MULTI_USRP_BW_RANGE_API +#define UHD_USRP_MULTI_USRP_USER_REGS_API +#define UHD_USRP_MULTI_USRP_GET_USRP_INFO_API + +#include <uhd/config.hpp> +#include <uhd/device.hpp> +#include <uhd/deprecated.hpp> +#include <uhd/types/ranges.hpp> +#include <uhd/types/stream_cmd.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 <boost/shared_ptr.hpp> +#include <boost/utility.hpp> +#include <complex> +#include <string> +#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 frontend 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 frontend specification size + * - All boards share a common TX frontend 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 frontend (RX channel 0) + * dev->set_rx_subdev_spec("A:A", 0); + * + * //set the board on 10.3 to use the B RX frontend (RX channel 1) + * dev->set_rx_subdev_spec("A:B", 1); + * + * //set both boards to use the AB TX frontend (TX channels 0 and 1) + * dev->set_tx_subdev_spec("A: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; + + //! Convenience method to get a RX streamer + rx_streamer::sptr get_rx_stream(const stream_args_t &args){ + return this->get_device()->get_rx_stream(args); + } + + //! Convenience method to get a TX streamer + tx_streamer::sptr get_tx_stream(const stream_args_t &args){ + return this->get_device()->get_tx_stream(args); + } + + /*! + * Returns identifying information about this USRP's configuration. + * Returns motherboard ID, name, and serial. + * Returns daughterboard RX ID, subdev name and spec, serial, and antenna. + * \param chan channel index 0 to N-1 + * \return RX info + */ + virtual dict<std::string, std::string> get_usrp_rx_info(size_t chan = 0) = 0; + + /*! + * Returns identifying information about this USRP's configuration. + * Returns motherboard ID, name, and serial. + * Returns daughterboard TX ID, subdev name and spec, serial, and antenna. + * \param chan channel index 0 to N-1 + * \return TX info + */ + virtual dict<std::string, std::string> get_usrp_tx_info(size_t chan = 0) = 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 + * \param mboard the motherboard index 0 to M-1 + */ + virtual void set_time_next_pps(const time_spec_t &time_spec, size_t mboard = ALL_MBOARDS) = 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; + + /*! + * Set the time at which the control commands will take effect. + * + * A timed command will back-pressure all subsequent timed commands, + * assuming that the subsequent commands occur within the time-window. + * If the time spec is late, the command will be activated upon arrival. + * + * \param time_spec the time at which the next command will activate + * \param mboard which motherboard to set the config + */ + virtual void set_command_time(const uhd::time_spec_t &time_spec, size_t mboard = ALL_MBOARDS) = 0; + + /*! + * Clear the command time so future commands are sent ASAP. + * + * \param mboard which motherboard to set the config + */ + virtual void clear_command_time(size_t mboard = ALL_MBOARDS) = 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. + * DEPRECATED in favor of set time and clock source calls. + * 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; + + /*! + * Set the time source for the usrp device. + * This sets the method of time synchronization, + * typically a pulse per second or an encoded time. + * Typical options for source: external, MIMO. + * \param source a string representing the time source + * \param mboard which motherboard to set the config + */ + virtual void set_time_source(const std::string &source, const size_t mboard = ALL_MBOARDS) = 0; + + /*! + * Get the currently set time source. + * \param mboard which motherboard to get the config + * \return the string representing the time source + */ + virtual std::string get_time_source(const size_t mboard) = 0; + + /*! + * Get a list of possible time sources. + * \param mboard which motherboard to get the list + * \return a vector of strings for possible settings + */ + virtual std::vector<std::string> get_time_sources(const size_t mboard) = 0; + + /*! + * Set the clock source for the usrp device. + * This sets the source for a 10 Mhz reference clock. + * Typical options for source: internal, external, MIMO. + * \param source a string representing the clock source + * \param mboard which motherboard to set the config + */ + virtual void set_clock_source(const std::string &source, const size_t mboard = ALL_MBOARDS) = 0; + + /*! + * Get the currently set clock source. + * \param mboard which motherboard to get the config + * \return the string representing the clock source + */ + virtual std::string get_clock_source(const size_t mboard) = 0; + + /*! + * Get a list of possible clock sources. + * \param mboard which motherboard to get the list + * \return a vector of strings for possible settings + */ + virtual std::vector<std::string> get_clock_sources(const size_t mboard) = 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; + + /*! + * Perform write on the user configuration register bus. These only exist if + * the user has implemented custom setting registers in the device FPGA. + * \param addr 8-bit register address + * \param data 32-bit register value + * \param mboard which motherboard to set the user register + */ + virtual void set_user_register(const boost::uint8_t addr, const boost::uint32_t data, size_t mboard = ALL_MBOARDS) = 0; + + /******************************************************************* + * RX methods + ******************************************************************/ + /*! + * Set the RX frontend 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 frontend 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 frontend specification. + * \param mboard the motherboard index 0 to M-1 + * \return the frontend 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 frontend. + * \param chan the channel index 0 to N-1 + * \return the frontend 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; + + /*! + * Get a range of possible RX rates. + * \param chan the channel index 0 to N-1 + * \return the meta range of rates + */ + virtual meta_range_t get_rx_rates(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; + + /*! + * Get the center frequency range of the RF frontend. + * \param chan the channel index 0 to N-1 + * \return a frequency range object + */ + virtual freq_range_t get_fe_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 frontend. + * \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 frontend. + * \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 frontend. + * \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 frontend. + * \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 frontend. + * \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 frontend. + * \param chan the channel index 0 to N-1 + * \return the bandwidth in Hz + */ + virtual double get_rx_bandwidth(size_t chan = 0) = 0; + + /*! + * Get the range of the possible RX bandwidth settings. + * \param chan the channel index 0 to N-1 + * \return a range of bandwidths in Hz + */ + virtual meta_range_t get_rx_bandwidth_range(size_t chan = 0) = 0; + + /*! + * Read the RSSI value on the RX frontend. + * \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 frontend. + * 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 frontend 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 frontend 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; + + /*! + * Enable/disable the automatic RX DC offset correction. + * The automatic correction subtracts out the long-run average. + * + * When disabled, the averaging option operation is halted. + * Once halted, the average value will be held constant + * until the user re-enables the automatic correction + * or overrides the value by manually setting the offset. + * + * \param enb true to enable automatic DC offset correction + * \param chan the channel index 0 to N-1 + */ + virtual void set_rx_dc_offset(const bool enb, size_t chan = ALL_CHANS) = 0; + + /*! + * Set a constant RX DC offset value. + * The value is complex to control both I and Q. + * Only set this when automatic correction is disabled. + * \param offset the dc offset (1.0 is full-scale) + * \param chan the channel index 0 to N-1 + */ + virtual void set_rx_dc_offset(const std::complex<double> &offset, size_t chan = ALL_CHANS) = 0; + + /*! + * Set the RX frontend IQ imbalance correction. + * Use this to adjust the magnitude and phase of I and Q. + * + * \param correction the complex correction (1.0 is full-scale) + * \param chan the channel index 0 to N-1 + */ + virtual void set_rx_iq_balance(const std::complex<double> &correction, size_t chan = ALL_CHANS) = 0; + + /******************************************************************* + * TX methods + ******************************************************************/ + /*! + * Set the TX frontend 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 frontend 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 frontend specification. + * \param mboard the motherboard index 0 to M-1 + * \return the frontend 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 frontend. + * \param chan the channel index 0 to N-1 + * \return the frontend 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; + + /*! + * Get a range of possible TX rates. + * \param chan the channel index 0 to N-1 + * \return the meta range of rates + */ + virtual meta_range_t get_tx_rates(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; + + /*! + * Get the center frequency range of the TX frontend. + * \param chan the channel index 0 to N-1 + * \return a frequency range object + */ + virtual freq_range_t get_fe_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 frontend. + * \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 frontend. + * \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 frontend. + * \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 frontend. + * \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 frontend. + * \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 frontend. + * \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 range of the possible TX bandwidth settings. + * \param chan the channel index 0 to N-1 + * \return a range of bandwidths in Hz + */ + virtual meta_range_t get_tx_bandwidth_range(size_t chan = 0) = 0; + + /*! + * Get the dboard interface object for the TX frontend. + * 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 frontend 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 frontend 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; + + /*! + * Set a constant TX DC offset value. + * The value is complex to control both I and Q. + * \param offset the dc offset (1.0 is full-scale) + * \param chan the channel index 0 to N-1 + */ + virtual void set_tx_dc_offset(const std::complex<double> &offset, size_t chan = ALL_CHANS) = 0; + + /*! + * Set the TX frontend IQ imbalance correction. + * Use this to adjust the magnitude and phase of I and Q. + * + * \param correction the complex correction (1.0 is full-scale) + * \param chan the channel index 0 to N-1 + */ + virtual void set_tx_iq_balance(const std::complex<double> &correction, size_t chan = ALL_CHANS) = 0; + +}; + +}} + +#endif /* INCLUDED_UHD_USRP_MULTI_USRP_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..62c1fc177 --- /dev/null +++ b/host/include/uhd/usrp/subdev_spec.hpp @@ -0,0 +1,91 @@ +// +// 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. + */ + 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/utils/CMakeLists.txt b/host/include/uhd/utils/CMakeLists.txt new file mode 100644 index 000000000..de91993fe --- /dev/null +++ b/host/include/uhd/utils/CMakeLists.txt @@ -0,0 +1,39 @@ +# +# Copyright 2010-2012 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 + atomic.hpp + byteswap.hpp + byteswap.ipp + csv.hpp + gain_group.hpp + images.hpp + log.hpp + msg.hpp + paths.hpp + pimpl.hpp + safe_call.hpp + safe_main.hpp + static.hpp + tasks.hpp + thread_priority.hpp + DESTINATION ${INCLUDE_DIR}/uhd/utils + COMPONENT headers +) 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/atomic.hpp b/host/include/uhd/utils/atomic.hpp new file mode 100644 index 000000000..7a81d8d5e --- /dev/null +++ b/host/include/uhd/utils/atomic.hpp @@ -0,0 +1,161 @@ +// +// Copyright 2012 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_ATOMIC_HPP +#define INCLUDED_UHD_UTILS_ATOMIC_HPP + +#include <uhd/config.hpp> +#include <uhd/types/time_spec.hpp> +#include <boost/thread/thread.hpp> +#include <boost/interprocess/detail/atomic.hpp> + +#include <boost/version.hpp> +#if BOOST_VERSION >= 104800 +# define BOOST_IPC_DETAIL boost::interprocess::ipcdetail +#else +# define BOOST_IPC_DETAIL boost::interprocess::detail +#endif + +namespace uhd{ + + //! A 32-bit integer that can be atomically accessed + class UHD_API atomic_uint32_t{ + public: + + //! Create a new atomic 32-bit integer, initialized to zero + UHD_INLINE atomic_uint32_t(void){ + this->write(0); + } + + //! Compare with cmp, swap with newval if same, return old value + UHD_INLINE boost::uint32_t cas(boost::uint32_t newval, boost::uint32_t cmp){ + return BOOST_IPC_DETAIL::atomic_cas32(&_num, newval, cmp); + } + + //! Sets the atomic integer to a new value + UHD_INLINE void write(const boost::uint32_t newval){ + BOOST_IPC_DETAIL::atomic_write32(&_num, newval); + } + + //! Gets the current value of the atomic integer + UHD_INLINE boost::uint32_t read(void){ + return BOOST_IPC_DETAIL::atomic_read32(&_num); + } + + //! Increment by 1 and return the old value + UHD_INLINE boost::uint32_t inc(void){ + return BOOST_IPC_DETAIL::atomic_inc32(&_num); + } + + //! Decrement by 1 and return the old value + UHD_INLINE boost::uint32_t dec(void){ + return BOOST_IPC_DETAIL::atomic_dec32(&_num); + } + + private: volatile boost::uint32_t _num; + }; + + /*! + * A reusable barrier to sync multiple threads. + * All threads spin on wait() until count is reset. + */ + class UHD_API reusable_barrier{ + public: + + //! Resize the barrier for N threads + void resize(const size_t size){ + _size = size; + _count.write(size); + } + + /*! + * Force the barrier wait to throw a boost::thread_interrupted + * The threads were not getting the interruption_point on windows. + */ + void interrupt(void) + { + _count.write(boost::uint32_t(~0)); + } + + //! Wait on the barrier condition + UHD_INLINE void wait(void){ + _count.dec(); + _count.cas(_size, 0); + while (_count.read() != _size){ + boost::this_thread::interruption_point(); + if (_count.read() == boost::uint32_t(~0)) + throw boost::thread_interrupted(); + boost::this_thread::yield(); + } + } + + private: + size_t _size; + atomic_uint32_t _count; + }; + + /*! + * Spin-wait on a condition with a timeout. + * \param cond an atomic variable to compare + * \param value compare to atomic for true/false + * \param timeout the timeout in seconds + * \return true for cond == value, false for timeout + */ + UHD_INLINE bool spin_wait_with_timeout( + atomic_uint32_t &cond, + boost::uint32_t value, + const double timeout + ){ + if (cond.read() == value) return true; + const time_spec_t exit_time = time_spec_t::get_system_time() + time_spec_t(timeout); + while (cond.read() != value){ + if (time_spec_t::get_system_time() > exit_time) return false; + boost::this_thread::interruption_point(); + boost::this_thread::yield(); + } + return true; + } + + /*! + * Claimer class to provide synchronization for multi-thread access. + * Claiming enables buffer classes to be used with a buffer queue. + */ + class simple_claimer{ + public: + simple_claimer(void){ + this->release(); + } + + UHD_INLINE void release(void){ + _locked.write(0); + } + + UHD_INLINE bool claim_with_wait(const double timeout){ + if (spin_wait_with_timeout(_locked, 0, timeout)){ + _locked.write(1); + return true; + } + return false; + } + + private: + atomic_uint32_t _locked; + }; + +} //namespace uhd + +#endif /* INCLUDED_UHD_UTILS_ATOMIC_HPP */ diff --git a/host/include/uhd/utils/byteswap.hpp b/host/include/uhd/utils/byteswap.hpp new file mode 100644 index 000000000..2b5a46c66 --- /dev/null +++ b/host/include/uhd/utils/byteswap.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_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); + + //! worknet to host: short, long, or long-long + template<typename T> T wtohx(T); + + //! host to worknet: short, long, or long-long + template<typename T> T htowx(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..5b2a7252f --- /dev/null +++ b/host/include/uhd/utils/byteswap.ipp @@ -0,0 +1,136 @@ +// +// 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_BYTESWAP_IPP +#define INCLUDED_UHD_UTILS_BYTESWAP_IPP + +/*********************************************************************** + * Platform-specific implementation details for byteswap below: + **********************************************************************/ +#if defined(BOOST_MSVC) //http://msdn.microsoft.com/en-us/library/a3140177%28VS.80%29.aspx + #include <cstdlib> + + 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__ >= 3 + + 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 +} + +template<typename T> UHD_INLINE T uhd::wtohx(T num){ + #ifdef BOOST_BIG_ENDIAN + return uhd::byteswap(num); + #else + return num; + #endif +} + +template<typename T> UHD_INLINE T uhd::htowx(T num){ + #ifdef BOOST_BIG_ENDIAN + return uhd::byteswap(num); + #else + return num; + #endif +} + +#endif /* INCLUDED_UHD_UTILS_BYTESWAP_IPP */ diff --git a/host/include/uhd/utils/csv.hpp b/host/include/uhd/utils/csv.hpp new file mode 100644 index 000000000..8dbb28377 --- /dev/null +++ b/host/include/uhd/utils/csv.hpp @@ -0,0 +1,35 @@ +// +// 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_CSV_HPP +#define INCLUDED_UHD_UTILS_CSV_HPP + +#include <uhd/config.hpp> +#include <vector> +#include <string> +#include <istream> + +namespace uhd{ namespace csv{ + typedef std::vector<std::string> row_type; + typedef std::vector<row_type> rows_type; + + //! Convert an input stream to csv rows. + UHD_API rows_type to_rows(std::istream &input); + +}} //namespace uhd::csv + +#endif /* INCLUDED_UHD_UTILS_CSV_HPP */ 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..a0934fb08 --- /dev/null +++ b/host/include/uhd/utils/images.hpp @@ -0,0 +1,53 @@ +// +// Copyright 2010,2012 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); + + /*! + * Search for the location of the UHD Images Downloader script. + * \return the full system path to uhd_images_downloader.py + */ + + UHD_API std::string find_images_downloader(void); + + /*! + * Return the error string for recommending using the UHD Images Downloader. + * String depends on OS. + * \return the message suggesting the use of uhd_images_downloader.py + */ + + UHD_API std::string print_images_error(void); + +} //namespace uhd + +#endif /* INCLUDED_UHD_UTILS_IMAGES_HPP */ diff --git a/host/include/uhd/utils/log.hpp b/host/include/uhd/utils/log.hpp new file mode 100644 index 000000000..1f515c15e --- /dev/null +++ b/host/include/uhd/utils/log.hpp @@ -0,0 +1,97 @@ +// +// 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_LOG_HPP +#define INCLUDED_UHD_UTILS_LOG_HPP + +#include <uhd/config.hpp> +#include <uhd/utils/pimpl.hpp> +#include <boost/current_function.hpp> +#include <ostream> +#include <string> + +/*! \file log.hpp + * The UHD logging facility. + * + * The logger enables UHD library code to easily log events into a file. + * Log entries are time-stamped and stored with file, line, and function. + * Each call to the UHD_LOG macros is synchronous and thread-safe. + * + * The log file can be found in the path <temp-directory>/uhd.log, + * where <temp-directory> is the user or system's temporary directory. + * To override <temp-directory>, set the UHD_TEMP_PATH environment variable. + * + * All log messages with verbosity greater than or equal to the log level + * (in other words, as often or less often than the current log level) + * are recorded into the log file. All other messages are sent to null. + * + * The default log level is "never", but can be overridden: + * - at compile time by setting the pre-processor define UHD_LOG_LEVEL. + * - at runtime by setting the environment variable UHD_LOG_LEVEL. + * + * UHD_LOG_LEVEL can be the name of a verbosity enum or integer value: + * - Example pre-processor define: -DUHD_LOG_LEVEL=3 + * - Example pre-processor define: -DUHD_LOG_LEVEL=regularly + * - Example environment variable: export UHD_LOG_LEVEL=3 + * - Example environment variable: export UHD_LOG_LEVEL=regularly + */ + +/*! + * A UHD logger macro with configurable verbosity. + * Usage: UHD_LOGV(very_rarely) << "the log message" << std::endl; + */ +#define UHD_LOGV(verbosity) \ + uhd::_log::log(uhd::_log::verbosity, __FILE__, __LINE__, BOOST_CURRENT_FUNCTION)() + +/*! + * A UHD logger macro with default verbosity. + * Usage: UHD_LOG << "the log message" << std::endl; + */ +#define UHD_LOG \ + UHD_LOGV(regularly) + + +namespace uhd{ namespace _log{ + + //! Verbosity levels for the logger + enum verbosity_t{ + always = 1, + often = 2, + regularly = 3, + rarely = 4, + very_rarely = 5, + never = 6, + }; + + //! Internal logging object (called by UHD_LOG macros) + class UHD_API log{ + public: + log( + const verbosity_t verbosity, + const std::string &file, + const unsigned int line, + const std::string &function + ); + ~log(void); + std::ostream &operator()(void); + private: + UHD_PIMPL_DECL(impl) _impl; + }; + +}} //namespace uhd::_log + +#endif /* INCLUDED_UHD_UTILS_LOG_HPP */ diff --git a/host/include/uhd/utils/msg.hpp b/host/include/uhd/utils/msg.hpp new file mode 100644 index 000000000..3aac9577a --- /dev/null +++ b/host/include/uhd/utils/msg.hpp @@ -0,0 +1,74 @@ +// +// 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_MSG_HPP +#define INCLUDED_UHD_UTILS_MSG_HPP + +#include <uhd/config.hpp> +#include <uhd/utils/pimpl.hpp> +#include <ostream> +#include <string> + +/*! + * A UHD message macro with configurable type. + * Usage: UHD_MSG(warning) << "some warning message" << std::endl; + */ +#define UHD_MSG(type) \ + uhd::msg::_msg(uhd::msg::type)() + +//! Helpful debug tool to print site info +#define UHD_HERE() \ + UHD_MSG(status) << __FILE__ << ":" << __LINE__ << std::endl + +//! Helpful debug tool to print a variable +#define UHD_VAR(var) \ + UHD_MSG(status) << #var << " = " << var << std::endl; + +namespace uhd{ namespace msg{ + + //! Possible message types + enum type_t{ + status = 's', + warning = 'w', + error = 'e', + fastpath= 'f' + }; + + //! Typedef for a user-registered message handler + typedef void (*handler_t)(type_t, const std::string &); + + /*! + * Register the handler for uhd system messages. + * Only one handler can be registered at once. + * This replaces the default std::cout/cerr handler. + * \param handler a new handler callback function + */ + UHD_API void register_handler(const handler_t &handler); + + //! Internal message object (called by UHD_MSG macro) + class UHD_API _msg{ + public: + _msg(const type_t type); + ~_msg(void); + std::ostream &operator()(void); + private: + UHD_PIMPL_DECL(impl) _impl; + }; + +}} //namespace uhd::msg + +#endif /* INCLUDED_UHD_UTILS_MSG_HPP */ diff --git a/host/include/uhd/utils/paths.hpp b/host/include/uhd/utils/paths.hpp new file mode 100644 index 000000000..f5a40b2c9 --- /dev/null +++ b/host/include/uhd/utils/paths.hpp @@ -0,0 +1,37 @@ +// +// Copyright 2011-2012 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_PATHS_HPP +#define INCLUDED_UHD_UTILS_PATHS_HPP + +#include <uhd/config.hpp> +#include <string> + +namespace uhd{ + + //! Get a string representing the system's temporary directory + UHD_API std::string get_tmp_path(void); + + //! Get a string representing the system's appdata directory + UHD_API std::string get_app_path(void); + + //! Get a string representing the system's pkg data directory + UHD_API std::string get_pkg_data_path(void); + +} //namespace uhd + +#endif /* INCLUDED_UHD_UTILS_PATHS_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/safe_call.hpp b/host/include/uhd/utils/safe_call.hpp new file mode 100644 index 000000000..ab287cc66 --- /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/log.hpp> + +//! helper macro for safe call to produce warnings +#define _UHD_SAFE_CALL_WARNING(code, what) UHD_LOGV(rarely) << \ + 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/tasks.hpp b/host/include/uhd/utils/tasks.hpp new file mode 100644 index 000000000..dcb003e39 --- /dev/null +++ b/host/include/uhd/utils/tasks.hpp @@ -0,0 +1,53 @@ +// +// Copyright 2011-2012 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_TASKS_HPP +#define INCLUDED_UHD_UTILS_TASKS_HPP + +#include <uhd/config.hpp> +#include <boost/shared_ptr.hpp> +#include <boost/function.hpp> +#include <boost/utility.hpp> + +namespace uhd{ + + class UHD_API task : boost::noncopyable{ + public: + typedef boost::shared_ptr<task> sptr; + typedef boost::function<void(void)> task_fcn_type; + + /*! + * Create a new task object with function callback. + * The task function callback will be run in a loop. + * until the thread is interrupted by the deconstructor. + * + * A task should return in a reasonable amount of time + * or may block forever under the following conditions: + * - The blocking call is interruptible. + * - The task polls the interrupt condition. + * + * \param task_fcn the task callback function + * \return a new task object + */ + static sptr make(const task_fcn_type &task_fcn); + + }; + +} //namespace uhd + +#endif /* INCLUDED_UHD_UTILS_TASKS_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/version.hpp b/host/include/uhd/version.hpp new file mode 100644 index 000000000..ab693f2b0 --- /dev/null +++ b/host/include/uhd/version.hpp @@ -0,0 +1,42 @@ +// +// Copyright 2010-2012 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> + +/*! + * The ABI version string that the client application builds against. + * Call get_abi_string() to check this against the library build. + * The format is oldest API compatible release - ABI compat number. + * The compatibility number allows pre-release ABI to be versioned. + */ +#define UHD_VERSION_ABI_STRING "3.4.0-3" + +namespace uhd{ + + //! Get the version string (dotted version number + build info) + UHD_API std::string get_version_string(void); + + //! Get the ABI compatibility string for this build of the library + UHD_API std::string get_abi_string(void); + +} //namespace uhd + +#endif /* INCLUDED_UHD_VERSION_HPP */ |