diff options
Diffstat (limited to 'host/include')
32 files changed, 797 insertions, 493 deletions
| diff --git a/host/include/config.h.in b/host/include/config.h.in index 8e72a1f00..0e8982488 100644 --- a/host/include/config.h.in +++ b/host/include/config.h.in @@ -18,10 +18,10 @@  #cmakedefine HAVE_LOG2  /* Version macros */ -#cmakedefine UHD_VERSION_MAJOR ${TRIMMED_VERSION_MAJOR} -#cmakedefine UHD_VERSION_API   ${TRIMMED_VERSION_API} -#cmakedefine UHD_VERSION_ABI   ${TRIMMED_VERSION_ABI} -#cmakedefine UHD_VERSION_PATCH ${TRIMMED_VERSION_PATCH} +#cmakedefine UHD_VERSION_MAJOR ${UHD_VERSION_MAJOR} +#cmakedefine UHD_VERSION_API   ${UHD_VERSION_API} +#cmakedefine UHD_VERSION_ABI   ${UHD_VERSION_ABI} +#cmakedefine UHD_VERSION_PATCH ${UHD_VERSION_PATCH}  #cmakedefine ENABLE_USB  #ifndef UHD_VERSION  #cmakedefine UHD_VERSION @UHD_VERSION_ADDED@ diff --git a/host/include/uhd/CMakeLists.txt b/host/include/uhd/CMakeLists.txt index e31ff80a0..805db13de 100644 --- a/host/include/uhd/CMakeLists.txt +++ b/host/include/uhd/CMakeLists.txt @@ -18,6 +18,7 @@  ADD_SUBDIRECTORY(rfnoc)  ADD_SUBDIRECTORY(transport)  ADD_SUBDIRECTORY(types) +ADD_SUBDIRECTORY(cal)  ADD_SUBDIRECTORY(usrp)  ADD_SUBDIRECTORY(usrp_clock)  ADD_SUBDIRECTORY(utils) @@ -33,7 +34,6 @@ UHD_INSTALL(FILES      convert.hpp      deprecated.hpp      device.hpp -    device_deprecated.ipp      exception.hpp      property_tree.ipp      property_tree.hpp diff --git a/host/include/uhd/cal/CMakeLists.txt b/host/include/uhd/cal/CMakeLists.txt new file mode 100644 index 000000000..14107ee53 --- /dev/null +++ b/host/include/uhd/cal/CMakeLists.txt @@ -0,0 +1,23 @@ +# +# 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/>. +# + +UHD_INSTALL(FILES +    container.hpp +    power_container.hpp +    DESTINATION ${INCLUDE_DIR}/uhd/cal +    COMPONENT headers +) diff --git a/host/include/uhd/cal/container.hpp b/host/include/uhd/cal/container.hpp new file mode 100644 index 000000000..e4f418311 --- /dev/null +++ b/host/include/uhd/cal/container.hpp @@ -0,0 +1,104 @@ +// +// Copyright 2016 Ettus Research +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program.  If not, see <http://www.gnu.org/licenses/>. +// + +#ifndef INCLUDED_UHD_CAL_CONTAINER_HPP +#define INCLUDED_UHD_CAL_CONTAINER_HPP + +#include <uhd/config.hpp> +#include <boost/serialization/serialization.hpp> +#include <boost/serialization/vector.hpp> +#include <boost/serialization/string.hpp> +#include <boost/serialization/map.hpp> +#include <boost/archive/text_iarchive.hpp> +#include <boost/archive/text_oarchive.hpp> +#include <boost/shared_ptr.hpp> + +namespace uhd { +namespace cal { + +class base_container { +public: +    typedef std::map<std::string, std::string> metadata_t; +    typedef boost::shared_ptr<base_container> sptr; +}; + +/*! + * An interface for creating and managing a generic calibration + * data container. + * + * These containers are used to represent N dimensional data structures + * in order to accommodate a mapping from multi-variable input to a scalar + * value (e.g. gain, frequency, temperature -> power level [dBm]). + * + * The container only supports inputs of the same type to be mapped. + * + */ +template<typename in_type, typename out_type> +class UHD_API cal_container : public base_container { +public: +    typedef std::map<in_type, out_type> container_t; + +    /*! +     * Get the mapping from an input to an output +     * from the calibration container. +     * +     * \param args input values +     * \returns the output of the mapping (a scalar value) +     * \throws uhd::assertion_error if the dimensions of the input args +     *         are incorrect for this container +     */ +    virtual out_type get(const in_type &args) = 0; + +    /*! +     * Add a data point to the container. +     * This function records a mapping R^n -> R between an input vector +     * and output scalar. +     * +     * \param output the output of the data point mapping +     * \param args input values +     */ +    virtual void add(const out_type output, const in_type &args) = 0; + +    /*! +     * Associate some metadata with the container. +     * +     * \param data a map of metadata (string -> string). +     */ +    virtual void add_metadata(const metadata_t &data) = 0; + +    /*! +     * Retrieve metadata from the container. +     * +     * \returns map of metadata. +     */ +    virtual const metadata_t &get_metadata() = 0; + +public: +    typedef boost::archive::text_iarchive iarchive_type; +    typedef boost::archive::text_oarchive oarchive_type; + +protected: +    friend class boost::serialization::access; + +    virtual void serialize(iarchive_type & ar, const unsigned int) = 0; +    virtual void serialize(oarchive_type & ar, const unsigned int) = 0; +}; + +} // namespace cal +} // namespace uhd + +#endif /* INCLUDED_UHD_CAL_CONTAINER_HPP */ diff --git a/host/include/uhd/cal/power_container.hpp b/host/include/uhd/cal/power_container.hpp new file mode 100644 index 000000000..37f7bd8df --- /dev/null +++ b/host/include/uhd/cal/power_container.hpp @@ -0,0 +1,79 @@ +// +// Copyright 2016 Ettus Research +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program.  If not, see <http://www.gnu.org/licenses/>. +// + +#ifndef INCLUDED_UHD_CAL_POWER_CONTAINER_HPP +#define INCLUDED_UHD_CAL_POWER_CONTAINER_HPP + +#include <uhd/config.hpp> +#include <uhd/cal/container.hpp> +#include <boost/shared_ptr.hpp> + +namespace uhd { +namespace cal { + +class UHD_API power_container : public cal_container<std::vector<double>, double> { +public: +    typedef boost::shared_ptr<power_container> sptr; + +    /*! +     * Create a container for data related to power calibration. +     * +     * \returns shared pointer to the container +     */ +    static sptr make(); + +    /*! +     * Get the mapping from an input to an output +     * from the calibration container. +     * +     * \param args input values +     * \returns the output of the mapping (a scalar value) +     * \throws uhd::assertion_error if the number of input values are incorrect +     *         for the container type +     */ +    virtual double get(const std::vector<double> &args) = 0; + +    /*! +     * Add a data point to the container. +     * This function records a mapping R^n -> R between an input vector +     * and output scalar. For example, a mapping might be +     * (power level, frequency, temperature) -> gain. +     * +     * \param output the output of the data point mapping +     * \param args input values +     */ +    virtual void add(const double output, const std::vector<double> &args) = 0; + +    /*! +     * Associate some metadata with the container. +     * +     * \param data a map of metadata (string -> string). +     */ +    virtual void add_metadata(const metadata_t &data) = 0; + +    /*! +     * Retrieve metadata from the container. +     * +     * \returns map of metadata. +     */ +    virtual const metadata_t &get_metadata() = 0; +}; + +} // namespace cal +} // namespace uhd + +#endif /* INCLUDED_UHD_CAL_POWER_CONTAINER_HPP */ diff --git a/host/include/uhd/device.hpp b/host/include/uhd/device.hpp index 894b48c47..28b81a0f6 100644 --- a/host/include/uhd/device.hpp +++ b/host/include/uhd/device.hpp @@ -105,14 +105,22 @@ public:       */      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      uhd::property_tree::sptr get_tree(void) const;      //! Get device type      device_filter_t get_device_type() const; -    #include <uhd/device_deprecated.ipp> -  protected:      uhd::property_tree::sptr _tree;      device_filter_t _type; diff --git a/host/include/uhd/device3.hpp b/host/include/uhd/device3.hpp index da23bb263..a2e530321 100644 --- a/host/include/uhd/device3.hpp +++ b/host/include/uhd/device3.hpp @@ -22,6 +22,7 @@  #include <uhd/rfnoc/graph.hpp>  #include <uhd/rfnoc/block_ctrl_base.hpp>  #include <boost/units/detail/utility.hpp> +#include <boost/thread/mutex.hpp>  #include <vector>  namespace uhd { @@ -53,12 +54,14 @@ class UHD_API device3 : public uhd::device {       *       * \param block_id Canonical block name (e.g. "0/FFT_1").       * \return true if a block with the specified id exists +     * \note this access is not thread safe if peformed during block enumeration       */      bool has_block(const rfnoc::block_id_t &block_id) const;      /*! Same as has_block(), but with a type check.       *       * \return true if a block of type T with the specified id exists +     * \note this access is not thread safe if peformed during block enumeration       */      template <typename T>      bool has_block(const rfnoc::block_id_t &block_id) const @@ -76,6 +79,7 @@ class UHD_API device3 : public uhd::device {       * on this device), it will throw a uhd::lookup_error.       *       * \param block_id Canonical block name (e.g. "0/FFT_1"). +     * \note this access is not thread safe if peformed during block enumeration       */      rfnoc::block_ctrl_base::sptr get_block_ctrl(const rfnoc::block_id_t &block_id) const; @@ -91,6 +95,7 @@ class UHD_API device3 : public uhd::device {       * uhd::rfnoc::my_block_ctrl::sptr block_controller = get_block_ctrl<my_block_ctrl>("0/MyBlock_0");       * block_controller->my_own_block_method();       * \endcode +     * \note this access is not thread safe if peformed during block enumeration       */      template <typename T>      boost::shared_ptr<T> get_block_ctrl(const rfnoc::block_id_t &block_id) const @@ -115,6 +120,7 @@ class UHD_API device3 : public uhd::device {       * // Assume DEV is a device3::sptr       * null_block_ctrl::sptr null_block = DEV->find_blocks<null_block_ctrl>("NullSrcSink");       * \endcode +     * \note this access is not thread safe if peformed during block enumeration       */      std::vector<rfnoc::block_id_t> find_blocks(const std::string &block_id_hint) const; @@ -138,6 +144,8 @@ class UHD_API device3 : public uhd::device {      //  It is the responsibility of the deriving class to make      //  sure this gets correctly populated.      std::vector< rfnoc::block_ctrl_base::sptr > _rfnoc_block_ctrl; +    //! Mutex to protect access to members +    boost::mutex                                _block_ctrl_mutex;  };  } //namespace uhd diff --git a/host/include/uhd/device_deprecated.ipp b/host/include/uhd/device_deprecated.ipp deleted file mode 100644 index 2741df4e3..000000000 --- a/host/include/uhd/device_deprecated.ipp +++ /dev/null @@ -1,201 +0,0 @@ -// -// 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 exhausted, - * 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(); -} - -/*! - * 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; - -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/image_loader.hpp b/host/include/uhd/image_loader.hpp index fd4a96781..4ebac288e 100644 --- a/host/include/uhd/image_loader.hpp +++ b/host/include/uhd/image_loader.hpp @@ -21,6 +21,7 @@  #include <string>  #include <boost/function.hpp> +#include <boost/noncopyable.hpp>  #include <uhd/config.hpp>  #include <uhd/types/device_addr.hpp> diff --git a/host/include/uhd/rfnoc/block_ctrl_base.hpp b/host/include/uhd/rfnoc/block_ctrl_base.hpp index e9dd9c233..87d9b3a71 100644 --- a/host/include/uhd/rfnoc/block_ctrl_base.hpp +++ b/host/include/uhd/rfnoc/block_ctrl_base.hpp @@ -46,7 +46,6 @@ struct make_args_t  {      make_args_t(const std::string &key="") :          device_index(0), -        is_big_endian(true),          block_name(""),          block_key(key)      {} @@ -61,7 +60,6 @@ struct make_args_t      //  property tree is /mboards/0, pass a subtree starting at /mboards/0      //  to the constructor.      uhd::property_tree::sptr tree; -    bool is_big_endian;      //! The name of the block as it will be addressed      std::string block_name;      //! The key of the block, i.e. how it was registered @@ -394,9 +392,6 @@ protected:      //! Root node of this block's properties      uhd::fs_path _root_path; -    //! Endianness of underlying transport (for data transport) -    bool _transport_is_big_endian; -      //! Block definition (stores info about the block such as ports)      blockdef::sptr _block_def; diff --git a/host/include/uhd/rfnoc/node_ctrl_base.hpp b/host/include/uhd/rfnoc/node_ctrl_base.hpp index 6fd6fd288..0505556ec 100644 --- a/host/include/uhd/rfnoc/node_ctrl_base.hpp +++ b/host/include/uhd/rfnoc/node_ctrl_base.hpp @@ -32,7 +32,7 @@  namespace uhd {      namespace rfnoc { -#define UHD_RFNOC_BLOCK_TRACE() UHD_LOGV(never) << "[" << unique_id() << "] " +#define UHD_RFNOC_BLOCK_TRACE() UHD_LOGGER_TRACE("RFNOC")  /*! \brief Abstract base class for streaming nodes.   * diff --git a/host/include/uhd/rfnoc/node_ctrl_base.ipp b/host/include/uhd/rfnoc/node_ctrl_base.ipp index d300f72a7..df92e2e8b 100644 --- a/host/include/uhd/rfnoc/node_ctrl_base.ipp +++ b/host/include/uhd/rfnoc/node_ctrl_base.ipp @@ -21,7 +21,7 @@  #define INCLUDED_LIBUHD_NODE_CTRL_BASE_IPP  #include <uhd/exception.hpp> -#include <uhd/utils/msg.hpp> +  #include <boost/shared_ptr.hpp>  #include <vector> diff --git a/host/include/uhd/rfnoc/radio_ctrl.hpp b/host/include/uhd/rfnoc/radio_ctrl.hpp index 1d7842051..be22c6e5e 100644 --- a/host/include/uhd/rfnoc/radio_ctrl.hpp +++ b/host/include/uhd/rfnoc/radio_ctrl.hpp @@ -18,6 +18,7 @@  #ifndef INCLUDED_LIBUHD_RFNOC_RADIO_CTRL_HPP  #define INCLUDED_LIBUHD_RFNOC_RADIO_CTRL_HPP +#include <uhd/types/ranges.hpp>  #include <uhd/types/direction.hpp>  #include <uhd/rfnoc/source_block_ctrl_base.hpp>  #include <uhd/rfnoc/sink_block_ctrl_base.hpp> @@ -43,6 +44,16 @@ public:      virtual ~radio_ctrl(){} + +    //! A wildcard channel index +    static const size_t ALL_CHANS = size_t(~0); + +    //! A wildcard gain element name +    static const std::string ALL_GAINS; + +    //! A wildcard local oscillator element name +    static const std::string ALL_LOS; +      /************************************************************************       * API calls       ***********************************************************************/ @@ -109,11 +120,13 @@ public:       */      virtual double get_rx_frequency(const size_t chan) /* const */ = 0; -    /*! Tune the RX LO for channel \p. +    /*! Tune the RX LO for channel \p chan.       *       * This function will attempt to tune as close as possible, and return a       * coerced value of the actual tuning result.       * +     * \param freq Requested LO frequency +     * \param chan Channel number.       * \return The actual LO frequency.       */      virtual double set_rx_frequency(const double freq, const size_t chan) = 0; @@ -148,6 +161,20 @@ public:       */      virtual double set_rx_gain(const double gain, const size_t chan) = 0; +    /*! Return the analog filter bandwidth channel \p chan +     * +     * \return The actual bandwidth value +     */ +    virtual double get_rx_bandwidth(const size_t chan) = 0; + +    /*! Set the analog filter bandwidth channel \p chan +     * +     * This function will attempt to set the analog bandwidth. +     * +     * \return The actual bandwidth value +     */ +    virtual double set_rx_bandwidth(const double bandwidth, const size_t chan) = 0; +      /*! Sets the time in the radio's timekeeper to the given value.       *       * Note that there is a non-deterministic delay between calling this @@ -186,6 +213,182 @@ public:       */      virtual time_spec_t get_time_last_pps() = 0; +    /*! Returns the list of GPIO banks that are associated with this radio. +     * +     * \returns list of GPIO bank names +     */ +    virtual std::vector<std::string> get_gpio_banks() const = 0; + +    /*! +     * Set a GPIO attribute on a particular GPIO bank. +     * Possible attribute names: +     *  - CTRL - 1 for ATR mode 0 for GPIO mode +     *  - DDR - 1 for output 0 for input +     *  - OUT - GPIO output level (not ATR mode) +     *  - ATR_0X - ATR idle state +     *  - ATR_RX - ATR receive only state +     *  - ATR_TX - ATR transmit only state +     *  - ATR_XX - ATR full duplex state +     * \param bank the name of a GPIO bank (e.g., FP0) +     * \param attr the name of a GPIO attribute (e.g., CTRL) +     * \param value the new value for this GPIO bank +     * \param mask the bit mask to effect which pins are changed +     */ +    virtual void set_gpio_attr( +            const std::string &bank, +            const std::string &attr, +            const uint32_t value, +            const uint32_t mask +    ) = 0; + +    /*! +     * Get a GPIO attribute on a particular GPIO bank. +     * Possible attribute names: +     *  - CTRL - 1 for ATR mode 0 for GPIO mode +     *  - DDR - 1 for output 0 for input +     *  - OUT - GPIO output level (not ATR mode) +     *  - ATR_0X - ATR idle state +     *  - ATR_RX - ATR receive only state +     *  - ATR_TX - ATR transmit only state +     *  - ATR_XX - ATR full duplex state +     *  - READBACK - readback input GPIOs +     * \param bank the name of a GPIO bank +     * \param attr the name of a GPIO attribute +     * \return the value set for this attribute +     */ +    virtual uint32_t get_gpio_attr(const std::string &bank, const std::string &attr) = 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(const size_t chan) = 0; + +    /*! +     * Get a list of possible LO sources. +     * Channels which do not have controllable LO sources +     * will return "internal". +     * \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, const size_t chan) = 0; + +    /*! +     * Get the LO frequency range of the RX LO. +     * If the channel does not have independently configurable LOs +     * the rf frequency range will be returned. +     * \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, const size_t chan) = 0; + +    /*! +     * Set the LO source for a channel. +     * 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, const size_t chan) = 0; + +    /*! +     * Get the currently set LO source. +     * Channels without controllable LO sources will return +     * "internal" +     * \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, const size_t chan) = 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, const size_t chan) = 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, const size_t chan) = 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, const size_t chan) = 0; + +    /*! +     * Get the current RX LO frequency (Advanced). +     * If the channel does not have independently configurable LOs +     * the current rf frequency will be returned. +     * \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, const size_t chan) = 0; + +    /*!  +     * Set the time source for this radio. +     * +     * May affect other radio blocks. +     * +     * \param source A string representing the time source +     * \throws uhd::value_error if the value can't be applied +     */ +    virtual void set_time_source(const std::string &source) = 0; + +    /*! +     * Get the currently set time source. +     * +     * \return the string representing the time source +     */ +    virtual std::string get_time_source() = 0; + +    /*! +     * Get a list of possible time sources. +     * +     * \return a vector of strings for possible settings +     */ +    virtual std::vector<std::string> get_time_sources() = 0; + +    /*! +     * Set the clock source for the usrp device (for reference clock). +     * +     * Typical options for source: internal, external. +     * +     * \param source a string representing the clock source +     */ +    virtual void set_clock_source(const std::string &source) = 0; + +    /*! +     * Get the currently set clock source. +     * +     * \return the string representing the clock source +     */ +    virtual std::string get_clock_source() = 0; + +    /*! +     * Get a list of possible clock sources. +     * +     * \return a vector of strings for possible settings +     */ +    virtual std::vector<std::string> get_clock_sources() = 0; +      /*! Given a frontend name, return the channel mapping.       *       * E.g.: For a TwinRX board, there's two frontends, '0' and '1', which diff --git a/host/include/uhd/transport/nirio/nirio_fifo.ipp b/host/include/uhd/transport/nirio/nirio_fifo.ipp index 5669f259f..bb21c2715 100644 --- a/host/include/uhd/transport/nirio/nirio_fifo.ipp +++ b/host/include/uhd/transport/nirio/nirio_fifo.ipp @@ -134,7 +134,6 @@ bool nirio_fifo<data_t>::_acquire_block_from_rio_buffer(      uint32_t elements_remaining_u32 = 0;      size_t elements_to_request = 0;      void* elements_buffer = NULL; -    char context_buffer[64];      if (fifo_optimization_option == MAXIMIZE_THROUGHPUT)      { diff --git a/host/include/uhd/transport/nirio/nirio_quirks.h b/host/include/uhd/transport/nirio/nirio_quirks.h index 45ef40394..f98432d6b 100644 --- a/host/include/uhd/transport/nirio/nirio_quirks.h +++ b/host/include/uhd/transport/nirio/nirio_quirks.h @@ -44,7 +44,7 @@ public:      UHD_INLINE void add_tx_fifo(uint32_t index) {          if (_tx_stream_fifo_indices.find(index) != _tx_stream_fifo_indices.end()) {              if (_tx_stream_count == 0) { -                UHD_LOG << "NI-RIO RX FIFO Transfer Check Quirk Enabled."; +                UHD_LOGGER_DEBUG("NIRIO") << "NI-RIO RX FIFO Transfer Check Quirk Enabled.";              }              _tx_stream_count++;          } @@ -54,7 +54,7 @@ public:          if (_tx_stream_fifo_indices.find(index) != _tx_stream_fifo_indices.end()) {              _tx_stream_count--;              if (_tx_stream_count == 0) { -                UHD_LOG << "NI-RIO RX FIFO Transfer Check Quirk Disabled."; +                UHD_LOGGER_DEBUG("NIRIO") << "NI-RIO RX FIFO Transfer Check Quirk Disabled.";              }          }      } diff --git a/host/include/uhd/transport/nirio/rpc/rpc_client.hpp b/host/include/uhd/transport/nirio/rpc/rpc_client.hpp index 78761c1fc..422f57e8a 100644 --- a/host/include/uhd/transport/nirio/rpc/rpc_client.hpp +++ b/host/include/uhd/transport/nirio/rpc/rpc_client.hpp @@ -65,11 +65,11 @@ private:      inline void _stop_io_service() {          if (_io_service_thread.get()) { -            UHD_LOG << "rpc_client stopping..." << std::endl; +            UHD_LOGGER_INFO("NIRIO") << "rpc_client stopping...";              _io_service.stop();              _io_service_thread->join();              _io_service_thread.reset(); -            UHD_LOG << "rpc_client stopped." << std::endl; +            UHD_LOGGER_INFO("NIRIO") << "rpc_client stopped.";          }      } diff --git a/host/include/uhd/transport/udp_simple.hpp b/host/include/uhd/transport/udp_simple.hpp index c159a95e3..d0f6f36b1 100644 --- a/host/include/uhd/transport/udp_simple.hpp +++ b/host/include/uhd/transport/udp_simple.hpp @@ -93,6 +93,11 @@ public:       * Only use this with the broadcast socket.       */      virtual std::string get_recv_addr(void) = 0; + +    /*! +     * Get the IP address for the destination +     */ +    virtual std::string get_send_addr(void) = 0;  };  }} //namespace diff --git a/host/include/uhd/transport/udp_zero_copy.hpp b/host/include/uhd/transport/udp_zero_copy.hpp index dcf020460..851e004d7 100644 --- a/host/include/uhd/transport/udp_zero_copy.hpp +++ b/host/include/uhd/transport/udp_zero_copy.hpp @@ -67,6 +67,8 @@ public:          udp_zero_copy::buff_params& buff_params_out,          const device_addr_t &hints = device_addr_t()      ); + +    virtual uint16_t get_local_port(void) const = 0;  };  }} //namespace diff --git a/host/include/uhd/types/filters.hpp b/host/include/uhd/types/filters.hpp index e3756b7a5..f91f35030 100644 --- a/host/include/uhd/types/filters.hpp +++ b/host/include/uhd/types/filters.hpp @@ -20,7 +20,7 @@  #include <uhd/config.hpp>  #include <uhd/utils/log.hpp> -#include <uhd/utils/msg.hpp> +  #include <stdint.h>  #include <boost/shared_ptr.hpp>  #include <boost/scoped_array.hpp> @@ -263,7 +263,7 @@ namespace uhd{          {              std::size_t num_taps = taps.size();              if(num_taps < this->_max_num_taps){ -                UHD_MSG(warning) << "digital_filter_fir::set_taps not enough coefficients. Appending zeros"; +                UHD_LOGGER_WARNING("FILTERS") << "digital_filter_fir::set_taps not enough coefficients. Appending zeros";                  std::vector<tap_t> coeffs;                  for (size_t i = 0; i < this->_max_num_taps; i++)                  { diff --git a/host/include/uhd/types/ranges.hpp b/host/include/uhd/types/ranges.hpp index ac632df93..b26b5d753 100644 --- a/host/include/uhd/types/ranges.hpp +++ b/host/include/uhd/types/ranges.hpp @@ -59,6 +59,12 @@ namespace uhd{          //! Convert this range to a printable string          const std::string to_pp_string(void) const; +        //! Equality operator +        bool operator==(const range_t &other) const; + +        //! Inequality operator +        bool operator!=(const range_t &other) const; +      private: double _start, _stop, _step;      }; diff --git a/host/include/uhd/types/sid.hpp b/host/include/uhd/types/sid.hpp index 5c31f2d5a..f9fa40273 100644 --- a/host/include/uhd/types/sid.hpp +++ b/host/include/uhd/types/sid.hpp @@ -1,5 +1,5 @@  // -// Copyright 2014 Ettus Research LLC +// Copyright 2014-2016 Ettus Research LLC  //  // This program is free software: you can redistribute it and/or modify  // it under the terms of the GNU General Public License as published by @@ -19,9 +19,8 @@  #define INCLUDED_UHD_TYPES_SID_HPP  #include <uhd/config.hpp> -#include <stdint.h> -#include <boost/shared_ptr.hpp>  #include <iostream> +#include <stdint.h>  namespace uhd {      /*! @@ -105,47 +104,47 @@ namespace uhd {          // Getters          //          //! Alias for get_sid() -        UHD_INLINE uint32_t get() const { return get_sid(); }; +        inline uint32_t get() const { return get_sid(); };          //! Returns a 32-Bit representation of the SID if set, or zero otherwise. -        UHD_INLINE uint32_t get_sid() const { return _set ? _sid : 0; }; +        inline uint32_t get_sid() const { return _set ? _sid : 0; };          //! Return the 16-bit source address of this SID -        UHD_INLINE uint32_t get_src() const { +        inline uint32_t get_src() const {              return (_sid >> 16) & 0xFFFF;          }          //! Return the 16-bit destination address of this SID -        UHD_INLINE uint32_t get_dst() const { +        inline uint32_t get_dst() const {              return _sid & 0xFFFF;          }          //! Return 8-bit address of the source -        UHD_INLINE uint32_t get_src_addr() const { +        inline uint32_t get_src_addr() const {              return (get_src() >> 8) & 0xFF;          }          //! Return endpoint of the source -        UHD_INLINE uint32_t get_src_endpoint() const { +        inline uint32_t get_src_endpoint() const {              return get_src() & 0xFF;          }          //! Return crossbar port of the source -        UHD_INLINE uint32_t get_src_xbarport() const { +        inline uint32_t get_src_xbarport() const {              return (get_src_endpoint() >> 4) & 0xF;          }          //! Return block port of the source -        UHD_INLINE uint32_t get_src_blockport() const { +        inline uint32_t get_src_blockport() const {              return (get_src_endpoint()) & 0xF;          }          //! Return 8-bit address of the destination -        UHD_INLINE uint32_t get_dst_addr() const { +        inline uint32_t get_dst_addr() const {              return (get_dst() >> 8) & 0xFF;          }          //! Return endpoint of the destination -        UHD_INLINE uint32_t get_dst_endpoint() const { +        inline uint32_t get_dst_endpoint() const {              return get_dst() & 0xFF;          }          //! Return crossbar port of the source -        UHD_INLINE uint32_t get_dst_xbarport() const { +        inline uint32_t get_dst_xbarport() const {              return (get_dst_endpoint() >> 4) & 0xF;          }          //! Return block port of the source -        UHD_INLINE uint32_t get_dst_blockport() const { +        inline uint32_t get_dst_blockport() const {              return (get_dst_endpoint()) & 0xF;          } @@ -174,14 +173,14 @@ namespace uhd {          // Manipulators          //! Swaps dst and src address and returns the new SID. -        sid_t reversed(); +        sid_t reversed() const; -        //! Swaps dst and src in-place. +        //! Swaps dst and src in-place. This modifies the current SID.          void reverse();          // Overloaded operators -        sid_t operator = (uint32_t new_sid) { +        sid_t operator = (const uint32_t new_sid) {              set_sid(new_sid);              return *this;          } @@ -191,6 +190,11 @@ namespace uhd {              return *this;          } +        sid_t operator = (const sid_t &sid) { +            set_sid(sid.get_sid()); +            return *this; +        } +          sid_t operator = (const std::string &sid_str) {              set_from_str(sid_str);              return *this; @@ -228,7 +232,7 @@ namespace uhd {      };      //! Stream output operator. Honors std::ios::hex. -    UHD_INLINE std::ostream& operator<< (std::ostream& out, const sid_t &sid) { +    inline std::ostream& operator<< (std::ostream& out, const sid_t &sid) {          std::ios_base::fmtflags ff = out.flags();          if (ff & std::ios::hex) {              out << sid.to_pp_string_hex(); diff --git a/host/include/uhd/usrp/subdev_spec.hpp b/host/include/uhd/usrp/subdev_spec.hpp index 62c1fc177..4165a45f7 100644 --- a/host/include/uhd/usrp/subdev_spec.hpp +++ b/host/include/uhd/usrp/subdev_spec.hpp @@ -44,6 +44,12 @@ namespace uhd{ namespace usrp{              const std::string &db_name = "",              const std::string &sd_name = ""          ); + +        //! overloaded equality operator +        bool operator==(const subdev_spec_pair_t &other); + +        //! overloaded inquality operator +        bool operator!=(const subdev_spec_pair_t &other);      };      //! overloaded comparison operator for subdev_spec_pair_t diff --git a/host/include/uhd/utils/CMakeLists.txt b/host/include/uhd/utils/CMakeLists.txt index af6d3ee47..cf5bb8aa8 100644 --- a/host/include/uhd/utils/CMakeLists.txt +++ b/host/include/uhd/utils/CMakeLists.txt @@ -28,8 +28,8 @@ UHD_INSTALL(FILES      fp_compare_epsilon.ipp      gain_group.hpp      log.hpp +    log_add.hpp      math.hpp -    msg.hpp      msg_task.hpp      paths.hpp      pimpl.hpp diff --git a/host/include/uhd/utils/assert_has.ipp b/host/include/uhd/utils/assert_has.ipp index 7b3c88cb7..974eea5a5 100644 --- a/host/include/uhd/utils/assert_has.ipp +++ b/host/include/uhd/utils/assert_has.ipp @@ -21,8 +21,8 @@  #include <uhd/utils/algorithm.hpp>  #include <uhd/exception.hpp>  #include <boost/format.hpp> -#include <boost/foreach.hpp>  #include <boost/lexical_cast.hpp> +#include <boost/foreach.hpp>  namespace uhd{ diff --git a/host/include/uhd/utils/atomic.hpp b/host/include/uhd/utils/atomic.hpp index ec4d3e0a2..d75a60c3b 100644 --- a/host/include/uhd/utils/atomic.hpp +++ b/host/include/uhd/utils/atomic.hpp @@ -1,5 +1,5 @@  // -// Copyright 2012-2013,2016 Ettus Research LLC +// Copyright 2012-2013,2016-2017 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 @@ -21,122 +21,10 @@  #include <uhd/config.hpp>  #include <uhd/types/time_spec.hpp>  #include <boost/thread/thread.hpp> -#include <boost/thread/mutex.hpp> -#include <boost/thread/condition_variable.hpp> -#include <boost/interprocess/detail/atomic.hpp> - -#include <boost/version.hpp> -#define BOOST_IPC_DETAIL boost::interprocess::ipcdetail +#include <atomic>  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 uint32_t cas(uint32_t newval, 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 uint32_t newval){ -            BOOST_IPC_DETAIL::atomic_write32(&_num, newval); -        } - -        //! Gets the current value of the atomic integer -        UHD_INLINE uint32_t read(void){ -            return BOOST_IPC_DETAIL::atomic_read32(&_num); -        } - -        //! Increment by 1 and return the old value -        UHD_INLINE uint32_t inc(void){ -            return BOOST_IPC_DETAIL::atomic_inc32(&_num); -        } - -        //! Decrement by 1 and return the old value -        UHD_INLINE uint32_t dec(void){ -            return BOOST_IPC_DETAIL::atomic_dec32(&_num); -        } - -    private: volatile 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: - -        reusable_barrier():_size (0) {} - -        reusable_barrier(const size_t size):_size(size) {} - -        //! Resize the barrier for N threads -        void resize(const size_t size){ -            _size = size; -        } - -        /*! -         * Force the barrier wait to throw a boost::thread_interrupted -         * The threads were not getting the interruption_point on windows. -         */ -        void interrupt(void) -        { -            _done.inc(); -        } - -        //! Wait on the barrier condition -        UHD_INLINE void wait(void) -        { -            if (_size == 1) return; - -            //entry barrier with condition variable -            _entry_counter.inc(); -            _entry_counter.cas(0, _size); -            boost::mutex::scoped_lock lock(_mutex); -            while (_entry_counter.read() != 0) -            { -                this->check_interrupt(); -                _cond.timed_wait(lock, boost::posix_time::milliseconds(1)); -            } -            lock.unlock(); //unlock before notify -            _cond.notify_one(); - -            //exit barrier to ensure known condition of entry count -            _exit_counter.inc(); -            _exit_counter.cas(0, _size); -            while (_exit_counter.read() != 0) this->check_interrupt(); -        } - -        //! Wait on the barrier condition -        UHD_INLINE void wait_others(void) -        { -            while (_entry_counter.read() != (_size-1)) this->check_interrupt(); -        } - -    private: -        size_t _size; -        atomic_uint32_t _entry_counter; -        atomic_uint32_t _exit_counter; -        atomic_uint32_t _done; -        boost::mutex _mutex; -        boost::condition_variable _cond; - -        UHD_INLINE void check_interrupt(void) -        { -            if (_done.read() != 0) throw boost::thread_interrupted(); -            boost::this_thread::interruption_point(); -            boost::this_thread::yield(); -        } -    }; -      /*!       * Spin-wait on a condition with a timeout.       * \param cond an atomic variable to compare @@ -144,15 +32,18 @@ namespace uhd{       * \param timeout the timeout in seconds       * \return true for cond == value, false for timeout       */ +    template<typename T>      UHD_INLINE bool spin_wait_with_timeout( -        atomic_uint32_t &cond, -        uint32_t value, +        std::atomic<T> &cond, +        const T value,          const double timeout      ){ -        if (cond.read() == value) return true; +        if (cond == 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; +        while (cond != value) { +            if (time_spec_t::get_system_time() > exit_time) { +                return false; +            }              boost::this_thread::interruption_point();              boost::this_thread::yield();          } @@ -170,19 +61,19 @@ namespace uhd{          }          UHD_INLINE void release(void){ -            _locked.write(0); +            _locked = false;          }          UHD_INLINE bool claim_with_wait(const double timeout){ -            if (spin_wait_with_timeout(_locked, 0, timeout)){ -                _locked.write(1); +            if (spin_wait_with_timeout(_locked, false, timeout)){ +                _locked = true;                  return true;              }              return false;          }      private: -        atomic_uint32_t _locked; +        std::atomic<bool> _locked;      };  } //namespace uhd diff --git a/host/include/uhd/utils/fp_compare_delta.ipp b/host/include/uhd/utils/fp_compare_delta.ipp index 292ef4bf6..9a03bd95b 100644 --- a/host/include/uhd/utils/fp_compare_delta.ipp +++ b/host/include/uhd/utils/fp_compare_delta.ipp @@ -15,7 +15,7 @@  // along with this program.  If not, see <http://www.gnu.org/licenses/>.  // -#include <uhd/utils/msg.hpp> +  #include <cmath>  #include <typeinfo> diff --git a/host/include/uhd/utils/fp_compare_epsilon.ipp b/host/include/uhd/utils/fp_compare_epsilon.ipp index ff2d585db..af71046ed 100644 --- a/host/include/uhd/utils/fp_compare_epsilon.ipp +++ b/host/include/uhd/utils/fp_compare_epsilon.ipp @@ -15,7 +15,7 @@  // along with this program.  If not, see <http://www.gnu.org/licenses/>.  // -#include <uhd/utils/msg.hpp> +  #include <cmath>  #include <typeinfo> diff --git a/host/include/uhd/utils/log.hpp b/host/include/uhd/utils/log.hpp index 106c0d9d5..58b3afed4 100644 --- a/host/include/uhd/utils/log.hpp +++ b/host/include/uhd/utils/log.hpp @@ -19,74 +19,273 @@  #define INCLUDED_UHD_UTILS_LOG_HPP  #include <uhd/config.hpp> -#include <uhd/utils/pimpl.hpp>  #include <boost/current_function.hpp> -#include <boost/format.hpp> +#include <boost/thread/thread.hpp>  #include <ostream>  #include <string>  #include <sstream> +#include <iostream>  /*! \file log.hpp - * The UHD logging facility.   * - * The logger enables UHD library code to easily log events into a file. + * \section loghpp_logging The UHD logging facility + * + * The logger enables UHD library code to easily log events into a file and + * display messages above a certain level in the terminal.   * Log entries are time-stamped and stored with file, line, and function. - * Each call to the UHD_LOG macros is synchronous and thread-safe. + * Each call to the UHD_LOG macros is thread-safe. Each thread will aquire the + * lock for the logger. + * + * Note: More information on the logging subsystem can be found on + * \ref page_logging. + * + * To disable console logging completely at compile time specify + * `-DUHD_LOG_CONSOLE_DISABLE` during configuration with CMake. + * + * By default no file logging will occur. Set a log file path: + *  - at compile time by specifying `-DUHD_LOG_FILE=$file_path` + *  - and/or override at runtime by setting the environment variable + *    `UHD_LOG_FILE`   * - * 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. + * \subsection loghpp_levels Log levels + * + * See also \ref logging_levels.   *   * 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. + * are recorded to std::clog and/or the log file. + * Log levels can be specified using string or numeric values of + * uhd::log::severity_level.   * - * 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. + * The default log level is "info", but can be overridden: + *  - at compile time by setting the pre-processor define `-DUHD_LOG_MIN_LEVEL`. + *  - at runtime by setting the environment variable `UHD_LOG_LEVEL`. + *  - for console logging by setting `(-D)UHD_LOG_CONSOLE_LEVEL` at + *    run-/compiletime + *  - for file logging by setting `(-D)UHD_LOG_FILE_LEVEL` at run-/compiletime   *   * 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 + *   - Example pre-processor define: `-DUHD_LOG_MIN_LEVEL=3` + *   - Example pre-processor define: `-DUHD_LOG_MIN_LEVEL=info` + *   - Example environment variable: `export UHD_LOG_LEVEL=3` + *   - Example environment variable: `export UHD_LOG_LEVEL=info` + * + * \subsection loghpp_formatting Log formatting + * + * The log format for messages going into a log file is CSV. + * All log messages going into a logfile will contain following fields: + * - timestamp + * - thread-id + * - source-file + line information + * - severity level + * - component/channel information which logged the information + * - the actual log message + * + * The log format of log messages displayed on the terminal is plain text with + * space separated tags prepended. + * For example: + *    - `[INFO] [X300] This is a informational log message` + * + * The log format for log output on the console by using these preprocessor + * defines in CMake: + * - `-DUHD_LOG_CONSOLE_TIME` adds a timestamp [2017-01-01 00:00:00.000000] + * - `-DUHD_LOG_CONSOLE_THREAD` adds a thread-id `[0x001234]` + * - `-DUHD_LOG_CONSOLE_SRC` adds a sourcefile and line tag `[src_file:line]`   */ -/*! - * A UHD logger macro with configurable verbosity. - * Usage: UHD_LOGV(very_rarely) << "the log message" << std::endl; +/* + * Advanced logging macros + * UHD_LOG_MIN_LEVEL definitions + * trace: 0 + * debug: 1 + * info: 2 + * warning: 3 + * error: 4 + * fatal: 5   */ -#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 { +        /*! Logging severity levels +         * +         * Either numeric value or string can be used to define loglevel in +         * CMake and environment variables +         */ +        enum severity_level { +            trace   = 0, /**< displays every available log message */ +            debug   = 1, /**< displays most log messages necessary for debugging internals */ +            info    = 2, /**< informational messages about setup and what is going on*/ +            warning = 3, /**< something is not right but operation can continue */ +            error   = 4, /**< something has gone wrong */ +            fatal   = 5, /**< something has gone horribly wrong */ +            off = 6, /**< logging is turned off */ +        }; +        /*! Logging info structure +         * +         * Information needed to create a log entry is fully contained in the +         * logging_info structure. +         */ +        struct UHD_API logging_info { +            logging_info() +                : verbosity(uhd::log::off) {} +            logging_info( +                const boost::posix_time::ptime &time_, +                const uhd::log::severity_level &verbosity_, +                const std::string &file_, +                const size_t &line_, +                const std::string &component_, +                const boost::thread::id &thread_id_ +            ) : time(time_), +                verbosity(verbosity_), +                file(file_), +                line(line_), +                component(component_), +                thread_id(thread_id_) +            { /* nop */ } -namespace uhd{ namespace _log{ +            boost::posix_time::ptime time; +            uhd::log::severity_level verbosity; +            std::string file; +            unsigned int line; +            std::string component; +            boost::thread::id thread_id; +            std::string message; +        }; -    //! Verbosity levels for the logger -    enum verbosity_t{ -        always      = 1, -        often       = 2, -        regularly   = 3, -        rarely      = 4, -        very_rarely = 5, -        never       = 6 -    }; +        /*! Set the global log level +         * +         * The global log level gets applied before the specific log level. +         * So, if the global log level is 'info', no logger can can print +         * messages at level 'debug' or below. +         */ +        UHD_API void set_log_level(uhd::log::severity_level level); + +        /*! Set the log level for the console logger (if defined). +         * +         * Short-hand for `set_logger_level("console", level);` +         */ +        UHD_API void set_console_level(uhd::log::severity_level level); + +        /*! Set the log level for the file logger (if defined) +         * +         * Short-hand for `set_logger_level("file", level);` +         */ +        UHD_API void set_file_level(uhd::log::severity_level level); + +        /*! Set the log level for any specific logger. +         * +         * \param logger Name of the logger +         * \param level New log level for this logger. +         * +         * \throws uhd::key_error if \p logger was not defined +         */ +        UHD_API void set_logger_level(const std::string &logger, uhd::log::severity_level level); +    } +} + +//! \cond +//! Internal logging macro to be used in other macros +#define _UHD_LOG_INTERNAL(component, level) \ +    uhd::_log::log(level, __FILE__, __LINE__, component, boost::this_thread::get_id()) +//! \endcond + +// macro-style logging (compile-time determined) +#if UHD_LOG_MIN_LEVEL < 1 +#define UHD_LOG_TRACE(component, message) \ +    _UHD_LOG_INTERNAL(component, uhd::log::trace) << message; +#else +#define UHD_LOG_TRACE(component, message) +#endif + +#if UHD_LOG_MIN_LEVEL < 2 +#define UHD_LOG_DEBUG(component, message) \ +    _UHD_LOG_INTERNAL(component, uhd::log::debug) << message; +#else +#define UHD_LOG_DEBUG(component, message) +#endif + +#if UHD_LOG_MIN_LEVEL < 3 +#define UHD_LOG_INFO(component, message) \ +    _UHD_LOG_INTERNAL(component, uhd::log::info) << message; +#else +#define UHD_LOG_INFO(component, message) +#endif + +#if UHD_LOG_MIN_LEVEL < 4 +#define UHD_LOG_WARNING(component, message) \ +    _UHD_LOG_INTERNAL(component, uhd::log::warning) << message; +#else +#define UHD_LOG_WARNING(component, message) +#endif + +#if UHD_LOG_MIN_LEVEL < 5 +#define UHD_LOG_ERROR(component, message) \ +    _UHD_LOG_INTERNAL(component, uhd::log::error) << message; +#else +#define UHD_LOG_ERROR(component, message) +#endif + +#if UHD_LOG_MIN_LEVEL < 6 +#define UHD_LOG_FATAL(component, message) \ +    _UHD_LOG_INTERNAL(component, uhd::log::fatal) << message; +#else +#define UHD_LOG_FATAL(component, message) +#endif + +#ifndef UHD_LOG_FASTPATH_DISABLE +//! Extra-fast logging macro for when speed matters. +// No metadata is tracked. Only the message is displayed. This does not go +// through the regular backends. Mostly used for printing the UOSDL characters +// during streaming. +#define UHD_LOG_FASTPATH(message)               \ +    uhd::_log::log_fastpath(message); +#else +#define UHD_LOG_FASTPATH(message) +#endif + +// iostream-style logging +#define UHD_LOGGER_TRACE(component) _UHD_LOG_INTERNAL(component, uhd::log::trace) +#define UHD_LOGGER_DEBUG(component) _UHD_LOG_INTERNAL(component, uhd::log::debug) +#define UHD_LOGGER_INFO(component) _UHD_LOG_INTERNAL(component, uhd::log::info) +#define UHD_LOGGER_WARNING(component) _UHD_LOG_INTERNAL(component, uhd::log::warning) +#define UHD_LOGGER_ERROR(component) _UHD_LOG_INTERNAL(component, uhd::log::error) +#define UHD_LOGGER_FATAL(component) _UHD_LOG_INTERNAL(component, uhd::log::fatal) + + +#if defined(__GNUG__) +//! Helpful debug tool to print site info +#define UHD_HERE()                                              \ +    UHD_LOGGER_DEBUG("DEBUG") << __FILE__ << ":" << __LINE__ << " (" << __PRETTY_FUNCTION__ << ")"; +#else +//! Helpful debug tool to print site info +#define UHD_HERE()                                              \ +    UHD_LOGGER_DEBUG("DEBUG") << __FILE__ << ":" << __LINE__; +#endif + +//! Helpful debug tool to print a variable +#define UHD_VAR(var)                                        \ +    UHD_LOGGER_DEBUG("DEBUG") << #var << " = " << var; + +//! Helpful debug tool to print a variable in hex +#define UHD_HEX(var)                                                    \ +    UHD_LOGGER_DEBUG("DEBUG") << #var << " = 0x" << std::hex << std::setfill('0') << std::setw(8) << var << std::dec; + +//! \cond +namespace uhd{ namespace _log { + +    //! Fastpath logging +    void UHD_API log_fastpath(const std::string &msg); -    //! Internal logging object (called by UHD_LOG macros) +    //! Internal logging object (called by UHD_LOG* macros)      class UHD_API log {      public:          log( -            const verbosity_t verbosity, +            const uhd::log::severity_level verbosity,              const std::string &file,              const unsigned int line, -            const std::string &function +            const std::string &component, +            const boost::thread::id thread_id          );          ~log(void); @@ -95,7 +294,9 @@ namespace uhd{ namespace _log{          // conversion of types if not logging.          #define INSERTION_OVERLOAD(x)   log& operator<< (x)             \                                          {                               \ -                                            if(_log_it) _ss << val;     \ +                                            if(_log_it) {               \ +                                                _ss << val ;            \ +                                            }                           \                                              return *this;               \                                          } @@ -109,10 +310,13 @@ namespace uhd{ namespace _log{          INSERTION_OVERLOAD(std::ios_base& (*val)(std::ios_base&))      private: +        uhd::log::logging_info _log_info;          std::ostringstream _ss; -        bool _log_it; +        const bool _log_it;      }; -}} //namespace uhd::_log +} //namespace uhd::_log +//! \endcond +} /* namespace uhd */  #endif /* INCLUDED_UHD_UTILS_LOG_HPP */ diff --git a/host/include/uhd/utils/log_add.hpp b/host/include/uhd/utils/log_add.hpp new file mode 100644 index 000000000..99b2e6dfc --- /dev/null +++ b/host/include/uhd/utils/log_add.hpp @@ -0,0 +1,46 @@ +// +// Copyright 2017 Ettus Research (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/>. +// + +// Note: Including this file requires C++11 features enabled. + +#ifndef INCLUDED_UHD_UTILS_LOG_ADD_HPP +#define INCLUDED_UHD_UTILS_LOG_ADD_HPP + +#include <uhd/config.hpp> +#include <uhd/utils/log.hpp> +#include <functional> + +namespace uhd { +    namespace log { + +        /*! Logging function type +         * +         * Every logging_backend has to define a function with this signature. +         * Can be added to the logging core. +         */ +        typedef std::function<void(const uhd::log::logging_info&)> log_fn_t ; + +        /*! Add logging backend to the log system +         * +         * \param key Identifies the logging backend in the logging core +         * \param logger_fn function which actually logs messages to this backend +         */ +        UHD_API void add_logger(const std::string &key, log_fn_t logger_fn); +    } +} /* namespace uhd::log */ + +#endif /* INCLUDED_UHD_UTILS_LOG_ADD_HPP */ diff --git a/host/include/uhd/utils/msg.hpp b/host/include/uhd/utils/msg.hpp deleted file mode 100644 index 2cc5893e7..000000000 --- a/host/include/uhd/utils/msg.hpp +++ /dev/null @@ -1,79 +0,0 @@ -// -// Copyright 2011-2013 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 <iomanip> -#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; - -//! Helpful debug tool to print a variable in hex -#define UHD_HEX(var) \ -    UHD_MSG(status) << #var << " = 0x" << std::hex << std::setfill('0') << std::setw(8) << var << std::dec << 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/safe_call.hpp b/host/include/uhd/utils/safe_call.hpp index ab287cc66..d04d89436 100644 --- a/host/include/uhd/utils/safe_call.hpp +++ b/host/include/uhd/utils/safe_call.hpp @@ -23,7 +23,7 @@  #include <uhd/utils/log.hpp>  //! helper macro for safe call to produce warnings -#define _UHD_SAFE_CALL_WARNING(code, what) UHD_LOGV(rarely) << \ +#define _UHD_SAFE_CALL_WARNING(code, what) UHD_LOGGER_ERROR("UHD") << \      UHD_THROW_SITE_INFO("Exception caught in safe-call.") + #code + " -> " + what \  ; diff --git a/host/include/uhd/version.hpp.in b/host/include/uhd/version.hpp.in index 8cfc7b8c6..c16739a78 100644 --- a/host/include/uhd/version.hpp.in +++ b/host/include/uhd/version.hpp.in @@ -24,7 +24,7 @@   * 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 "@TRIMMED_VERSION_MAJOR@.@TRIMMED_VERSION_API@.@TRIMMED_VERSION_ABI@" +#define UHD_VERSION_ABI_STRING "@UHD_VERSION_MAJOR@.@UHD_VERSION_API@.@UHD_VERSION_ABI@"  /*!   * A macro to check UHD version at compile-time. | 
