diff options
Diffstat (limited to 'host/include')
22 files changed, 575 insertions, 233 deletions
| diff --git a/host/include/CMakeLists.txt b/host/include/CMakeLists.txt index 34b705cab..3f7ca2cb7 100644 --- a/host/include/CMakeLists.txt +++ b/host/include/CMakeLists.txt @@ -17,8 +17,3 @@  ADD_SUBDIRECTORY(uhd) - -INSTALL(FILES -    uhd.hpp -    DESTINATION ${HEADER_DIR} -) diff --git a/host/include/uhd.hpp b/host/include/uhd.hpp deleted file mode 100644 index ee8c13dfe..000000000 --- a/host/include/uhd.hpp +++ /dev/null @@ -1,24 +0,0 @@ -// -// Copyright 2010 Ettus Research LLC -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program.  If not, see <http://www.gnu.org/licenses/>. -// - -#ifndef INCLUDED_UHD_HPP -#define INCLUDED_UHD_HPP - -//include convenience headers -#include <uhd/device.hpp> - -#endif /* INCLUDED_UHD_HPP */ diff --git a/host/include/uhd/CMakeLists.txt b/host/include/uhd/CMakeLists.txt index f4fb96786..522f43afd 100644 --- a/host/include/uhd/CMakeLists.txt +++ b/host/include/uhd/CMakeLists.txt @@ -26,6 +26,7 @@ INSTALL(FILES      gain_handler.hpp      metadata.hpp      props.hpp +    simple_device.hpp      time_spec.hpp      utils.hpp      wax.hpp diff --git a/host/include/uhd/device.hpp b/host/include/uhd/device.hpp index ba5337d33..c9d608bcf 100644 --- a/host/include/uhd/device.hpp +++ b/host/include/uhd/device.hpp @@ -37,6 +37,19 @@ class device : boost::noncopyable, public wax::obj{  public:      typedef boost::shared_ptr<device> sptr; +    typedef boost::function<device_addrs_t(const device_addr_t &)> discover_t; +    typedef boost::function<sptr(const device_addr_t &)> make_t; + +    /*! +     * Register a device into the discovery and factory system. +     * +     * \param discover a function that discovers devices +     * \param make a factory function that makes a device +     */ +    static void register_device( +        const discover_t &discover, +        const make_t &make +    );      /*!       * \brief Discover usrp devices attached to the host. @@ -70,6 +83,16 @@ public:      /*!       * Send a buffer containing IF data with its metadata.       * +     * Send handles fragmentation as follows: +     * If the buffer has more samples than the maximum supported, +     * the send method will send the maximum number of samples +     * as supported by the transport and return the number sent. +     * It is up to the caller to call send again on the un-sent +     * portions of the buffer, until the buffer is exhausted. +     * +     * This is a blocking call and will not return until the number +     * of samples returned have been read out of the buffer. +     *       * \param buff a buffer pointing to some read-only memory       * \param metadata data describing the buffer's contents       * \param the type of data loaded in the buffer (32fc, 16sc) @@ -77,13 +100,31 @@ public:       */      virtual size_t send(          const boost::asio::const_buffer &buff, -        const metadata_t &metadata, +        const tx_metadata_t &metadata,          const std::string &type = "32fc"      ) = 0;      /*!       * Receive a buffer containing IF data and its metadata.       * +     * Receive handles fragmentation as follows: +     * If the buffer has insufficient space to hold all samples +     * that were received in a single packet over-the-wire, +     * then the buffer will be completely filled and the implementation +     * will hold a pointer into the remaining portion of the packet. +     * Subsequent calls will load from the remainder of the packet, +     * and will flag the metadata to show that this is a fragment. +     * The next call to receive, after the remainder becomes exahausted, +     * will perform an over-the-wire receive as usual. +     * +     * This is a blocking call and will not return until the number +     * of samples returned have been written into the buffer. +     * However, a call to receive may timeout and return zero samples. +     * The timeout duration is decided by the underlying transport layer. +     * The caller should assume that the call to receive will not return +     * immediately when no packets are available to the transport layer, +     * and that the timeout duration is reasonably tuned for performance. +     *       * \param buff the buffer to fill with IF data       * \param metadata data to fill describing the buffer       * \param the type of data to fill into the buffer (32fc, 16sc) @@ -91,7 +132,7 @@ public:       */      virtual size_t recv(          const boost::asio::mutable_buffer &buff, -        metadata_t &metadata, +        rx_metadata_t &metadata,          const std::string &type = "32fc"      ) = 0;  }; diff --git a/host/include/uhd/device_addr.hpp b/host/include/uhd/device_addr.hpp index d02febd6c..ed538453a 100644 --- a/host/include/uhd/device_addr.hpp +++ b/host/include/uhd/device_addr.hpp @@ -56,9 +56,9 @@ namespace uhd{       * \param device_addr a device address instance       * \return the string representation       */ -    struct device_addr{ -        static std::string to_string(const device_addr_t &device_addr); -    }; +    namespace device_addr{ +        std::string to_string(const device_addr_t &device_addr); +    }  } //namespace uhd diff --git a/host/include/uhd/dict.hpp b/host/include/uhd/dict.hpp index 1ed28551a..2224a0063 100644 --- a/host/include/uhd/dict.hpp +++ b/host/include/uhd/dict.hpp @@ -57,6 +57,14 @@ namespace uhd{          }          /*! +         * Get the number of elements in this dict. +         * \param the number of elements +         */ +        std::size_t size(void) const{ +            return _map.size(); +        } + +        /*!           * Get a list of the keys in this dict.           * \return vector of keys           */ diff --git a/host/include/uhd/gain_handler.hpp b/host/include/uhd/gain_handler.hpp index 06800315a..a71d63c84 100644 --- a/host/include/uhd/gain_handler.hpp +++ b/host/include/uhd/gain_handler.hpp @@ -15,11 +15,9 @@  // along with this program.  If not, see <http://www.gnu.org/licenses/>.  // -#include <boost/shared_ptr.hpp>  #include <uhd/wax.hpp> -#include <uhd/props.hpp> +#include <boost/shared_ptr.hpp>  #include <boost/function.hpp> -#include <boost/bind.hpp>  #ifndef INCLUDED_UHD_GAIN_HANDLER_HPP  #define INCLUDED_UHD_GAIN_HANDLER_HPP @@ -29,29 +27,37 @@ namespace uhd{  class gain_handler{  public:      typedef boost::shared_ptr<gain_handler> sptr; +    typedef boost::function<bool(const wax::obj &, const wax::obj &)> is_equal_t; -    template <class T> gain_handler( -        wax::obj *wax_obj_ptr, const T &gain_prop, -        const T &gain_min_prop, const T &gain_max_prop, -        const T &gain_step_prop, const T &gain_names_prop -    ){ -        _wax_obj_ptr = wax_obj_ptr; -        _gain_prop = gain_prop; -        _gain_min_prop = gain_min_prop; -        _gain_max_prop = gain_max_prop; -        _gain_step_prop = gain_step_prop; -        _gain_names_prop = gain_names_prop; -        _is_equal = boost::bind(&gain_handler::is_equal<T>, _1, _2); -    } +    /*! +     * A set of properties for dealing with gains. +     */ +    struct props_t{ +        wax::obj value, range, names; +        props_t(void); //default constructor +    }; -    ~gain_handler(void); +    /*! +     * Make a new gain handler. +     * The construction arguments are agnostic to the property type. +     * It is up to the caller to provide an "is_equal" function that +     * can tell weather two properties (in a wax obj) are equal. +     * \param link a link to the wax obj with properties +     * \param props a struct of properties keys +     * \param is_equal the function that tests for equal properties +     */ +    static sptr make( +        const wax::obj &link, +        const props_t &props, +        is_equal_t is_equal +    );      /*!       * Intercept gets for overall gain, min, max, step.       * Ensures that the gain name is valid.       * \return true for handled, false to pass on       */ -    bool intercept_get(const wax::obj &key, wax::obj &val); +    virtual bool intercept_get(const wax::obj &key, wax::obj &val) = 0;      /*!       * Intercept sets for overall gain. @@ -59,39 +65,21 @@ public:       * Ensures that the new gain is within range.       * \return true for handled, false to pass on       */ -    bool intercept_set(const wax::obj &key, const wax::obj &val); - -private: - -    wax::obj     *_wax_obj_ptr; -    wax::obj      _gain_prop; -    wax::obj      _gain_min_prop; -    wax::obj      _gain_max_prop; -    wax::obj      _gain_step_prop; -    wax::obj      _gain_names_prop; +    virtual bool intercept_set(const wax::obj &key, const wax::obj &val) = 0;      /*! -     * Verify that the key is valid: -     * If its a named prop for gain, ensure that name is valid. -     * If the name if not valid, throw a std::invalid_argument. -     * The name can only be valid if its in the list of gain names. -     */ -    void _check_key(const wax::obj &key); - -    /* -     * Private interface to test if two wax types are equal: +     * Function template to test if two wax types are equal:       * The constructor will bind an instance of this for a specific type.       * This bound equals functions allows the intercept methods to be non-templated.       */      template <class T> static bool is_equal(const wax::obj &a, const wax::obj &b){          try{ -            return wax::cast<T>(a) == wax::cast<T>(b); +            return a.as<T>() == b.as<T>();          }          catch(const wax::bad_cast &){              return false;          }      } -    boost::function<bool(const wax::obj &, const wax::obj &)> _is_equal;  }; diff --git a/host/include/uhd/metadata.hpp b/host/include/uhd/metadata.hpp index 70842e7bc..0588ef0ed 100644 --- a/host/include/uhd/metadata.hpp +++ b/host/include/uhd/metadata.hpp @@ -23,12 +23,27 @@  namespace uhd{  /*! - * Metadata structure for describing the IF data. - * Includes stream ID, time specification, and burst flags. + * RX metadata structure for describing sent IF data. + * Includes stream ID, time specification, and fragmentation flags.   * The receive routines will convert IF data headers into metadata. + */ +struct rx_metadata_t{ +    uint32_t stream_id; +    bool has_stream_id; +    time_spec_t time_spec; +    bool has_time_spec; +    bool is_fragment; + +    //default constructor +    rx_metadata_t(void); +}; + +/*! + * TX metadata structure for describing received IF data. + * Includes stream ID, time specification, and burst flags.   * The send routines will convert the metadata to IF data headers.   */ -struct metadata_t{ +struct tx_metadata_t{      uint32_t stream_id;      bool has_stream_id;      time_spec_t time_spec; @@ -36,14 +51,8 @@ struct metadata_t{      bool start_of_burst;      bool end_of_burst; -    metadata_t(void){ -        stream_id = 0; -        has_stream_id = false; -        time_spec = time_spec_t(); -        has_time_spec = false; -        start_of_burst = false; -        end_of_burst = false; -    } +    //default constructor +    tx_metadata_t(void);  };  } //namespace uhd diff --git a/host/include/uhd/props.hpp b/host/include/uhd/props.hpp index 2b6daf6c5..0dddba647 100644 --- a/host/include/uhd/props.hpp +++ b/host/include/uhd/props.hpp @@ -30,6 +30,12 @@ namespace uhd{      typedef float gain_t;      typedef double freq_t; +    //gain range tuple (min, max, step) +    typedef boost::tuple<gain_t, gain_t, gain_t> gain_range_t; + +    //freq range tuple (min, max) +    typedef boost::tuple<freq_t, freq_t> freq_range_t; +      //scalar types (have not used yet, dont uncomment until needed)      //typedef int int_scalar_t;      //typedef float real_scalar_t; @@ -51,7 +57,7 @@ namespace uhd{       */      inline named_prop_t extract_named_prop(const wax::obj &key, const std::string &name = ""){          if (key.type() == typeid(named_prop_t)){ -            return wax::cast<named_prop_t>(key); +            return key.as<named_prop_t>();          }          return named_prop_t(key, name);      } @@ -65,7 +71,9 @@ namespace uhd{      enum device_prop_t{          DEVICE_PROP_NAME,              //ro, std::string          DEVICE_PROP_MBOARD,            //ro, wax::obj -        DEVICE_PROP_MBOARD_NAMES       //ro, prop_names_t +        DEVICE_PROP_MBOARD_NAMES,      //ro, prop_names_t +        DEVICE_PROP_MAX_RX_SAMPLES,    //ro, size_t +        DEVICE_PROP_MAX_TX_SAMPLES     //ro, size_t      };      /*! @@ -77,7 +85,6 @@ namespace uhd{      enum mboard_prop_t{          MBOARD_PROP_NAME,              //ro, std::string          MBOARD_PROP_OTHERS,            //ro, prop_names_t -        MBOARD_PROP_MTU,               //ro, size_t          MBOARD_PROP_CLOCK_RATE,        //ro, freq_t          MBOARD_PROP_RX_DSP,            //ro, wax::obj          MBOARD_PROP_RX_DSP_NAMES,      //ro, prop_names_t @@ -115,16 +122,16 @@ namespace uhd{      enum dboard_prop_t{          DBOARD_PROP_NAME,              //ro, std::string          DBOARD_PROP_SUBDEV,            //ro, wax::obj -        DBOARD_PROP_SUBDEV_NAMES,      //ro, prop_names_t -        DBOARD_PROP_CODEC              //ro, wax::obj -    }; +        DBOARD_PROP_SUBDEV_NAMES       //ro, prop_names_t +        //DBOARD_PROP_CODEC              //ro, wax::obj //----> not sure, dont have to deal with yet +    };  -    /*! +    /*! ------ not dealing with yet, commented out ------------      * Possible device codec properties:      *   A codec is expected to have a rate and gain elements.      *   Other properties can be discovered through the others prop.      */ -    enum codec_prop_t{ +    /*enum codec_prop_t{          CODEC_PROP_NAME,               //ro, std::string          CODEC_PROP_OTHERS,             //ro, prop_names_t          CODEC_PROP_GAIN,               //rw, gain_t @@ -132,8 +139,8 @@ namespace uhd{          CODEC_PROP_GAIN_MIN,           //ro, gain_t          CODEC_PROP_GAIN_STEP,          //ro, gain_t          CODEC_PROP_GAIN_NAMES,         //ro, prop_names_t -        CODEC_PROP_CLOCK_RATE          //ro, freq_t -    }; +        //CODEC_PROP_CLOCK_RATE          //ro, freq_t //----> not sure we care to know +    };*/      /*!      * Possible device subdev properties @@ -142,22 +149,19 @@ namespace uhd{          SUBDEV_PROP_NAME,              //ro, std::string          SUBDEV_PROP_OTHERS,            //ro, prop_names_t          SUBDEV_PROP_GAIN,              //rw, gain_t -        SUBDEV_PROP_GAIN_MAX,          //ro, gain_t -        SUBDEV_PROP_GAIN_MIN,          //ro, gain_t -        SUBDEV_PROP_GAIN_STEP,         //ro, gain_t +        SUBDEV_PROP_GAIN_RANGE,        //ro, gain_range_t          SUBDEV_PROP_GAIN_NAMES,        //ro, prop_names_t          SUBDEV_PROP_FREQ,              //rw, freq_t -        SUBDEV_PROP_FREQ_MAX,          //ro, freq_t -        SUBDEV_PROP_FREQ_MIN,          //ro, freq_t +        SUBDEV_PROP_FREQ_RANGE,        //ro, freq_range_t          SUBDEV_PROP_ANTENNA,           //rw, std::string          SUBDEV_PROP_ANTENNA_NAMES,     //ro, prop_names_t          SUBDEV_PROP_ENABLED,           //rw, bool          SUBDEV_PROP_QUADRATURE,        //ro, bool          SUBDEV_PROP_IQ_SWAPPED,        //ro, bool          SUBDEV_PROP_SPECTRUM_INVERTED, //ro, bool -        SUBDEV_PROP_IS_TX,             //ro, bool -        SUBDEV_PROP_RSSI,              //ro, gain_t -        SUBDEV_PROP_BANDWIDTH          //rw, freq_t +        SUBDEV_PROP_LO_INTERFERES      //ro, bool +        //SUBDEV_PROP_RSSI,              //ro, gain_t //----> not on all boards, use named prop +        //SUBDEV_PROP_BANDWIDTH          //rw, freq_t //----> not on all boards, use named prop      };  } //namespace uhd diff --git a/host/include/uhd/simple_device.hpp b/host/include/uhd/simple_device.hpp new file mode 100644 index 000000000..c43155ff2 --- /dev/null +++ b/host/include/uhd/simple_device.hpp @@ -0,0 +1,105 @@ +// +// Copyright 2010 Ettus Research LLC +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program.  If not, see <http://www.gnu.org/licenses/>. +// + +#include <boost/shared_ptr.hpp> +#include <boost/utility.hpp> +#include <uhd/device.hpp> +#include <vector> + +#ifndef INCLUDED_UHD_SIMPLE_DEVICE_HPP +#define INCLUDED_UHD_SIMPLE_DEVICE_HPP + +namespace uhd{ + +/*! + * The tune result struct holds result of a 2-phase tuning: + * The struct hold the result of tuning the dboard as + * the target and actual intermediate frequency. + * The struct hold the result of tuning the DDC/DUC as + * the target and actual digital converter frequency. + * It also tell us weather or not the spectrum is inverted. + */ +struct tune_result_t{ +    double target_inter_freq; +    double actual_inter_freq; +    double target_dxc_freq; +    double actual_dxc_freq; +    bool spectrum_inverted; +    tune_result_t(void); +}; + +/*! + * The simple UHD device class: + * A simple device facilitates ease-of-use for most use-case scenarios. + * The wrapper provides convenience functions to tune the devices + * as well as to set the dboard gains, antennas, and other properties. + */ +class simple_device : boost::noncopyable{ +public: +    typedef boost::shared_ptr<simple_device> sptr; +    static sptr make(const std::string &args); + +    virtual device::sptr get_device(void) = 0; + +    virtual std::string get_name(void) = 0; + +    /******************************************************************* +     * Streaming +     ******************************************************************/ +    virtual void set_streaming(bool enb) = 0; +    virtual bool get_streaming(void) = 0; + +    /******************************************************************* +     * RX methods +     ******************************************************************/ +    virtual void set_rx_rate(double rate) = 0; +    virtual double get_rx_rate(void) = 0; +    virtual std::vector<double> get_rx_rates(void) = 0; + +    virtual tune_result_t set_rx_freq(double freq) = 0; +    virtual std::vector<double> get_rx_freq_range(void) = 0; + +    virtual void set_rx_gain(float gain) = 0; +    virtual float get_rx_gain(void) = 0; +    virtual std::vector<float> get_rx_gain_range(void) = 0; + +    virtual void set_rx_antenna(const std::string &ant) = 0; +    virtual std::string get_rx_antenna(void) = 0; +    virtual std::vector<std::string> get_rx_antennas(void) = 0; + +    /******************************************************************* +     * TX methods +     ******************************************************************/ +    virtual void set_tx_rate(double rate) = 0; +    virtual double get_tx_rate(void) = 0; +    virtual std::vector<double> get_tx_rates(void) = 0; + +    virtual tune_result_t set_tx_freq(double freq) = 0; +    virtual std::vector<double> get_tx_freq_range(void) = 0; + +    virtual void set_tx_gain(float gain) = 0; +    virtual float get_tx_gain(void) = 0; +    virtual std::vector<float> get_tx_gain_range(void) = 0; + +    virtual void set_tx_antenna(const std::string &ant) = 0; +    virtual std::string get_tx_antenna(void) = 0; +    virtual std::vector<std::string> get_tx_antennas(void) = 0; +}; + +} //namespace uhd + +#endif /* INCLUDED_UHD_SIMPLE_DEVICE_HPP */ diff --git a/host/include/uhd/time_spec.hpp b/host/include/uhd/time_spec.hpp index e5657e555..7e182236b 100644 --- a/host/include/uhd/time_spec.hpp +++ b/host/include/uhd/time_spec.hpp @@ -15,6 +15,7 @@  // along with this program.  If not, see <http://www.gnu.org/licenses/>.  // +#include <boost/date_time/posix_time/posix_time.hpp>  #include <stdint.h>  #ifndef INCLUDED_UHD_TIME_SPEC_HPP @@ -36,20 +37,22 @@ namespace uhd{           * Create a time_spec_t that holds a wildcard time.           * This will have implementation-specific meaning.           */ -        time_spec_t(void){ -            secs = ~0; -            ticks = ~0; -        } +        time_spec_t(void);          /*!           * Create a time_spec_t from seconds and ticks.           * \param new_secs the new seconds           * \param new_ticks the new ticks (default = 0)           */ -        time_spec_t(uint32_t new_secs, uint32_t new_ticks = 0){ -            secs = new_secs; -            ticks = new_ticks; -        } +        time_spec_t(uint32_t new_secs, uint32_t new_ticks = 0); + +        /*! +         * Create a time_spec_t from boost posix time. +         * \param time fine-grained boost posix time +         * \param tick_rate the rate of ticks per second +         */ +        time_spec_t(boost::posix_time::ptime time, double tick_rate); +      };  } //namespace uhd diff --git a/host/include/uhd/transport/CMakeLists.txt b/host/include/uhd/transport/CMakeLists.txt index b786eb945..7f5db2128 100644 --- a/host/include/uhd/transport/CMakeLists.txt +++ b/host/include/uhd/transport/CMakeLists.txt @@ -17,6 +17,9 @@  INSTALL(FILES -    udp.hpp +    smart_buffer.hpp +    udp_simple.hpp +    udp_zero_copy.hpp +    vrt.hpp      DESTINATION ${HEADER_DIR}/uhd/transport  ) diff --git a/host/include/uhd/transport/smart_buffer.hpp b/host/include/uhd/transport/smart_buffer.hpp new file mode 100644 index 000000000..914c02f50 --- /dev/null +++ b/host/include/uhd/transport/smart_buffer.hpp @@ -0,0 +1,45 @@ +// +// Copyright 2010 Ettus Research LLC +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program.  If not, see <http://www.gnu.org/licenses/>. +// + +#include <boost/asio.hpp> +#include <boost/utility.hpp> +#include <boost/shared_ptr.hpp> + +#ifndef INCLUDED_UHD_TRANSPORT_SMART_BUFFER_HPP +#define INCLUDED_UHD_TRANSPORT_SMART_BUFFER_HPP + +namespace uhd{ namespace transport{ + +/*! + * A buffer that knows how to free itself: + * + * This is just the smart buffer interface. + * A transport implementation will have its own + * internal (custom) smart buffer implementation. + * + * A smart buffer contains a boost asio const buffer. + * On destruction, the buffer contents will be freed. + */ +class smart_buffer : boost::noncopyable{ +public: +    typedef boost::shared_ptr<smart_buffer> sptr; +    virtual const boost::asio::const_buffer &get(void) const = 0; +}; + +}} //namespace + +#endif /* INCLUDED_UHD_TRANSPORT_SMART_BUFFER_HPP */ diff --git a/host/include/uhd/transport/udp.hpp b/host/include/uhd/transport/udp_simple.hpp index 8c6fb096f..0d8fcc5f0 100644 --- a/host/include/uhd/transport/udp.hpp +++ b/host/include/uhd/transport/udp_simple.hpp @@ -19,32 +19,43 @@  #include <boost/utility.hpp>  #include <boost/shared_ptr.hpp> -#ifndef INCLUDED_UHD_TRANSPORT_UDP_HPP -#define INCLUDED_UHD_TRANSPORT_UDP_HPP +#ifndef INCLUDED_UHD_TRANSPORT_UDP_SIMPLE_HPP +#define INCLUDED_UHD_TRANSPORT_UDP_SIMPLE_HPP  namespace uhd{ namespace transport{ -class udp : boost::noncopyable{ +class udp_simple : boost::noncopyable{  public: -    typedef boost::shared_ptr<udp> sptr; +    typedef boost::shared_ptr<udp_simple> sptr;      /*! -     * Make a new udp transport. +     * Make a new connected udp transport: +     * This transport is for sending and receiving +     * between this host and a single endpoint. +     * The primary usage for this transport will be control transactions. +     * The underlying implementation is simple and portable (not fast). +     *       * The address will be resolved, it can be a host name or ipv4.       * The port will be resolved, it can be a port type or number. +     *       * \param addr a string representing the destination address       * \param port a string representing the destination port -     * \param bcast if true, enable the broadcast option on the socket       */ -    static sptr make(const std::string &addr, const std::string &port, bool bcast = false); +    static sptr make_connected(const std::string &addr, const std::string &port);      /*! -     * Send a vector of buffer (like send_msg). -     * Blocks until the data is sent. -     * \param buffs a vector of asio buffers -     * \return the number of bytes sent +     * Make a new broadcasting udp transport: +     * This transport can send udp broadcast datagrams +     * and receive datagrams from multiple sources. +     * The primary usage for this transport will be to discover devices. +     * +     * The address will be resolved, it can be a host name or ipv4. +     * The port will be resolved, it can be a port type or number. +     * +     * \param addr a string representing the destination address +     * \param port a string representing the destination port       */ -    virtual size_t send(const std::vector<boost::asio::const_buffer> &buffs) = 0; +    static sptr make_broadcast(const std::string &addr, const std::string &port);      /*!       * Send a single buffer. @@ -55,22 +66,14 @@ public:      virtual size_t send(const boost::asio::const_buffer &buff) = 0;      /*! -     * Receive a buffer. Write into the memory provided. -     * Returns empty when data is not available. -     * \param buffs a vector of asio buffers -     * \return the number of bytes received. -     */ -    virtual size_t recv(const std::vector<boost::asio::mutable_buffer> &buffs) = 0; - -    /*! -     * Receive a buffer. Write into the memory provided. -     * Returns empty when data is not available. +     * Receive into the provided buffer. +     * Blocks until data is received or a timeout occurs.       * \param buff a mutable buffer to receive into -     * \return the number of bytes received. +     * \return the number of bytes received or zero on timeout       */      virtual size_t recv(const boost::asio::mutable_buffer &buff) = 0;  };  }} //namespace -#endif /* INCLUDED_UHD_TRANSPORT_UDP_HPP */ +#endif /* INCLUDED_UHD_TRANSPORT_UDP_SIMPLE_HPP */ diff --git a/host/include/uhd/transport/udp_zero_copy.hpp b/host/include/uhd/transport/udp_zero_copy.hpp new file mode 100644 index 000000000..1a8d822fd --- /dev/null +++ b/host/include/uhd/transport/udp_zero_copy.hpp @@ -0,0 +1,76 @@ +// +// Copyright 2010 Ettus Research LLC +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program.  If not, see <http://www.gnu.org/licenses/>. +// + +#include <uhd/transport/smart_buffer.hpp> +#include <boost/asio.hpp> +#include <boost/utility.hpp> +#include <boost/shared_ptr.hpp> + +#ifndef INCLUDED_UHD_TRANSPORT_UDP_ZERO_COPY_HPP +#define INCLUDED_UHD_TRANSPORT_UDP_ZERO_COPY_HPP + +namespace uhd{ namespace transport{ + +/*! + * A zero copy udp transport provides an efficient way to handle data. + * by avoiding the extra copy when recv() is called on the socket. + * Rather, the zero copy transport gives the caller a memory reference. + * The caller informs the transport when it is finished with the reference. + * + * On linux systems, the zero copy transport can use a kernel packet ring. + * If no platform specific solution is available, make returns a boost asio + * implementation that wraps the functionality around a standard recv() call. + */ +class udp_zero_copy : boost::noncopyable{ +public: +    typedef boost::shared_ptr<udp_zero_copy> sptr; + +    /*! +     * Make a new zero copy udp transport: +     * This transport is for sending and receiving +     * between this host and a single endpoint. +     * The primary usage for this transport will be data transactions. +     * The underlying implementation is fast and platform specific. +     * +     * The address will be resolved, it can be a host name or ipv4. +     * The port will be resolved, it can be a port type or number. +     * +     * \param addr a string representing the destination address +     * \param port a string representing the destination port +     */ +    static sptr make(const std::string &addr, const std::string &port); + +    /*! +     * Send a single buffer. +     * Blocks until the data is sent. +     * \param buff single asio buffer +     * \return the number of bytes sent +     */ +    virtual size_t send(const boost::asio::const_buffer &buff) = 0; + +    /*! +     * Receive a buffer. +     * Blocks until data is received or a timeout occurs. +     * The memory is managed by the implementation. +     * \return a smart buffer (empty on timeout) +     */ +    virtual smart_buffer::sptr recv(void) = 0; +}; + +}} //namespace + +#endif /* INCLUDED_UHD_TRANSPORT_UDP_ZERO_COPY_HPP */ diff --git a/host/include/uhd/transport/vrt.hpp b/host/include/uhd/transport/vrt.hpp new file mode 100644 index 000000000..1700d2785 --- /dev/null +++ b/host/include/uhd/transport/vrt.hpp @@ -0,0 +1,70 @@ +// +// Copyright 2010 Ettus Research LLC +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program.  If not, see <http://www.gnu.org/licenses/>. +// + +#include <uhd/metadata.hpp> +#include <cstddef> + +#ifndef INCLUDED_UHD_TRANSPORT_VRT_HPP +#define INCLUDED_UHD_TRANSPORT_VRT_HPP + +namespace uhd{ namespace transport{ + +namespace vrt{ + +    static const size_t max_header_words32 = 7; + +    /*! +     * Pack a vrt header from metadata. +     * \param metadata the tx metadata with flags and timestamps +     * \param header_buff memory to write the packed vrt header +     * \param num_header_words32 number of words in the vrt header +     * \param num_payload_words32 the length of the payload +     * \param num_packet_words32 the length of the packet +     * \param packet_count the packet count sequence number +     */ +    void pack( +        const tx_metadata_t &metadata, //input +        uint32_t *header_buff,         //output +        size_t &num_header_words32,    //output +        size_t num_payload_words32,    //input +        size_t &num_packet_words32,    //output +        size_t packet_count            //input +    ); + +    /*! +     * Unpack a vrt header to metadata. +     * \param metadata the rx metadata with flags and timestamps +     * \param header_buff memory to read the packed vrt header +     * \param num_header_words32 number of words in the vrt header +     * \param num_payload_words32 the length of the payload +     * \param num_packet_words32 the length of the packet +     * \param packet_count the packet count sequence number +     */ +    void unpack( +        rx_metadata_t &metadata,         //output +        const uint32_t *header_buff,     //input +        size_t &num_header_words32,      //output +        size_t &num_payload_words32,     //output +        size_t num_packet_words32,       //input +        size_t &packet_count             //output +    ); + +} //namespace vrt + +}} //namespace + +#endif /* INCLUDED_UHD_TRANSPORT_VRT_HPP */ diff --git a/host/include/uhd/usrp/dboard_base.hpp b/host/include/uhd/usrp/dboard_base.hpp index b5c0d40ed..9048344ac 100644 --- a/host/include/uhd/usrp/dboard_base.hpp +++ b/host/include/uhd/usrp/dboard_base.hpp @@ -56,9 +56,9 @@ protected:      dboard_id_t get_tx_id(void);  private: -    std::string        _subdev_name; +    std::string               _subdev_name;      dboard_interface::sptr    _dboard_interface; -    dboard_id_t        _rx_id, _tx_id; +    dboard_id_t               _rx_id, _tx_id;  };  /*! @@ -71,6 +71,7 @@ public:       * Create a new xcvr dboard object, override in subclasses.       */      xcvr_dboard_base(ctor_args_t const&); +      virtual ~xcvr_dboard_base(void);  }; diff --git a/host/include/uhd/usrp/dboard_id.hpp b/host/include/uhd/usrp/dboard_id.hpp index 8e904ff33..34406863d 100644 --- a/host/include/uhd/usrp/dboard_id.hpp +++ b/host/include/uhd/usrp/dboard_id.hpp @@ -16,21 +16,20 @@  //  #include <string> +#include <stdint.h>  #ifndef INCLUDED_UHD_USRP_DBOARD_ID_HPP  #define INCLUDED_UHD_USRP_DBOARD_ID_HPP  namespace uhd{ namespace usrp{ -enum dboard_id_t{ -    ID_NONE     = 0xffff, -    ID_BASIC_TX = 0x0000, -    ID_BASIC_RX = 0x0001 -}; +typedef uint16_t dboard_id_t; -struct dboard_id{ -    static std::string to_string(const dboard_id_t &id); -}; +static const dboard_id_t ID_NONE = 0xffff; + +namespace dboard_id{ +    std::string to_string(const dboard_id_t &id); +}  }} //namespace diff --git a/host/include/uhd/usrp/dboard_manager.hpp b/host/include/uhd/usrp/dboard_manager.hpp index 042947ac4..0c32c6dba 100644 --- a/host/include/uhd/usrp/dboard_manager.hpp +++ b/host/include/uhd/usrp/dboard_manager.hpp @@ -40,15 +40,17 @@ public:      typedef dboard_base::sptr(*dboard_ctor_t)(dboard_base::ctor_args_t const&);      /*! -     * Register subdevices for a given dboard id. +     * Register a dboard into the system.       *       * \param dboard_id the dboard id (rx or tx)       * \param dboard_ctor the dboard constructor function pointer +     * \param name the canonical name for the dboard represented       * \param subdev_names the names of the subdevs on this dboard       */ -    static void register_subdevs( +    static void register_dboard(          dboard_id_t dboard_id,          dboard_ctor_t dboard_ctor, +        const std::string &name,          const prop_names_t &subdev_names      ); diff --git a/host/include/uhd/usrp/usrp2.hpp b/host/include/uhd/usrp/usrp2.hpp index da7ec595a..b13786546 100644 --- a/host/include/uhd/usrp/usrp2.hpp +++ b/host/include/uhd/usrp/usrp2.hpp @@ -29,6 +29,11 @@ class usrp2 : public device{  public:      /*!       * Discover usrp2 devices over the ethernet. +     * +     * Recommended key/value pairs for the device hint address: +     * hint["addr"] = address, where address is a resolvable address +     * or ip address, which may or may not be a broadcast address. +     *       * This static method will be called by the device::discover.       * \param hint a device addr with the usrp2 address filled in       * \return a vector of device addresses for all usrp2s found @@ -37,6 +42,11 @@ public:      /*!       * Make a usrp2 from a device address. +     * +     * Required key/value pairs for the device address: +     * hint["addr"] = address, where address is a resolvable address +     * or ip address, which must be the specific address of a usrp2. +     *       * \param addr the device address       * \return a device sptr to a new usrp2       */ diff --git a/host/include/uhd/utils.hpp b/host/include/uhd/utils.hpp index 4331aba7e..995cb9926 100644 --- a/host/include/uhd/utils.hpp +++ b/host/include/uhd/utils.hpp @@ -15,17 +15,27 @@  // along with this program.  If not, see <http://www.gnu.org/licenses/>.  // -#include <uhd/wax.hpp> -#include <boost/foreach.hpp> -#include <boost/format.hpp> -#include <boost/function.hpp> +#ifndef INCLUDED_UHD_UTILS_HPP +#define INCLUDED_UHD_UTILS_HPP +  #include <stdexcept>  #include <algorithm> -#include <vector> -#include <map> +#include <boost/format.hpp> +#include <boost/current_function.hpp> -#ifndef INCLUDED_UHD_UTILS_HPP -#define INCLUDED_UHD_UTILS_HPP +/*! + * Defines a function that implements the "construct on first use" idiom + * \param _t the type definition for the instance + * \param _x the name of the defined function + * \return a reference to the lazy instance + */ +#define STATIC_INSTANCE(_t, _x) static _t &_x(){static _t _x; return _x;} + +/*! + * Defines a static code block that will be called before main() + * \param _x the name of the defined struct (must be unique in file) + */ +#define STATIC_BLOCK(_x) static struct _x{_x();}_x;_x::_x()  /*!   * Useful templated functions and classes that I like to pretend are part of stl @@ -40,7 +50,9 @@ namespace std{      };      #define ASSERT_THROW(_x) if (not (_x)) { \ -        throw std::assert_error("Assertion Failed: " + std::string(#_x)); \ +        throw std::assert_error(str(boost::format( \ +            "Assertion Failed:\n  %s:%d\n  %s\n  ---> %s <---" \ +        ) % __FILE__ % __LINE__ % BOOST_CURRENT_FUNCTION % std::string(#_x))); \      }      template<class T, class InputIterator, class Function> @@ -52,14 +64,19 @@ namespace std{          return tmp;      } +    template<class T, class Iterable, class Function> +    T reduce(Iterable iterable, Function fcn, T init = 0){ +        return reduce(iterable.begin(), iterable.end(), fcn, init); +    } +      template<class T, class InputIterator>      bool has(InputIterator first, InputIterator last, const T &elem){          return last != std::find(first, last, elem);      } -    template<class T> -    T sum(const T &a, const T &b){ -        return a + b; +    template<class T, class Iterable> +    bool has(const Iterable &iterable, const T &elem){ +        return has(iterable.begin(), iterable.end(), elem);      }      template<typename T> T signum(T n){ @@ -70,52 +87,43 @@ namespace std{  }//namespace std -/*namespace uhd{ - -inline void tune( -    freq_t target_freq, -    freq_t lo_offset, -    wax::obj subdev_freq_proxy, -    bool subdev_quadrature, -    bool subdev_spectrum_inverted, -    bool subdev_is_tx, -    wax::obj dsp_freq_proxy, -    freq_t dsp_sample_rate -){ -    // Ask the d'board to tune as closely as it can to target_freq+lo_offset -    subdev_freq_proxy = target_freq + lo_offset; -    freq_t inter_freq = wax::cast<freq_t>(subdev_freq_proxy); - -    // Calculate the DDC setting that will downconvert the baseband from the -    // daughterboard to our target frequency. -    freq_t delta_freq = target_freq - inter_freq; -    freq_t delta_sign = std::signum(delta_freq); -    delta_freq *= delta_sign; -    delta_freq = fmod(delta_freq, dsp_sample_rate); -    bool inverted = delta_freq > dsp_sample_rate/2.0; -    freq_t dxc_freq = inverted? (delta_freq - dsp_sample_rate) : (-delta_freq); -    dxc_freq *= delta_sign; - -    // If the spectrum is inverted, and the daughterboard doesn't do -    // quadrature downconversion, we can fix the inversion by flipping the -    // sign of the dxc_freq...  (This only happens using the basic_rx board) -    if (subdev_spectrum_inverted){ -        inverted = not inverted; -    } -    if (inverted and not subdev_quadrature){ -        dxc_freq = -dxc_freq; -        inverted = not inverted; -    } -    if (subdev_is_tx){ -        dxc_freq = -dxc_freq;	// down conversion versus up conversion +#include <boost/format.hpp> +#include <boost/foreach.hpp> +#include <boost/lexical_cast.hpp> + +namespace uhd{ + +    /*! +     * Check that an element is found in a container. +     * If not, throw a meaningful assertion error. +     * The "what" in the error will show what is +     * being set and a list of known good values. +     * +     * \param iterable a list of possible settings +     * \param elem an element that may be in the list +     * \param what a description of what is being set +     * \throw assertion_error when elem not in list +     */ +    template<class T, class Iterable> void assert_has( +        const Iterable &iterable, +        const T &elem, +        const std::string &what = "unknown" +    ){ +        if (std::has(iterable, elem)) return; +        std::string possible_values = ""; +        BOOST_FOREACH(T e, iterable){ +            if (e != iterable.begin()[0]) possible_values += ", "; +            possible_values += boost::lexical_cast<std::string>(e); +        } +        throw std::assert_error(str(boost::format( +                "Error: %s is not a valid %s. " +                "Possible values are: [%s]." +            ) +            % boost::lexical_cast<std::string>(elem) +            % what % possible_values +        ));      } -    dsp_freq_proxy = dxc_freq; -    //freq_t actual_dxc_freq = wax::cast<freq_t>(dsp_freq_proxy); - -    //return some kind of tune result tuple/struct -} - -} //namespace uhd*/ +}//namespace uhd  #endif /* INCLUDED_UHD_UTILS_HPP */ diff --git a/host/include/uhd/wax.hpp b/host/include/uhd/wax.hpp index 1d5054351..0291a06b7 100644 --- a/host/include/uhd/wax.hpp +++ b/host/include/uhd/wax.hpp @@ -19,32 +19,35 @@  #define INCLUDED_WAX_HPP  #include <boost/any.hpp> -#include <iostream>  /*!   * WAX - it's a metaphor!   * - * The WAX framework allows object to have generic/anyobj properties. + * The WAX framework allows an object to have generic/anyobj properties.   * These properties can be addressed through generic/anyobj identifiers. - * A property of a WAX object may even be another WAX object.   * - * When a property is a WAX object, the returned value must be an obj pointer. - * A WAX object provides two objs of pointers: obj::ptr and obj::sptr. - * The choice of pointer vs smart pointer depends on the owner of the memory. + * The WAX object itself is an anytype container much like boost::any. + * To retrieve the value of the appropriate type, use my_obj.as<type>().   *   * Proprties may be referenced though the [] overloaded operator.   * The [] operator returns a special proxy that allows for assigment.   * Also, the [] operators may be chained as in the folowing examples: - *   my_obj[prop1][prop2][prop3] = value - *   value = my_obj[prop1][prop2][prop3] + *   my_obj[prop1][prop2][prop3] = value; + *   value = my_obj[prop1][prop2][prop3].as<type>();   * - * Any value returned from an access operation is of wax::obj. - * To use this value, it must be cast with wax::cast<new_obj>(value). + * Property nesting occurs when a WAX object gets another object's link. + * This special link is obtained through a call to my_obj.get_link().   */  namespace wax{      /*! +     * The wax::bad cast will be thrown when +     * cast is called with the wrong typeid. +     */ +    typedef boost::bad_any_cast bad_cast; + +    /*!       * WAX object base class:       *       * A wax obj has two major purposes: @@ -124,6 +127,17 @@ namespace wax{           */          const std::type_info & type(void) const; +        /*! +         * Cast this obj into the desired type. +         * Usage: myobj.as<type>() +         * +         * \return an object of the desired type +         * \throw wax::bad_cast when the cast fails +         */ +        template<class T> T as(void) const{ +            return boost::any_cast<T>(resolve()); +        } +      private:          //private interface (override in subclasses)          virtual void get(const obj &, obj &); @@ -137,31 +151,12 @@ namespace wax{           * \return a boost any type with contents           */          boost::any resolve(void) const; -        template<class T> friend T cast(const obj &);          //private contents of this obj          boost::any _contents;      }; -    /*! -     * The wax::bad cast will be thrown when -     * cast is called with the wrong typeid. -     */ -    typedef boost::bad_any_cast bad_cast; - -    /*! -     * Cast a wax::obj into the desired obj. -     * Usage wax::cast<new_obj>(my_value). -     * -     * \param val the obj to cast -     * \return an object of the desired type -     * \throw wax::bad_cast when the cast fails -     */ -    template<class T> T cast(const obj &val){ -        return boost::any_cast<T>(val.resolve()); -    } -  } //namespace wax  #endif /* INCLUDED_WAX_HPP */ | 
