diff options
Diffstat (limited to 'host/include')
30 files changed, 934 insertions, 178 deletions
diff --git a/host/include/config.h.in b/host/include/config.h.in index bd690299e..8931d6580 100644 --- a/host/include/config.h.in +++ b/host/include/config.h.in @@ -1,5 +1,5 @@ /* - * Copyright 2015 Ettus Research LLC + * Copyright 2015,2016 Ettus Research LLC * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -19,6 +19,8 @@ /* Version macros */ #cmakedefine UHD_VERSION_MAJOR ${TRIMMED_VERSION_MAJOR} -#cmakedefine UHD_VERSION_MINOR ${TRIMMED_VERSION_MINOR} +#cmakedefine UHD_VERSION_API ${TRIMMED_VERSION_API} +#cmakedefine UHD_VERSION_ABI ${TRIMMED_VERSION_ABI} #cmakedefine UHD_VERSION_PATCH ${TRIMMED_VERSION_PATCH} +#cmakedefine ENABLE_USB #cmakedefine UHD_VERSION @UHD_VERSION_ADDED@ diff --git a/host/include/uhd/CMakeLists.txt b/host/include/uhd/CMakeLists.txt index 083ec4951..e55141549 100644 --- a/host/include/uhd/CMakeLists.txt +++ b/host/include/uhd/CMakeLists.txt @@ -27,6 +27,7 @@ CONFIGURE_FILE( ) UHD_INSTALL(FILES + build_info.hpp config.hpp convert.hpp deprecated.hpp diff --git a/host/include/uhd/build_info.hpp b/host/include/uhd/build_info.hpp new file mode 100644 index 000000000..2e6571ad0 --- /dev/null +++ b/host/include/uhd/build_info.hpp @@ -0,0 +1,55 @@ +// +// Copyright 2015 National Instruments Corp. +// +// 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_BUILD_INFO_HPP +#define INCLUDED_UHD_BUILD_INFO_HPP + +#include <uhd/config.hpp> + +#include <string> + +namespace uhd { namespace build_info { + + //! Return the version of Boost this build was built with. + UHD_API const std::string boost_version(); + + //! Return the date and time (GMT) this UHD build was built. + UHD_API const std::string build_date(); + + //! Return the C compiler used for this build. + UHD_API const std::string c_compiler(); + + //! Return the C++ compiler used for this build. + UHD_API const std::string cxx_compiler(); + + //! Return the C flags passed into this build. + UHD_API const std::string c_flags(); + + //! Return the C++ flags passed into this build. + UHD_API const std::string cxx_flags(); + + //! Return the UHD components enabled for this build, comma-delimited. + UHD_API const std::string enabled_components(); + + //! Return the default CMake install prefix for this build. + UHD_API const std::string install_prefix(); + + //! Return the version of libusb this build was built with. + UHD_API const std::string libusb_version(); +}} + +#endif /* INCLUDED_UHD_BUILD_INFO_HPP */ diff --git a/host/include/uhd/config.h b/host/include/uhd/config.h index 1677c80ec..3c3f9b01b 100644 --- a/host/include/uhd/config.h +++ b/host/include/uhd/config.h @@ -43,7 +43,7 @@ typedef ptrdiff_t ssize_t; #define UHD_DEPRECATED __declspec(deprecated) #define UHD_ALIGNED(x) __declspec(align(x)) #define UHD_UNUSED(x) x __attribute__((unused)) -#elif defined(__GNUG__) && __GNUG__ >= 4 +#elif defined(__GNUC__) && __GNUC__ >= 4 #define UHD_EXPORT __attribute__((visibility("default"))) #define UHD_IMPORT __attribute__((visibility("default"))) #define UHD_INLINE inline __attribute__((always_inline)) diff --git a/host/include/uhd/config.hpp b/host/include/uhd/config.hpp index 00466501e..8cbcab860 100644 --- a/host/include/uhd/config.hpp +++ b/host/include/uhd/config.hpp @@ -53,6 +53,7 @@ typedef ptrdiff_t ssize_t; #define UHD_EXPORT __declspec(dllexport) #define UHD_IMPORT __declspec(dllimport) #define UHD_INLINE __forceinline + #define UHD_FORCE_INLINE __forceinline #define UHD_DEPRECATED __declspec(deprecated) #define UHD_ALIGNED(x) __declspec(align(x)) #define UHD_UNUSED(x) x @@ -60,6 +61,7 @@ typedef ptrdiff_t ssize_t; #define UHD_EXPORT __declspec(dllexport) #define UHD_IMPORT __declspec(dllimport) #define UHD_INLINE inline + #define UHD_FORCE_INLINE inline #define UHD_DEPRECATED __declspec(deprecated) #define UHD_ALIGNED(x) __declspec(align(x)) #define UHD_UNUSED(x) x __attribute__((unused)) @@ -67,6 +69,7 @@ typedef ptrdiff_t ssize_t; #define UHD_EXPORT __attribute__((visibility("default"))) #define UHD_IMPORT __attribute__((visibility("default"))) #define UHD_INLINE inline __attribute__((always_inline)) + #define UHD_FORCE_INLINE inline __attribute__((always_inline)) #define UHD_DEPRECATED __attribute__((deprecated)) #define UHD_ALIGNED(x) __attribute__((aligned(x))) #define UHD_UNUSED(x) x __attribute__((unused)) @@ -74,6 +77,7 @@ typedef ptrdiff_t ssize_t; #define UHD_EXPORT #define UHD_IMPORT #define UHD_INLINE inline + #define UHD_FORCE_INLINE inline #define UHD_DEPRECATED #define UHD_ALIGNED(x) #define UHD_UNUSED(x) x diff --git a/host/include/uhd/error.h b/host/include/uhd/error.h index f0ac41d1f..77216dc72 100644 --- a/host/include/uhd/error.h +++ b/host/include/uhd/error.h @@ -158,7 +158,7 @@ extern "C" { * strings into a buffer that can be queried with this function. Functions that * do take in UHD structs/handles will place their error strings in both locations. */ -uhd_error uhd_get_last_error( +UHD_API uhd_error uhd_get_last_error( char* error_out, size_t strbuffer_len ); diff --git a/host/include/uhd/property_tree.hpp b/host/include/uhd/property_tree.hpp index a92654ba2..93353568a 100644 --- a/host/include/uhd/property_tree.hpp +++ b/host/include/uhd/property_tree.hpp @@ -1,5 +1,5 @@ // -// Copyright 2011,2014 Ettus Research LLC +// Copyright 2011,2014-2016 Ettus Research // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by @@ -27,8 +27,51 @@ namespace uhd{ /*! - * A templated property interface for holding a value + * A templated property interface for holding the state + * associated with a property in a uhd::property_tree * and registering callbacks when that value changes. + * + * A property is defined to have two separate vales: + * - Desired value: Value requested by the user + * - Coerced value: Value that was actually possible + * given HW and other requirements + * + * By default, the desired and coerced values are + * identical as long as the property is not coerced. + * A property can be coerced in two way: + * 1. Using a coercer: A callback function that takes + * in a desired value and produces a coerced value. + * A property must have *exactly one* coercer. + * 2. Manual coercion: Manually calling the set_coerced + * API fnction to coerce the value of the propery. In + * order to use manual coercion, the propery must be + * created with the MANUAL_COERCE mode. + * If the coerce mode for a property is AUTO_COERCE then + * it always has a coercer. If the set_coercer API is + * never used, then the default coercer is used which + * simply set the coerced value to the desired value. + * + * It is possible to get notified every time the desired + * or coerced values of a property potentially change + * using subscriber callbacks. Every property can have + * zero or more desired and coerced subscribers. + * + * If storing the property readback state in software is + * not appropriate (for example if it needs to be queried + * from hardware) then it is possible to use a publisher + * callback to get the value of the property. Calling + * get on the property will always call the publisher and + * the cached desired and coerced values are updated only + * using set* calls. A preprty must have *at most one* + * publisher. It is legal to have both a coercer + * and publisher for a property but the only way to access + * the desired and coerced values in that case would be by + * notification using the desired and coerced subscribers. + * Publishers are useful for creating read-only properties. + * + * Requirements for the template type T: + * - T must have a copy constructor + * - T must have an assignment operator */ template <typename T> class property : boost::noncopyable{ public: @@ -40,60 +83,107 @@ public: /*! * Register a coercer into the property. - * A coercer is a special subscriber that coerces the value. + * A coercer is a callback function that updates the + * coerced value of a property. + * * 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 + * \throws uhd::assertion_error if called more than once */ - virtual property<T> &coerce(const coercer_type &coercer) = 0; + virtual property<T> &set_coercer(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. + * A publisher is a callback function the provides the value + * for a property. + * * 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 + * \throws uhd::assertion_error if called more than once */ - virtual property<T> &publish(const publisher_type &publisher) = 0; + virtual property<T> &set_publisher(const publisher_type &publisher) = 0; /*! * Register a subscriber into the property. - * All subscribers are called when the value changes. + * All desired subscribers are called when the desired value + * potentially 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; + virtual property<T> &add_desired_subscriber(const subscriber_type &subscriber) = 0; + + /*! + * Register a subscriber into the property. + * All coerced subscribers are called when the coerced value + * potentially 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> &add_coerced_subscriber(const subscriber_type &subscriber) = 0; /*! * Update calls all subscribers w/ the current value. + * * \return a reference to this property for chaining + * \throws uhd::assertion_error */ 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. + * Set the new value and call all the necessary subscribers. + * Order of operations: + * - The desired value of the property is updated + * - All desired subscribers are called + * - If coerce mode is AUTO then the coercer is called + * - If coerce mode is AUTO then all coerced subscribers are called + * * \param value the new value to set on this property * \return a reference to this property for chaining + * \throws uhd::assertion_error */ virtual property<T> &set(const T &value) = 0; /*! + * Set a coerced value and call all subscribers. + * The coercer is bypassed, and the specified value is + * used as the coerced value. All coerced subscribers + * are called. This function can only be used when the + * coerce mode is set to MANUAL_COERCE. + * + * \param value the new value to set on this property + * \return a reference to this property for chaining + * \throws uhd::assertion_error + */ + virtual property<T> &set_coerced(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. + * otherwise an internal coerced value is returned. + * * \return the current value in the property + * \throws uhd::assertion_error */ - virtual T get(void) const = 0; + virtual const T get(void) const = 0; + + /*! + * Get the current desired value of this property. + * + * \return the current desired value in the property + * \throws uhd::assertion_error + */ + virtual const T get_desired(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; @@ -129,6 +219,8 @@ class UHD_API property_tree : boost::noncopyable{ public: typedef boost::shared_ptr<property_tree> sptr; + enum coerce_mode_t { AUTO_COERCE, MANUAL_COERCE }; + virtual ~property_tree(void) = 0; //! Create a new + empty property tree @@ -147,7 +239,9 @@ public: 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); + template <typename T> property<T> &create( + const fs_path &path, + coerce_mode_t coerce_mode = AUTO_COERCE); //! Get access to a property in the tree template <typename T> property<T> &access(const fs_path &path); diff --git a/host/include/uhd/property_tree.ipp b/host/include/uhd/property_tree.ipp index 93962c963..6ed1056e6 100644 --- a/host/include/uhd/property_tree.ipp +++ b/host/include/uhd/property_tree.ipp @@ -1,5 +1,5 @@ // -// Copyright 2011,2014 Ettus Research LLC +// Copyright 2011,2014-2016 Ettus Research // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by @@ -20,6 +20,7 @@ #include <uhd/exception.hpp> #include <boost/foreach.hpp> +#include <boost/scoped_ptr.hpp> #include <vector> /*********************************************************************** @@ -29,23 +30,38 @@ namespace uhd{ namespace /*anon*/{ template <typename T> class property_impl : public property<T>{ public: + property_impl<T>(property_tree::coerce_mode_t mode) : _coerce_mode(mode){ + if (_coerce_mode == property_tree::AUTO_COERCE) { + _coercer = DEFAULT_COERCER; + } + } ~property_impl<T>(void){ /* NOP */ } - property<T> &coerce(const typename property<T>::coercer_type &coercer){ + property<T> &set_coercer(const typename property<T>::coercer_type &coercer){ + if (not _coercer.empty()) uhd::assertion_error("cannot register more than one coercer for a property"); + if (_coerce_mode == property_tree::MANUAL_COERCE) uhd::assertion_error("cannot register coercer for a manually coerced property"); + _coercer = coercer; return *this; } - property<T> &publish(const typename property<T>::publisher_type &publisher){ + property<T> &set_publisher(const typename property<T>::publisher_type &publisher){ + if (not _publisher.empty()) uhd::assertion_error("cannot register more than one publisher for a property"); + _publisher = publisher; return *this; } - property<T> &subscribe(const typename property<T>::subscriber_type &subscriber){ - _subscribers.push_back(subscriber); + property<T> &add_desired_subscriber(const typename property<T>::subscriber_type &subscriber){ + _desired_subscribers.push_back(subscriber); + return *this; + } + + property<T> &add_coerced_subscriber(const typename property<T>::subscriber_type &subscriber){ + _coerced_subscribers.push_back(subscriber); return *this; } @@ -54,17 +70,49 @@ public: return *this; } + void _set_coerced(const T &value){ + init_or_set_value(_coerced_value, value); + BOOST_FOREACH(typename property<T>::subscriber_type &csub, _coerced_subscribers){ + csub(get_value_ref(_coerced_value)); //let errors propagate + } + } + 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 + init_or_set_value(_value, value); + BOOST_FOREACH(typename property<T>::subscriber_type &dsub, _desired_subscribers){ + dsub(get_value_ref(_value)); //let errors propagate } + if (not _coercer.empty()) { + _set_coerced(_coercer(get_value_ref(_value))); + } else { + if (_coerce_mode == property_tree::AUTO_COERCE) uhd::assertion_error("coercer missing for an auto coerced property"); + } + return *this; + } + + property<T> &set_coerced(const T &value){ + if (_coerce_mode == property_tree::AUTO_COERCE) uhd::assertion_error("cannot set coerced value an auto coerced property"); + _set_coerced(value); return *this; } - T get(void) const{ - if (empty()) throw uhd::runtime_error("Cannot get() on an empty property"); - return _publisher.empty()? *_value : _publisher(); + const T get(void) const{ + if (empty()) { + throw uhd::runtime_error("Cannot get() on an uninitialized (empty) property"); + } + if (not _publisher.empty()) { + return _publisher(); + } else { + if (_coerced_value.get() == NULL and _coerce_mode == property_tree::MANUAL_COERCE) + throw uhd::runtime_error("uninitialized coerced value for manually coerced attribute"); + return get_value_ref(_coerced_value); + } + } + + const T get_desired(void) const{ + if (_value.get() == NULL) throw uhd::runtime_error("Cannot get_desired() on an uninitialized (empty) property"); + + return get_value_ref(_value); } bool empty(void) const{ @@ -72,10 +120,30 @@ public: } 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; + static T DEFAULT_COERCER(const T& value) { + return value; + } + + static void init_or_set_value(boost::scoped_ptr<T>& scoped_value, const T& init_val) { + if (scoped_value.get() == NULL) { + scoped_value.reset(new T(init_val)); + } else { + *scoped_value = init_val; + } + } + + static const T& get_value_ref(const boost::scoped_ptr<T>& scoped_value) { + if (scoped_value.get() == NULL) throw uhd::assertion_error("Cannot use uninitialized property data"); + return *scoped_value.get(); + } + + const property_tree::coerce_mode_t _coerce_mode; + std::vector<typename property<T>::subscriber_type> _desired_subscribers; + std::vector<typename property<T>::subscriber_type> _coerced_subscribers; + typename property<T>::publisher_type _publisher; + typename property<T>::coercer_type _coercer; + boost::scoped_ptr<T> _value; + boost::scoped_ptr<T> _coerced_value; }; }} //namespace uhd::/*anon*/ @@ -85,8 +153,8 @@ private: **********************************************************************/ 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>())); + template <typename T> property<T> &property_tree::create(const fs_path &path, coerce_mode_t coerce_mode){ + this->_create(path, typename boost::shared_ptr<property<T> >(new property_impl<T>(coerce_mode))); return this->access<T>(path); } diff --git a/host/include/uhd/transport/muxed_zero_copy_if.hpp b/host/include/uhd/transport/muxed_zero_copy_if.hpp new file mode 100644 index 000000000..17213885e --- /dev/null +++ b/host/include/uhd/transport/muxed_zero_copy_if.hpp @@ -0,0 +1,72 @@ +// +// Copyright 2016 Ettus Research LLC +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// 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_LIBUHD_TRANSPORT_MUXED_ZERO_COPY_IF_HPP +#define INCLUDED_LIBUHD_TRANSPORT_MUXED_ZERO_COPY_IF_HPP + +#include <uhd/transport/zero_copy.hpp> +#include <uhd/config.hpp> +#include <boost/function.hpp> +#include <boost/noncopyable.hpp> +#include <stdint.h> + +namespace uhd { namespace transport { + +/*! + * Implements a software muxed-demuxed zero-copy transport + * This is a wrapper around a base transport that allows + * creation of virtual zero_copy_if streams that are + * indistinguishable from physical transport streams. + * This class handles demuxing receive streams into the + * appropriate virtual streams with the given classifier + * function. A worker therad is spawned to handle the demuxing. + */ +class muxed_zero_copy_if : private boost::noncopyable { +public: + typedef boost::shared_ptr<muxed_zero_copy_if> sptr; + + /*! + * Function to classify the stream based on the payload. + * The classifier must return a stream number, an arbitrary + * identifier for a virtual stream that is consistent with + * the stream number used in the make_stream and remove_stream + * fuctions + * \param buff a pointer to the payload of the frame + * \param size number of bytes in the frame payload + * \return stream number + */ + typedef boost::function<uint32_t(void* buff, size_t size)> stream_classifier_fn; + + //! virtual dtor + virtual ~muxed_zero_copy_if() {} + + //! Make a virtual transport for the specified stream number + virtual zero_copy_if::sptr make_stream(const uint32_t stream_num) = 0; + + //! Unregister the stream number. All packets destined to the stream will be dropped. + virtual void remove_stream(const uint32_t stream_num) = 0; + + //! Get number of frames dropped due to unregistered streams + virtual size_t get_num_dropped_frames() const = 0; + + //! Make a new demuxer from a transport and parameters + static sptr make(zero_copy_if::sptr base_xport, stream_classifier_fn classify_fn, size_t max_streams); +}; + +}} //namespace uhd::transport + +#endif /* INCLUDED_LIBUHD_TRANSPORT_MUXED_ZERO_COPY_IF_HPP */ diff --git a/host/include/uhd/transport/zero_copy_recv_offload.hpp b/host/include/uhd/transport/zero_copy_recv_offload.hpp new file mode 100644 index 000000000..793753276 --- /dev/null +++ b/host/include/uhd/transport/zero_copy_recv_offload.hpp @@ -0,0 +1,50 @@ +// +// Copyright 2016 Ettus Research +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. +// + +#ifndef INCLUDED_UHD_ZERO_COPY_RECV_OFFLOAD_HPP +#define INCLUDED_UHD_ZERO_COPY_RECV_OFFLOAD_HPP + +#include <uhd/config.hpp> +#include <uhd/transport/zero_copy.hpp> +#include <boost/shared_ptr.hpp> + +namespace uhd{ namespace transport{ + +/*! + * A threaded transport offload that is meant to relieve the main thread of + * the responsibility of making receive calls. + */ +class UHD_API zero_copy_recv_offload : public virtual zero_copy_if { +public: + typedef boost::shared_ptr<zero_copy_recv_offload> sptr; + + /*! + * This transport offload adds a receive thread in order to + * communicate with the underlying transport. It is meant to be + * used in cases where the main thread needs to be relieved of the burden + * of the underlying transport receive calls. + * + * \param transport a shared pointer to the transport interface + * \param timeout a general timeout for pushing and pulling on the bounded buffer + */ + static sptr make(zero_copy_if::sptr transport, + const double timeout); +}; + +}} //namespace + +#endif /* INCLUDED_ZERO_COPY_OFFLOAD_HPP */ diff --git a/host/include/uhd/types/CMakeLists.txt b/host/include/uhd/types/CMakeLists.txt index 3f34782e2..682d3cd9b 100644 --- a/host/include/uhd/types/CMakeLists.txt +++ b/host/include/uhd/types/CMakeLists.txt @@ -1,5 +1,5 @@ # -# Copyright 2010-2011,2015 Ettus Research LLC +# Copyright 2010-2011,2015-2016 Ettus Research LLC # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by diff --git a/host/include/uhd/types/filters.hpp b/host/include/uhd/types/filters.hpp index 976ae233d..2c30c1007 100644 --- a/host/include/uhd/types/filters.hpp +++ b/host/include/uhd/types/filters.hpp @@ -55,12 +55,12 @@ namespace uhd{ //NOP } - inline virtual bool is_bypassed() + UHD_INLINE virtual bool is_bypassed() { return _bypass; } - inline filter_type get_type() + UHD_INLINE filter_type get_type() { return _type; } @@ -98,7 +98,7 @@ namespace uhd{ //NOP } - inline const std::string& get_analog_type() + UHD_INLINE const std::string& get_analog_type() { return _analog_type; } @@ -128,17 +128,17 @@ namespace uhd{ //NOP } - inline double get_cutoff() + UHD_INLINE double get_cutoff() { return _cutoff; } - inline double get_rolloff() + UHD_INLINE double get_rolloff() { return _cutoff; } - inline void set_cutoff(const double cutoff) + UHD_INLINE void set_cutoff(const double cutoff) { _cutoff = cutoff; } @@ -181,32 +181,32 @@ namespace uhd{ //NOP } - inline double get_output_rate() + UHD_INLINE double get_output_rate() { return (_bypass ? _rate : (_rate / _decimation * _interpolation)); } - inline double get_input_rate() + UHD_INLINE double get_input_rate() { return _rate; } - inline double get_interpolation() + UHD_INLINE double get_interpolation() { return _interpolation; } - inline double get_decimation() + UHD_INLINE double get_decimation() { return _decimation; } - inline double get_tap_full_scale() + UHD_INLINE double get_tap_full_scale() { return _tap_full_scale; } - inline std::vector<tap_t>& get_taps() + UHD_INLINE std::vector<tap_t>& get_taps() { return _taps; } diff --git a/host/include/uhd/types/sensors.hpp b/host/include/uhd/types/sensors.hpp index 529e1e3e3..de1ed014f 100644 --- a/host/include/uhd/types/sensors.hpp +++ b/host/include/uhd/types/sensors.hpp @@ -91,6 +91,12 @@ namespace uhd{ const std::string &unit ); + /*! + * Create a sensor value from another sensor value. + * \param source the source sensor value to copy + */ + sensor_value_t(const sensor_value_t& source); + //! convert the sensor value to a boolean bool to_bool(void) const; @@ -101,21 +107,21 @@ namespace uhd{ double to_real(void) const; //! The name of the sensor value - const std::string name; + 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; + 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; + std::string unit; //! Enumeration of possible data types in a sensor enum data_type_t { @@ -126,10 +132,13 @@ namespace uhd{ }; //! The data type of the value - const data_type_t type; + data_type_t type; //! Convert this sensor value into a printable string std::string to_pp_string(void) const; + + //! Assignment operator for sensor value + sensor_value_t& operator=(const sensor_value_t& value); }; } //namespace uhd diff --git a/host/include/uhd/types/serial.hpp b/host/include/uhd/types/serial.hpp index 7b565c633..5b7f34fbd 100644 --- a/host/include/uhd/types/serial.hpp +++ b/host/include/uhd/types/serial.hpp @@ -118,13 +118,19 @@ namespace uhd{ //! on what edge is the miso data valid? edge_t miso_edge; + //! Set the clock speed for this transaction + bool use_custom_divider; + + //! Optionally set the SPI clock divider for this transaction + size_t divider; + /*! * 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. diff --git a/host/include/uhd/usrp/CMakeLists.txt b/host/include/uhd/usrp/CMakeLists.txt index e974f808d..fd37ef560 100644 --- a/host/include/uhd/usrp/CMakeLists.txt +++ b/host/include/uhd/usrp/CMakeLists.txt @@ -18,6 +18,7 @@ UHD_INSTALL(FILES #### dboard headers ### + fe_connection.hpp dboard_base.hpp dboard_eeprom.hpp dboard_id.hpp @@ -26,6 +27,7 @@ UHD_INSTALL(FILES ### utilities ### gps_ctrl.hpp + gpio_defs.hpp mboard_eeprom.hpp subdev_spec.hpp diff --git a/host/include/uhd/usrp/dboard_base.hpp b/host/include/uhd/usrp/dboard_base.hpp index 31b3643c7..b106a1ac6 100644 --- a/host/include/uhd/usrp/dboard_base.hpp +++ b/host/include/uhd/usrp/dboard_base.hpp @@ -44,6 +44,10 @@ public: //structors dboard_base(ctor_args_t); + virtual ~dboard_base() {} + + //post-construction initializer + virtual void initialize() {} protected: std::string get_subdev_name(void); @@ -67,6 +71,7 @@ public: * Create a new xcvr dboard object, override in subclasses. */ xcvr_dboard_base(ctor_args_t); + virtual ~xcvr_dboard_base() {} }; /*! @@ -79,6 +84,7 @@ public: * Create a new rx dboard object, override in subclasses. */ rx_dboard_base(ctor_args_t); + virtual ~rx_dboard_base() {} }; /*! @@ -91,6 +97,7 @@ public: * Create a new rx dboard object, override in subclasses. */ tx_dboard_base(ctor_args_t); + virtual ~tx_dboard_base() {} }; }} //namespace diff --git a/host/include/uhd/usrp/dboard_iface.hpp b/host/include/uhd/usrp/dboard_iface.hpp index 686deb48d..52d226004 100644 --- a/host/include/uhd/usrp/dboard_iface.hpp +++ b/host/include/uhd/usrp/dboard_iface.hpp @@ -1,5 +1,5 @@ // -// Copyright 2010-2013 Ettus Research LLC +// Copyright 2010-2013,2015-2016 Ettus Research LLC // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by @@ -22,6 +22,8 @@ #include <uhd/utils/pimpl.hpp> #include <uhd/types/serial.hpp> #include <uhd/types/time_spec.hpp> +#include <uhd/usrp/fe_connection.hpp> +#include <uhd/usrp/gpio_defs.hpp> #include <boost/shared_ptr.hpp> #include <boost/cstdint.hpp> #include <string> @@ -63,16 +65,9 @@ public: //! 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') + UNIT_RX = int('r'), + UNIT_TX = int('t'), + UNIT_BOTH = int('b'), }; //! aux dac selection enums (per unit) @@ -89,6 +84,10 @@ public: AUX_ADC_B = int('b') }; + typedef uhd::usrp::gpio_atr::gpio_atr_reg_t atr_reg_t; + + virtual ~dboard_iface(void) {}; + /*! * Get special properties information for this dboard slot. * This call helps the dboard code to handle implementation @@ -123,8 +122,8 @@ public: * \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 - ); + unit_t unit, boost::uint32_t value, boost::uint32_t mask = 0xffff + ) = 0; /*! * Read back the pin control setting. @@ -132,7 +131,7 @@ public: * \param unit which unit rx or tx * \return the 16-bit settings value */ - virtual boost::uint16_t get_pin_ctrl(unit_t unit); + virtual boost::uint32_t get_pin_ctrl(unit_t unit) = 0; /*! * Set a daughterboard ATR register. @@ -143,8 +142,8 @@ public: * \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 - ); + unit_t unit, atr_reg_t reg, boost::uint32_t value, boost::uint32_t mask = 0xffff + ) = 0; /*! * Read back an ATR register setting. @@ -153,7 +152,7 @@ public: * \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); + virtual boost::uint32_t get_atr_reg(unit_t unit, atr_reg_t reg) = 0; /*! * Set daughterboard GPIO data direction setting. @@ -163,8 +162,8 @@ public: * \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 - ); + unit_t unit, boost::uint32_t value, boost::uint32_t mask = 0xffff + ) = 0; /*! * Read back the GPIO data direction setting. @@ -172,7 +171,7 @@ public: * \param unit which unit rx or tx * \return the 16-bit settings value */ - virtual boost::uint16_t get_gpio_ddr(unit_t unit); + virtual boost::uint32_t get_gpio_ddr(unit_t unit) = 0; /*! * Set daughterboard GPIO pin output setting. @@ -182,8 +181,8 @@ public: * \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 - ); + unit_t unit, boost::uint32_t value, boost::uint32_t mask = 0xffff + ) = 0; /*! * Read back the GPIO pin output setting. @@ -191,15 +190,7 @@ public: * \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; + virtual boost::uint32_t get_gpio_out(unit_t unit) = 0; /*! * Read daughterboard GPIO pin values. @@ -207,7 +198,7 @@ public: * \param unit which unit rx or tx * \return the value of the gpio unit */ - virtual boost::uint16_t read_gpio(unit_t unit) = 0; + virtual boost::uint32_t read_gpio(unit_t unit) = 0; /*! * Write data to SPI bus peripheral. @@ -282,29 +273,29 @@ public: virtual double get_codec_rate(unit_t unit) = 0; /*! + * Configure the front-end connection parameters. + * + * \param unit which unit rx or tx + * \param fe_name name of the front-end to update + * \param fe_conn connection parameters class + */ + virtual void set_fe_connection( + unit_t unit, + const std::string& fe_name, + const uhd::usrp::fe_connection_t& fe_conn + ) = 0; + + /*! * Get the command time. * \return the command time */ - virtual uhd::time_spec_t get_command_time(void); + virtual uhd::time_spec_t get_command_time(void) = 0; /*! * Set the command time. * \param t the time */ - virtual void set_command_time(const uhd::time_spec_t& t); - -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); -public: - virtual ~dboard_iface(void); + virtual void set_command_time(const uhd::time_spec_t& t) = 0; }; diff --git a/host/include/uhd/usrp/dboard_manager.hpp b/host/include/uhd/usrp/dboard_manager.hpp index d3a3ffb5c..4ce943972 100644 --- a/host/include/uhd/usrp/dboard_manager.hpp +++ b/host/include/uhd/usrp/dboard_manager.hpp @@ -45,15 +45,17 @@ public: * 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 db_subdev_ctor the dboard sub-device constructor function pointer (one instance per subdev name) * \param name the canonical name for the dboard represented * \param subdev_names the names of the subdevs on this dboard + * \param db_container_ctor the dboard container constructor function pointer (one instance per dboard) */ static void register_dboard( const dboard_id_t &dboard_id, - dboard_ctor_t dboard_ctor, + dboard_ctor_t db_subdev_ctor, const std::string &name, - const std::vector<std::string> &subdev_names = std::vector<std::string>(1, "0") + const std::vector<std::string> &subdev_names = std::vector<std::string>(1, "0"), + dboard_ctor_t db_container_ctor = NULL ); /*! @@ -61,16 +63,58 @@ public: * 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 db_subdev_ctor the dboard sub-device constructor function pointer (one instance per subdev name) * \param name the canonical name for the dboard represented * \param subdev_names the names of the subdevs on this dboard + * \param db_container_ctor the dboard container constructor function pointer (one instance per dboard) */ static void register_dboard( const dboard_id_t &rx_dboard_id, const dboard_id_t &tx_dboard_id, - dboard_ctor_t dboard_ctor, + dboard_ctor_t db_subdev_ctor, const std::string &name, - const std::vector<std::string> &subdev_names = std::vector<std::string>(1, "0") + const std::vector<std::string> &subdev_names = std::vector<std::string>(1, "0"), + dboard_ctor_t db_container_ctor = NULL + ); + + /*! + * Register a restricted rx or tx dboard into the system. + * A restricted dboard does not add its dboard_iface object into the property tree. + * For single subdevice boards, omit subdev_names. + * The iface for a restricted board is not registered into the property tree. + * \param dboard_id the dboard id (rx or tx) + * \param db_subdev_ctor the dboard sub-device constructor function pointer (one instance per subdev name) + * \param name the canonical name for the dboard represented + * \param subdev_names the names of the subdevs on this dboard + * \param db_container_ctor the dboard container constructor function pointer (one instance per dboard) + */ + static void register_dboard_restricted( + const dboard_id_t &dboard_id, + dboard_ctor_t db_subdev_ctor, + const std::string &name, + const std::vector<std::string> &subdev_names = std::vector<std::string>(1, "0"), + dboard_ctor_t db_container_ctor = NULL + ); + + /*! + * Register a restricted xcvr dboard into the system. + * A restricted dboard does not add its dboard_iface object into the property tree. + * For single subdevice boards, omit subdev_names. + * The iface for a restricted board is not registered into the property tree. + * \param rx_dboard_id the rx unit dboard id + * \param tx_dboard_id the tx unit dboard id + * \param db_subdev_ctor the dboard sub-device constructor function pointer (one instance per subdev name) + * \param name the canonical name for the dboard represented + * \param subdev_names the names of the subdevs on this dboard + * \param db_container_ctor the dboard container constructor function pointer (one instance per dboard) + */ + static void register_dboard_restricted( + const dboard_id_t &rx_dboard_id, + const dboard_id_t &tx_dboard_id, + dboard_ctor_t db_subdev_ctor, + const std::string &name, + const std::vector<std::string> &subdev_names = std::vector<std::string>(1, "0"), + dboard_ctor_t db_container_ctor = NULL ); /*! @@ -89,6 +133,20 @@ public: dboard_iface::sptr iface, property_tree::sptr subtree ); + + virtual ~dboard_manager() {} + + /*! + * Returns a vector of RX frontend (subdev) names + * \return a vector of names + */ + virtual const std::vector<std::string>& get_rx_frontends() const = 0; + + /*! + * Returns a vector of TX frontend (subdev) names + * \return a vector of names + */ + virtual const std::vector<std::string>& get_tx_frontends() const = 0; }; }} //namespace diff --git a/host/include/uhd/usrp/fe_connection.hpp b/host/include/uhd/usrp/fe_connection.hpp new file mode 100644 index 000000000..969246087 --- /dev/null +++ b/host/include/uhd/usrp/fe_connection.hpp @@ -0,0 +1,127 @@ +// +// Copyright 2016 Ettus Research LLC +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// 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_FE_CONNECTION_HPP +#define INCLUDED_UHD_USRP_FE_CONNECTION_HPP + +#include <uhd/config.hpp> +#include <boost/operators.hpp> +#include <string> + +namespace uhd { namespace usrp { + + class UHD_API fe_connection_t : boost::equality_comparable<fe_connection_t> { + public: + /** Sampling mode. + * Represents the sampling architecture for the front-end + */ + enum sampling_t { + QUADRATURE, /**< Complex sampling (Complex input, Complex output). */ + HETERODYNE, /**< Heterodyne sampling (Real input, Complex output). Only one of the I and Q inputs is used. */ + REAL /**< Real sampling (Real input, Real output). Only one of the I and Q inputs is used. */ + }; + + /*! + * Create a frontend connection class from individual settings. + * \param sampling_mode can be { QUADRATURE, HETERODYNE, REAL } + * \param iq_swapped indicates if the IQ channels are swapped (after inverion and heterodyne correction) + * \param i_inverted indicates if the I channel is inverted (negated) + * \param q_inverted indicates if the Q channel is inverted (negated) + * \param if_freq the baseband sampling frequency. + */ + fe_connection_t( + sampling_t sampling_mode, bool iq_swapped, + bool i_inverted, bool q_inverted, double if_freq = 0.0 + ); + + /*! + * Create a frontend connection class from a connection string + * The connection string can be: + * - in {I, Q}: Real mode sampling with no inversion. + * - in {Ib, Qb}: Real mode sampling with inversion. + * - in {IQ, QI}: Quadrature sampling with no inversion. + * - in {IbQb, QbIb}: Quadrature sampling with inversion. + * - in {II, QQ}: Heterodyne sampling with no inversion. + * - in {IbIb, QbQb}: Heterodyne sampling with inversion. + * + * \param conn_str the connection string. + * \param if_freq the baseband sampling frequency. + */ + fe_connection_t(const std::string& conn_str, double if_freq = 0.0); + + /*! + * Accessor for sampling mode + */ + inline sampling_t get_sampling_mode() const { + return _sampling_mode; + } + + /*! + * Accessor for IQ swap parameter + */ + inline bool is_iq_swapped() const { + return _iq_swapped; + } + + /*! + * Accessor for I inversion parameter + */ + inline bool is_i_inverted() const { + return _i_inverted; + } + + /*! + * Accessor for Q inversion parameter + */ + inline bool is_q_inverted() const { + return _q_inverted; + } + + /*! + * Accessor for IF frequency + */ + inline double get_if_freq() const { + return _if_freq; + } + + /*! + * Mutator for IF frequency + */ + inline void set_if_freq(double freq) { + _if_freq = freq; + } + + private: + sampling_t _sampling_mode; + bool _iq_swapped; + bool _i_inverted; + bool _q_inverted; + double _if_freq; + }; + + /*! + * Comparator operator overloaded for fe_connection_t. + * The boost::equality_comparable provides the !=. + * \param lhs the fe_connection_t to the left of the operator + * \param rhs the fe_connection_t to the right of the operator + * \return true when the fe connections are equal + */ + UHD_API bool operator==(const fe_connection_t &lhs, const fe_connection_t &rhs); + +}} //namespace + +#endif /* INCLUDED_UHD_USRP_FE_CONNECTION_HPP */ diff --git a/host/include/uhd/usrp/gpio_defs.hpp b/host/include/uhd/usrp/gpio_defs.hpp new file mode 100644 index 000000000..c32f22f28 --- /dev/null +++ b/host/include/uhd/usrp/gpio_defs.hpp @@ -0,0 +1,70 @@ +// +// Copyright 2011,2014,2015 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_LIBUHD_USRP_GPIO_DEFS_HPP +#define INCLUDED_LIBUHD_USRP_GPIO_DEFS_HPP + +#include <uhd/config.hpp> +#include <boost/assign.hpp> +#include <boost/utility.hpp> +#include <map> + +namespace uhd { namespace usrp { namespace gpio_atr { + +enum gpio_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') +}; + +enum gpio_atr_mode_t { + MODE_ATR = 0, //Output driven by the auto-transmit-receive engine + MODE_GPIO = 1 //Output value is static +}; + +enum gpio_ddr_t { + DDR_INPUT = 0, + DDR_OUTPUT = 1 +}; + +enum gpio_attr_t { + GPIO_CTRL, + GPIO_DDR, + GPIO_OUT, + GPIO_ATR_0X, + GPIO_ATR_RX, + GPIO_ATR_TX, + GPIO_ATR_XX +}; + +typedef std::map<gpio_attr_t, std::string> gpio_attr_map_t; + +static const gpio_attr_map_t gpio_attr_map = + boost::assign::map_list_of + (GPIO_CTRL, "CTRL") + (GPIO_DDR, "DDR") + (GPIO_OUT, "OUT") + (GPIO_ATR_0X, "ATR_0X") + (GPIO_ATR_RX, "ATR_RX") + (GPIO_ATR_TX, "ATR_TX") + (GPIO_ATR_XX, "ATR_XX") +; + +}}} //namespaces + +#endif /* INCLUDED_LIBUHD_USRP_GPIO_DEFS_HPP */ diff --git a/host/include/uhd/usrp/multi_usrp.hpp b/host/include/uhd/usrp/multi_usrp.hpp index 715a57242..ab757be8a 100644 --- a/host/include/uhd/usrp/multi_usrp.hpp +++ b/host/include/uhd/usrp/multi_usrp.hpp @@ -31,6 +31,7 @@ #define UHD_USRP_MULTI_USRP_GPIO_API #define UHD_USRP_MULTI_USRP_REGISTER_API #define UHD_USRP_MULTI_USRP_FILTER_API +#define UHD_USRP_MULTI_USRP_LO_CONFIG_API #include <uhd/config.hpp> #include <uhd/device.hpp> @@ -112,6 +113,9 @@ public: //! A wildcard gain element name static const std::string ALL_GAINS; + //! A wildcard gain element name + static const std::string ALL_LOS; + /*! * Make a new multi usrp from the device address. * \param dev_addr the device address @@ -487,6 +491,82 @@ public: virtual freq_range_t get_fe_rx_freq_range(size_t chan = 0) = 0; /*! + * Get a list of possible LO stage names + * \param chan the channel index 0 to N-1 + * \return a vector of strings for possible LO names + */ + virtual std::vector<std::string> get_rx_lo_names(size_t chan = 0) = 0; + + /*! + * Set the LO source for the usrp device. + * For usrps that support selectable LOs, this function + * allows switching between them. + * Typical options for source: internal, external. + * \param src a string representing the LO source + * \param name the name of the LO stage to update + * \param chan the channel index 0 to N-1 + */ + virtual void set_rx_lo_source(const std::string &src, const std::string &name = ALL_LOS, size_t chan = 0) = 0; + + /*! + * Get the currently set LO source. + * \param name the name of the LO stage to query + * \param chan the channel index 0 to N-1 + * \return the configured LO source + */ + virtual const std::string get_rx_lo_source(const std::string &name = ALL_LOS, size_t chan = 0) = 0; + + /*! + * Get a list of possible LO sources. + * \param name the name of the LO stage to query + * \param chan the channel index 0 to N-1 + * \return a vector of strings for possible settings + */ + virtual std::vector<std::string> get_rx_lo_sources(const std::string &name = ALL_LOS, size_t chan = 0) = 0; + + /*! + * Set whether the LO used by the usrp device is exported + * For usrps that support exportable LOs, this function + * configures if the LO used by chan is exported or not. + * \param enabled if true then export the LO + * \param name the name of the LO stage to update + * \param chan the channel index 0 to N-1 for the source channel + */ + virtual void set_rx_lo_export_enabled(bool enabled, const std::string &name = ALL_LOS, size_t chan = 0) = 0; + + /*! + * Returns true if the currently selected LO is being exported. + * \param name the name of the LO stage to query + * \param chan the channel index 0 to N-1 + */ + virtual bool get_rx_lo_export_enabled(const std::string &name = ALL_LOS, size_t chan = 0) = 0; + + /*! + * Set the RX LO frequency (Advanced). + * \param freq the frequency to set the LO to + * \param name the name of the LO stage to update + * \param chan the channel index 0 to N-1 + * \return a coerced LO frequency + */ + virtual double set_rx_lo_freq(double freq, const std::string &name, size_t chan = 0) = 0; + + /*! + * Get the current RX LO frequency (Advanced). + * \param name the name of the LO stage to query + * \param chan the channel index 0 to N-1 + * \return the configured LO frequency + */ + virtual double get_rx_lo_freq(const std::string &name, size_t chan = 0) = 0; + + /*! + * Get the LO frequency range of the RX LO. + * \param name the name of the LO stage to query + * \param chan the channel index 0 to N-1 + * \return a frequency range object + */ + virtual freq_range_t get_rx_lo_freq_range(const std::string &name, 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 diff --git a/host/include/uhd/usrp/usrp.h b/host/include/uhd/usrp/usrp.h index 651279e22..f24d12b85 100644 --- a/host/include/uhd/usrp/usrp.h +++ b/host/include/uhd/usrp/usrp.h @@ -1,5 +1,5 @@ // -// Copyright 2015 Ettus Research LLC +// Copyright 2015-2016 Ettus Research LLC // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by @@ -726,6 +726,83 @@ UHD_API uhd_error uhd_usrp_get_fe_rx_freq_range( uhd_meta_range_handle freq_range_out ); +//! A wildcard for all LO names +UHD_UNUSED(static const char* UHD_USRP_ALL_LOS) = "all"; + +//! Get a list of possible LO stage names +/* + * See uhd::usrp::multi_usrp::get_rx_lo_names() for more details. + */ +UHD_API uhd_error uhd_usrp_get_rx_lo_names( + uhd_usrp_handle h, + size_t chan, + uhd_string_vector_handle *rx_lo_names_out +); + +//! Set the LO source for the USRP device +/* + * See uhd::usrp::multi_usrp::set_rx_lo_source() for more details. + */ +UHD_API uhd_error uhd_usrp_set_rx_lo_source( + uhd_usrp_handle h, + const char* src, + const char* name, + size_t chan +); + +//! Get the currently set LO source +UHD_API uhd_error uhd_usrp_get_rx_lo_source( + uhd_usrp_handle h, + const char* name, + size_t chan, + char* rx_lo_source_out, + size_t strbuffer_len +); + +//! Get a list of possible LO sources +UHD_API uhd_error uhd_usrp_get_rx_lo_sources( + uhd_usrp_handle h, + const char* name, + size_t chan, + uhd_string_vector_handle *rx_lo_sources_out +); + +//! Set whether the LO used by the USRP device is exported +/* + * See uhd::usrp::multi_usrp::set_rx_lo_enabled() for more details. + */ +UHD_API uhd_error uhd_usrp_set_rx_lo_export_enabled( + uhd_usrp_handle h, + bool enabled, + const char* name, + size_t chan +); + +//! Returns true if the currently selected LO is being exported. +UHD_API uhd_error uhd_usrp_get_rx_lo_export_enabled( + uhd_usrp_handle h, + const char* name, + size_t chan, + bool* result_out +); + +//! Set the RX LO frequency. +UHD_API uhd_error uhd_usrp_set_rx_lo_freq( + uhd_usrp_handle h, + double freq, + const char* name, + size_t chan, + double* coerced_freq_out +); + +//! Get the current RX LO frequency. +UHD_API uhd_error uhd_usrp_get_rx_lo_freq( + uhd_usrp_handle h, + const char* name, + size_t chan, + double* rx_lo_freq_out +); + //! Set the RX gain for the given channel and name UHD_API uhd_error uhd_usrp_set_rx_gain( uhd_usrp_handle h, diff --git a/host/include/uhd/utils/algorithm.hpp b/host/include/uhd/utils/algorithm.hpp index 704d745d9..6c6cdf033 100644 --- a/host/include/uhd/utils/algorithm.hpp +++ b/host/include/uhd/utils/algorithm.hpp @@ -1,5 +1,5 @@ // -// Copyright 2010-2014 Ettus Research LLC +// Copyright 2010-2015 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 @@ -39,7 +39,7 @@ namespace uhd{ * \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){ + template<typename Range> UHD_INLINE Range sorted(const Range &range){ Range r(range); std::sort(boost::begin(r), boost::end(r)); return r; } @@ -53,7 +53,7 @@ namespace uhd{ * \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){ + template<typename Range> UHD_INLINE Range reversed(const Range &range){ Range r(range); std::reverse(boost::begin(r), boost::end(r)); return r; } @@ -66,7 +66,7 @@ namespace uhd{ * \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 + template<typename Range, typename T> UHD_INLINE bool has(const Range &range, const T &value){ return boost::end(range) != std::find(boost::begin(range), boost::end(range), value); } @@ -78,7 +78,7 @@ namespace uhd{ * \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){ + template<typename T> UHD_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); diff --git a/host/include/uhd/utils/atomic.hpp b/host/include/uhd/utils/atomic.hpp index 55769d2fd..8c5e6a5da 100644 --- a/host/include/uhd/utils/atomic.hpp +++ b/host/include/uhd/utils/atomic.hpp @@ -1,5 +1,5 @@ // -// Copyright 2012-2013 Ettus Research LLC +// Copyright 2012-2013,2016 Ettus Research LLC // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by @@ -26,11 +26,7 @@ #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 +#define BOOST_IPC_DETAIL boost::interprocess::ipcdetail namespace uhd{ diff --git a/host/include/uhd/utils/cast.hpp b/host/include/uhd/utils/cast.hpp index 9db92c526..869d53053 100644 --- a/host/include/uhd/utils/cast.hpp +++ b/host/include/uhd/utils/cast.hpp @@ -1,5 +1,5 @@ // -// Copyright 2014 Ettus Research LLC +// Copyright 2014-2015 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 @@ -28,7 +28,7 @@ namespace uhd{ namespace cast{ // Example: // boost::uint16_t x = hexstr_cast<boost::uint16_t>("0xDEADBEEF"); // Uses stringstream. - template<typename T> inline T hexstr_cast(const std::string &in) + template<typename T> UHD_INLINE T hexstr_cast(const std::string &in) { T x; std::stringstream ss; diff --git a/host/include/uhd/utils/dirty_tracked.hpp b/host/include/uhd/utils/dirty_tracked.hpp index d228a9e65..561beec9b 100644 --- a/host/include/uhd/utils/dirty_tracked.hpp +++ b/host/include/uhd/utils/dirty_tracked.hpp @@ -1,5 +1,5 @@ // -// Copyright 2010-2014 Ettus Research LLC +// Copyright 2010-2015 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 @@ -60,7 +60,7 @@ namespace uhd{ /*! * Get underlying data */ - inline const data_t& get() const { + UHD_INLINE const data_t& get() const { return _data; } @@ -68,21 +68,21 @@ namespace uhd{ * Has the underlying data changed since the last * time it was cleaned? */ - inline bool is_dirty() const { + UHD_INLINE bool is_dirty() const { return _dirty; } /*! * Mark the underlying data as clean */ - inline void mark_clean() { + UHD_INLINE void mark_clean() { _dirty = false; } /*! * Mark the underlying data as dirty */ - inline void force_dirty() { + UHD_INLINE void force_dirty() { _dirty = true; } @@ -91,7 +91,7 @@ namespace uhd{ * Store the specified value and mark it as dirty * if it is not equal to the underlying data. */ - inline dirty_tracked& operator=(const data_t& value) + UHD_INLINE dirty_tracked& operator=(const data_t& value) { if(!(_data == value)) { //data_t must have an equality operator _dirty = true; @@ -107,7 +107,7 @@ namespace uhd{ * This exists to optimize out an implicit cast from dirty_tracked * type to data type. */ - inline dirty_tracked& operator=(const dirty_tracked& source) { + UHD_INLINE dirty_tracked& operator=(const dirty_tracked& source) { if (!(_data == source._data)) { _dirty = true; _data = source._data; @@ -118,7 +118,7 @@ namespace uhd{ /*! * Explicit conversion from this type to data_t */ - inline operator const data_t&() const { + UHD_INLINE operator const data_t&() const { return get(); } diff --git a/host/include/uhd/utils/math.hpp b/host/include/uhd/utils/math.hpp index 088983167..0b35f1f17 100644 --- a/host/include/uhd/utils/math.hpp +++ b/host/include/uhd/utils/math.hpp @@ -32,19 +32,6 @@ namespace uhd { namespace math { /*! - * Numeric limits of certain types. - * - * There are many sources for getting these, including std::numeric_limits, - * `<cstdint>`, `<climits>`, and Boost. The `<cstdint>` option is preferable as it - * gives us fixed-width constants, but unfortunately is new as of C++11. - * Since this isn't available on many systems, we need to use one of the - * other options. We will use the Boost option, here, since we use Boost - * data types for portability across UHD. - */ - static const boost::int32_t BOOST_INT32_MAX = boost::numeric::bounds<boost::int32_t>::highest(); - static const boost::int32_t BOOST_INT32_MIN = boost::numeric::bounds<boost::int32_t>::lowest(); - - /*! * Define epsilon values for floating point comparisons. * * There are a lot of different sources for epsilon values that we could use diff --git a/host/include/uhd/utils/msg_task.hpp b/host/include/uhd/utils/msg_task.hpp index d46fdd69e..8ae789d72 100644 --- a/host/include/uhd/utils/msg_task.hpp +++ b/host/include/uhd/utils/msg_task.hpp @@ -1,5 +1,5 @@ // -// Copyright 2011-2014 Ettus Research LLC +// Copyright 2011-2015 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 @@ -42,7 +42,7 @@ namespace uhd{ */ virtual msg_payload_t get_msg_from_dump_queue(boost::uint32_t sid) = 0; - inline static std::vector<boost::uint8_t> buff_to_vector(boost::uint8_t* p, size_t n) { + UHD_INLINE static std::vector<boost::uint8_t> buff_to_vector(boost::uint8_t* p, size_t n) { if(p and n > 0){ std::vector<boost::uint8_t> v(n); memcpy(&v.front(), p, n); diff --git a/host/include/uhd/utils/soft_register.hpp b/host/include/uhd/utils/soft_register.hpp index a2c34a4ec..09a69fce2 100644 --- a/host/include/uhd/utils/soft_register.hpp +++ b/host/include/uhd/utils/soft_register.hpp @@ -57,7 +57,7 @@ namespace uhd { //TODO: These hints were added to boost 1.53. /** \brief hint for the branch prediction */ -inline bool likely(bool expr) +UHD_INLINE bool likely(bool expr) { #ifdef __GNUC__ return __builtin_expect(expr, true); @@ -67,7 +67,7 @@ inline bool likely(bool expr) } /** \brief hint for the branch prediction */ -inline bool unlikely(bool expr) +UHD_INLINE bool unlikely(bool expr) { #ifdef __GNUC__ return __builtin_expect(expr, false); @@ -86,16 +86,16 @@ inline bool unlikely(bool expr) typedef boost::uint32_t soft_reg_field_t; namespace soft_reg_field { - inline size_t width(const soft_reg_field_t field) { + UHD_INLINE size_t width(const soft_reg_field_t field) { return (field & 0xFF); } - inline size_t shift(const soft_reg_field_t field) { + UHD_INLINE size_t shift(const soft_reg_field_t field) { return ((field >> 8) & 0xFF); } template<typename data_t> - inline size_t mask(const soft_reg_field_t field) { + UHD_INLINE size_t mask(const soft_reg_field_t field) { static const data_t ONE = static_cast<data_t>(1); //Behavior for the left shift operation is undefined in C++ //if the shift amount is >= bitwidth of the datatype @@ -122,7 +122,7 @@ public: * Cast the soft_register generic reference to a more specific type */ template <typename soft_reg_t> - inline static soft_reg_t& cast(soft_register_base& reg) { + UHD_INLINE static soft_reg_t& cast(soft_register_base& reg) { soft_reg_t* ptr = dynamic_cast<soft_reg_t*>(®); if (ptr) { return *ptr; @@ -150,7 +150,7 @@ public: /*! * Generic constructor for all soft_register types */ - explicit soft_register_t( + soft_register_t( wb_iface::wb_addr_type wr_addr, wb_iface::wb_addr_type rd_addr, soft_reg_flush_mode_t mode = ALWAYS_FLUSH): @@ -172,7 +172,7 @@ public: * Can be optionally synced with hardware. * NOTE: Memory management of the iface is up to the caller */ - inline void initialize(wb_iface& iface, bool sync = false) + UHD_INLINE void initialize(wb_iface& iface, bool sync = false) { _iface = &iface; @@ -186,7 +186,7 @@ public: * Performs a read-modify-write operation so all other field are preserved. * NOTE: This does not write the value to hardware. */ - inline void set(const soft_reg_field_t field, const reg_data_t value) + UHD_INLINE void set(const soft_reg_field_t field, const reg_data_t value) { _soft_copy = (_soft_copy & ~soft_reg_field::mask<reg_data_t>(field)) | ((value << soft_reg_field::shift(field)) & soft_reg_field::mask<reg_data_t>(field)); @@ -196,7 +196,7 @@ public: * Get the value of the specified field from the soft-copy. * NOTE: This does not read anything from hardware. */ - inline reg_data_t get(const soft_reg_field_t field) + UHD_INLINE reg_data_t get(const soft_reg_field_t field) { return (_soft_copy & soft_reg_field::mask<reg_data_t>(field)) >> soft_reg_field::shift(field); } @@ -204,7 +204,7 @@ public: /*! * Write the contents of the soft-copy to hardware. */ - inline void flush() + UHD_INLINE void flush() { if (writable && _iface) { //If optimized flush then poke only if soft copy is dirty @@ -223,14 +223,14 @@ public: _soft_copy.mark_clean(); } } else { - throw uhd::not_implemented_error("soft_register is not writable."); + throw uhd::not_implemented_error("soft_register is not writable or uninitialized."); } } /*! * Read the contents of the register from hardware and update the soft copy. */ - inline void refresh() + UHD_INLINE void refresh() { if (readable && _iface) { if (get_bitwidth() <= 16) { @@ -244,14 +244,14 @@ public: } _soft_copy.mark_clean(); } else { - throw uhd::not_implemented_error("soft_register is not readable."); + throw uhd::not_implemented_error("soft_register is not readable or uninitialized."); } } /*! * Shortcut for a set and a flush. */ - inline void write(const soft_reg_field_t field, const reg_data_t value) + UHD_INLINE void write(const soft_reg_field_t field, const reg_data_t value) { set(field, value); flush(); @@ -260,7 +260,7 @@ public: /*! * Shortcut for refresh and get */ - inline reg_data_t read(const soft_reg_field_t field) + UHD_INLINE reg_data_t read(const soft_reg_field_t field) { refresh(); return get(field); @@ -269,7 +269,7 @@ public: /*! * Get bitwidth for this register */ - inline size_t get_bitwidth() + UHD_INLINE size_t get_bitwidth() { static const size_t BITS_IN_BYTE = 8; return sizeof(reg_data_t) * BITS_IN_BYTE; @@ -278,7 +278,7 @@ public: /*! * Is the register readable? */ - inline bool is_readable() + UHD_INLINE bool is_readable() { return readable; } @@ -286,7 +286,7 @@ public: /*! * Is the register writable? */ - inline bool is_writable() + UHD_INLINE bool is_writable() { return writable; } @@ -308,7 +308,7 @@ class UHD_API soft_register_sync_t : public soft_register_t<reg_data_t, readable public: typedef boost::shared_ptr< soft_register_sync_t<reg_data_t, readable, writable> > sptr; - explicit soft_register_sync_t( + soft_register_sync_t( wb_iface::wb_addr_type wr_addr, wb_iface::wb_addr_type rd_addr, soft_reg_flush_mode_t mode = ALWAYS_FLUSH): @@ -321,43 +321,43 @@ public: soft_register_t<reg_data_t, readable, writable>(addr, mode), _mutex() {} - inline void initialize(wb_iface& iface, bool sync = false) + UHD_INLINE void initialize(wb_iface& iface, bool sync = false) { boost::lock_guard<boost::mutex> lock(_mutex); soft_register_t<reg_data_t, readable, writable>::initialize(iface, sync); } - inline void set(const soft_reg_field_t field, const reg_data_t value) + UHD_INLINE void set(const soft_reg_field_t field, const reg_data_t value) { boost::lock_guard<boost::mutex> lock(_mutex); soft_register_t<reg_data_t, readable, writable>::set(field, value); } - inline reg_data_t get(const soft_reg_field_t field) + UHD_INLINE reg_data_t get(const soft_reg_field_t field) { boost::lock_guard<boost::mutex> lock(_mutex); return soft_register_t<reg_data_t, readable, writable>::get(field); } - inline void flush() + UHD_INLINE void flush() { boost::lock_guard<boost::mutex> lock(_mutex); soft_register_t<reg_data_t, readable, writable>::flush(); } - inline void refresh() + UHD_INLINE void refresh() { boost::lock_guard<boost::mutex> lock(_mutex); soft_register_t<reg_data_t, readable, writable>::refresh(); } - inline void write(const soft_reg_field_t field, const reg_data_t value) + UHD_INLINE void write(const soft_reg_field_t field, const reg_data_t value) { boost::lock_guard<boost::mutex> lock(_mutex); soft_register_t<reg_data_t, readable, writable>::write(field, value); } - inline reg_data_t read(const soft_reg_field_t field) + UHD_INLINE reg_data_t read(const soft_reg_field_t field) { boost::lock_guard<boost::mutex> lock(_mutex); return soft_register_t<reg_data_t, readable, writable>::read(field); @@ -469,7 +469,7 @@ public: /*! * Get the name of this register map */ - virtual inline const std::string& get_name() const { return _name; } + virtual UHD_INLINE const std::string& get_name() const { return _name; } /*! * Initialize all registers in this register map using a bus. @@ -542,7 +542,7 @@ protected: /*! * Add a register to this map with an identifier "name" and visibility */ - inline void add_to_map(soft_register_base& reg, const std::string& name, const visibility_t visible = PRIVATE) { + UHD_INLINE void add_to_map(soft_register_base& reg, const std::string& name, const visibility_t visible = PRIVATE) { boost::lock_guard<boost::mutex> lock(_mutex); if (visible == PUBLIC) { //Only add to the map if this register is publicly visible diff --git a/host/include/uhd/version.hpp.in b/host/include/uhd/version.hpp.in index e2c64812d..85c0aac9f 100644 --- a/host/include/uhd/version.hpp.in +++ b/host/include/uhd/version.hpp.in @@ -1,5 +1,5 @@ // -// Copyright 2010-2014 Ettus Research LLC +// Copyright 2010-2015 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 @@ -27,11 +27,11 @@ * 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.9.0-0" +#define UHD_VERSION_ABI_STRING "3.10.0-0" /*! * A macro to check UHD version at compile-time. - * The value of this macro is MAJOR * 10000 + MINOR * 100 + PATCH + * The value of this macro is MAJOR * 1000000 + API * 10000 + ABI * 100 + PATCH * (e.g., for UHD 3.8.1 this is 30801). */ #cmakedefine UHD_VERSION @UHD_VERSION_ADDED@ |