diff options
Diffstat (limited to 'host/include')
31 files changed, 791 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_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..5a6e9a48f 100644 --- a/host/include/uhd/utils/CMakeLists.txt +++ b/host/include/uhd/utils/CMakeLists.txt @@ -29,7 +29,6 @@ UHD_INSTALL(FILES gain_group.hpp log.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. |