diff options
Diffstat (limited to 'host/include')
73 files changed, 7514 insertions, 0 deletions
| diff --git a/host/include/CMakeLists.txt b/host/include/CMakeLists.txt new file mode 100644 index 000000000..3f7ca2cb7 --- /dev/null +++ b/host/include/CMakeLists.txt @@ -0,0 +1,19 @@ +# +# Copyright 2010 Ettus Research LLC +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program.  If not, see <http://www.gnu.org/licenses/>. +# + + +ADD_SUBDIRECTORY(uhd) diff --git a/host/include/linux/usrp_e.h b/host/include/linux/usrp_e.h new file mode 100644 index 000000000..4c6a5dd89 --- /dev/null +++ b/host/include/linux/usrp_e.h @@ -0,0 +1,91 @@ + +/* + *  Copyright (C) 2010 Ettus Research, LLC + * + *  Written by Philip Balister <philip@opensdr.com> + * + *  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 2 of the License, or + *  (at your option) any later version. + */ + +#ifndef __USRP_E_H +#define __USRP_E_H + +#include <linux/types.h> +#include <linux/ioctl.h> + +struct usrp_e_ctl16 { +	__u32 offset; +	__u32 count; +	__u16 buf[20]; +}; + +struct usrp_e_ctl32 { +	__u32 offset; +	__u32 count; +	__u32 buf[10]; +}; + +/* SPI interface */ + +#define UE_SPI_TXONLY	0 +#define UE_SPI_TXRX	1 + +/* Defines for spi ctrl register */ +#define UE_SPI_CTRL_TXNEG	(1<<10) +#define UE_SPI_CTRL_RXNEG	(1<<9) + +#define UE_SPI_PUSH_RISE	0 +#define UE_SPI_PUSH_FALL	UE_SPI_CTRL_TXNEG +#define UE_SPI_LATCH_RISE	0 +#define UE_SPI_LATCH_FALL	UE_SPI_CTRL_RXNEG + +struct usrp_e_spi { +	__u8 readback; +	__u32 slave; +	__u32 data; +	__u32 length; +	__u32 flags; +}; + +struct usrp_e_i2c { +	__u8 addr; +	__u32 len; +	__u8 data[]; +}; + +#define USRP_E_IOC_MAGIC	'u' +#define USRP_E_WRITE_CTL16	_IOW(USRP_E_IOC_MAGIC, 0x20, struct usrp_e_ctl16) +#define USRP_E_READ_CTL16	_IOWR(USRP_E_IOC_MAGIC, 0x21, struct usrp_e_ctl16) +#define USRP_E_WRITE_CTL32	_IOW(USRP_E_IOC_MAGIC, 0x22, struct usrp_e_ctl32) +#define USRP_E_READ_CTL32	_IOWR(USRP_E_IOC_MAGIC, 0x23, struct usrp_e_ctl32) +#define USRP_E_SPI		_IOWR(USRP_E_IOC_MAGIC, 0x24, struct usrp_e_spi) +#define USRP_E_I2C_READ		_IOWR(USRP_E_IOC_MAGIC, 0x25, struct usrp_e_i2c) +#define USRP_E_I2C_WRITE	_IOW(USRP_E_IOC_MAGIC, 0x26, struct usrp_e_i2c) +#define USRP_E_GET_RB_INFO      _IOR(USRP_E_IOC_MAGIC, 0x27, struct usrp_e_ring_buffer_size_t) +#define USRP_E_GET_COMPAT_NUMBER _IO(USRP_E_IOC_MAGIC, 0x28) + +#define USRP_E_COMPAT_NUMBER 1 + +/* Flag defines */ +#define RB_USER (1<<0) +#define RB_KERNEL (1<<1) +#define RB_OVERRUN (1<<2) +#define RB_DMA_ACTIVE (1<<3) +#define RB_USER_PROCESS (1<<4) + +struct ring_buffer_info { +	int flags; +	int len; +}; + +struct usrp_e_ring_buffer_size_t { +	int num_pages_rx_flags; +	int num_rx_frames; +	int num_pages_tx_flags; +	int num_tx_frames; +}; + +#endif diff --git a/host/include/uhd/CMakeLists.txt b/host/include/uhd/CMakeLists.txt new file mode 100644 index 000000000..ad528c9fb --- /dev/null +++ b/host/include/uhd/CMakeLists.txt @@ -0,0 +1,31 @@ +# +# Copyright 2010 Ettus Research LLC +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program.  If not, see <http://www.gnu.org/licenses/>. +# + + +ADD_SUBDIRECTORY(transport) +ADD_SUBDIRECTORY(types) +ADD_SUBDIRECTORY(usrp) +ADD_SUBDIRECTORY(utils) + +INSTALL(FILES +    config.hpp +    device.hpp +    device.ipp +    version.hpp +    wax.hpp +    DESTINATION ${INCLUDE_DIR}/uhd +) diff --git a/host/include/uhd/config.hpp b/host/include/uhd/config.hpp new file mode 100644 index 000000000..2918c2340 --- /dev/null +++ b/host/include/uhd/config.hpp @@ -0,0 +1,116 @@ +// +// 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_CONFIG_HPP +#define INCLUDED_UHD_CONFIG_HPP + +// suppress warnings +#include <boost/config.hpp> +#ifdef BOOST_MSVC +//# pragma warning(push) +//# pragma warning(disable: 4511) // copy constructor can't not be generated +//# pragma warning(disable: 4512) // assignment operator can't not be generated +//# pragma warning(disable: 4100) // unreferenced formal parameter +//# pragma warning(disable: 4996) // <symbol> was declared deprecated +//# pragma warning(disable: 4355) // 'this' : used in base member initializer list +//# pragma warning(disable: 4706) // assignment within conditional expression +# pragma warning(disable: 4251) // class 'A<T>' needs to have dll-interface to be used by clients of class 'B' +//# pragma warning(disable: 4127) // conditional expression is constant +//# pragma warning(disable: 4290) // C++ exception specification ignored except to ... +//# pragma warning(disable: 4180) // qualifier applied to function type has no meaning; ignored +# pragma warning(disable: 4275) // non dll-interface class ... used as base for dll-interface class ... +//# pragma warning(disable: 4267) // 'var' : conversion from 'size_t' to 'type', possible loss of data +//# pragma warning(disable: 4511) // 'class' : copy constructor could not be generated +//# pragma warning(disable: 4250) // 'class' : inherits 'method' via dominance +# pragma warning(disable: 4200) // nonstandard extension used : zero-sized array in struct/union +#endif + +// define logical operators +#ifdef BOOST_MSVC +    #include <ciso646> +#endif + +// define ssize_t +#ifdef BOOST_MSVC +    #include <cstddef> +    typedef ptrdiff_t ssize_t; +#endif + +// http://gcc.gnu.org/wiki/Visibility +// Generic helper definitions for shared library support +#if defined(BOOST_HAS_DECLSPEC) +    #define UHD_HELPER_DLL_IMPORT __declspec(dllimport) +    #define UHD_HELPER_DLL_EXPORT __declspec(dllexport) +    #define UHD_HELPER_DLL_LOCAL +#elif defined(__GNUG__) && __GNUG__ >= 4 +    #define UHD_HELPER_DLL_IMPORT __attribute__ ((visibility("default"))) +    #define UHD_HELPER_DLL_EXPORT __attribute__ ((visibility("default"))) +    #define UHD_HELPER_DLL_LOCAL  __attribute__ ((visibility("hidden"))) +#else +    #define UHD_HELPER_DLL_IMPORT +    #define UHD_HELPER_DLL_EXPORT +    #define UHD_HELPER_DLL_LOCAL +#endif + +// Now we use the generic helper definitions above to define UHD_API and UHD_LOCAL. +// UHD_API is used for the public API symbols. It either DLL imports or DLL exports (or does nothing for static build) +// UHD_LOCAL is used for non-api symbols. + +#define UHD_DLL // defined here, put into configuration if we need to make static libs + +#ifdef UHD_DLL // defined if UHD is compiled as a DLL +    #ifdef UHD_DLL_EXPORTS // defined if we are building the UHD DLL (instead of using it) +        #define UHD_API UHD_HELPER_DLL_EXPORT +    #else +        #define UHD_API UHD_HELPER_DLL_IMPORT +    #endif // UHD_DLL_EXPORTS +    #define UHD_LOCAL UHD_HELPER_DLL_LOCAL +#else // UHD_DLL is not defined: this means UHD is a static lib. +    #define UHD_API +    #define UHD_LOCAL +#endif // UHD_DLL + +// Define force inline macro +#if defined(BOOST_MSVC) +    #define UHD_INLINE __forceinline +#elif defined(__GNUG__) && __GNUG__ >= 4 +    #define UHD_INLINE inline __attribute__((always_inline)) +#else +    #define UHD_INLINE inline +#endif + +// Define deprecated attribute macro +#if defined(BOOST_MSVC) +    #define UHD_DEPRECATED __declspec(deprecated) +#elif defined(__GNUG__) && __GNUG__ >= 4 +    #define UHD_DEPRECATED __attribute__ ((deprecated)) +#else +    #define UHD_DEPRECATED +#endif + +// Platform defines for conditional parts of headers: +// Taken from boost/config/select_platform_config.hpp, +// however, we define macros, not strings for platforms. +#if defined(linux) || defined(__linux) || defined(__linux__) +    #define UHD_PLATFORM_LINUX +#elif defined(_WIN32) || defined(__WIN32__) || defined(WIN32) +    #define UHD_PLATFORM_WIN32 +#elif defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__) +    #define UHD_PLATFORM_MACOS +#endif + +#endif /* INCLUDED_UHD_CONFIG_HPP */ diff --git a/host/include/uhd/device.hpp b/host/include/uhd/device.hpp new file mode 100644 index 000000000..992276928 --- /dev/null +++ b/host/include/uhd/device.hpp @@ -0,0 +1,224 @@ +// +// 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_DEVICE_HPP +#define INCLUDED_UHD_DEVICE_HPP + +#include <uhd/config.hpp> +#include <uhd/types/device_addr.hpp> +#include <uhd/types/metadata.hpp> +#include <uhd/types/io_type.hpp> +#include <uhd/wax.hpp> +#include <boost/utility.hpp> +#include <boost/shared_ptr.hpp> +#include <boost/function.hpp> +#include <vector> + +namespace uhd{ + +/*! + * The usrp device interface represents the usrp hardware. + * The api allows for discovery, configuration, and streaming. + */ +class UHD_API device : boost::noncopyable, public wax::obj{ + +public: +    typedef boost::shared_ptr<device> sptr; +    typedef boost::function<device_addrs_t(const device_addr_t &)> find_t; +    typedef boost::function<sptr(const device_addr_t &)> make_t; + +    /*! +     * Register a device into the discovery and factory system. +     * +     * \param find a function that discovers devices +     * \param make a factory function that makes a device +     */ +    static void register_device( +        const find_t &find, +        const make_t &make +    ); + +    /*! +     * \brief Find usrp devices attached to the host. +     * +     * The hint device address should be used to narrow down the search +     * to particular transport types and/or transport arguments. +     * +     * \param hint a partially (or fully) filled in device address +     * \return a vector of device addresses for all usrps on the system +     */ +    static device_addrs_t find(const device_addr_t &hint); + +    /*! +     * \brief Create a new usrp device from the device address hint. +     * +     * The make routine will call find and pick one of the results. +     * By default, the first result will be used to create a new device. +     * Use the which parameter as an index into the list of results. +     * +     * \param hint a partially (or fully) filled in device address +     * \param which which address to use when multiple are found +     * \return a shared pointer to a new device instance +     */ +    static sptr make(const device_addr_t &hint, size_t which = 0); + +    /*! +     * 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 +    }; + +    /*! +     * 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 +     */ +    virtual size_t send( +        const std::vector<const void *> &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 +    ) = 0; + +    /*! +     * Convenience wrapper for send that takes a single buffer. +     */ +    size_t send( +        const void *buff, +        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 +    ); + +    /*! +     * Receive buffers containing IF data described by the metadata. +     * +     * Receive handles fragmentation as follows: +     * If the buffer has insufficient space to hold all samples +     * that were received in a single packet over-the-wire, +     * then the buffer will be completely filled and the implementation +     * will hold a pointer into the remaining portion of the packet. +     * Subsequent calls will load from the remainder of the packet, +     * and will flag the metadata to show that this is a fragment. +     * The next call to receive, after the remainder becomes exahausted, +     * will perform an over-the-wire receive as usual. +     * See the rx metadata fragment flags and offset fields for details. +     * +     * This is a blocking call and will not return until the number +     * of samples returned have been written into each buffer. +     * Under a timeout condition, the number of samples returned +     * may be less than the number of samples specified. +     * +     * When using the full buffer recv mode, the metadata only applies +     * to the first packet received and written into the recv buffers. +     * Use the one packet recv mode to get per packet metadata. +     * +     * \param buffs a vector of writable memory to fill with IF data +     * \param nsamps_per_buff the size of each buffer in number of samples +     * \param metadata data to fill describing the buffer +     * \param io_type the type of data to fill into the buffer +     * \param recv_mode tells recv how to load the buffer +     * \param timeout the timeout in seconds to wait for a packet +     * \return the number of samples received or 0 on error +     */ +    virtual size_t recv( +        const std::vector<void *> &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 +    ) = 0; + +    /*! +     * Convenience wrapper for recv that takes a single buffer. +     */ +    size_t recv( +        void *buff, +        size_t nsamps_per_buff, +        rx_metadata_t &metadata, +        const io_type_t &io_type, +        recv_mode_t recv_mode, +        double timeout = 0.1 +    ); + +    /*! +     * Get the maximum number of samples per packet on send. +     * \return the number of samples +     */ +    virtual size_t get_max_send_samps_per_packet(void) const = 0; + +    /*! +     * Get the maximum number of samples per packet on recv. +     * \return the number of samples +     */ +    virtual size_t get_max_recv_samps_per_packet(void) const = 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; + +}; + +} //namespace uhd + +#include <uhd/device.ipp> + +#endif /* INCLUDED_UHD_DEVICE_HPP */ diff --git a/host/include/uhd/device.ipp b/host/include/uhd/device.ipp new file mode 100644 index 000000000..e2e51ecd0 --- /dev/null +++ b/host/include/uhd/device.ipp @@ -0,0 +1,55 @@ +// +// Copyright 2010 Ettus Research LLC +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program.  If not, see <http://www.gnu.org/licenses/>. +// + +#ifndef INCLUDED_UHD_DEVICE_IPP +#define INCLUDED_UHD_DEVICE_IPP + +namespace uhd{ + +    UHD_INLINE size_t device::send( +        const void *buff, +        size_t nsamps_per_buff, +        const tx_metadata_t &metadata, +        const io_type_t &io_type, +        send_mode_t send_mode, +        double timeout +    ){ +        return this->send( +            std::vector<const void *>(1, buff), +            nsamps_per_buff, metadata, +            io_type, send_mode, timeout +        ); +    } + +    UHD_INLINE size_t device::recv( +        void *buff, +        size_t nsamps_per_buff, +        rx_metadata_t &metadata, +        const io_type_t &io_type, +        recv_mode_t recv_mode, +        double timeout +    ){ +        return this->recv( +            std::vector<void *>(1, buff), +            nsamps_per_buff, metadata, +            io_type, recv_mode, timeout +        ); +    } + +} //namespace uhd + +#endif /* INCLUDED_UHD_DEVICE_IPP */ diff --git a/host/include/uhd/transport/CMakeLists.txt b/host/include/uhd/transport/CMakeLists.txt new file mode 100644 index 000000000..2c84c0724 --- /dev/null +++ b/host/include/uhd/transport/CMakeLists.txt @@ -0,0 +1,35 @@ +# +# 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/>. +# + + +INSTALL(FILES +    alignment_buffer.hpp +    alignment_buffer.ipp +    bounded_buffer.hpp +    bounded_buffer.ipp +    convert_types.hpp +    convert_types.ipp +    if_addrs.hpp +    udp_simple.hpp +    udp_zero_copy.hpp +    usb_control.hpp +    usb_zero_copy.hpp +    usb_device_handle.hpp +    vrt_if_packet.hpp +    zero_copy.hpp +    DESTINATION ${INCLUDE_DIR}/uhd/transport +) diff --git a/host/include/uhd/transport/alignment_buffer.hpp b/host/include/uhd/transport/alignment_buffer.hpp new file mode 100644 index 000000000..f44a037f8 --- /dev/null +++ b/host/include/uhd/transport/alignment_buffer.hpp @@ -0,0 +1,69 @@ +// +// Copyright 2010 Ettus Research LLC +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program.  If not, see <http://www.gnu.org/licenses/>. +// + +#ifndef INCLUDED_UHD_TRANSPORT_ALIGNMENT_BUFFER_HPP +#define INCLUDED_UHD_TRANSPORT_ALIGNMENT_BUFFER_HPP + +#include <uhd/config.hpp> +#include <uhd/transport/bounded_buffer.hpp> //time_duration_t +#include <boost/shared_ptr.hpp> +#include <vector> + +namespace uhd{ namespace transport{ + +    /*! +     * Implement a templated alignment buffer: +     * Used for aligning asynchronously pushed elements with matching ids. +     */ +    template <typename elem_type, typename seq_type> class alignment_buffer{ +    public: +        typedef boost::shared_ptr<alignment_buffer<elem_type, seq_type> > sptr; + +        /*! +         * Make a new alignment buffer object. +         * \param capacity the maximum elements per index +         * \param width the number of elements to align +         */ +        static sptr make(size_t capacity, size_t width); + +        /*! +         * Push an element with sequence id into the buffer at index. +         * \param elem the element to push +         * \param seq the sequence identifier +         * \param index the buffer index +         * \return true if the element fit without popping for space +         */ +        virtual bool push_with_pop_on_full( +            const elem_type &elem, const seq_type &seq, size_t index +        ) = 0; + +        /*! +         * Pop an aligned set of elements from this alignment buffer. +         * \param elems a collection to store the aligned elements +         * \param timeout the timeout in seconds +         * \return false when the operation times out +         */ +        virtual bool pop_elems_with_timed_wait( +            std::vector<elem_type> &elems, double timeout +        ) = 0; +    }; + +}} //namespace + +#include <uhd/transport/alignment_buffer.ipp> + +#endif /* INCLUDED_UHD_TRANSPORT_ALIGNMENT_BUFFER_HPP */ diff --git a/host/include/uhd/transport/alignment_buffer.ipp b/host/include/uhd/transport/alignment_buffer.ipp new file mode 100644 index 000000000..833b5d399 --- /dev/null +++ b/host/include/uhd/transport/alignment_buffer.ipp @@ -0,0 +1,144 @@ +// +// Copyright 2010 Ettus Research LLC +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program.  If not, see <http://www.gnu.org/licenses/>. +// + +#ifndef INCLUDED_UHD_TRANSPORT_ALIGNMENT_BUFFER_IPP +#define INCLUDED_UHD_TRANSPORT_ALIGNMENT_BUFFER_IPP + +#include <uhd/transport/bounded_buffer.hpp> +#include <boost/thread/condition_variable.hpp> +#include <utility> + +namespace uhd{ namespace transport{ namespace{ /*anon*/ + +    /*! +     * Imlement a templated alignment buffer: +     * Used for aligning asynchronously pushed elements with matching ids. +     */ +    template <typename elem_type, typename seq_type> +    class alignment_buffer_impl : public alignment_buffer<elem_type, seq_type>{ +    public: + +        alignment_buffer_impl(size_t capacity, size_t width) : _last_seqs(width){ +            for (size_t i = 0; i < width; i++){ +                _buffs.push_back(bounded_buffer<buff_contents_type>::make(capacity)); +                _all_indexes.push_back(i); +            } +            _there_was_a_clear = false; +        } + +        UHD_INLINE bool push_with_pop_on_full( +            const elem_type &elem, const seq_type &seq, size_t index +        ){ +            //clear the buffer for this index if the seqs are mis-ordered +            if (seq < _last_seqs[index]){ +                _buffs[index]->clear(); +                _there_was_a_clear = true; +            } _last_seqs[index] = seq; +            return _buffs[index]->push_with_pop_on_full(buff_contents_type(elem, seq)); +        } + +        UHD_INLINE bool pop_elems_with_timed_wait( +            std::vector<elem_type> &elems, double timeout +        ){ +            boost::system_time exit_time = boost::get_system_time() + to_time_dur(timeout); +            buff_contents_type buff_contents_tmp; +            std::list<size_t> indexes_to_do(_all_indexes); + +            //do an initial pop to load an initial sequence id +            size_t index = indexes_to_do.front(); +            if (not _buffs[index]->pop_with_timed_wait( +                buff_contents_tmp, from_time_dur(exit_time - boost::get_system_time()) +            )) return false; +            elems[index] = buff_contents_tmp.first; +            seq_type expected_seq_id = buff_contents_tmp.second; +            indexes_to_do.pop_front(); + +            //get an aligned set of elements from the buffers: +            while(indexes_to_do.size() != 0){ + +                //respond to a clear by starting from scratch +                if(_there_was_a_clear){ +                    _there_was_a_clear = false; +                    indexes_to_do = _all_indexes; +                    index = indexes_to_do.front(); +                    if (not _buffs[index]->pop_with_timed_wait( +                        buff_contents_tmp, from_time_dur(exit_time - boost::get_system_time()) +                    )) return false; +                    elems[index] = buff_contents_tmp.first; +                    expected_seq_id = buff_contents_tmp.second; +                    indexes_to_do.pop_front(); +                } + +                //pop an element off for this index +                index = indexes_to_do.front(); +                if (not _buffs[index]->pop_with_timed_wait( +                    buff_contents_tmp, from_time_dur(exit_time - boost::get_system_time()) +                )) return false; + +                //if the sequence id matches: +                //  store the popped element into the output, +                //  remove this index from the list and continue +                if (buff_contents_tmp.second == expected_seq_id){ +                    elems[index] = buff_contents_tmp.first; +                    indexes_to_do.pop_front(); +                    continue; +                } + +                //if the sequence id is older: +                //  continue with the same index to try again +                if (buff_contents_tmp.second < expected_seq_id){ +                    continue; +                } + +                //if the sequence id is newer: +                //  store the popped element into the output, +                //  add all other indexes back into the list +                if (buff_contents_tmp.second > expected_seq_id){ +                    elems[index] = buff_contents_tmp.first; +                    expected_seq_id = buff_contents_tmp.second; +                    indexes_to_do = _all_indexes; +                    indexes_to_do.remove(index); +                    continue; +                } +            } +            return true; +        } + +    private: +        //a vector of bounded buffers for each index +        typedef std::pair<elem_type, seq_type> buff_contents_type; +        std::vector<typename bounded_buffer<buff_contents_type>::sptr> _buffs; +        std::vector<seq_type> _last_seqs; +        std::list<size_t> _all_indexes; +        bool _there_was_a_clear; +    }; + +}}} //namespace + +namespace uhd{ namespace transport{ + +    template <typename elem_type, typename seq_type> +    typename alignment_buffer<elem_type, seq_type>::sptr +    alignment_buffer<elem_type, seq_type>::make(size_t capacity, size_t width){ +        return typename alignment_buffer<elem_type, seq_type>::sptr( +            new alignment_buffer_impl<elem_type, seq_type>(capacity, width) +        ); +    } + +}} //namespace + +#endif /* INCLUDED_UHD_TRANSPORT_ALIGNMENT_BUFFER_IPP */ diff --git a/host/include/uhd/transport/bounded_buffer.hpp b/host/include/uhd/transport/bounded_buffer.hpp new file mode 100644 index 000000000..aca93b071 --- /dev/null +++ b/host/include/uhd/transport/bounded_buffer.hpp @@ -0,0 +1,94 @@ +// +// Copyright 2010 Ettus Research LLC +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program.  If not, see <http://www.gnu.org/licenses/>. +// + +#ifndef INCLUDED_UHD_TRANSPORT_BOUNDED_BUFFER_HPP +#define INCLUDED_UHD_TRANSPORT_BOUNDED_BUFFER_HPP + +#include <uhd/config.hpp> +#include <boost/shared_ptr.hpp> + +namespace uhd{ namespace transport{ + +    /*! +     * Implement a templated bounded buffer: +     * Used for passing elements between threads in a producer-consumer model. +     * The bounded buffer implemented waits and timed waits with condition variables. +     * The pop operation blocks on the bounded_buffer to become non empty. +     * The push operation blocks on the bounded_buffer to become non full. +     */ +    template <typename elem_type> class bounded_buffer{ +    public: +        typedef boost::shared_ptr<bounded_buffer<elem_type> > sptr; + +        /*! +         * Make a new bounded buffer object. +         * \param capacity the bounded_buffer capacity +         */ +        static sptr make(size_t capacity); + +        /*! +         * Push a new element into the bounded buffer. +         * If the buffer is full prior to the push, +         * make room by poping the oldest element. +         * \param elem the new element to push +         * \return true if the element fit without popping for space +         */ +        virtual bool push_with_pop_on_full(const elem_type &elem) = 0; + +        /*! +         * Push a new element into the bounded_buffer. +         * Wait until the bounded_buffer becomes non-full. +         * \param elem the new element to push +         */ +        virtual void push_with_wait(const elem_type &elem) = 0; + +        /*! +         * Push a new element into the bounded_buffer. +         * Wait until the bounded_buffer becomes non-full or timeout. +         * \param elem the new element to push +         * \param timeout the timeout in seconds +         * \return false when the operation times out +         */ +        virtual bool push_with_timed_wait(const elem_type &elem, double timeout) = 0; + +        /*! +         * Pop an element from the bounded_buffer. +         * Wait until the bounded_buffer becomes non-empty. +         * \param elem the element reference pop to +         */ +        virtual void pop_with_wait(elem_type &elem) = 0; + +        /*! +         * Pop an element from the bounded_buffer. +         * Wait until the bounded_buffer becomes non-empty or timeout. +         * \param elem the element reference pop to +         * \param timeout the timeout in seconds +         * \return false when the operation times out +         */ +        virtual bool pop_with_timed_wait(elem_type &elem, double timeout) = 0; + +        /*! +         * Clear all elements from the bounded_buffer. +         */ +        virtual void clear(void) = 0; +    }; + +}} //namespace + +#include <uhd/transport/bounded_buffer.ipp> + +#endif /* INCLUDED_UHD_TRANSPORT_BOUNDED_BUFFER_HPP */ diff --git a/host/include/uhd/transport/bounded_buffer.ipp b/host/include/uhd/transport/bounded_buffer.ipp new file mode 100644 index 000000000..edc7faa06 --- /dev/null +++ b/host/include/uhd/transport/bounded_buffer.ipp @@ -0,0 +1,142 @@ +// +// Copyright 2010 Ettus Research LLC +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program.  If not, see <http://www.gnu.org/licenses/>. +// + +#ifndef INCLUDED_UHD_TRANSPORT_BOUNDED_BUFFER_IPP +#define INCLUDED_UHD_TRANSPORT_BOUNDED_BUFFER_IPP + +#include <boost/bind.hpp> +#include <boost/function.hpp> +#include <boost/circular_buffer.hpp> +#include <boost/thread/condition.hpp> +#include <boost/date_time/posix_time/posix_time_types.hpp> + +namespace uhd{ namespace transport{ namespace{ /*anon*/ + +    static UHD_INLINE boost::posix_time::time_duration to_time_dur(double timeout){ +        return boost::posix_time::microseconds(long(timeout*1e6)); +    } + +    static UHD_INLINE double from_time_dur(const boost::posix_time::time_duration &time_dur){ +        return 1e-6*time_dur.total_microseconds(); +    } + +    template <typename elem_type> +    class bounded_buffer_impl : public bounded_buffer<elem_type>{ +    public: + +        bounded_buffer_impl(size_t capacity) : _buffer(capacity){ +            _not_full_fcn = boost::bind(&bounded_buffer_impl<elem_type>::not_full, this); +            _not_empty_fcn = boost::bind(&bounded_buffer_impl<elem_type>::not_empty, this); +        } + +        UHD_INLINE bool push_with_pop_on_full(const elem_type &elem){ +            boost::unique_lock<boost::mutex> lock(_mutex); +            if(_buffer.full()){ +                _buffer.pop_back(); +                _buffer.push_front(elem); +                lock.unlock(); +                _empty_cond.notify_one(); +                return false; +            } +            else{ +                _buffer.push_front(elem); +                lock.unlock(); +                _empty_cond.notify_one(); +                return true; +            } +        } + +        UHD_INLINE void push_with_wait(const elem_type &elem){ +            boost::unique_lock<boost::mutex> lock(_mutex); +            _full_cond.wait(lock, _not_full_fcn); +            _buffer.push_front(elem); +            lock.unlock(); +            _empty_cond.notify_one(); +        } + +        UHD_INLINE bool push_with_timed_wait(const elem_type &elem, double timeout){ +            boost::unique_lock<boost::mutex> lock(_mutex); +            if (not _full_cond.timed_wait( +                lock, to_time_dur(timeout), _not_full_fcn +            )) return false; +            _buffer.push_front(elem); +            lock.unlock(); +            _empty_cond.notify_one(); +            return true; +        } + +        UHD_INLINE void pop_with_wait(elem_type &elem){ +            boost::unique_lock<boost::mutex> lock(_mutex); +            _empty_cond.wait(lock, _not_empty_fcn); +            elem = this->pop_back(); +            lock.unlock(); +            _full_cond.notify_one(); +        } + +        UHD_INLINE bool pop_with_timed_wait(elem_type &elem, double timeout){ +            boost::unique_lock<boost::mutex> lock(_mutex); +            if (not _empty_cond.timed_wait( +                lock, to_time_dur(timeout), _not_empty_fcn +            )) return false; +            elem = this->pop_back(); +            lock.unlock(); +            _full_cond.notify_one(); +            return true; +        } + +        UHD_INLINE void clear(void){ +            boost::unique_lock<boost::mutex> lock(_mutex); +            while (not_empty()) this->pop_back(); +            lock.unlock(); +            _full_cond.notify_one(); +        } + +    private: +        boost::mutex _mutex; +        boost::condition _empty_cond, _full_cond; +        boost::circular_buffer<elem_type> _buffer; + +        bool not_full(void) const{return not _buffer.full();} +        bool not_empty(void) const{return not _buffer.empty();} + +        boost::function<bool(void)> _not_full_fcn, _not_empty_fcn; + +        /*! +         * Three part operation to pop an element: +         * 1) assign elem to the back element +         * 2) assign the back element to empty +         * 3) pop the back to move the counter +         */ +        UHD_INLINE elem_type pop_back(void){ +            elem_type elem = _buffer.back(); +            _buffer.back() = elem_type(); +            _buffer.pop_back(); +            return elem; +        } +    }; +}}} //namespace + +namespace uhd{ namespace transport{ + +    template <typename elem_type> typename bounded_buffer<elem_type>::sptr +    bounded_buffer<elem_type>::make(size_t capacity){ +        return typename bounded_buffer<elem_type>::sptr(new bounded_buffer_impl<elem_type>(capacity)); +    } + +}} //namespace + +#endif /* INCLUDED_UHD_TRANSPORT_BOUNDED_BUFFER_IPP */ diff --git a/host/include/uhd/transport/convert_types.hpp b/host/include/uhd/transport/convert_types.hpp new file mode 100644 index 000000000..dc7fa6c1a --- /dev/null +++ b/host/include/uhd/transport/convert_types.hpp @@ -0,0 +1,96 @@ +// +// Copyright 2010 Ettus Research LLC +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program.  If not, see <http://www.gnu.org/licenses/>. +// + +#ifndef INCLUDED_UHD_TRANSPORT_CONVERT_TYPES_HPP +#define INCLUDED_UHD_TRANSPORT_CONVERT_TYPES_HPP + +#include <uhd/config.hpp> +#include <uhd/types/io_type.hpp> +#include <uhd/types/otw_type.hpp> +#include <vector> + +namespace uhd{ namespace transport{ + +/*! + * Convert IO samples to OWT samples. + * + * \param io_buff memory containing samples + * \param io_type the type of these samples + * \param otw_buff memory to write converted samples + * \param otw_type the type of these samples + * \param num_samps the number of samples in io_buff + */ +UHD_API void convert_io_type_to_otw_type( +    const void *io_buff, const io_type_t &io_type, +    void *otw_buff, const otw_type_t &otw_type, +    size_t num_samps +); + +/*! + * Convert IO samples to OWT samples + interleave. + * + * \param io_buffs buffers containing samples + * \param io_type the type of these samples + * \param otw_buff memory to write converted samples + * \param otw_type the type of these samples + * \param nsamps_per_io_buff samples per io_buff + */ +UHD_API void convert_io_type_to_otw_type( +    const std::vector<const void *> &io_buffs, +    const io_type_t &io_type, +    void *otw_buff, +    const otw_type_t &otw_type, +    size_t nsamps_per_io_buff +); + +/*! + * Convert OTW samples to IO samples. + * + * \param otw_buff memory containing samples + * \param otw_type the type of these samples + * \param io_buff memory to write converted samples + * \param io_type the type of these samples + * \param num_samps the number of samples in io_buff + */ +UHD_API void convert_otw_type_to_io_type( +    const void *otw_buff, const otw_type_t &otw_type, +    void *io_buff, const io_type_t &io_type, +    size_t num_samps +); + +/*! + * Convert OTW samples to IO samples + de-interleave. + * + * \param otw_buff memory containing samples + * \param otw_type the type of these samples + * \param io_buffs buffers to write converted samples + * \param io_type the type of these samples + * \param nsamps_per_io_buff samples per io_buff + */ +UHD_API void convert_otw_type_to_io_type( +    const void *otw_buff, +    const otw_type_t &otw_type, +    std::vector<void *> &io_buffs, +    const io_type_t &io_type, +    size_t nsamps_per_io_buff +); + +}} //namespace + +#include <uhd/transport/convert_types.ipp> + +#endif /* INCLUDED_UHD_TRANSPORT_CONVERT_TYPES_HPP */ diff --git a/host/include/uhd/transport/convert_types.ipp b/host/include/uhd/transport/convert_types.ipp new file mode 100644 index 000000000..914ca6f17 --- /dev/null +++ b/host/include/uhd/transport/convert_types.ipp @@ -0,0 +1,43 @@ +// +// Copyright 2010 Ettus Research LLC +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program.  If not, see <http://www.gnu.org/licenses/>. +// + +#ifndef INCLUDED_UHD_TRANSPORT_CONVERT_TYPES_IPP +#define INCLUDED_UHD_TRANSPORT_CONVERT_TYPES_IPP + +UHD_INLINE void uhd::transport::convert_io_type_to_otw_type( +    const void *io_buff, const io_type_t &io_type, +    void *otw_buff, const otw_type_t &otw_type, +    size_t num_samps +){ +    std::vector<const void *> buffs(1, io_buff); +    return uhd::transport::convert_io_type_to_otw_type( +        buffs, io_type, otw_buff, otw_type, num_samps +    ); +} + +UHD_INLINE void uhd::transport::convert_otw_type_to_io_type( +    const void *otw_buff, const otw_type_t &otw_type, +    void *io_buff, const io_type_t &io_type, +    size_t num_samps +){ +    std::vector<void *> buffs(1, io_buff); +    return uhd::transport::convert_otw_type_to_io_type( +        otw_buff, otw_type, buffs, io_type, num_samps +    ); +} + +#endif /* INCLUDED_UHD_TRANSPORT_CONVERT_TYPES_IPP */ diff --git a/host/include/uhd/transport/if_addrs.hpp b/host/include/uhd/transport/if_addrs.hpp new file mode 100644 index 000000000..fbbb35e1d --- /dev/null +++ b/host/include/uhd/transport/if_addrs.hpp @@ -0,0 +1,47 @@ +// +// 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_IFADDRS_HPP +#define INCLUDED_UHD_IFADDRS_HPP + +#include <uhd/config.hpp> +#include <string> +#include <vector> + +namespace uhd{ namespace transport{ + +    /*! +     * The address for a network interface. +     */ +    struct UHD_API if_addrs_t{ +        std::string inet; +        std::string mask; +        std::string bcast; +        if_addrs_t(void); +    }; + +    /*! +     * Get a list of network interface addresses. +     * The internal implementation is system-dependent. +     * \return a vector of if addrs +     */ +    UHD_API std::vector<if_addrs_t> get_if_addrs(void); + +}} //namespace + + +#endif /* INCLUDED_UHD_IFADDRS_HPP */ diff --git a/host/include/uhd/transport/udp_simple.hpp b/host/include/uhd/transport/udp_simple.hpp new file mode 100644 index 000000000..c84393ecf --- /dev/null +++ b/host/include/uhd/transport/udp_simple.hpp @@ -0,0 +1,84 @@ +// +// Copyright 2010 Ettus Research LLC +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program.  If not, see <http://www.gnu.org/licenses/>. +// + +#ifndef INCLUDED_UHD_TRANSPORT_UDP_SIMPLE_HPP +#define INCLUDED_UHD_TRANSPORT_UDP_SIMPLE_HPP + +#include <uhd/config.hpp> +#include <boost/asio/buffer.hpp> +#include <boost/utility.hpp> +#include <boost/shared_ptr.hpp> + +namespace uhd{ namespace transport{ + +class UHD_API udp_simple : boost::noncopyable{ +public: +    typedef boost::shared_ptr<udp_simple> sptr; + +    //! The maximum number of bytes per udp packet. +    static const size_t mtu = 1500 - 20 - 8; //default ipv4 mtu - ipv4 header - udp header + +    /*! +     * Make a new connected udp transport: +     * This transport is for sending and receiving +     * between this host and a single endpoint. +     * The primary usage for this transport will be control transactions. +     * The underlying implementation is simple and portable (not fast). +     * +     * The address will be resolved, it can be a host name or ipv4. +     * The port will be resolved, it can be a port type or number. +     * +     * \param addr a string representing the destination address +     * \param port a string representing the destination port +     */ +    static sptr make_connected(const std::string &addr, const std::string &port); + +    /*! +     * Make a new broadcasting udp transport: +     * This transport can send udp broadcast datagrams +     * and receive datagrams from multiple sources. +     * The primary usage for this transport will be to discover devices. +     * +     * The address will be resolved, it can be a host name or ipv4. +     * The port will be resolved, it can be a port type or number. +     * +     * \param addr a string representing the destination address +     * \param port a string representing the destination port +     */ +    static sptr make_broadcast(const std::string &addr, const std::string &port); + +    /*! +     * Send a single buffer. +     * Blocks until the data is sent. +     * \param buff single asio buffer +     * \return the number of bytes sent +     */ +    virtual size_t send(const boost::asio::const_buffer &buff) = 0; + +    /*! +     * Receive into the provided buffer. +     * Blocks until data is received or a timeout occurs. +     * \param buff a mutable buffer to receive into +     * \param timeout_ms the timeout in milliseconds +     * \return the number of bytes received or zero on timeout +     */ +    virtual size_t recv(const boost::asio::mutable_buffer &buff, size_t timeout_ms) = 0; +}; + +}} //namespace + +#endif /* INCLUDED_UHD_TRANSPORT_UDP_SIMPLE_HPP */ diff --git a/host/include/uhd/transport/udp_zero_copy.hpp b/host/include/uhd/transport/udp_zero_copy.hpp new file mode 100644 index 000000000..bbba97b21 --- /dev/null +++ b/host/include/uhd/transport/udp_zero_copy.hpp @@ -0,0 +1,65 @@ +// +// Copyright 2010 Ettus Research LLC +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program.  If not, see <http://www.gnu.org/licenses/>. +// + +#ifndef INCLUDED_UHD_TRANSPORT_UDP_ZERO_COPY_HPP +#define INCLUDED_UHD_TRANSPORT_UDP_ZERO_COPY_HPP + +#include <uhd/config.hpp> +#include <uhd/transport/zero_copy.hpp> +#include <uhd/types/device_addr.hpp> +#include <boost/shared_ptr.hpp> + +namespace uhd{ namespace transport{ + +/*! + * A zero copy udp transport provides an efficient way to handle data. + * by avoiding the extra copy when recv() or send() is called on the socket. + * Rather, the zero copy transport gives the caller memory references. + * The caller informs the transport when it is finished with the reference. + * + * On linux systems, the zero copy transport can use a kernel packet ring. + * If no platform specific solution is available, make returns a boost asio + * implementation that wraps the functionality around a standard send/recv calls. + */ +class UHD_API udp_zero_copy : public virtual zero_copy_if{ +public: +    typedef boost::shared_ptr<udp_zero_copy> sptr; + +    /*! +     * Make a new zero copy udp transport: +     * This transport is for sending and receiving +     * between this host and a single endpoint. +     * The primary usage for this transport will be data transactions. +     * The underlying implementation is fast and platform specific. +     * +     * The address will be resolved, it can be a host name or ipv4. +     * The port will be resolved, it can be a port type or number. +     * +     * \param addr a string representing the destination address +     * \param port a string representing the destination port +     * \param hints optional parameters to pass to the underlying transport +     */ +    static sptr make( +        const std::string &addr, +        const std::string &port, +        const device_addr_t &hints = device_addr_t() +    ); +}; + +}} //namespace + +#endif /* INCLUDED_UHD_TRANSPORT_UDP_ZERO_COPY_HPP */ diff --git a/host/include/uhd/transport/usb_control.hpp b/host/include/uhd/transport/usb_control.hpp new file mode 100644 index 000000000..e6c32f78e --- /dev/null +++ b/host/include/uhd/transport/usb_control.hpp @@ -0,0 +1,65 @@ +// +// Copyright 2010 Ettus Research LLC +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program.  If not, see <http://www.gnu.org/licenses/>. +// + +#ifndef INCLUDED_UHD_TRANSPORT_USB_CONTROL_HPP +#define INCLUDED_UHD_TRANSPORT_USB_CONTROL_HPP + +#include <uhd/transport/usb_device_handle.hpp> + +namespace uhd { namespace transport { + +class UHD_API usb_control : boost::noncopyable { +public: +    typedef boost::shared_ptr<usb_control> sptr; + +    /*! +     * Create a new usb control transport: +     * This transport is for sending and receiving control information from +     * the host to device using the Default Control Pipe. +     * +     * \param handle a device handle that uniquely identifies a USB device +     */ +    static sptr make(usb_device_handle::sptr handle); + +    /*! +     * Submit a USB device request: +     * Blocks until the request returns +     * +     * For format and corresponding USB request fields +     * see USB Specification Revision 2.0 - 9.3 USB Device Requests +     * +     * Usage is device specific +     * +     * \param request_type 1-byte bitmask (bmRequestType) +     * \param request      1-byte (bRequest) +     * \param value        2-byte (wValue) +     * \param index        2-byte (wIndex) +     * \param buff         buffer to hold send or receive data +     * \param length       2-byte (wLength) +     * \return             number of bytes submitted or error code +     */ +    virtual ssize_t submit(boost::uint8_t request_type, +                          boost::uint8_t request, +                          boost::uint16_t value, +                          boost::uint16_t index,  +                          unsigned char *buff, +                          boost::uint16_t length) = 0;  +}; + +}} //namespace + +#endif /* INCLUDED_UHD_TRANSPORT_USB_CONTROL_HPP */ diff --git a/host/include/uhd/transport/usb_device_handle.hpp b/host/include/uhd/transport/usb_device_handle.hpp new file mode 100644 index 000000000..6f8d868be --- /dev/null +++ b/host/include/uhd/transport/usb_device_handle.hpp @@ -0,0 +1,73 @@ +// +// Copyright 2010 Ettus Research LLC +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program.  If not, see <http://www.gnu.org/licenses/>. +// + +#ifndef INCLUDED_UHD_TRANSPORT_USB_DEVICE_HANDLE_HPP +#define INCLUDED_UHD_TRANSPORT_USB_DEVICE_HANDLE_HPP + +#include <uhd/config.hpp> +#include <boost/utility.hpp> +#include <boost/shared_ptr.hpp> +#include <boost/cstdint.hpp> +#include <vector> + +namespace uhd { namespace transport { + +/*! + * Device handle class that represents a USB device + * Used for identifying devices on the USB bus and selecting which device is + * used when creating a  USB transport. A minimal subset of USB descriptor + * fields are used. Fields can be found in the USB 2.0 specification Table + * 9-8 (Standard Device Descriptor). In addition to fields of the device + * descriptor, the interface returns the device's USB device address. + * + * Note: The USB 2.0 Standard Device Descriptor contains an index rather then + *       a true descriptor serial number string. This interface returns the + *       actual string descriptor. + */ +class UHD_API usb_device_handle : boost::noncopyable { +public: +    typedef boost::shared_ptr<usb_device_handle> sptr; + +    /*! +     * Return the device's serial number  +     * \return a string describing the device's serial number +     */ +    virtual std::string get_serial() const = 0; + +    /*! +     * Return the device's Vendor ID (usually assigned by the USB-IF) +     * \return a Vendor ID +     */ +    virtual boost::uint16_t get_vendor_id() const = 0; + +    /*! +     * Return the device's Product ID (usually assigned by manufacturer) +     * \return a Product ID +     */ +    virtual boost::uint16_t get_product_id() const = 0; + +    /*! +     * Return a vector of USB devices on this host  +     * \return a vector of USB device handles that match vid and pid +     */ +    static std::vector<usb_device_handle::sptr> get_device_list(boost::uint16_t vid, boost::uint16_t pid); + +}; //namespace usb + +}} //namespace + +#endif /* INCLUDED_UHD_TRANSPORT_USB_DEVICE_HANDLE_HPP */ diff --git a/host/include/uhd/transport/usb_zero_copy.hpp b/host/include/uhd/transport/usb_zero_copy.hpp new file mode 100644 index 000000000..b39171fba --- /dev/null +++ b/host/include/uhd/transport/usb_zero_copy.hpp @@ -0,0 +1,63 @@ +// +// Copyright 2010 Ettus Research LLC +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program.  If not, see <http://www.gnu.org/licenses/>. +// + +#ifndef INCLUDED_UHD_TRANSPORT_USB_ZERO_COPY_HPP +#define INCLUDED_UHD_TRANSPORT_USB_ZERO_COPY_HPP + +#include <uhd/transport/usb_device_handle.hpp> +#include <uhd/transport/zero_copy.hpp> +#include <uhd/types/device_addr.hpp> + +namespace uhd { namespace transport { + +/*! + * A zero copy usb transport provides an efficient way to handle data. + * by avoiding the extra copy when recv() or send() is called on the handle. + * Rather, the zero copy transport gives the caller memory references. + * The caller informs the transport when it is finished with the reference. + * + * On linux systems, the zero copy transport can use a kernel packet ring. + * If no platform specific solution is available, make returns a boost asio + * implementation that wraps functionality around standard send/recv calls. + */ +class UHD_API usb_zero_copy : public virtual zero_copy_if { +public: +    typedef boost::shared_ptr<usb_zero_copy> sptr; + +    /*! +     * Make a new zero copy usb transport: +     * This transport is for sending and receiving between the host +     * and a pair of USB bulk transfer endpoints. +     * The primary usage for this transport is data transactions. +     * The underlying implementation may be platform specific. +     * +     * \param handle a device handle that uniquely identifying the device +     * \param recv_endpoint an integer specifiying an IN endpoint number +     * \param send_endpoint an integer specifiying an OUT endpoint number +     * \param hints optional parameters to pass to the underlying transport +     */ +    static sptr make( +        usb_device_handle::sptr handle, +        size_t recv_endpoint, +        size_t send_endpoint, +        const device_addr_t &hints = device_addr_t() +    ); +}; + +}} //namespace + +#endif /* INCLUDED_UHD_TRANSPORT_USB_ZERO_COPY_HPP */ diff --git a/host/include/uhd/transport/vrt_if_packet.hpp b/host/include/uhd/transport/vrt_if_packet.hpp new file mode 100644 index 000000000..51bd81bb1 --- /dev/null +++ b/host/include/uhd/transport/vrt_if_packet.hpp @@ -0,0 +1,106 @@ +// +// Copyright 2010 Ettus Research LLC +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program.  If not, see <http://www.gnu.org/licenses/>. +// + +#ifndef INCLUDED_UHD_TRANSPORT_VRT_IF_PACKET_HPP +#define INCLUDED_UHD_TRANSPORT_VRT_IF_PACKET_HPP + +#include <uhd/config.hpp> +#include <boost/cstdint.hpp> +#include <cstddef> //size_t + +namespace uhd{ namespace transport{ + +namespace vrt{ + +    //! The maximum number of 32-bit words in a vrt if packet header +    static const size_t max_if_hdr_words32 = 7; //hdr+sid+cid+tsi+tsf + +    /*! +     * Definition for fields that can be packed into a vrt if header. +     * The size fields are used for input and output depending upon +     * the operation used (ie the pack or unpack function call). +     */ +    struct UHD_API if_packet_info_t{ +        //packet type (pack only supports data) +        enum packet_type_t { +            PACKET_TYPE_DATA      = 0x0, +            PACKET_TYPE_EXTENSION = 0x1, +            PACKET_TYPE_CONTEXT   = 0x2 +        } packet_type; + +        //size fields +        size_t num_payload_words32; //required in pack, derived in unpack +        size_t num_header_words32;  //derived in pack, derived in unpack +        size_t num_packet_words32;  //derived in pack, required in unpack + +        //header fields +        size_t packet_count; +        bool sob, eob; + +        //optional fields +        bool has_sid; boost::uint32_t sid; +        bool has_cid; boost::uint64_t cid; +        bool has_tsi; boost::uint32_t tsi; +        bool has_tsf; boost::uint64_t tsf; +        bool has_tlr; boost::uint32_t tlr; +    }; + +    /*! +     * Pack a vrt header from metadata (big endian format). +     * \param packet_buff memory to write the packed vrt header +     * \param if_packet_info the if packet info (read/write) +     */ +    UHD_API void if_hdr_pack_be( +        boost::uint32_t *packet_buff, +        if_packet_info_t &if_packet_info +    ); + +    /*! +     * Unpack a vrt header to metadata (big endian format). +     * \param packet_buff memory to read the packed vrt header +     * \param if_packet_info the if packet info (read/write) +     */ +    UHD_API void if_hdr_unpack_be( +        const boost::uint32_t *packet_buff, +        if_packet_info_t &if_packet_info +    ); + +    /*! +     * Pack a vrt header from metadata (little endian format). +     * \param packet_buff memory to write the packed vrt header +     * \param if_packet_info the if packet info (read/write) +     */ +    UHD_API void if_hdr_pack_le( +        boost::uint32_t *packet_buff, +        if_packet_info_t &if_packet_info +    ); + +    /*! +     * Unpack a vrt header to metadata (little endian format). +     * \param packet_buff memory to read the packed vrt header +     * \param if_packet_info the if packet info (read/write) +     */ +    UHD_API void if_hdr_unpack_le( +        const boost::uint32_t *packet_buff, +        if_packet_info_t &if_packet_info +    ); + +} //namespace vrt + +}} //namespace + +#endif /* INCLUDED_UHD_TRANSPORT_VRT_IF_PACKET_HPP */ diff --git a/host/include/uhd/transport/zero_copy.hpp b/host/include/uhd/transport/zero_copy.hpp new file mode 100644 index 000000000..7d8fb4b83 --- /dev/null +++ b/host/include/uhd/transport/zero_copy.hpp @@ -0,0 +1,196 @@ +// +// Copyright 2010 Ettus Research LLC +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program.  If not, see <http://www.gnu.org/licenses/>. +// + +#ifndef INCLUDED_UHD_TRANSPORT_ZERO_COPY_HPP +#define INCLUDED_UHD_TRANSPORT_ZERO_COPY_HPP + +#include <uhd/config.hpp> +#include <boost/asio/buffer.hpp> +#include <boost/utility.hpp> +#include <boost/shared_ptr.hpp> +#include <boost/function.hpp> + +namespace uhd{ namespace transport{ + +    /*! +     * A managed receive buffer: +     * Contains a reference to transport-managed memory, +     * and a method to release the memory after reading. +     */ +    class UHD_API managed_recv_buffer : boost::noncopyable{ +    public: +        typedef boost::shared_ptr<managed_recv_buffer> sptr; +        typedef boost::function<void(void)> release_fcn_t; + +        /*! +         * Make a safe managed receive buffer: +         * A safe managed buffer ensures that release is called once, +         * either by the user or automatically upon deconstruction. +         * \param buff a reference to the constant buffer +         * \param release_fcn callback to release the memory +         * \return a new managed receive buffer +         */ +        static sptr make_safe( +            const boost::asio::const_buffer &buff, +            const release_fcn_t &release_fcn +        ); + +        /*! +         * Signal to the transport that we are done with the buffer. +         * This should be called to release the buffer to the transport object. +         * After calling, the referenced memory should be considered invalid. +         */ +        virtual void release(void) = 0; + +        /*! +         * Get the size of the underlying buffer. +         * \return the number of bytes +         */ +        inline size_t size(void) const{ +            return boost::asio::buffer_size(this->get()); +        } + +        /*! +         * Get a pointer to the underlying buffer. +         * \return a pointer into memory +         */ +        template <class T> inline T cast(void) const{ +            return boost::asio::buffer_cast<T>(this->get()); +        } + +    private: +        /*! +         * Get a reference to the internal const buffer. +         * The buffer has a reference to memory and a size. +         * \return a boost asio const buffer +         */ +        virtual const boost::asio::const_buffer &get(void) const = 0; +    }; + +    /*! +     * A managed send buffer: +     * Contains a reference to transport-managed memory, +     * and a method to commit the memory after writing. +     */ +    class UHD_API managed_send_buffer : boost::noncopyable{ +    public: +        typedef boost::shared_ptr<managed_send_buffer> sptr; +        typedef boost::function<void(size_t)> commit_fcn_t; + +        /*! +         * Make a safe managed send buffer: +         * A safe managed buffer ensures that commit is called once, +         * either by the user or automatically upon deconstruction. +         * In the later case, the deconstructor will call commit(0). +         * \param buff a reference to the mutable buffer +         * \param commit_fcn callback to commit the memory +         * \return a new managed send buffer +         */ +        static sptr make_safe( +            const boost::asio::mutable_buffer &buff, +            const commit_fcn_t &commit_fcn +        ); + +        /*! +         * Signal to the transport that we are done with the buffer. +         * This should be called to commit the write to the transport object. +         * After calling, the referenced memory should be considered invalid. +         * \param num_bytes the number of bytes written into the buffer +         */ +        virtual void commit(size_t num_bytes) = 0; + +        /*! +         * Get the size of the underlying buffer. +         * \return the number of bytes +         */ +        inline size_t size(void) const{ +            return boost::asio::buffer_size(this->get()); +        } + +        /*! +         * Get a pointer to the underlying buffer. +         * \return a pointer into memory +         */ +        template <class T> inline T cast(void) const{ +            return boost::asio::buffer_cast<T>(this->get()); +        } + +    private: +        /*! +         * Get a reference to the internal mutable buffer. +         * The buffer has a reference to memory and a size. +         * \return a boost asio mutable buffer +         */ +        virtual const boost::asio::mutable_buffer &get(void) const = 0; +    }; + +    /*! +     * A zero-copy interface for transport objects. +     * Provides a way to get send and receive buffers +     * with memory managed by the transport object. +     */ +    class UHD_API zero_copy_if : boost::noncopyable{ +    public: +        typedef boost::shared_ptr<zero_copy_if> sptr; + +        /*! +         * Get a new receive buffer from this transport object. +         * \param timeout the timeout to get the buffer in seconds +         * \return a managed buffer, or null sptr on timeout/error +         */ +        virtual managed_recv_buffer::sptr get_recv_buff(double timeout = 0.1) = 0; + +        /*! +         * Get the number of receive frames: +         * The number of simultaneous receive buffers in use. +         * \return number of frames +         */ +        virtual size_t get_num_recv_frames(void) const = 0; + +        /*! +         * Get the size of a receive frame: +         * The maximum capacity of a single receive buffer. +         * \return frame size in bytes +         */ +        virtual size_t get_recv_frame_size(void) const = 0; + +        /*! +         * Get a new send buffer from this transport object. +         * \param timeout the timeout to get the buffer in seconds +         * \return a managed buffer, or null sptr on timeout/error +         */ +        virtual managed_send_buffer::sptr get_send_buff(double timeout = 0.1) = 0; + +        /*! +         * Get the number of send frames: +         * The number of simultaneous send buffers in use. +         * \return number of frames +         */ +        virtual size_t get_num_send_frames(void) const = 0; + +        /*! +         * Get the size of a send frame: +         * The maximum capacity of a single send buffer. +         * \return frame size in bytes +         */ +        virtual size_t get_send_frame_size(void) const = 0; + +    }; + +}} //namespace + +#endif /* INCLUDED_UHD_TRANSPORT_ZERO_COPY_HPP */ diff --git a/host/include/uhd/types/CMakeLists.txt b/host/include/uhd/types/CMakeLists.txt new file mode 100644 index 000000000..a96976b5e --- /dev/null +++ b/host/include/uhd/types/CMakeLists.txt @@ -0,0 +1,35 @@ +# +# 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/>. +# + + +INSTALL(FILES +    clock_config.hpp +    device_addr.hpp +    dict.ipp +    dict.hpp +    io_type.hpp +    mac_addr.hpp +    metadata.hpp +    otw_type.hpp +    ranges.hpp +    serial.hpp +    stream_cmd.hpp +    time_spec.hpp +    tune_request.hpp +    tune_result.hpp +    DESTINATION ${INCLUDE_DIR}/uhd/types +) diff --git a/host/include/uhd/types/clock_config.hpp b/host/include/uhd/types/clock_config.hpp new file mode 100644 index 000000000..9342fbb7b --- /dev/null +++ b/host/include/uhd/types/clock_config.hpp @@ -0,0 +1,51 @@ +// +// Copyright 2010 Ettus Research LLC +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program.  If not, see <http://www.gnu.org/licenses/>. +// + +#ifndef INCLUDED_UHD_TYPES_CLOCK_CONFIG_HPP +#define INCLUDED_UHD_TYPES_CLOCK_CONFIG_HPP + +#include <uhd/config.hpp> + +namespace uhd{ + +    /*! +     * Clock configuration settings: +     * The source for the 10MHz reference clock. +     * The source and polarity for the PPS clock. +     */ +    struct UHD_API clock_config_t{ +        enum ref_source_t { +            REF_AUTO = 'a', //automatic (device specific) +            REF_INT  = 'i', //internal reference +            REF_SMA  = 's', //external sma port +            REF_MIMO = 'm'  //mimo cable (usrp2 only) +        } ref_source; +        enum pps_source_t { +            PPS_INT  = 'i', //there is no internal +            PPS_SMA  = 's', //external sma port +            PPS_MIMO = 'm'  //mimo cable (usrp2 only) +        } pps_source; +        enum pps_polarity_t { +            PPS_NEG = 'n', //negative edge +            PPS_POS = 'p'  //positive edge +        } pps_polarity; +        clock_config_t(void); +    }; + +} //namespace uhd + +#endif /* INCLUDED_UHD_TYPES_CLOCK_CONFIG_HPP */ diff --git a/host/include/uhd/types/device_addr.hpp b/host/include/uhd/types/device_addr.hpp new file mode 100644 index 000000000..eb3394230 --- /dev/null +++ b/host/include/uhd/types/device_addr.hpp @@ -0,0 +1,92 @@ +// +// Copyright 2010 Ettus Research LLC +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program.  If not, see <http://www.gnu.org/licenses/>. +// + +#ifndef INCLUDED_UHD_TYPES_DEVICE_ADDR_HPP +#define INCLUDED_UHD_TYPES_DEVICE_ADDR_HPP + +#include <uhd/config.hpp> +#include <uhd/types/dict.hpp> +#include <boost/lexical_cast.hpp> +#include <stdexcept> +#include <vector> +#include <string> + +namespace uhd{ + +    /*! +     * Mapping of key/value pairs for locating devices on the system. +     * When left empty, the device discovery routines will search +     * all available transports on the system (ethernet, usb...). +     * +     * To narrow down the discovery process to a particular device, +     * specify a transport key/value pair specific to your device. +     * - Ex, to find a usrp2: my_dev_addr["addr"] = [resolvable_hostname_or_ip] +     * +     * The device address can also be used to pass arguments into +     * the transport layer control to set (for example) buffer sizes. +     * +     * An arguments string, is a way to represent a device address +     * using a single string with delimiter characters. +     * - Ex: addr=192.168.10.2 +     * - Ex: addr=192.168.10.2, recv_buff_size=1e6 +     */ +    class UHD_API device_addr_t : public dict<std::string, std::string>{ +    public: +        /*! +         * Create a device address from an args string. +         * \param args the arguments string +         */ +        device_addr_t(const std::string &args = ""); + +        /*! +         * Convert a device address into a pretty print string. +         * \return a printable string representing the device address +         */ +        std::string to_pp_string(void) const; + +        /*! +         * Convert the device address into an args string. +         * The args string contains delimiter symbols. +         * \return a string with delimiter markup +         */ +        std::string to_string(void) const; + +        /*! +         * Lexically cast a parameter to the specified type, +         * or use the default value if the key is not found. +         * \param key the key as one of the address parameters +         * \param def the value to use when key is not present +         * \return the casted value as type T or the default +         * \throw error when the parameter cannot be casted +         */ +        template <typename T> T cast(const std::string &key, const T &def) const{ +            if (not this->has_key(key)) return def; +            try{ +                return boost::lexical_cast<T>((*this)[key]); +            } +            catch(const boost::bad_lexical_cast &){ +                throw std::runtime_error("cannot cast " + key + " = " + (*this)[key]); +            } +        } +    }; + +    //handy typedef for a vector of device addresses +    typedef std::vector<device_addr_t> device_addrs_t; + +} //namespace uhd + +#endif /* INCLUDED_UHD_TYPES_DEVICE_ADDR_HPP */ diff --git a/host/include/uhd/types/dict.hpp b/host/include/uhd/types/dict.hpp new file mode 100644 index 000000000..b14fc5425 --- /dev/null +++ b/host/include/uhd/types/dict.hpp @@ -0,0 +1,107 @@ +// +// Copyright 2010 Ettus Research LLC +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program.  If not, see <http://www.gnu.org/licenses/>. +// + +#ifndef INCLUDED_UHD_TYPES_DICT_HPP +#define INCLUDED_UHD_TYPES_DICT_HPP + +#include <uhd/config.hpp> +#include <vector> +#include <list> + +namespace uhd{ + +    /*! +     * A templated dictionary class with a python-like interface. +     */ +    template <typename Key, typename Val> class dict{ +    public: +        /*! +         * Create a new empty dictionary. +         */ +        dict(void); + +        /*! +         * Input iterator constructor: +         * Makes boost::assign::map_list_of work. +         * \param first the begin iterator +         * \param last the end iterator +         */ +        template <typename InputIterator> +        dict(InputIterator first, InputIterator last); + +        /*! +         * Get the number of elements in this dict. +         * \return the number of elements +         */ +        std::size_t size(void) const; + +        /*! +         * Get a list of the keys in this dict. +         * Key order depends on insertion precedence. +         * \return vector of keys +         */ +        const std::vector<Key> keys(void) const; + +        /*! +         * Get a list of the values in this dict. +         * Value order depends on insertion precedence. +         * \return vector of values +         */ +        const std::vector<Val> vals(void) const; + +        /*! +         * Does the dictionary contain this key? +         * \param key the key to look for +         * \return true if found +         */ +        bool has_key(const Key &key) const; + +        /*! +         * Get a value for the given key if it exists. +         * If the key is not found throw an error. +         * \param key the key to look for +         * \return the value at the key +         * \throw an exception when not found +         */ +        const Val &operator[](const Key &key) const; + +        /*! +         * Set a value for the given key, however, in reality +         * it really returns a reference which can be assigned to. +         * \param key the key to set to +         * \return a reference to the value +         */ +        Val &operator[](const Key &key); + +        /*! +         * Pop an item out of the dictionary. +         * \param key the item key +         * \return the value of the item +         * \throw an exception when not found +         */ +        Val pop(const Key &key); + +    private: +        typedef std::pair<Key, Val> pair_t; +        std::list<pair_t> _map; //private container +    }; + +} //namespace uhd + +#include <uhd/types/dict.ipp> + +#endif /* INCLUDED_UHD_TYPES_DICT_HPP */ diff --git a/host/include/uhd/types/dict.ipp b/host/include/uhd/types/dict.ipp new file mode 100644 index 000000000..85071e6fd --- /dev/null +++ b/host/include/uhd/types/dict.ipp @@ -0,0 +1,120 @@ +// +// Copyright 2010 Ettus Research LLC +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program.  If not, see <http://www.gnu.org/licenses/>. +// + +#ifndef INCLUDED_UHD_TYPES_DICT_IPP +#define INCLUDED_UHD_TYPES_DICT_IPP + +#include <boost/foreach.hpp> +#include <boost/format.hpp> +#include <boost/lexical_cast.hpp> +#include <stdexcept> +#include <typeinfo> + +namespace uhd{ + +    namespace /*anon*/{ +        template<typename Key, typename Val> +        struct UHD_API key_not_found: std::out_of_range{ +            key_not_found(const Key &key): std::out_of_range( +                str(boost::format( +                    "key \"%s\" not found in dict(%s, %s)" +                    ) % boost::lexical_cast<std::string>(key) +                    % typeid(Key).name() % typeid(Val).name() +                ) +            ){ +                /* NOP */ +            } +        }; +    } // namespace /*anon*/ + +    template <typename Key, typename Val> +    dict<Key, Val>::dict(void){ +        /* NOP */ +    } + +    template <typename Key, typename Val> +    template <typename InputIterator> +    dict<Key, Val>::dict(InputIterator first, InputIterator last){ +        for(InputIterator it = first; it != last; it++){ +            _map.push_back(*it); +        } +    } + +    template <typename Key, typename Val> +    std::size_t dict<Key, Val>::size(void) const{ +        return _map.size(); +    } + +    template <typename Key, typename Val> +    const std::vector<Key> dict<Key, Val>::keys(void) const{ +        std::vector<Key> keys; +        BOOST_FOREACH(const pair_t &p, _map){ +            keys.push_back(p.first); +        } +        return keys; +    } + +    template <typename Key, typename Val> +    const std::vector<Val> dict<Key, Val>::vals(void) const{ +        std::vector<Val> vals; +        BOOST_FOREACH(const pair_t &p, _map){ +            vals.push_back(p.second); +        } +        return vals; +    } + +    template <typename Key, typename Val> +    bool dict<Key, Val>::has_key(const Key &key) const{ +        BOOST_FOREACH(const pair_t &p, _map){ +            if (p.first == key) return true; +        } +        return false; +    } + +    template <typename Key, typename Val> +    const Val &dict<Key, Val>::operator[](const Key &key) const{ +        BOOST_FOREACH(const pair_t &p, _map){ +            if (p.first == key) return p.second; +        } +        throw key_not_found<Key, Val>(key); +    } + +    template <typename Key, typename Val> +    Val &dict<Key, Val>::operator[](const Key &key){ +        BOOST_FOREACH(pair_t &p, _map){ +            if (p.first == key) return p.second; +        } +        _map.push_back(std::make_pair(key, Val())); +        return _map.back().second; +    } + +    template <typename Key, typename Val> +    Val dict<Key, Val>::pop(const Key &key){ +        typename std::list<pair_t>::iterator it; +        for (it = _map.begin(); it != _map.end(); it++){ +            if (it->first == key){ +                Val val = it->second; +                _map.erase(it); +                return val; +            } +        } +        throw key_not_found<Key, Val>(key); +    } + +} //namespace uhd + +#endif /* INCLUDED_UHD_TYPES_DICT_IPP */ diff --git a/host/include/uhd/types/io_type.hpp b/host/include/uhd/types/io_type.hpp new file mode 100644 index 000000000..5176374d6 --- /dev/null +++ b/host/include/uhd/types/io_type.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/>. +// + +#ifndef INCLUDED_UHD_TYPES_IO_TYPE_HPP +#define INCLUDED_UHD_TYPES_IO_TYPE_HPP + +#include <uhd/config.hpp> + +namespace uhd{ + +    /*! +     * The Input/Output configuration struct: +     * Used to specify the IO type with device send/recv. +     */ +    class UHD_API io_type_t{ +    public: + +        /*! +         * Built in IO types known to the system. +         */ +        enum tid_t{ +            CUSTOM_TYPE =     '?', +            COMPLEX_FLOAT32 = 'f', +            COMPLEX_INT16 =   's', +            COMPLEX_INT8 =    'b' +        }; + +        /*! +         * The size of this io type in bytes. +         */ +        const size_t size; + +        /*! +         * The type id of this io type. +         * Good for using with switch statements. +         */ +        const tid_t tid; + +        /*! +         * Create an io type from a built-in type id. +         * \param tid a type id known to the system +         */ +        io_type_t(tid_t tid); + +        /*! +         * Create an io type from attributes. +         * The tid will be set to custom. +         * \param size the size in bytes +         */ +        io_type_t(size_t size); + +    }; + +} //namespace uhd + +#endif /* INCLUDED_UHD_TYPES_IO_TYPE_HPP */ diff --git a/host/include/uhd/types/mac_addr.hpp b/host/include/uhd/types/mac_addr.hpp new file mode 100644 index 000000000..0ced2e734 --- /dev/null +++ b/host/include/uhd/types/mac_addr.hpp @@ -0,0 +1,66 @@ +// +// Copyright 2010 Ettus Research LLC +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program.  If not, see <http://www.gnu.org/licenses/>. +// + +#ifndef INCLUDED_UHD_TYPES_MAC_ADDR_HPP +#define INCLUDED_UHD_TYPES_MAC_ADDR_HPP + +#include <uhd/config.hpp> +#include <uhd/types/serial.hpp> +#include <string> + +namespace uhd{ + +    /*! +    * Wrapper for an ethernet mac address. +    * Provides conversion between string and binary formats. +    */ +    class UHD_API mac_addr_t{ +    public: +        /*! +         * Create a mac address a byte array. +         * \param bytes a vector of bytes +         * \return a new mac address +         */ +        static mac_addr_t from_bytes(const byte_vector_t &bytes); + +        /*! +         * Create a mac address from a string. +         * \param mac_addr_str the string with delimiters +         * \return a new mac address +         */ +        static mac_addr_t from_string(const std::string &mac_addr_str); + +        /*! +         * Get the byte representation of the mac address. +         * \return a vector of bytes +         */ +        byte_vector_t to_bytes(void) const; + +        /*! +         * Get the string representation of this mac address. +         * \return a string with delimiters +         */ +        std::string to_string(void) const; + +    private: +        mac_addr_t(const byte_vector_t &bytes); //private constructor +        const byte_vector_t _bytes; //internal representation +    }; + +} //namespace uhd + +#endif /* INCLUDED_UHD_TYPES_MAC_ADDR_HPP */ diff --git a/host/include/uhd/types/metadata.hpp b/host/include/uhd/types/metadata.hpp new file mode 100644 index 000000000..3f250d13e --- /dev/null +++ b/host/include/uhd/types/metadata.hpp @@ -0,0 +1,152 @@ +// +// Copyright 2010 Ettus Research LLC +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program.  If not, see <http://www.gnu.org/licenses/>. +// + +#ifndef INCLUDED_UHD_TYPES_METADATA_HPP +#define INCLUDED_UHD_TYPES_METADATA_HPP + +#include <uhd/config.hpp> +#include <uhd/types/time_spec.hpp> + +namespace uhd{ + +    /*! +     * RX metadata structure for describing sent IF data. +     * Includes time specification, fragmentation flags, burst flags, and error codes. +     * The receive routines will convert IF data headers into metadata. +     */ +    struct UHD_API rx_metadata_t{ +        //! Has time specification? +        bool has_time_spec; + +        //! Time of the first sample. +        time_spec_t time_spec; + +        /*! +         * Fragmentation flag: +         * Similar to IPv4 fragmentation: http://en.wikipedia.org/wiki/IPv4#Fragmentation_and_reassembly +         * More fragments is true when the input buffer has insufficient size to fit +         * an entire received packet. More fragments will be false for the last fragment. +         */ +        bool more_fragments; + +        /*! +         * Fragmentation offset: +         * The fragment offset is the sample number at the start of the receive buffer. +         * For non-fragmented receives, the fragment offset should always be zero. +         */ +        size_t fragment_offset; + +        //! Start of burst will be true for the first packet in the chain. +        bool start_of_burst; + +        //! End of burst will be true for the last packet in the chain. +        bool end_of_burst; + +        /*! +         * The error condition on a receive call. +         * +         * Note: When an overrun occurs in continuous streaming mode, +         * the device will continue to send samples to the host. +         * For other streaming modes, streaming will discontinue +         * until the user issues a new stream command. +         * +         * The metadata fields have meaning for the following error codes: +         * - none +         * - late command +         * - broken chain +         * - overflow +         */ +        enum error_code_t { +            //! No error associated with this metadata. +            ERROR_CODE_NONE         = 0x0, +            //! No packet received, implementation timed-out. +            ERROR_CODE_TIMEOUT      = 0x1, +            //! A stream command was issued in the past. +            ERROR_CODE_LATE_COMMAND = 0x2, +            //! Expected another stream command. +            ERROR_CODE_BROKEN_CHAIN = 0x4, +            //! An internal receive buffer has filled. +            ERROR_CODE_OVERFLOW     = 0x8, +            //! The packet could not be parsed. +            ERROR_CODE_BAD_PACKET   = 0xf +        } error_code; +    }; + +    /*! +     * TX metadata structure for describing received IF data. +     * Includes time specification, and start and stop burst flags. +     * The send routines will convert the metadata to IF data headers. +     */ +    struct UHD_API tx_metadata_t{ +        /*! +         * Has time specification? +         * - Set false to send immediately. +         * - Set true to send at the time specified by time spec. +         */ +        bool has_time_spec; + +        //! When to send the first sample. +        time_spec_t time_spec; + +        //! Set start of burst to true for the first packet in the chain. +        bool start_of_burst; + +        //! Set end of burst to true for the last packet in the chain. +        bool end_of_burst; + +        /*! +         * The default constructor: +         * Sets the fields to default values (flags set to false). +         */ +        tx_metadata_t(void); +    }; + +    /*! +     * Async metadata structure for describing transmit related events. +     */ +    struct UHD_API async_metadata_t{ +        //! The channel number in a mimo configuration +        size_t channel; + +        //! Has time specification? +        bool has_time_spec; + +        //! When the async event occurred. +        time_spec_t time_spec; + +        /*! +         * The type of event for a receive async message call. +         */ +        enum event_code_t { +            //! A packet was successfully transmitted. +            EVENT_CODE_SUCCESS    = 0x1, +            //! An internal send buffer has emptied. +            EVENT_CODE_UNDERFLOW  = 0x2, +            //! Packet loss between host and device. +            EVENT_CODE_SEQ_ERROR  = 0x4, +            //! Packet had time that was late (or too early). +            EVENT_CODE_TIME_ERROR = 0x8, +            //! Underflow occurred inside a packet. +            EVENT_CODE_UNDERFLOW_IN_PACKET = 0x10, +            //! Packet loss within a burst. +            EVENT_CODE_SEQ_ERROR_IN_BURST  = 0x20 +        } event_code; +    }; + +} //namespace uhd + +#endif /* INCLUDED_UHD_TYPES_METADATA_HPP */ diff --git a/host/include/uhd/types/otw_type.hpp b/host/include/uhd/types/otw_type.hpp new file mode 100644 index 000000000..8e3e65d78 --- /dev/null +++ b/host/include/uhd/types/otw_type.hpp @@ -0,0 +1,69 @@ +// +// Copyright 2010 Ettus Research LLC +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program.  If not, see <http://www.gnu.org/licenses/>. +// + +#ifndef INCLUDED_UHD_TYPES_OTW_TYPE_HPP +#define INCLUDED_UHD_TYPES_OTW_TYPE_HPP + +#include <uhd/config.hpp> + +namespace uhd{ + +    /*! +     * Description for over-the-wire integers: +     * The DSP units in the FPGA deal with signed 16-bit integers. +     * The width and shift define the translation between OTW and DSP, +     * defined by the following relation: otw_int = dsp_int >> shift +     * +     * Note: possible combinations of width, shift, and byteorder +     * depend on the internals of the FPGA. Not all are supported! +     */ +    struct UHD_API otw_type_t{ + +        /*! +         * Width of an over-the-wire integer in bits. +         */ +        size_t width; //in bits + +        /*! +         * Shift of an over-the-wire integer in bits. +         * otw_int = dsp_int >> shift +         * dsp_int = otw_int << shift +         */ +        size_t shift; //in bits + +        /*! +         * Constants for byte order (borrowed from numpy's dtype) +         */ +        enum /*bo_t*/ { +            BO_NATIVE         = '=', +            BO_LITTLE_ENDIAN  = '<', +            BO_BIG_ENDIAN     = '>', +            BO_NOT_APPLICABLE = '|' +        } byteorder; + +        /*! +         * Get the sample size of this otw type. +         * \return the size of a sample in bytes +         */ +        size_t get_sample_size(void) const; + +        otw_type_t(void); +    }; + +} //namespace uhd + +#endif /* INCLUDED_UHD_TYPES_OTW_TYPE_HPP */ diff --git a/host/include/uhd/types/ranges.hpp b/host/include/uhd/types/ranges.hpp new file mode 100644 index 000000000..a2057d1c8 --- /dev/null +++ b/host/include/uhd/types/ranges.hpp @@ -0,0 +1,46 @@ +// +// Copyright 2010 Ettus Research LLC +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program.  If not, see <http://www.gnu.org/licenses/>. +// + +#ifndef INCLUDED_UHD_TYPES_RANGES_HPP +#define INCLUDED_UHD_TYPES_RANGES_HPP + +#include <uhd/config.hpp> + +namespace uhd{ + +    /*! +     * The gain range struct describes possible gain settings. +     * The mimumum gain, maximum gain, and step size are in dB. +     */ +    struct UHD_API gain_range_t{ +        float min, max, step; +        gain_range_t(float min = 0.0, float max = 0.0, float step = 0.0); +    }; + +    /*! +     * The frequency range struct describes possible frequency settings. +     * Because tuning is very granular (sub-Hz), step size is not listed. +     * The mimumum frequency and maximum frequency are in Hz. +     */ +    struct UHD_API freq_range_t{ +        double min, max; +        freq_range_t(double min = 0.0, double max = 0.0); +    }; + +} //namespace uhd + +#endif /* INCLUDED_UHD_TYPES_RANGES_HPP */ diff --git a/host/include/uhd/types/serial.hpp b/host/include/uhd/types/serial.hpp new file mode 100644 index 000000000..c134725f5 --- /dev/null +++ b/host/include/uhd/types/serial.hpp @@ -0,0 +1,122 @@ +// +// Copyright 2010 Ettus Research LLC +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program.  If not, see <http://www.gnu.org/licenses/>. +// + +#ifndef INCLUDED_UHD_TYPES_SERIAL_HPP +#define INCLUDED_UHD_TYPES_SERIAL_HPP + +#include <uhd/config.hpp> +#include <boost/cstdint.hpp> +#include <vector> + +namespace uhd{ + +    /*! +     * Byte vector typedef for passing data in and out of I2C interfaces. +     */ +    typedef std::vector<boost::uint8_t> byte_vector_t; + +    /*! +     * The i2c interface class: +     * Provides i2c and eeprom functionality. +     * A subclass should only have to implement the i2c routines. +     * An eeprom implementation comes for free with the interface. +     * +     * The eeprom routines are implemented on top of i2c. +     * The built in eeprom implementation only does single +     * byte reads and byte writes over the i2c interface, +     * so it should be portable across multiple eeproms. +     * Override the eeprom routines if this is not acceptable. +     */ +    class UHD_API i2c_iface{ +    public: +        /*! +         * Write bytes over the i2c. +         * \param addr the address +         * \param buf the vector of bytes +         */ +        virtual void write_i2c( +            boost::uint8_t addr, +            const byte_vector_t &buf +        ) = 0; + +        /*! +         * Read bytes over the i2c. +         * \param addr the address +         * \param num_bytes number of bytes to read +         * \return a vector of bytes +         */ +        virtual byte_vector_t read_i2c( +            boost::uint8_t addr, +            size_t num_bytes +        ) = 0; + +        /*! +         * Write bytes to an eeprom. +         * \param addr the address +         * \param offset byte offset +         * \param buf the vector of bytes +         */ +        virtual void write_eeprom( +            boost::uint8_t addr, +            boost::uint8_t offset, +            const byte_vector_t &buf +        ); + +        /*! +         * Read bytes from an eeprom. +         * \param addr the address +         * \param offset byte offset +         * \param num_bytes number of bytes to read +         * \return a vector of bytes +         */ +        virtual byte_vector_t read_eeprom( +            boost::uint8_t addr, +            boost::uint8_t offset, +            size_t num_bytes +        ); +    }; + +    /*! +     * The SPI configuration struct: +     * Used to configure a SPI transaction interface. +     */ +    struct UHD_API spi_config_t{ +        /*! +         * The edge type specifies when data is valid +         * relative to the edge of the serial clock. +         */ +        enum edge_t{ +            EDGE_RISE = 'r', +            EDGE_FALL = 'f' +        }; + +        //! on what edge is the mosi data valid? +        edge_t mosi_edge; + +        //! on what edge is the miso data valid? +        edge_t miso_edge; + +        /*! +         * Create a new spi config. +         * \param edge the default edge for mosi and miso +         */ +        spi_config_t(edge_t edge = EDGE_RISE); +    }; + +} //namespace uhd + +#endif /* INCLUDED_UHD_TYPES_SERIAL_HPP */ diff --git a/host/include/uhd/types/stream_cmd.hpp b/host/include/uhd/types/stream_cmd.hpp new file mode 100644 index 000000000..41708e2e2 --- /dev/null +++ b/host/include/uhd/types/stream_cmd.hpp @@ -0,0 +1,64 @@ +// +// Copyright 2010 Ettus Research LLC +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program.  If not, see <http://www.gnu.org/licenses/>. +// + +#ifndef INCLUDED_UHD_TYPES_STREAM_CMD_HPP +#define INCLUDED_UHD_TYPES_STREAM_CMD_HPP + +#include <uhd/config.hpp> +#include <uhd/types/time_spec.hpp> + +namespace uhd{ + +    /*! +     * Command struct for configuration and control of streaming: +     * +     * A stream command defines how the device sends samples to the host. +     * Streaming is controlled by submitting a stream command to the rx dsp. +     * Granular control over what the device streams to the host can be +     * achieved through submission of multiple (carefully-crafted) commands. +     * +     * The mode parameter controls how streaming is issued to the device: +     *   - "Start continuous" tells the device to stream samples indefinitely. +     *   - "Stop continuous" tells the device to end continuous streaming. +     *   - "Num samps and done" tells the device to stream num samps and +     *      to not expect a future stream command for contiguous samples. +     *   - "Num samps and more" tells the device to stream num samps and +     *      to expect a future stream command for contiguous samples. +     * +     * The stream now parameter controls when the stream begins. +     * When true, the device will begin streaming ASAP. When false, +     * the device will begin streaming at a time specified by time_spec. +     */ +    struct UHD_API stream_cmd_t{ + +        enum stream_mode_t { +            STREAM_MODE_START_CONTINUOUS   = 'a', +            STREAM_MODE_STOP_CONTINUOUS    = 'o', +            STREAM_MODE_NUM_SAMPS_AND_DONE = 'd', +            STREAM_MODE_NUM_SAMPS_AND_MORE = 'm' +        } stream_mode; +        size_t num_samps; + +        bool stream_now; +        time_spec_t time_spec; + +        stream_cmd_t(const stream_mode_t &stream_mode); +    }; + +} //namespace uhd + +#endif /* INCLUDED_UHD_TYPES_STREAM_CMD_HPP */ diff --git a/host/include/uhd/types/time_spec.hpp b/host/include/uhd/types/time_spec.hpp new file mode 100644 index 000000000..57d002d48 --- /dev/null +++ b/host/include/uhd/types/time_spec.hpp @@ -0,0 +1,110 @@ +// +// Copyright 2010 Ettus Research LLC +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program.  If not, see <http://www.gnu.org/licenses/>. +// + +#ifndef INCLUDED_UHD_TYPES_TIME_SPEC_HPP +#define INCLUDED_UHD_TYPES_TIME_SPEC_HPP + +#include <uhd/config.hpp> +#include <boost/operators.hpp> +#include <ctime> + +namespace uhd{ + +    /*! +     * A time_spec_t holds a seconds and a fractional seconds time value. +     * Depending upon usage, the time_spec_t can represent absolute times, +     * relative times, or time differences (between absolute times). +     * +     * The time_spec_t provides clock-domain independent time storage, +     * but can convert fractional seconds to/from clock-domain specific units. +     * +     * The fractional seconds are stored as double precision floating point. +     * This gives the fractional seconds enough precision to unambiguously +     * specify a clock-tick/sample-count up to rates of several petahertz. +     */ +    class UHD_API time_spec_t : boost::additive<time_spec_t>, boost::totally_ordered<time_spec_t>{ +    public: + +        /*! +         * Create a time_spec_t from a real-valued seconds count. +         * \param secs the real-valued seconds count (default = 0) +         */ +        time_spec_t(double secs = 0); + +        /*! +         * Create a time_spec_t from whole and fractional seconds. +         * \param full_secs the whole/integer seconds count +         * \param frac_secs the fractional seconds count (default = 0) +         */ +        time_spec_t(time_t full_secs, double frac_secs = 0); + +        /*! +         * Create a time_spec_t from whole and fractional seconds. +         * Translation from clock-domain specific units. +         * \param full_secs the whole/integer seconds count +         * \param tick_count the fractional seconds tick count +         * \param tick_rate the number of ticks per second +         */ +        time_spec_t(time_t full_secs, long tick_count, double tick_rate); + +        /*! +         * Convert the fractional seconds to clock ticks. +         * Translation into clock-domain specific units. +         * \param tick_rate the number of ticks per second +         * \return the fractional seconds tick count +         */ +        long get_tick_count(double tick_rate) const; + +        /*! +         * Get the time as a real-valued seconds count. +         * Note: If this time_spec_t represents an absolute time, +         * the precision of the fractional seconds may be lost. +         * \return the real-valued seconds +         */ +        double get_real_secs(void) const; + +        /*! +         * Get the whole/integer part of the time in seconds. +         * \return the whole/integer seconds +         */ +        time_t get_full_secs(void) const; + +        /*! +         * Get the fractional part of the time in seconds. +         * \return the fractional seconds +         */ +        double get_frac_secs(void) const; + +        //! Implement addable interface +        time_spec_t &operator+=(const time_spec_t &); + +        //! Implement subtractable interface +        time_spec_t &operator-=(const time_spec_t &); + +    //private time storage details +    private: time_t _full_secs; double _frac_secs; +    }; + +    //! Implement equality_comparable interface +    UHD_API bool operator==(const time_spec_t &, const time_spec_t &); + +    //! Implement less_than_comparable interface +    UHD_API bool operator<(const time_spec_t &, const time_spec_t &); + +} //namespace uhd + +#endif /* INCLUDED_UHD_TYPES_TIME_SPEC_HPP */ diff --git a/host/include/uhd/types/tune_request.hpp b/host/include/uhd/types/tune_request.hpp new file mode 100644 index 000000000..942b93251 --- /dev/null +++ b/host/include/uhd/types/tune_request.hpp @@ -0,0 +1,95 @@ +// +// Copyright 2010 Ettus Research LLC +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program.  If not, see <http://www.gnu.org/licenses/>. +// + +#ifndef INCLUDED_UHD_TYPES_TUNE_REQUEST_HPP +#define INCLUDED_UHD_TYPES_TUNE_REQUEST_HPP + +#include <uhd/config.hpp> + +namespace uhd{ + +    /*! +     * A tune request instructs the implementation how to tune the RF chain. +     * The policies can be used to select automatic tuning or +     * fined control over the daughterboard IF and DSP tuning. +     * Not all combinations of policies are applicable. +     * Convenience constructors are supplied for most use cases. +     */ +    struct UHD_API tune_request_t{ +        /*! +         * Make a new tune request for a particular center frequency. +         * Use an automatic policy for the intermediate and DSP frequency +         * to tune the chain as close as possible to the target frequency. +         * \param target_freq the target frequency in Hz +         */ +        tune_request_t(double target_freq = 0); + +        /*! +         * Make a new tune request for a particular center frequency. +         * Use a manual policy for the intermediate frequency, +         * and an automatic policy for the DSP frequency, +         * to tune the chain as close as possible to the target frequency. +         * \param target_freq the target frequency in Hz +         * \param lo_off the LO offset frequency in Hz +         */ +        tune_request_t(double target_freq, double lo_off); + +        //! Policy options for tunable elements in the RF chain. +        enum policy_t { +            //! Do not set this argument, use current setting. +            POLICY_NONE   = 'N', +            //! Automatically determine the argument's value. +            POLICY_AUTO   = 'A', +            //! Use the argument's value for the setting. +            POLICY_MANUAL = 'M' +        }; + +        /*! +         * The target frequency of the overall chain in Hz. +         * Set this even if all policies are set to manual. +         */ +        double target_freq; + +        /*! +         * The policy for the intermediate frequency. +         * Automatic behavior: the target frequency + default LO offset. +         */ +        policy_t inter_freq_policy; + +        /*! +         * The intermediate frequency in Hz. +         * Set when the policy is set to manual. +         */ +        double inter_freq; + +        /*! +         * The policy for the DSP frequency. +         * Automatic behavior: the difference between the target and IF. +         */ +        policy_t dsp_freq_policy; + +        /*! +         * The DSP frequency in Hz. +         * Set when the policy is set to manual. +         */ +        double dsp_freq; + +    }; + +} //namespace uhd + +#endif /* INCLUDED_UHD_TYPES_TUNE_REQUEST_HPP */ diff --git a/host/include/uhd/types/tune_result.hpp b/host/include/uhd/types/tune_result.hpp new file mode 100644 index 000000000..9eebc161a --- /dev/null +++ b/host/include/uhd/types/tune_result.hpp @@ -0,0 +1,48 @@ +// +// Copyright 2010 Ettus Research LLC +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program.  If not, see <http://www.gnu.org/licenses/>. +// + +#ifndef INCLUDED_UHD_TYPES_TUNE_RESULT_HPP +#define INCLUDED_UHD_TYPES_TUNE_RESULT_HPP + +#include <uhd/config.hpp> +#include <string> + +namespace uhd{ + +    /*! +     * The tune result struct holds result of a 2-phase tuning: +     * The struct hold the result of tuning the dboard as +     * the target and actual intermediate frequency. +     * The struct hold the result of tuning the DSP as +     * the target and actual digital converter frequency. +     */ +    struct UHD_API tune_result_t{ +        double target_inter_freq; +        double actual_inter_freq; +        double target_dsp_freq; +        double actual_dsp_freq; + +        /*! +         * Create a pretty print string for this tune result struct. +         * \return the printable string +         */ +        std::string to_pp_string(void) const; +    }; + +} //namespace uhd + +#endif /* INCLUDED_UHD_TYPES_TUNE_RESULT_HPP */ diff --git a/host/include/uhd/usrp/CMakeLists.txt b/host/include/uhd/usrp/CMakeLists.txt new file mode 100644 index 000000000..abddf3951 --- /dev/null +++ b/host/include/uhd/usrp/CMakeLists.txt @@ -0,0 +1,48 @@ +# +# 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/>. +# + + +INSTALL(FILES +    #### props headers ### +    codec_props.hpp +    dboard_props.hpp +    device_props.hpp +    dsp_props.hpp +    mboard_props.hpp +    subdev_props.hpp + +    #### dboard headers ### +    dboard_base.hpp +    dboard_eeprom.hpp +    dboard_id.hpp +    dboard_iface.hpp +    dboard_manager.hpp + +    ### utilities ### +    dsp_utils.hpp +    misc_utils.hpp +    subdev_spec.hpp +    tune_helper.hpp + +    ### interfaces ### +    simple_usrp.hpp +    single_usrp.hpp +    mimo_usrp.hpp +    multi_usrp.hpp + +    DESTINATION ${INCLUDE_DIR}/uhd/usrp +) diff --git a/host/include/uhd/usrp/codec_props.hpp b/host/include/uhd/usrp/codec_props.hpp new file mode 100644 index 000000000..ab09b1703 --- /dev/null +++ b/host/include/uhd/usrp/codec_props.hpp @@ -0,0 +1,42 @@ +// +// Copyright 2010 Ettus Research LLC +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program.  If not, see <http://www.gnu.org/licenses/>. +// + +#ifndef INCLUDED_UHD_USRP_CODEC_PROPS_HPP +#define INCLUDED_UHD_USRP_CODEC_PROPS_HPP + +#include <uhd/utils/props.hpp> + +namespace uhd{ namespace usrp{ + +    /*! +    * 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{ +        CODEC_PROP_NAME           = 'n', //ro, std::string +        CODEC_PROP_OTHERS         = 'o', //ro, prop_names_t +        CODEC_PROP_GAIN_I         = 'i', //rw, float +        CODEC_PROP_GAIN_Q         = 'q', //rw, float +        CODEC_PROP_GAIN_RANGE     = 'r', //ro, gain_range_t +        CODEC_PROP_GAIN_NAMES     = 'G'  //ro, prop_names_t +    }; + + +}} //namespace + +#endif /* INCLUDED_UHD_USRP_CODEC_PROPS_HPP */ diff --git a/host/include/uhd/usrp/dboard_base.hpp b/host/include/uhd/usrp/dboard_base.hpp new file mode 100644 index 000000000..9b75d791f --- /dev/null +++ b/host/include/uhd/usrp/dboard_base.hpp @@ -0,0 +1,117 @@ +// +// Copyright 2010 Ettus Research LLC +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program.  If not, see <http://www.gnu.org/licenses/>. +// + +#ifndef INCLUDED_UHD_USRP_DBOARD_BASE_HPP +#define INCLUDED_UHD_USRP_DBOARD_BASE_HPP + +#include <uhd/config.hpp> +#include <uhd/wax.hpp> +#include <uhd/utils/pimpl.hpp> +#include <boost/utility.hpp> +#include <boost/shared_ptr.hpp> +#include <uhd/usrp/dboard_id.hpp> +#include <uhd/usrp/dboard_iface.hpp> + +namespace uhd{ namespace usrp{ + +/*! + * A daughter board dboard_base class for all dboards. + * Only other dboard dboard_base classes should inherit this. + */ +class UHD_API dboard_base : boost::noncopyable{ +public: +    typedef boost::shared_ptr<dboard_base> sptr; +    /*! +     * An opaque type for the dboard constructor args. +     * Derived classes should pass the args into the base class, +     * but should not deal with the internals of the args. +     */ +    typedef void * ctor_args_t; + +    //structors +    dboard_base(ctor_args_t); +    virtual ~dboard_base(void); + +    //interface +    virtual void rx_get(const wax::obj &key, wax::obj &val) = 0; +    virtual void rx_set(const wax::obj &key, const wax::obj &val) = 0; +    virtual void tx_get(const wax::obj &key, wax::obj &val) = 0; +    virtual void tx_set(const wax::obj &key, const wax::obj &val) = 0; + +protected: +    std::string get_subdev_name(void); +    dboard_iface::sptr get_iface(void); +    dboard_id_t get_rx_id(void); +    dboard_id_t get_tx_id(void); + +private: +    UHD_PIMPL_DECL(impl) _impl; +}; + +/*! + * A xcvr daughter board implements rx and tx methods + * Sub classes for xcvr boards should inherit this. + */ +class UHD_API xcvr_dboard_base : public dboard_base{ +public: +    /*! +     * Create a new xcvr dboard object, override in subclasses. +     */ +    xcvr_dboard_base(ctor_args_t); + +    virtual ~xcvr_dboard_base(void); +}; + +/*! + * A rx daughter board only implements rx methods. + * Sub classes for rx-only boards should inherit this. + */ +class UHD_API rx_dboard_base : public dboard_base{ +public: +    /*! +     * Create a new rx dboard object, override in subclasses. +     */ +    rx_dboard_base(ctor_args_t); + +    virtual ~rx_dboard_base(void); + +    //override here so the derived classes cannot +    void tx_get(const wax::obj &key, wax::obj &val); +    void tx_set(const wax::obj &key, const wax::obj &val); +}; + +/*! + * A tx daughter board only implements tx methods. + * Sub classes for rx-only boards should inherit this. + */ +class UHD_API tx_dboard_base : public dboard_base{ +public: +    /*! +     * Create a new rx dboard object, override in subclasses. +     */ +    tx_dboard_base(ctor_args_t); + +    virtual ~tx_dboard_base(void); + +    //override here so the derived classes cannot +    void rx_get(const wax::obj &key, wax::obj &val); +    void rx_set(const wax::obj &key, const wax::obj &val); +}; + +}} //namespace + +#endif /* INCLUDED_UHD_USRP_DBOARD_BASE_HPP */ diff --git a/host/include/uhd/usrp/dboard_eeprom.hpp b/host/include/uhd/usrp/dboard_eeprom.hpp new file mode 100644 index 000000000..108027b46 --- /dev/null +++ b/host/include/uhd/usrp/dboard_eeprom.hpp @@ -0,0 +1,60 @@ +// +// Copyright 2010 Ettus Research LLC +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program.  If not, see <http://www.gnu.org/licenses/>. +// + +#ifndef INCLUDED_UHD_USRP_DBOARD_EEPROM_HPP +#define INCLUDED_UHD_USRP_DBOARD_EEPROM_HPP + +#include <uhd/config.hpp> +#include <uhd/usrp/dboard_id.hpp> +#include <uhd/types/serial.hpp> +#include <string> + +namespace uhd{ namespace usrp{ + +struct UHD_API dboard_eeprom_t{ +    /*! +     * The dboard id that was read from eeprom or will be set to eeprom. +     */ +    dboard_id_t id; + +    /*! +     * Create a dboard eeprom struct from the bytes read out of eeprom. +     * The constructor will parse out the dboard id from a vector of bytes. +     * To be valid, the bytes vector should be at least num_bytes() long. +     * If the parsing fails due to bad checksum or incomplete length, +     * the dboard id in this struct will be set to dboard_id::NONE. +     * \param bytes the vector of bytes +     */ +    dboard_eeprom_t(const uhd::byte_vector_t &bytes = uhd::byte_vector_t(0)); + +    /*! +     * Get the bytes that would be written to dboard eeprom. +     * \return a vector of bytes +     */ +    uhd::byte_vector_t get_eeprom_bytes(void); + +    /*! +     * Get the number of bytes in the dboard eeprom segment. +     * Use this value when reading out of the dboard eeprom. +     * \return the number of bytes used by dboard eeprom +     */ +    static size_t num_bytes(void); +}; + +}} //namespace + +#endif /* INCLUDED_UHD_USRP_DBOARD_EEPROM_HPP */ diff --git a/host/include/uhd/usrp/dboard_id.hpp b/host/include/uhd/usrp/dboard_id.hpp new file mode 100644 index 000000000..1fda8182e --- /dev/null +++ b/host/include/uhd/usrp/dboard_id.hpp @@ -0,0 +1,96 @@ +// +// Copyright 2010 Ettus Research LLC +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program.  If not, see <http://www.gnu.org/licenses/>. +// + +#ifndef INCLUDED_UHD_USRP_DBOARD_ID_HPP +#define INCLUDED_UHD_USRP_DBOARD_ID_HPP + +#include <uhd/config.hpp> +#include <boost/cstdint.hpp> +#include <boost/operators.hpp> +#include <string> + +namespace uhd{ namespace usrp{ + +    class UHD_API dboard_id_t : boost::equality_comparable<dboard_id_t>{ +    public: +        /*! +         * Create a dboard id from an integer. +         * \param id the integer representation +         */ +        dboard_id_t(boost::uint16_t id = 0xffff); + +        /*! +         * Obtain a dboard id that represents no dboard. +         * \return the dboard id with the 0xffff id. +         */ +        static dboard_id_t none(void); + +        /*! +         * Create a new dboard id from an integer representation. +         * \param uint16 an unsigned 16 bit integer +         * \return a new dboard id containing the integer +         */ +        static dboard_id_t from_uint16(boost::uint16_t uint16); + +        /*! +         * Get the dboard id represented as an integer. +         * \return an unsigned 16 bit integer representation +         */ +        boost::uint16_t to_uint16(void) const; + +        /*! +         * Create a new dboard id from a string representation. +         * If the string has a 0x prefix, it will be parsed as hex. +         * \param string a numeric string, possibly hex +         * \return a new dboard id containing the integer +         */ +        static dboard_id_t from_string(const std::string &string); + +        /*! +         * Get the dboard id represented as an integer. +         * \return a hex string representation with 0x prefix +         */ +        std::string to_string(void) const; + +        /*! +         * Get the dboard id represented as a canonical name. +         * \return the canonical string representation +         */ +        std::string to_cname(void) const; + +        /*! +         * Get the pretty print representation of this dboard id. +         * \return a string with the dboard name and id number +         */ +        std::string to_pp_string(void) const; + +    private: +        boost::uint16_t _id; //internal representation +    }; + +    /*! +     * Comparator operator overloaded for dboard ids. +     * The boost::equality_comparable provides the !=. +     * \param lhs the dboard id to the left of the operator +     * \param rhs the dboard id to the right of the operator +     * \return true when the dboard ids are equal +     */ +    UHD_API bool operator==(const dboard_id_t &lhs, const dboard_id_t &rhs); + +}} //namespace + +#endif /* INCLUDED_UHD_USRP_DBOARD_ID_HPP */ diff --git a/host/include/uhd/usrp/dboard_iface.hpp b/host/include/uhd/usrp/dboard_iface.hpp new file mode 100644 index 000000000..c430ecd3f --- /dev/null +++ b/host/include/uhd/usrp/dboard_iface.hpp @@ -0,0 +1,258 @@ +// +// Copyright 2010 Ettus Research LLC +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program.  If not, see <http://www.gnu.org/licenses/>. +// + +#ifndef INCLUDED_UHD_USRP_DBOARD_IFACE_HPP +#define INCLUDED_UHD_USRP_DBOARD_IFACE_HPP + +#include <uhd/config.hpp> +#include <uhd/types/serial.hpp> +#include <boost/shared_ptr.hpp> +#include <boost/cstdint.hpp> +#include <string> +#include <vector> + +namespace uhd{ namespace usrp{ + +/*! + * The daughter board dboard interface to be subclassed. + * A dboard instance interfaces with the mboard though this api. + * This interface provides i2c, spi, gpio, atr, aux dac/adc access. + * Each mboard should have a specially tailored iface for its dboard. + */ +class UHD_API dboard_iface{ +public: +    typedef boost::shared_ptr<dboard_iface> sptr; + +    //! tells the host which unit to use +    enum unit_t{ +        UNIT_RX = 'r', +        UNIT_TX = 't' +    }; + +    //! possible atr registers +    enum atr_reg_t{ +        ATR_REG_IDLE        = 'i', +        ATR_REG_TX_ONLY     = 't', +        ATR_REG_RX_ONLY     = 'r', +        ATR_REG_FULL_DUPLEX = 'f' +    }; + +    //! aux dac selection enums (per unit) +    enum aux_dac_t{ +        AUX_DAC_A = 'a', +        AUX_DAC_B = 'b', +        AUX_DAC_C = 'c', +        AUX_DAC_D = 'd' +    }; + +    //! aux adc selection enums (per unit) +    enum aux_adc_t{ +        AUX_ADC_A = 'a', +        AUX_ADC_B = 'b' +    }; + +    //! Special properties that differentiate this daughterboard slot +    struct special_props_t{ +        /*! +         * Soft clock divider: +         * When a motherboard cannot provided a divided dboard clock, +         * it may provided a "soft" divided clock over an FPGA GPIO. +         * The implementation must know the type of clock provided. +         */ +        bool soft_clock_divider; + +        /*! +         * Mangle i2c addresses: +         * When i2c is shared across multiple daugterboard slots, +         * the i2c addresses will be mangled on the secondary slot +         * to avoid conflicts between slots in the i2c address space. +         * The mangling is daguhterboard specific so the implementation +         * needs to know whether it should use mangled addresses or not. +         */ +        bool mangle_i2c_addrs; +    }; + +    /*! +     * Get special properties information for this dboard slot. +     * This call helps the dboard code to handle implementation +     * differences between different motherboards and dboard slots. +     * \return the special properties struct +     */ +    virtual special_props_t get_special_props(void) = 0; + +    /*! +     * Write to an aux dac. +     * +     * \param unit which unit rx or tx +     * \param which_dac the dac index 0, 1, 2, 3... +     * \param value the value in volts +     */ +    virtual void write_aux_dac(unit_t unit, aux_dac_t which_dac, float value) = 0; + +    /*! +     * Read from an aux adc. +     * +     * \param unit which unit rx or tx +     * \param which_adc the adc index 0, 1, 2, 3... +     * \return the value in volts +     */ +    virtual float read_aux_adc(unit_t unit, aux_adc_t which_adc) = 0; + +    /*! +     * Set a daughterboard output pin control source. +     * By default, the outputs are all GPIO controlled. +     * +     * \param unit which unit rx or tx +     * \param value 16-bits, 0=GPIO controlled, 1=ATR controlled +     */ +    virtual void set_pin_ctrl(unit_t unit, boost::uint16_t value) = 0; + +    /*! +     * Set a daughterboard ATR register. +     * +     * \param unit which unit rx or tx +     * \param reg which ATR register to set +     * \param value 16-bits, 0=ATR output low, 1=ATR output high +     */ +    virtual void set_atr_reg(unit_t unit, atr_reg_t reg, boost::uint16_t value) = 0; + +    /*! +     * Set daughterboard GPIO data direction register. +     * By default, the GPIO pins are all inputs. +     * +     * \param unit which unit rx or tx +     * \param value 16-bits, 0=GPIO input, 1=GPIO output +     */ +    virtual void set_gpio_ddr(unit_t unit, boost::uint16_t value) = 0; + +    /*! +     * Read daughterboard GPIO pin values. +     * +     * \param unit which unit rx or tx +     * \param value 16-bits, 0=GPIO output low, 1=GPIO output high +     */ +    virtual void write_gpio(unit_t unit, boost::uint16_t value) = 0; + +    /*! +     * Setup the GPIO debug mux. +     * +     * \param unit which unit rx or tx +     * \param which which debug: 0, 1 +     */ +    virtual void set_gpio_debug(unit_t unit, int which) = 0; + +    /*! +     * Read daughterboard GPIO pin values. +     * +     * \param unit which unit rx or tx +     * \return the value of the gpio unit +     */ +    virtual boost::uint16_t read_gpio(unit_t unit) = 0; + +    /*! +     * Write to an I2C peripheral. +     * +     * \param addr I2C bus address (7-bits) +     * \param bytes the data to write +     */ +    virtual void write_i2c(boost::uint8_t addr, const byte_vector_t &bytes) = 0; + +    /*! +     * Read from an I2C peripheral. +     * +     * \param addr I2C bus address (7-bits) +     * \param num_bytes number of bytes to read +     * \return the data read if successful, else a zero length string. +     */ +    virtual byte_vector_t read_i2c(boost::uint8_t addr, size_t num_bytes) = 0; + +    /*! +     * Write data to SPI bus peripheral. +     * +     * \param unit which unit, rx or tx +     * \param config configuration settings +     * \param data the bits to write LSB first +     * \param num_bits the number of bits in data +     */ +    virtual void write_spi( +        unit_t unit, +        const spi_config_t &config, +        boost::uint32_t data, +        size_t num_bits +    ) = 0; + +    /*! +     * Read and write data to SPI bus peripheral. +     * +     * \param unit which unit, rx or tx +     * \param config configuration settings +     * \param data the bits to write LSB first +     * \param num_bits the number of bits in data +     * \return the data that was read +     */ +    virtual boost::uint32_t read_write_spi( +        unit_t unit, +        const spi_config_t &config, +        boost::uint32_t data, +        size_t num_bits +    ) = 0; + +    /*! +     * Set the rate of a dboard clock. +     * +     * \param unit which unit rx or tx +     * \param rate the clock rate in Hz +     */ +    virtual void set_clock_rate(unit_t unit, double rate) = 0; + +    /*! +     * Get the rate of a dboard clock. +     * +     * \param unit which unit rx or tx +     * \return the clock rate in Hz +     */ +    virtual double get_clock_rate(unit_t unit) = 0; + +    /*! +     * Get a list of possible rates for the dboard clock. +     * +     * \param unit which unit rx or tx +     * \return a list of clock rates in Hz +     */ +    virtual std::vector<double> get_clock_rates(unit_t unit) = 0; + +    /*! +     * Enable or disable a dboard clock. +     * +     * \param unit which unit rx or tx +     * \param enb true for enabled +     */ +    virtual void set_clock_enabled(unit_t unit, bool enb) = 0; + +    /*! +     * Get the rate of the codec. +     * For rx, this is the rate the ADC feeds the DSP. +     * For tx, this is the rate the DSP feeds the DAC. +     * \param unit which unit rx or tx +     * \return the codec rate in Hz +     */ +    virtual double get_codec_rate(unit_t unit) = 0; +}; + +}} //namespace + +#endif /* INCLUDED_UHD_USRP_DBOARD_IFACE_HPP */ diff --git a/host/include/uhd/usrp/dboard_manager.hpp b/host/include/uhd/usrp/dboard_manager.hpp new file mode 100644 index 000000000..c68f069f0 --- /dev/null +++ b/host/include/uhd/usrp/dboard_manager.hpp @@ -0,0 +1,96 @@ +// +// Copyright 2010 Ettus Research LLC +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program.  If not, see <http://www.gnu.org/licenses/>. +// + +#ifndef INCLUDED_UHD_USRP_DBOARD_MANAGER_HPP +#define INCLUDED_UHD_USRP_DBOARD_MANAGER_HPP + +#include <uhd/config.hpp> +#include <uhd/utils/props.hpp> +#include <uhd/usrp/dboard_base.hpp> +#include <uhd/usrp/dboard_id.hpp> +#include <boost/utility.hpp> +#include <boost/shared_ptr.hpp> + +namespace uhd{ namespace usrp{ + +/*! + * A daughter board subdev dboard_manager class. + * Create subdev instances for each subdev on a dboard. + * Provide wax::obj access to the subdevs inside. + */ +class UHD_API dboard_manager : boost::noncopyable{ +public: +    typedef boost::shared_ptr<dboard_manager> sptr; + +    //dboard constructor (each dboard should have a ::make with this signature) +    typedef dboard_base::sptr(*dboard_ctor_t)(dboard_base::ctor_args_t); + +    /*! +     * Register a rx or tx dboard into the system. +     * For single subdevice boards, omit subdev_names. +     * \param dboard_id the dboard id (rx or tx) +     * \param dboard_ctor the dboard constructor function pointer +     * \param name the canonical name for the dboard represented +     * \param subdev_names the names of the subdevs on this dboard +     */ +    static void register_dboard( +        const dboard_id_t &dboard_id, +        dboard_ctor_t dboard_ctor, +        const std::string &name, +        const prop_names_t &subdev_names = prop_names_t(1, "0") +    ); + +    /*! +     * Register an xcvr dboard into the system. +     * For single subdevice boards, omit subdev_names. +     * \param rx_dboard_id the rx unit dboard id +     * \param tx_dboard_id the tx unit dboard id +     * \param dboard_ctor the dboard constructor function pointer +     * \param name the canonical name for the dboard represented +     * \param subdev_names the names of the subdevs on this dboard +     */ +    static void register_dboard( +        const dboard_id_t &rx_dboard_id, +        const dboard_id_t &tx_dboard_id, +        dboard_ctor_t dboard_ctor, +        const std::string &name, +        const prop_names_t &subdev_names = prop_names_t(1, "") +    ); + +    /*! +     * Make a new dboard manager. +     * \param rx_dboard_id the id of the rx dboard +     * \param tx_dboard_id the id of the tx dboard +     * \param iface the custom dboard interface +     * \return an sptr to the new dboard manager +     */ +    static sptr make( +        dboard_id_t rx_dboard_id, +        dboard_id_t tx_dboard_id, +        dboard_iface::sptr iface +    ); + +    //dboard manager interface +    virtual prop_names_t get_rx_subdev_names(void) = 0; +    virtual prop_names_t get_tx_subdev_names(void) = 0; +    virtual wax::obj get_rx_subdev(const std::string &subdev_name) = 0; +    virtual wax::obj get_tx_subdev(const std::string &subdev_name) = 0; +}; + +}} //namespace + +#endif /* INCLUDED_UHD_USRP_DBOARD_MANAGER_HPP */ diff --git a/host/include/uhd/usrp/dboard_props.hpp b/host/include/uhd/usrp/dboard_props.hpp new file mode 100644 index 000000000..aab6c31ce --- /dev/null +++ b/host/include/uhd/usrp/dboard_props.hpp @@ -0,0 +1,42 @@ +// +// Copyright 2010 Ettus Research LLC +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program.  If not, see <http://www.gnu.org/licenses/>. +// + +#ifndef INCLUDED_UHD_USRP_DBOARD_PROPS_HPP +#define INCLUDED_UHD_USRP_DBOARD_PROPS_HPP + +#include <uhd/utils/props.hpp> + +namespace uhd{ namespace usrp{ + +    /*! +     * Possible device dboard properties: +     *    A dboard has an id, one or more subdevices, and a codec. +     *    A dboard is considered to be unidirectional (RX or TX). +     */ +    enum dboard_prop_t{ +        DBOARD_PROP_NAME         = 'n', //ro, std::string +        DBOARD_PROP_SUBDEV       = 's', //ro, wax::obj +        DBOARD_PROP_SUBDEV_NAMES = 'S', //ro, prop_names_t +        DBOARD_PROP_DBOARD_ID    = 'i', //rw, dboard_id_t +        DBOARD_PROP_DBOARD_IFACE = 'f', //ro, dboard_iface::sptr +        DBOARD_PROP_CODEC        = 'c', //ro, wax::obj +        DBOARD_PROP_GAIN_GROUP   = 'g'  //ro, gain_group +    };  + +}} //namespace + +#endif /* INCLUDED_UHD_USRP_DBOARD_PROPS_HPP */ diff --git a/host/include/uhd/usrp/device_props.hpp b/host/include/uhd/usrp/device_props.hpp new file mode 100644 index 000000000..346eec179 --- /dev/null +++ b/host/include/uhd/usrp/device_props.hpp @@ -0,0 +1,39 @@ +// +// Copyright 2010 Ettus Research LLC +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program.  If not, see <http://www.gnu.org/licenses/>. +// + +#ifndef INCLUDED_UHD_USRP_DEVICE_PROPS_HPP +#define INCLUDED_UHD_USRP_DEVICE_PROPS_HPP + +#include <uhd/utils/props.hpp> + +namespace uhd{ namespace usrp{ + +    /*! +     * Possible device properties: +     *   In general, a device will have a single mboard. +     *   In certain mimo applications, multiple boards +     *   will be present in the interface for configuration. +     */ +    enum device_prop_t{ +        DEVICE_PROP_NAME           = 'n', //ro, std::string +        DEVICE_PROP_MBOARD         = 'm', //ro, wax::obj +        DEVICE_PROP_MBOARD_NAMES   = 'M'  //ro, prop_names_t +    }; + +}} //namespace + +#endif /* INCLUDED_UHD_USRP_DEVICE_PROPS_HPP */ diff --git a/host/include/uhd/usrp/dsp_props.hpp b/host/include/uhd/usrp/dsp_props.hpp new file mode 100644 index 000000000..54ea5666b --- /dev/null +++ b/host/include/uhd/usrp/dsp_props.hpp @@ -0,0 +1,50 @@ +// +// Copyright 2010 Ettus Research LLC +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program.  If not, see <http://www.gnu.org/licenses/>. +// + +#ifndef INCLUDED_UHD_USRP_DSP_PROPS_HPP +#define INCLUDED_UHD_USRP_DSP_PROPS_HPP + +#include <uhd/utils/props.hpp> + +namespace uhd{ namespace usrp{ + +    /*! +     * Possible device dsp properties: +     *   A dsp is a black box fpga component found between +     *   the over-the-wire data and the codec pins. +     * +     *   The host rate can be modified to control resampling. +     *   Resampling can take the form of decimation, interpolation, +     *   or more complex fractional resampling techniques. +     *   As usual, read back the host rate after setting it +     *   to get the actual rate that was set (implementation dependent). +     * +     *   A dsp can also shift the digital stream in frequency. +     *   Set the shift property and read it back to get actual shift. +     */ +    enum dsp_prop_t{ +        DSP_PROP_NAME              = 'n', //ro, std::string +        DSP_PROP_OTHERS            = 'o', //ro, prop_names_t +        DSP_PROP_FREQ_SHIFT        = 'f', //rw, double Hz +        DSP_PROP_FREQ_SHIFT_NAMES  = 'F', //ro, prop_names_t +        DSP_PROP_CODEC_RATE        = 'c', //ro, double Sps +        DSP_PROP_HOST_RATE         = 'h'  //rw, double Sps +    }; + +}} //namespace + +#endif /* INCLUDED_UHD_USRP_DSP_PROPS_HPP */ diff --git a/host/include/uhd/usrp/dsp_utils.hpp b/host/include/uhd/usrp/dsp_utils.hpp new file mode 100644 index 000000000..8ec04dd2f --- /dev/null +++ b/host/include/uhd/usrp/dsp_utils.hpp @@ -0,0 +1,99 @@ +// +// Copyright 2010 Ettus Research LLC +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program.  If not, see <http://www.gnu.org/licenses/>. +// + +#ifndef INCLUDED_UHD_USRP_DSP_UTILS_HPP +#define INCLUDED_UHD_USRP_DSP_UTILS_HPP + +#include <uhd/config.hpp> +#include <uhd/types/stream_cmd.hpp> +#include <uhd/usrp/subdev_props.hpp> +#include <boost/cstdint.hpp> + +namespace uhd{ namespace usrp{ + +namespace dsp_type1{ + +    /*! +     * Calculate the rx mux word from properties. +     * \param subdev_conn the subdev connection type +     * \return the 32-bit rx mux control word +     */ +    UHD_API boost::uint32_t calc_rx_mux_word(subdev_conn_t subdev_conn); + +    /*! +     * Calculate the tx mux word from properties. +     * \param subdev_conn the subdev connection type +     * \return the 32-bit tx mux control word +     */ +    UHD_API boost::uint32_t calc_tx_mux_word(subdev_conn_t subdev_conn); + +    /*! +     * Calculate the cordic word from the frequency and clock rate. +     * The frequency will be set to the actual (possible) frequency. +     * +     * \param freq the requested frequency in Hz +     * \param codec_rate the dsp codec rate in Hz +     * \return the 32-bit cordic control word +     */ +    UHD_API boost::uint32_t calc_cordic_word_and_update( +        double &freq, double codec_rate +    ); + +    /*! +     * Calculate the CIC filter word from the rate. +     * Check if requested decim/interp rate is: +     *      multiple of 4, enable two halfband filters +     *      multiple of 2, enable one halfband filter +     *      handle remainder in CIC +     * +     * \param rate the requested rate in Sps +     * \return the 32-bit cic filter control word +     */ +    UHD_API boost::uint32_t calc_cic_filter_word(unsigned rate); + +    /*! +     * Calculate the IQ scale factor word from I and Q components. +     * \param i the I component of the scalar +     * \param q the Q component of the scalar +     * \return the 32-bit scale factor control word +     */ +    UHD_API boost::uint32_t calc_iq_scale_word( +        boost::int16_t i, boost::int16_t q +    ); + +    /*! +     * Calculate the IQ scale factor word from the rate. +     * \param rate the requested rate in Sps +     * \return the 32-bit scale factor control word +     */ +    UHD_API boost::uint32_t calc_iq_scale_word(unsigned rate); + +    /*! +     * Calculate the stream command word from the stream command struct. +     * \param stream_cmd the requested stream command with mode, flags, timestamp +     * \param num_samps_continuous number of samples to request in continuous mode +     * \return the 32-bit stream command word +     */ +    UHD_API boost::uint32_t calc_stream_cmd_word( +        const stream_cmd_t &stream_cmd, size_t num_samps_continuous +    ); + +} //namespace dsp_type1 + +}} //namespace + +#endif /* INCLUDED_UHD_USRP_DSP_UTILS_HPP */ diff --git a/host/include/uhd/usrp/mboard_props.hpp b/host/include/uhd/usrp/mboard_props.hpp new file mode 100644 index 000000000..0f250f439 --- /dev/null +++ b/host/include/uhd/usrp/mboard_props.hpp @@ -0,0 +1,52 @@ +// +// Copyright 2010 Ettus Research LLC +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program.  If not, see <http://www.gnu.org/licenses/>. +// + +#ifndef INCLUDED_UHD_USRP_MBOARD_PROPS_HPP +#define INCLUDED_UHD_USRP_MBOARD_PROPS_HPP + +#include <uhd/utils/props.hpp> + +namespace uhd{ namespace usrp{ + +    /*! +     * Possible device mboard properties: +     *   The general mboard properties are listed below. +     *   Custom properties can be identified with a string +     *   and discovered though the others property. +     */ +    enum mboard_prop_t{ +        MBOARD_PROP_NAME            = 'n', //ro, std::string +        MBOARD_PROP_OTHERS          = 'o', //ro, prop_names_t +        MBOARD_PROP_RX_DSP          = 'd', //ro, wax::obj +        MBOARD_PROP_RX_DSP_NAMES    = 'D', //ro, prop_names_t +        MBOARD_PROP_TX_DSP          = 'u', //ro, wax::obj +        MBOARD_PROP_TX_DSP_NAMES    = 'U', //ro, prop_names_t +        MBOARD_PROP_RX_DBOARD       = 'e', //ro, wax::obj +        MBOARD_PROP_RX_DBOARD_NAMES = 'E', //ro, prop_names_t +        MBOARD_PROP_TX_DBOARD       = 'v', //ro, wax::obj +        MBOARD_PROP_TX_DBOARD_NAMES = 'V', //ro, prop_names_t +        MBOARD_PROP_RX_SUBDEV_SPEC  = 'r', //rw, subdev_spec_t +        MBOARD_PROP_TX_SUBDEV_SPEC  = 'R', //rw, subdev_spec_t +        MBOARD_PROP_CLOCK_CONFIG    = 'C', //rw, clock_config_t +        MBOARD_PROP_TIME_NOW        = 't', //rw, time_spec_t +        MBOARD_PROP_TIME_NEXT_PPS   = 'T', //wo, time_spec_t +        MBOARD_PROP_STREAM_CMD      = 's'  //wo, stream_cmd_t +    }; + +}} //namespace + +#endif /* INCLUDED_UHD_USRP_MBOARD_PROPS_HPP */ diff --git a/host/include/uhd/usrp/mimo_usrp.hpp b/host/include/uhd/usrp/mimo_usrp.hpp new file mode 100644 index 000000000..a2092f04f --- /dev/null +++ b/host/include/uhd/usrp/mimo_usrp.hpp @@ -0,0 +1,525 @@ +// +// Copyright 2010 Ettus Research LLC +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program.  If not, see <http://www.gnu.org/licenses/>. +// + +#ifndef INCLUDED_UHD_USRP_MIMO_USRP_HPP +#define INCLUDED_UHD_USRP_MIMO_USRP_HPP + +#include <uhd/config.hpp> +#include <uhd/device.hpp> +#include <uhd/types/ranges.hpp> +#include <uhd/types/stream_cmd.hpp> +#include <uhd/types/clock_config.hpp> +#include <uhd/types/tune_result.hpp> +#include <uhd/usrp/subdev_spec.hpp> +#include <boost/shared_ptr.hpp> +#include <boost/utility.hpp> +#include <vector> + +namespace uhd{ namespace usrp{ + +/*! + * The MIMO USRP device class (DEPRECATED): + * A mimo usrp facilitates ease-of-use for multi-usrp scenarios. + * The wrapper provides convenience functions to control the group + * of underlying devices as if they consisted of a single device. + */ +class UHD_API UHD_DEPRECATED mimo_usrp : boost::noncopyable{ +public: +    typedef boost::shared_ptr<mimo_usrp> sptr; + +    /*! +     * Make a new mimo usrp from the device address. +     * \param dev_addr the device address +     * \return a new mimo usrp object +     */ +    static sptr make(const device_addr_t &dev_addr); + +    /*! +     * Get the underlying device object. +     * This is needed to get access to the streaming API and properties. +     * \return the device object within this simple usrp +     */ +    virtual device::sptr get_device(void) = 0; + +    /*! +     * Get a printable name for this mimo usrp. +     * \return a printable string +     */ +    virtual std::string get_pp_string(void) = 0; + +    /*! +     * Get the number of channels in this mimo configuration. +     * The number of rx channels == the number of tx channels. +     * \return the number of channels +     */ +    virtual size_t get_num_channels(void) = 0; + +    /******************************************************************* +     * Misc +     ******************************************************************/ +    /*! +     * Gets the current time in the usrp time registers. +     * \return a timespec representing current usrp time +     */ +    virtual time_spec_t get_time_now(void) = 0; + +    /*! +     * Set the time registers on the usrp at the next pps tick. +     * The values will not be latched in until the pulse occurs. +     * It is recommended that the user sleep(1) after calling to ensure +     * that the time registers will be in a known state prior to use. +     * This call works across all mboards in the mimo configuration. +     * +     * Note: Because this call sets the time on the "next" pps, +     * the seconds in the time spec should be current seconds + 1. +     * +     * \param time_spec the time to latch into the usrp device +     */ +    virtual void set_time_next_pps(const time_spec_t &time_spec) = 0; + +    /*! +     * Synchronize the times across all motherboards in this configuration. +     * Use this method to sync the times when the edge of the PPS is unknown. +     * +     * Ex: Host machine is not attached to serial port of GPSDO +     * and can therefore not query the GPSDO for the PPS edge. +     * +     * This is a 3-step process, and will take at most 3 seconds to complete. +     * Upon completion, the times will be synchronized to the time provided. +     * +     * - Step1: set the time at the next pps (potential race condition) +     * - Step2: wait for the seconds to rollover to catch the pps edge +     * - Step3: set the time at the next pps (synchronous for all boards) +     * +     * \param time_spec the time to latch into the usrp device +     */ +    virtual void set_time_unknown_pps(const time_spec_t &time_spec) = 0; + +    /*! +     * Issue a stream command to the usrp device. +     * This tells the usrp to send samples into the host. +     * See the documentation for stream_cmd_t for more info. +     * \param stream_cmd the stream command to issue +     */ +    virtual void issue_stream_cmd(const stream_cmd_t &stream_cmd) = 0; + +    /******************************************************************* +     * RX methods +     ******************************************************************/ +    virtual void set_rx_subdev_spec(size_t chan, const uhd::usrp::subdev_spec_t &spec) = 0; +    virtual uhd::usrp::subdev_spec_t get_rx_subdev_spec(size_t chan) = 0; + +    virtual void set_rx_rate_all(double rate) = 0; +    virtual double get_rx_rate_all(void) = 0; + +    virtual tune_result_t set_rx_freq(size_t chan, double freq) = 0; +    //virtual tune_result_t set_rx_freq(size_t chan, double freq, double lo_off) = 0; +    virtual double get_rx_freq(size_t chan) = 0; +    virtual freq_range_t get_rx_freq_range(size_t chan) = 0; + +    virtual void set_rx_gain(size_t chan, float gain) = 0; +    virtual float get_rx_gain(size_t chan) = 0; +    virtual gain_range_t get_rx_gain_range(size_t chan) = 0; + +    virtual void set_rx_antenna(size_t chan, const std::string &ant) = 0; +    virtual std::string get_rx_antenna(size_t chan) = 0; +    virtual std::vector<std::string> get_rx_antennas(size_t chan) = 0; + +    virtual bool get_rx_lo_locked(size_t chan) = 0; + +    /*! +     * Read the RSSI value from a usrp device. +     * Or throw if the dboard does not support an RSSI readback. +     * \param chan which mimo channel 0 to N-1 +     * \return the rssi in dB +     */ +    virtual float read_rssi(size_t chan) = 0; +     +    virtual void set_rx_bandwidth(size_t chan, float bandwidth) = 0; + +    /******************************************************************* +     * TX methods +     ******************************************************************/ +    virtual void set_tx_subdev_spec(size_t chan, const uhd::usrp::subdev_spec_t &spec) = 0; +    virtual uhd::usrp::subdev_spec_t get_tx_subdev_spec(size_t chan) = 0; + +    virtual void set_tx_rate_all(double rate) = 0; +    virtual double get_tx_rate_all(void) = 0; + +    virtual tune_result_t set_tx_freq(size_t chan, double freq) = 0; +    //virtual tune_result_t set_tx_freq(size_t chan, double freq, double lo_off) = 0; +    virtual double get_tx_freq(size_t chan) = 0; +    virtual freq_range_t get_tx_freq_range(size_t chan) = 0; + +    virtual void set_tx_gain(size_t chan, float gain) = 0; +    virtual float get_tx_gain(size_t chan) = 0; +    virtual gain_range_t get_tx_gain_range(size_t chan) = 0; + +    virtual void set_tx_antenna(size_t chan, const std::string &ant) = 0; +    virtual std::string get_tx_antenna(size_t chan) = 0; +    virtual std::vector<std::string> get_tx_antennas(size_t chan) = 0; + +    virtual bool get_tx_lo_locked(size_t chan) = 0; + +}; + +}} + +#include <uhd/utils/warning.hpp> +#include <uhd/usrp/tune_helper.hpp> +#include <uhd/utils/assert.hpp> +#include <uhd/utils/gain_group.hpp> +#include <uhd/utils/algorithm.hpp> +#include <uhd/utils/warning.hpp> +#include <uhd/usrp/subdev_props.hpp> +#include <uhd/usrp/mboard_props.hpp> +#include <uhd/usrp/device_props.hpp> +#include <uhd/usrp/dboard_props.hpp> +#include <uhd/usrp/dsp_props.hpp> +#include <boost/foreach.hpp> +#include <boost/format.hpp> +#include <boost/thread.hpp> +#include <stdexcept> +#include <iostream> + +namespace uhd{ namespace usrp{ namespace /*anon*/{ + +static inline freq_range_t add_dsp_shift(const freq_range_t &range, wax::obj dsp){ +    double codec_rate = dsp[DSP_PROP_CODEC_RATE].as<double>(); +    return freq_range_t(range.min - codec_rate/2.0, range.max + codec_rate/2.0); +} + +/*********************************************************************** + * MIMO USRP Implementation + **********************************************************************/ +class mimo_usrp_impl : public mimo_usrp{ +public: +    mimo_usrp_impl(const device_addr_t &addr){ +        _dev = device::make(addr); + +        //set the clock config across all mboards (TODO set through api) +        clock_config_t clock_config; +        clock_config.ref_source = clock_config_t::REF_SMA; +        clock_config.pps_source = clock_config_t::PPS_SMA; +        for (size_t chan = 0; chan < get_num_channels(); chan++){ +            _mboard(chan)[MBOARD_PROP_CLOCK_CONFIG] = clock_config; +        } +    } + +    ~mimo_usrp_impl(void){ +        /* NOP */ +    } + +    device::sptr get_device(void){ +        return _dev; +    } + +    std::string get_pp_string(void){ +        std::string buff = str(boost::format( +            "MIMO USRP:\n" +            "  Device: %s\n" +        ) +            % (*_dev)[DEVICE_PROP_NAME].as<std::string>() +        ); +        for (size_t chan = 0; chan < get_num_channels(); chan++){ +            buff += str(boost::format( +                "  Channel: %u\n" +                "    Mboard: %s\n" +                "    RX DSP: %s\n" +                "    RX Dboard: %s\n" +                "    RX Subdev: %s\n" +                "    TX DSP: %s\n" +                "    TX Dboard: %s\n" +                "    TX Subdev: %s\n" +            ) % chan +                % _mboard(chan)[MBOARD_PROP_NAME].as<std::string>() +                % _rx_dsp(chan)[DSP_PROP_NAME].as<std::string>() +                % _rx_dboard(chan)[DBOARD_PROP_NAME].as<std::string>() +                % _rx_subdev(chan)[SUBDEV_PROP_NAME].as<std::string>() +                % _tx_dsp(chan)[DSP_PROP_NAME].as<std::string>() +                % _tx_dboard(chan)[DBOARD_PROP_NAME].as<std::string>() +                % _tx_subdev(chan)[SUBDEV_PROP_NAME].as<std::string>() +            ); +        } +        return buff; +    } + +    size_t get_num_channels(void){ +        return (*_dev)[DEVICE_PROP_MBOARD_NAMES].as<prop_names_t>().size(); +    } + +    /******************************************************************* +     * Misc +     ******************************************************************/ +    time_spec_t get_time_now(void){ +        //the time on the first mboard better be the same on all +        return _mboard(0)[MBOARD_PROP_TIME_NOW].as<time_spec_t>(); +    } + +    void set_time_next_pps(const time_spec_t &time_spec){ +        for (size_t chan = 0; chan < get_num_channels(); chan++){ +            _mboard(chan)[MBOARD_PROP_TIME_NEXT_PPS] = time_spec; +        } +    } + +    void set_time_unknown_pps(const time_spec_t &time_spec){ +        std::cout << "Set time with unknown pps edge:" << std::endl; +        std::cout << "    1) set times next pps (race condition)" << std::endl; +        set_time_next_pps(time_spec); +        boost::this_thread::sleep(boost::posix_time::seconds(1)); + +        std::cout << "    2) catch seconds rollover at pps edge" << std::endl; +        time_t last_secs = 0, curr_secs = 0; +        while(curr_secs == last_secs){ +            last_secs = curr_secs; +            curr_secs = get_time_now().get_full_secs(); +        } + +        std::cout << "    3) set times next pps (synchronously)" << std::endl; +        set_time_next_pps(time_spec); +        boost::this_thread::sleep(boost::posix_time::seconds(1)); + +        //verify that the time registers are read to be within a few RTT +        for (size_t chan = 1; chan < get_num_channels(); chan++){ +            time_spec_t time_0 = _mboard(0)[MBOARD_PROP_TIME_NOW].as<time_spec_t>(); +            time_spec_t time_i = _mboard(chan)[MBOARD_PROP_TIME_NOW].as<time_spec_t>(); +            if (time_i < time_0 or (time_i - time_0) > time_spec_t(0.01)){ //10 ms: greater than RTT but not too big +                uhd::warning::post(str(boost::format( +                    "Detected time deviation between board %d and board 0.\n" +                    "Board 0 time is %f seconds.\n" +                    "Board %d time is %f seconds.\n" +                ) % chan % time_0.get_real_secs() % chan % time_i.get_real_secs())); +            } +        } +    } + +    void issue_stream_cmd(const stream_cmd_t &stream_cmd){ +        for (size_t chan = 0; chan < get_num_channels(); chan++){ +            _mboard(chan)[MBOARD_PROP_STREAM_CMD] = stream_cmd; +        } +    } + +    /******************************************************************* +     * RX methods +     ******************************************************************/ +    void set_rx_subdev_spec(size_t chan, const subdev_spec_t &spec){ +        UHD_ASSERT_THROW(spec.size() <= 1); +        _mboard(chan)[MBOARD_PROP_RX_SUBDEV_SPEC] = spec; +    } + +    subdev_spec_t get_rx_subdev_spec(size_t chan){ +        return _mboard(chan)[MBOARD_PROP_RX_SUBDEV_SPEC].as<subdev_spec_t>(); +    } + +    void set_rx_rate_all(double rate){ +        std::vector<double> _actual_rates; +        for (size_t chan = 0; chan < get_num_channels(); chan++){ +            _rx_dsp(chan)[DSP_PROP_HOST_RATE] = rate; +            _actual_rates.push_back(_rx_dsp(chan)[DSP_PROP_HOST_RATE].as<double>()); +        } +        _rx_rate = _actual_rates.front(); +        if (std::count(_actual_rates, _rx_rate) != _actual_rates.size()) throw std::runtime_error( +            "MIMO configuratio error: rx rate inconsistent across mboards" +        ); +    } + +    double get_rx_rate_all(void){ +        return _rx_rate; +    } + +    tune_result_t set_rx_freq(size_t chan, double target_freq){ +        return tune_rx_subdev_and_dsp(_rx_subdev(chan), _rx_dsp(chan), 0, target_freq); +    } + +    //tune_result_t set_rx_freq(size_t chan, double target_freq, double lo_off){ +    //    return tune_rx_subdev_and_dsp(_rx_subdev(chan), _rx_dsp(chan), 0, target_freq, lo_off); +    //} + +    double get_rx_freq(size_t chan){ +        return derive_freq_from_rx_subdev_and_dsp(_rx_subdev(chan), _rx_dsp(chan), 0); +    } + +    freq_range_t get_rx_freq_range(size_t chan){ +        return add_dsp_shift(_rx_subdev(chan)[SUBDEV_PROP_FREQ_RANGE].as<freq_range_t>(), _rx_dsp(chan)); +    } + +    void set_rx_gain(size_t chan, float gain){ +        return _rx_gain_group(chan)->set_value(gain); +    } + +    float get_rx_gain(size_t chan){ +        return _rx_gain_group(chan)->get_value(); +    } + +    gain_range_t get_rx_gain_range(size_t chan){ +        return _rx_gain_group(chan)->get_range(); +    } + +    void set_rx_antenna(size_t chan, const std::string &ant){ +        _rx_subdev(chan)[SUBDEV_PROP_ANTENNA] = ant; +    } + +    std::string get_rx_antenna(size_t chan){ +        return _rx_subdev(chan)[SUBDEV_PROP_ANTENNA].as<std::string>(); +    } + +    std::vector<std::string> get_rx_antennas(size_t chan){ +        return _rx_subdev(chan)[SUBDEV_PROP_ANTENNA_NAMES].as<prop_names_t>(); +    } + +    bool get_rx_lo_locked(size_t chan){ +        return _rx_subdev(chan)[SUBDEV_PROP_LO_LOCKED].as<bool>(); +    } + +    float read_rssi(size_t chan){ +        return _rx_subdev(chan)[SUBDEV_PROP_RSSI].as<float>(); +    } +     +    void set_rx_bandwidth(size_t chan, float bandwidth){ +        _rx_subdev(chan)[SUBDEV_PROP_BANDWIDTH] = bandwidth; +    } + +    /******************************************************************* +     * TX methods +     ******************************************************************/ +    void set_tx_subdev_spec(size_t chan, const subdev_spec_t &spec){ +        UHD_ASSERT_THROW(spec.size() <= 1); +        _mboard(chan)[MBOARD_PROP_TX_SUBDEV_SPEC] = spec; +    } + +    subdev_spec_t get_tx_subdev_spec(size_t chan){ +        return _mboard(chan)[MBOARD_PROP_TX_SUBDEV_SPEC].as<subdev_spec_t>(); +    } + +    void set_tx_rate_all(double rate){ +        std::vector<double> _actual_rates; +        for (size_t chan = 0; chan < get_num_channels(); chan++){ +            _tx_dsp(chan)[DSP_PROP_HOST_RATE] = rate; +            _actual_rates.push_back(_tx_dsp(chan)[DSP_PROP_HOST_RATE].as<double>()); +        } +        _tx_rate = _actual_rates.front(); +        if (std::count(_actual_rates, _tx_rate) != _actual_rates.size()) throw std::runtime_error( +            "MIMO configuratio error: tx rate inconsistent across mboards" +        ); +    } + +    double get_tx_rate_all(void){ +        return _tx_rate; +    } + +    tune_result_t set_tx_freq(size_t chan, double target_freq){ +        return tune_tx_subdev_and_dsp(_tx_subdev(chan), _tx_dsp(chan), 0, target_freq); +    } + +    //tune_result_t set_tx_freq(size_t chan, double target_freq, double lo_off){ +    //    return tune_tx_subdev_and_dsp(_tx_subdev(chan), _tx_dsp(chan), 0, target_freq, lo_off); +    //} + +    double get_tx_freq(size_t chan){ +        return derive_freq_from_tx_subdev_and_dsp(_tx_subdev(chan), _tx_dsp(chan), 0); +    } + +    freq_range_t get_tx_freq_range(size_t chan){ +        return add_dsp_shift(_tx_subdev(chan)[SUBDEV_PROP_FREQ_RANGE].as<freq_range_t>(), _tx_dsp(chan)); +    } + +    void set_tx_gain(size_t chan, float gain){ +        return _tx_gain_group(chan)->set_value(gain); +    } + +    float get_tx_gain(size_t chan){ +        return _tx_gain_group(chan)->get_value(); +    } + +    gain_range_t get_tx_gain_range(size_t chan){ +        return _tx_gain_group(chan)->get_range(); +    } + +    void set_tx_antenna(size_t chan, const std::string &ant){ +        _tx_subdev(chan)[SUBDEV_PROP_ANTENNA] = ant; +    } + +    std::string get_tx_antenna(size_t chan){ +        return _tx_subdev(chan)[SUBDEV_PROP_ANTENNA].as<std::string>(); +    } + +    std::vector<std::string> get_tx_antennas(size_t chan){ +        return _tx_subdev(chan)[SUBDEV_PROP_ANTENNA_NAMES].as<prop_names_t>(); +    } + +    bool get_tx_lo_locked(size_t chan){ +        return _tx_subdev(chan)[SUBDEV_PROP_LO_LOCKED].as<bool>(); +    } + +private: +    device::sptr _dev; +    wax::obj _mboard(size_t chan){ +        prop_names_t names = (*_dev)[DEVICE_PROP_MBOARD_NAMES].as<prop_names_t>(); +        return (*_dev)[named_prop_t(DEVICE_PROP_MBOARD, names.at(chan))]; +    } +    wax::obj _rx_dsp(size_t chan){ +        return _mboard(chan)[MBOARD_PROP_RX_DSP]; +    } +    wax::obj _tx_dsp(size_t chan){ +        return _mboard(chan)[MBOARD_PROP_TX_DSP]; +    } +    wax::obj _rx_dboard(size_t chan){ +        std::string db_name = _mboard(chan)[MBOARD_PROP_RX_SUBDEV_SPEC].as<subdev_spec_t>().front().db_name; +        return _mboard(chan)[named_prop_t(MBOARD_PROP_RX_DBOARD, db_name)]; +    } +    wax::obj _tx_dboard(size_t chan){ +        std::string db_name = _mboard(chan)[MBOARD_PROP_TX_SUBDEV_SPEC].as<subdev_spec_t>().front().db_name; +        return _mboard(chan)[named_prop_t(MBOARD_PROP_TX_DBOARD, db_name)]; +    } +    wax::obj _rx_subdev(size_t chan){ +        std::string sd_name = _mboard(chan)[MBOARD_PROP_RX_SUBDEV_SPEC].as<subdev_spec_t>().front().sd_name; +        return _rx_dboard(chan)[named_prop_t(DBOARD_PROP_SUBDEV, sd_name)]; +    } +    wax::obj _tx_subdev(size_t chan){ +        std::string sd_name = _mboard(chan)[MBOARD_PROP_TX_SUBDEV_SPEC].as<subdev_spec_t>().front().sd_name; +        return _tx_dboard(chan)[named_prop_t(DBOARD_PROP_SUBDEV, sd_name)]; +    } +    gain_group::sptr _rx_gain_group(size_t chan){ +        std::string sd_name = _mboard(chan)[MBOARD_PROP_RX_SUBDEV_SPEC].as<subdev_spec_t>().front().sd_name; +        return _rx_dboard(chan)[named_prop_t(DBOARD_PROP_GAIN_GROUP, sd_name)].as<gain_group::sptr>(); +    } +    gain_group::sptr _tx_gain_group(size_t chan){ +        std::string sd_name = _mboard(chan)[MBOARD_PROP_TX_SUBDEV_SPEC].as<subdev_spec_t>().front().sd_name; +        return _tx_dboard(chan)[named_prop_t(DBOARD_PROP_GAIN_GROUP, sd_name)].as<gain_group::sptr>(); +    } + +    //shadows +    double _rx_rate, _tx_rate; +}; +}}} + +namespace uhd{ namespace usrp{ +/*********************************************************************** + * The Make Function + **********************************************************************/ +inline mimo_usrp::sptr mimo_usrp::make(const device_addr_t &dev_addr){ +    uhd::warning::post( +        "The mimo USRP interface has been deprecated.\n" +        "Please switch to the multi USRP interface.\n" +        "#include <uhd/usrp/multi_usrp.hpp>\n" +        "multi_usrp::sptr sdev = multi_usrp::make(args);\n" +    ); +    return sptr(new mimo_usrp_impl(dev_addr)); +} +}} + +#endif /* INCLUDED_UHD_USRP_MIMO_USRP_HPP */ diff --git a/host/include/uhd/usrp/misc_utils.hpp b/host/include/uhd/usrp/misc_utils.hpp new file mode 100644 index 000000000..37860a1a5 --- /dev/null +++ b/host/include/uhd/usrp/misc_utils.hpp @@ -0,0 +1,71 @@ +// +// Copyright 2010 Ettus Research LLC +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program.  If not, see <http://www.gnu.org/licenses/>. +// + +#ifndef INCLUDED_UHD_USRP_MISC_UTILS_HPP +#define INCLUDED_UHD_USRP_MISC_UTILS_HPP + +#include <uhd/config.hpp> +#include <uhd/wax.hpp> +#include <uhd/usrp/dboard_id.hpp> +#include <uhd/usrp/subdev_spec.hpp> +#include <uhd/utils/gain_group.hpp> + +namespace uhd{ namespace usrp{ + +    /*! +     * Different policies for gain group prioritization. +     */ +    enum gain_group_policy_t{ +        GAIN_GROUP_POLICY_RX = 'R', +        GAIN_GROUP_POLICY_TX = 'T' +    }; + +    /*! +     * Create a gain group that represents the subdevice and its codec. +     * \param dboard_id the dboard id for this subdevice +     * \param subdev the object with subdevice properties +     * \param codec the object with codec properties +     * \param gain_group_policy the policy to use +     */ +    UHD_API gain_group::sptr make_gain_group( +        const dboard_id_t &dboard_id, +        wax::obj subdev, wax::obj codec, +        gain_group_policy_t gain_group_policy +    ); + +    /*! +     * Verify the rx subdevice specification. +     * If the subdev spec if empty, automatically fill it. +     * \param subdev_spec the subdev spec to verify/fill +     * \param mboard the motherboard properties object +     * \throw exception when the subdev spec is invalid +     */ +    UHD_API void verify_rx_subdev_spec(subdev_spec_t &subdev_spec, wax::obj mboard); + +    /*! +     * Verify the tx subdevice specification. +     * If the subdev spec if empty, automatically fill it. +     * \param subdev_spec the subdev spec to verify/fill +     * \param mboard the motherboard properties object +     * \throw exception when the subdev spec is invalid +     */ +    UHD_API void verify_tx_subdev_spec(subdev_spec_t &subdev_spec, wax::obj mboard); + +}} //namespace + +#endif /* INCLUDED_UHD_USRP_MISC_UTILS_HPP */ + diff --git a/host/include/uhd/usrp/multi_usrp.hpp b/host/include/uhd/usrp/multi_usrp.hpp new file mode 100644 index 000000000..5380d177d --- /dev/null +++ b/host/include/uhd/usrp/multi_usrp.hpp @@ -0,0 +1,522 @@ +// +// Copyright 2010 Ettus Research LLC +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program.  If not, see <http://www.gnu.org/licenses/>. +// + +#ifndef INCLUDED_UHD_USRP_MULTI_USRP_HPP +#define INCLUDED_UHD_USRP_MULTI_USRP_HPP + +#include <uhd/config.hpp> +#include <uhd/device.hpp> +#include <uhd/types/ranges.hpp> +#include <uhd/types/stream_cmd.hpp> +#include <uhd/types/clock_config.hpp> +#include <uhd/types/tune_request.hpp> +#include <uhd/types/tune_result.hpp> +#include <uhd/usrp/subdev_spec.hpp> +#include <uhd/usrp/dboard_iface.hpp> +#include <boost/shared_ptr.hpp> +#include <boost/utility.hpp> +#include <vector> + +namespace uhd{ namespace usrp{ + +/*! + * The multi-USRP device class: + * A multi-USRP facilitates ease-of-use for multiple USRP scenarios. + * The wrapper provides convenience functions to control the group + * of underlying devices as if they consisted of a single device. + * + * A few notes about a multi-USRP configuration: + *  - All boards share a common RX sample rate + *  - All boards share a common TX sample rate + *  - All boards share a common RX subdevice specification size + *  - All boards share a common TX subdevice specification size + *  - All boards must have synchronized times (see the set_time_*() calls) + * + * Example to setup channel mapping: + * <pre> + * + * //create a multi_usrp with two boards in the configuration + * device_addr_t dev_addr; + * dev_addr["addr"] = "192.168.10.2 192.168.10.3"; + * multi_usrp::sptr dev = multi_usrp::make(dev_addr); + * + * //set the board on 10.2 to use the A RX subdevice (RX channel 0) + * dev->set_rx_subdev_spec(":A", 0); + * + * //set the board on 10.3 to use the B RX subdevice (RX channel 1) + * dev->set_rx_subdev_spec(":B", 1); + * + * //set both boards to use the AB TX subdevice (TX channels 0 and 1) + * dev->set_tx_subdev_spec(":AB", multi_usrp::ALL_MBOARDS); + * + * //now that all the channels are mapped, continue with configuration... + * + * </pre> + */ +class UHD_API multi_usrp : boost::noncopyable{ +public: +    typedef boost::shared_ptr<multi_usrp> sptr; + +    //! A wildcard motherboard index +    static const size_t ALL_MBOARDS = size_t(~0); + +    //! A wildcard gain element name +    static const std::string ALL_GAINS; + +    /*! +     * Make a new multi usrp from the device address. +     * \param dev_addr the device address +     * \return a new single usrp object +     */ +    static sptr make(const device_addr_t &dev_addr); + +    /*! +     * Get the underlying device object. +     * This is needed to get access to the streaming API and properties. +     * \return the device object within this single usrp +     */ +    virtual device::sptr get_device(void) = 0; + +    /******************************************************************* +     * Mboard methods +     ******************************************************************/ +    /*! +     * Get a printable summary for this USRP configuration. +     * \return a printable string +     */ +    virtual std::string get_pp_string(void) = 0; + +    /*! +     * Get canonical name for this USRP motherboard. +     * \param mboard which motherboard to query +     * \return a string representing the name +     */ +    virtual std::string get_mboard_name(size_t mboard) = 0; + +    /*! +     * Gets the current time in the usrp time registers. +     * \return a timespec representing current usrp time +     */ +    virtual time_spec_t get_time_now(void) = 0; + +    /*! +     * Set the time registers on the usrp at the next pps tick. +     * The values will not be latched in until the pulse occurs. +     * It is recommended that the user sleep(1) after calling to ensure +     * that the time registers will be in a known state prior to use. +     * +     * Note: Because this call sets the time on the "next" pps, +     * the seconds in the time spec should be current seconds + 1. +     * +     * \param time_spec the time to latch into the usrp device +     */ +    virtual void set_time_next_pps(const time_spec_t &time_spec) = 0; + +    /*! +     * Synchronize the times across all motherboards in this configuration. +     * Use this method to sync the times when the edge of the PPS is unknown. +     * +     * Ex: Host machine is not attached to serial port of GPSDO +     * and can therefore not query the GPSDO for the PPS edge. +     * +     * This is a 3-step process, and will take at most 3 seconds to complete. +     * Upon completion, the times will be synchronized to the time provided. +     * +     * - Step1: set the time at the next pps (potential race condition) +     * - Step2: wait for the seconds to rollover to catch the pps edge +     * - Step3: set the time at the next pps (synchronous for all boards) +     * +     * \param time_spec the time to latch into the usrp device +     */ +    virtual void set_time_unknown_pps(const time_spec_t &time_spec) = 0; + +    /*! +     * Issue a stream command to the usrp device. +     * This tells the usrp to send samples into the host. +     * See the documentation for stream_cmd_t for more info. +     * \param stream_cmd the stream command to issue +     */ +    virtual void issue_stream_cmd(const stream_cmd_t &stream_cmd) = 0; + +    /*! +     * Set the clock configuration for the usrp device. +     * This tells the usrp how to get a 10Mhz reference and PPS clock. +     * See the documentation for clock_config_t for more info. +     * \param clock_config the clock configuration to set +     * \param mboard which motherboard to set the config +     */ +    virtual void set_clock_config(const clock_config_t &clock_config, size_t mboard) = 0; + +    /*! +     * Get the number of USRP motherboards in this configuration. +     */ +    virtual size_t get_num_mboards(void) = 0; + +    /******************************************************************* +     * RX methods +     ******************************************************************/ +    /*! +     * Set the RX subdevice specification: +     * The subdev spec maps a physical part of a daughter-board to a channel number. +     * Set the subdev spec before calling into any methods with a channel number. +     * The subdev spec must be the same size across all motherboards. +     * \param spec the new subdevice specification +     * \param mboard the motherboard index 0 to M-1 +     */ +    virtual void set_rx_subdev_spec(const uhd::usrp::subdev_spec_t &spec, size_t mboard) = 0; + +    /*! +     * Get the RX subdevice specification. +     * \param mboard the motherboard index 0 to M-1 +     * \return the subdevice specification in use +     */ +    virtual uhd::usrp::subdev_spec_t get_rx_subdev_spec(size_t mboard) = 0; + +    /*! +     * Get the number of RX channels in this configuration. +     * This is the number of USRPs times the number of RX channels per board, +     * where the number of RX channels per board is homogeneous among all USRPs. +     */ +    virtual size_t get_rx_num_channels(void) = 0; + +    /*! +     * Get the name of the RX subdevice. +     * \param chan the channel index 0 to N-1 +     * \return the subdevice name +     */ +    virtual std::string get_rx_subdev_name(size_t chan) = 0; + +    /*! +     * Set the RX sample rate across all channels. +     * \param rate the rate in Sps +     */ +    virtual void set_rx_rate(double rate) = 0; + +    /*! +     * Gets the RX sample rate for all channels. +     * \return the rate in Sps +     */ +    virtual double get_rx_rate(void) = 0; + +    /*! +     * Set the RX center frequency. +     * \param tune_request tune request instructions +     * \param chan the channel index 0 to N-1 +     * \return a tune result object +     */ +    virtual tune_result_t set_rx_freq( +        const tune_request_t &tune_request, size_t chan = 0 +    ) = 0; + +    /*! +     * Get the RX center frequency. +     * \param chan the channel index 0 to N-1 +     * \return the frequency in Hz +     */ +    virtual double get_rx_freq(size_t chan) = 0; + +    /*! +     * Get the RX center frequency range. +     * \param chan the channel index 0 to N-1 +     * \return a frequency range object +     */ +    virtual freq_range_t get_rx_freq_range(size_t chan) = 0; + +    /*! +     * Set the RX gain value for the specified gain element. +     * For an empty name, distribute across all gain elements. +     * \param gain the gain in dB +     * \param name the name of the gain element +     * \param chan the channel index 0 to N-1 +     */ +    virtual void set_rx_gain(float gain, const std::string &name, size_t chan) = 0; + +    //! A convenience wrapper for setting overall RX gain +    void set_rx_gain(float gain, size_t chan){ +        return this->set_rx_gain(gain, ALL_GAINS, chan); +    } + +    /*! +     * Get the RX gain value for the specified gain element. +     * For an empty name, sum across all gain elements. +     * \param name the name of the gain element +     * \param chan the channel index 0 to N-1 +     * \return the gain in dB +     */ +    virtual float get_rx_gain(const std::string &name, size_t chan) = 0; + +    //! A convenience wrapper for getting overall RX gain +    float get_rx_gain(size_t chan){ +        return this->get_rx_gain(ALL_GAINS, chan); +    } + +    /*! +     * Get the RX gain range for the specified gain element. +     * For an empty name, calculate the overall gain range. +     * \param name the name of the gain element +     * \param chan the channel index 0 to N-1 +     * \return a gain range object +     */ +    virtual gain_range_t get_rx_gain_range(const std::string &name, size_t chan) = 0; + +    //! A convenience wrapper for getting overall RX gain range +    gain_range_t get_rx_gain_range(size_t chan){ +        return this->get_rx_gain_range(ALL_GAINS, chan); +    } + +    /*! +     * Get the names of the gain elements in the RX chain. +     * Gain elements are ordered from antenna to FPGA. +     * \param chan the channel index 0 to N-1 +     * \return a vector of gain element names +     */ +    virtual std::vector<std::string> get_rx_gain_names(size_t chan) = 0; + +    /*! +     * Select the RX antenna on the subdevice. +     * \param ant the antenna name +     * \param chan the channel index 0 to N-1 +     */ +    virtual void set_rx_antenna(const std::string &ant, size_t chan) = 0; + +    /*! +     * Get the selected RX antenna on the subdevice. +     * \param chan the channel index 0 to N-1 +     * \return the antenna name +     */ +    virtual std::string get_rx_antenna(size_t chan) = 0; + +    /*! +     * Get a list of possible RX antennas on the subdevice. +     * \param chan the channel index 0 to N-1 +     * \return a vector of antenna names +     */ +    virtual std::vector<std::string> get_rx_antennas(size_t chan) = 0; + +    /*! +     * Get the locked status of the LO on the subdevice. +     * \param chan the channel index 0 to N-1 +     * \return true for locked +     */ +    virtual bool get_rx_lo_locked(size_t chan) = 0; + +    /*! +     * Set the RX bandwidth on the subdevice. +     * \param bandwidth the bandwidth in Hz +     * \param chan the channel index 0 to N-1 +     */ +    virtual void set_rx_bandwidth(double bandwidth, size_t chan) = 0; + +    /*! +     * Get the RX bandwidth on the subdevice. +     * \param chan the channel index 0 to N-1 +     * \return the bandwidth in Hz +     */ +    virtual double get_rx_bandwidth(size_t chan) = 0; + +    /*! +     * Read the RSSI value on the RX subdevice. +     * \param chan the channel index 0 to N-1 +     * \return the rssi in dB +     * \throw exception if RSSI readback not supported +     */ +    virtual float read_rssi(size_t chan) = 0; + +    /*! +     * Get the dboard interface object for the RX subdevice. +     * The dboard interface gives access to GPIOs, SPI, I2C, low-speed ADC and DAC. +     * Use at your own risk! +     * \param chan the channel index 0 to N-1 +     * \return the dboard interface sptr +     */ +    virtual dboard_iface::sptr get_rx_dboard_iface(size_t chan) = 0; + +    /******************************************************************* +     * TX methods +     ******************************************************************/ +    /*! +     * Set the TX subdevice specification: +     * The subdev spec maps a physical part of a daughter-board to a channel number. +     * Set the subdev spec before calling into any methods with a channel number. +     * The subdev spec must be the same size across all motherboards. +     * \param spec the new subdevice specification +     * \param mboard the motherboard index 0 to M-1 +     */ +    virtual void set_tx_subdev_spec(const uhd::usrp::subdev_spec_t &spec, size_t mboard) = 0; + +    /*! +     * Get the TX subdevice specification. +     * \param mboard the motherboard index 0 to M-1 +     * \return the subdevice specification in use +     */ +    virtual uhd::usrp::subdev_spec_t get_tx_subdev_spec(size_t mboard) = 0; + +    /*! +     * Get the number of TX channels in this configuration. +     * This is the number of USRPs times the number of TX channels per board, +     * where the number of TX channels per board is homogeneous among all USRPs. +     */ +    virtual size_t get_tx_num_channels(void) = 0; + +    /*! +     * Get the name of the TX subdevice. +     * \param chan the channel index 0 to N-1 +     * \return the subdevice name +     */ +    virtual std::string get_tx_subdev_name(size_t chan) = 0; + +    /*! +     * Set the TX sample rate across all channels. +     * \param rate the rate in Sps +     */ +    virtual void set_tx_rate(double rate) = 0; + +    /*! +     * Gets the TX sample rate for all channels. +     * \return the rate in Sps +     */ +    virtual double get_tx_rate(void) = 0; + +    /*! +     * Set the TX center frequency. +     * \param tune_request tune request instructions +     * \param chan the channel index 0 to N-1 +     * \return a tune result object +     */ +    virtual tune_result_t set_tx_freq( +        const tune_request_t &tune_request, size_t chan = 0 +    ) = 0; + +    /*! +     * Get the TX center frequency. +     * \param chan the channel index 0 to N-1 +     * \return the frequency in Hz +     */ +    virtual double get_tx_freq(size_t chan) = 0; + +    /*! +     * Get the TX center frequency range. +     * \param chan the channel index 0 to N-1 +     * \return a frequency range object +     */ +    virtual freq_range_t get_tx_freq_range(size_t chan) = 0; + +    /*! +     * Set the TX gain value for the specified gain element. +     * For an empty name, distribute across all gain elements. +     * \param gain the gain in dB +     * \param name the name of the gain element +     * \param chan the channel index 0 to N-1 +     */ +    virtual void set_tx_gain(float gain, const std::string &name, size_t chan) = 0; + +    //! A convenience wrapper for setting overall TX gain +    void set_tx_gain(float gain, size_t chan){ +        return this->set_tx_gain(gain, ALL_GAINS, chan); +    } + +    /*! +     * Get the TX gain value for the specified gain element. +     * For an empty name, sum across all gain elements. +     * \param name the name of the gain element +     * \param chan the channel index 0 to N-1 +     * \return the gain in dB +     */ +    virtual float get_tx_gain(const std::string &name, size_t chan) = 0; + +    //! A convenience wrapper for getting overall TX gain +    float get_tx_gain(size_t chan){ +        return this->get_tx_gain(ALL_GAINS, chan); +    } + +    /*! +     * Get the TX gain range for the specified gain element. +     * For an empty name, calculate the overall gain range. +     * \param name the name of the gain element +     * \param chan the channel index 0 to N-1 +     * \return a gain range object +     */ +    virtual gain_range_t get_tx_gain_range(const std::string &name, size_t chan) = 0; + +    //! A convenience wrapper for getting overall TX gain range +    gain_range_t get_tx_gain_range(size_t chan){ +        return this->get_tx_gain_range(ALL_GAINS, chan); +    } + +    /*! +     * Get the names of the gain elements in the TX chain. +     * Gain elements are ordered from antenna to FPGA. +     * \param chan the channel index 0 to N-1 +     * \return a vector of gain element names +     */ +    virtual std::vector<std::string> get_tx_gain_names(size_t chan) = 0; + +    /*! +     * Select the TX antenna on the subdevice. +     * \param ant the antenna name +     * \param chan the channel index 0 to N-1 +     */ +    virtual void set_tx_antenna(const std::string &ant, size_t chan) = 0; + +    /*! +     * Get the selected TX antenna on the subdevice. +     * \param chan the channel index 0 to N-1 +     * \return the antenna name +     */ +    virtual std::string get_tx_antenna(size_t chan) = 0; + +    /*! +     * Get a list of possible TX antennas on the subdevice. +     * \param chan the channel index 0 to N-1 +     * \return a vector of antenna names +     */ +    virtual std::vector<std::string> get_tx_antennas(size_t chan) = 0; + +    /*! +     * Get the locked status of the LO on the subdevice. +     * \param chan the channel index 0 to N-1 +     * \return true for locked +     */ +    virtual bool get_tx_lo_locked(size_t chan) = 0; + +    /*! +     * Set the TX bandwidth on the subdevice. +     * \param bandwidth the bandwidth in Hz +     * \param chan the channel index 0 to N-1 +     */ +    virtual void set_tx_bandwidth(double bandwidth, size_t chan) = 0; + +    /*! +     * Get the TX bandwidth on the subdevice. +     * \param chan the channel index 0 to N-1 +     * \return the bandwidth in Hz +     */ +    virtual double get_tx_bandwidth(size_t chan) = 0; + +    /*! +     * Get the dboard interface object for the TX subdevice. +     * The dboard interface gives access to GPIOs, SPI, I2C, low-speed ADC and DAC. +     * Use at your own risk! +     * \param chan the channel index 0 to N-1 +     * \return the dboard interface sptr +     */ +    virtual dboard_iface::sptr get_tx_dboard_iface(size_t chan) = 0; +}; + +}} + +#endif /* INCLUDED_UHD_USRP_MULTI_USRP_HPP */ diff --git a/host/include/uhd/usrp/simple_usrp.hpp b/host/include/uhd/usrp/simple_usrp.hpp new file mode 100644 index 000000000..77416dbbd --- /dev/null +++ b/host/include/uhd/usrp/simple_usrp.hpp @@ -0,0 +1,388 @@ +// +// Copyright 2010 Ettus Research LLC +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program.  If not, see <http://www.gnu.org/licenses/>. +// + +#ifndef INCLUDED_UHD_USRP_SIMPLE_USRP_HPP +#define INCLUDED_UHD_USRP_SIMPLE_USRP_HPP + +#include <uhd/config.hpp> +#include <uhd/device.hpp> +#include <uhd/types/ranges.hpp> +#include <uhd/types/stream_cmd.hpp> +#include <uhd/types/clock_config.hpp> +#include <uhd/types/tune_result.hpp> +#include <uhd/usrp/subdev_spec.hpp> +#include <uhd/usrp/dboard_iface.hpp> +#include <boost/shared_ptr.hpp> +#include <boost/utility.hpp> +#include <vector> + +namespace uhd{ namespace usrp{ + +/*! + * The simple USRP device class (DEPRECATED): + * This interface has been deprecated in favor of the single USRP interface. + * A simple usrp 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 UHD_API UHD_DEPRECATED simple_usrp : boost::noncopyable{ +public: +    typedef boost::shared_ptr<simple_usrp> sptr; + +    /*! +     * Make a new simple usrp from the device address. +     * \param dev_addr the device address +     * \return a new simple usrp object +     */ +    static sptr make(const device_addr_t &dev_addr); + +    /*! +     * Get the underlying device object. +     * This is needed to get access to the streaming API and properties. +     * \return the device object within this simple usrp +     */ +    virtual device::sptr get_device(void) = 0; + +    /*! +     * Get a printable name for this simple usrp. +     * \return a printable string +     */ +    virtual std::string get_pp_string(void) = 0; + +    /******************************************************************* +     * Misc +     ******************************************************************/ +    /*! +     * Gets the current time in the usrp time registers. +     * \return a timespec representing current usrp time +     */ +    virtual time_spec_t get_time_now(void) = 0; + +    /*! +     * Sets the time registers on the usrp immediately. +     * \param time_spec the time to latch into the usrp device +     */ +    virtual void set_time_now(const time_spec_t &time_spec) = 0; + +    /*! +     * Set the time registers on the usrp at the next pps tick. +     * The values will not be latched in until the pulse occurs. +     * It is recommended that the user sleep(1) after calling to ensure +     * that the time registers will be in a known state prior to use. +     * +     * Note: Because this call sets the time on the "next" pps, +     * the seconds in the time spec should be current seconds + 1. +     * +     * \param time_spec the time to latch into the usrp device +     */ +    virtual void set_time_next_pps(const time_spec_t &time_spec) = 0; + +    /*! +     * Issue a stream command to the usrp device. +     * This tells the usrp to send samples into the host. +     * See the documentation for stream_cmd_t for more info. +     * \param stream_cmd the stream command to issue +     */ +    virtual void issue_stream_cmd(const stream_cmd_t &stream_cmd) = 0; + +    /*! +     * Set the clock configuration for the usrp device. +     * This tells the usrp how to get a 10Mhz reference and PPS clock. +     * See the documentation for clock_config_t for more info. +     * \param clock_config the clock configuration to set +     */ +    virtual void set_clock_config(const clock_config_t &clock_config) = 0; + +    /******************************************************************* +     * RX methods +     ******************************************************************/ +    virtual void set_rx_subdev_spec(const uhd::usrp::subdev_spec_t &spec) = 0; +    virtual uhd::usrp::subdev_spec_t get_rx_subdev_spec(void) = 0; + +    virtual void set_rx_rate(double rate) = 0; +    virtual double get_rx_rate(void) = 0; + +    virtual tune_result_t set_rx_freq(double freq) = 0; +    //virtual tune_result_t set_rx_freq(double freq, double lo_off) = 0; +    virtual double get_rx_freq(void) = 0; +    virtual freq_range_t get_rx_freq_range(void) = 0; + +    virtual void set_rx_gain(float gain) = 0; +    virtual float get_rx_gain(void) = 0; +    virtual gain_range_t 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; + +    virtual bool get_rx_lo_locked(void) = 0; + +    /*! +     * Read the RSSI value from a usrp device. +     * Or throw if the dboard does not support an RSSI readback. +     * \return the rssi in dB +     */ +    virtual float read_rssi(void) = 0; + +    virtual dboard_iface::sptr get_rx_dboard_iface(void) = 0; +     +    virtual void set_rx_bandwidth(float) = 0; + +    /******************************************************************* +     * TX methods +     ******************************************************************/ +    virtual void set_tx_subdev_spec(const uhd::usrp::subdev_spec_t &spec) = 0; +    virtual uhd::usrp::subdev_spec_t get_tx_subdev_spec(void) = 0; + +    virtual void set_tx_rate(double rate) = 0; +    virtual double get_tx_rate(void) = 0; + +    virtual tune_result_t set_tx_freq(double freq) = 0; +    //virtual tune_result_t set_tx_freq(double freq, double lo_off) = 0; +    virtual double get_tx_freq(void) = 0; +    virtual freq_range_t get_tx_freq_range(void) = 0; + +    virtual void set_tx_gain(float gain) = 0; +    virtual float get_tx_gain(void) = 0; +    virtual gain_range_t 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; + +    virtual bool get_tx_lo_locked(void) = 0; + +    virtual dboard_iface::sptr get_tx_dboard_iface(void) = 0; +}; + +}} + +#include <uhd/usrp/single_usrp.hpp> +#include <uhd/utils/warning.hpp> + +namespace uhd{ namespace usrp{ namespace /*anon*/{ + +/*********************************************************************** + * Simple USRP Implementation + **********************************************************************/ +class simple_usrp_impl : public simple_usrp{ +public: +    simple_usrp_impl(const device_addr_t &addr){ +        _sdev = single_usrp::make(addr); +    } + +    ~simple_usrp_impl(void){ +        /* NOP */ +    } + +    device::sptr get_device(void){ +        return _sdev->get_device(); +    } + +    std::string get_pp_string(void){ +        return _sdev->get_pp_string(); +    } + +    /******************************************************************* +     * Misc +     ******************************************************************/ +    time_spec_t get_time_now(void){ +        return _sdev->get_time_now(); +    } + +    void set_time_now(const time_spec_t &time_spec){ +        return _sdev->set_time_now(time_spec); +    } + +    void set_time_next_pps(const time_spec_t &time_spec){ +        return _sdev->set_time_next_pps(time_spec); +    } + +    void issue_stream_cmd(const stream_cmd_t &stream_cmd){ +        return _sdev->issue_stream_cmd(stream_cmd); +    } + +    void set_clock_config(const clock_config_t &clock_config){ +        return _sdev->set_clock_config(clock_config); +    } + +    /******************************************************************* +     * RX methods +     ******************************************************************/ +    void set_rx_subdev_spec(const subdev_spec_t &spec){ +        return _sdev->set_rx_subdev_spec(spec); +    } + +    subdev_spec_t get_rx_subdev_spec(void){ +        return _sdev->get_rx_subdev_spec(); +    } + +    void set_rx_rate(double rate){ +        return _sdev->set_rx_rate(rate); +    } + +    double get_rx_rate(void){ +        return _sdev->get_rx_rate(); +    } + +    tune_result_t set_rx_freq(double target_freq){ +        return _sdev->set_rx_freq(target_freq); +    } + +    //tune_result_t set_rx_freq(double target_freq, double lo_off){ +    //    return _sdev->set_rx_freq(target_freq, lo_off); +    //} + +    double get_rx_freq(void){ +        return _sdev->get_rx_freq(); +    } + +    freq_range_t get_rx_freq_range(void){ +        return _sdev->get_rx_freq_range(); +    } + +    void set_rx_gain(float gain){ +        return _sdev->set_rx_gain(gain); +    } + +    float get_rx_gain(void){ +        return _sdev->get_rx_gain(); +    } + +    gain_range_t get_rx_gain_range(void){ +        return _sdev->get_rx_gain_range(); +    } + +    void set_rx_antenna(const std::string &ant){ +        return _sdev->set_rx_antenna(ant); +    } + +    std::string get_rx_antenna(void){ +        return _sdev->get_rx_antenna(); +    } + +    std::vector<std::string> get_rx_antennas(void){ +        return _sdev->get_rx_antennas(); +    } + +    bool get_rx_lo_locked(void){ +        return _sdev->get_rx_lo_locked(); +    } + +    float read_rssi(void){ +        return _sdev->read_rssi(); +    } + +    dboard_iface::sptr get_rx_dboard_iface(void){ +        return _sdev->get_rx_dboard_iface(); +    } +     +    void set_rx_bandwidth(float bandwidth) { +        return _sdev->set_rx_bandwidth(bandwidth); +    } + +    /******************************************************************* +     * TX methods +     ******************************************************************/ +    void set_tx_subdev_spec(const subdev_spec_t &spec){ +        return _sdev->set_tx_subdev_spec(spec); +    } + +    subdev_spec_t get_tx_subdev_spec(void){ +        return _sdev->get_tx_subdev_spec(); +    } + +    void set_tx_rate(double rate){ +        return _sdev->set_tx_rate(rate); +    } + +    double get_tx_rate(void){ +        return _sdev->get_tx_rate(); +    } + +    tune_result_t set_tx_freq(double target_freq){ +        return _sdev->set_tx_freq(target_freq); +    } + +    //tune_result_t set_tx_freq(double target_freq, double lo_off){ +    //    return _sdev->set_tx_freq(target_freq, lo_off); +    //} + +    double get_tx_freq(void){ +        return _sdev->get_tx_freq(); +    } + +    freq_range_t get_tx_freq_range(void){ +        return _sdev->get_tx_freq_range(); +    } + +    void set_tx_gain(float gain){ +        return _sdev->set_tx_gain(gain); +    } + +    float get_tx_gain(void){ +        return _sdev->get_tx_gain(); +    } + +    gain_range_t get_tx_gain_range(void){ +        return _sdev->get_tx_gain_range(); +    } + +    void set_tx_antenna(const std::string &ant){ +        return _sdev->set_tx_antenna(ant); +    } + +    std::string get_tx_antenna(void){ +        return _sdev->get_tx_antenna(); +    } + +    std::vector<std::string> get_tx_antennas(void){ +        return _sdev->get_tx_antennas(); +    } + +    bool get_tx_lo_locked(void){ +        return _sdev->get_tx_lo_locked(); +    } + +    dboard_iface::sptr get_tx_dboard_iface(void){ +        return _sdev->get_tx_dboard_iface(); +    } + +private: +    single_usrp::sptr _sdev; +}; + +}}} + +namespace uhd{ namespace usrp{ + +/*********************************************************************** + * The Make Function + **********************************************************************/ +inline simple_usrp::sptr simple_usrp::make(const device_addr_t &dev_addr){ +    uhd::warning::post( +        "The simple USRP interface has been deprecated.\n" +        "Please switch to the single USRP interface.\n" +        "#include <uhd/usrp/single_usrp.hpp>\n" +        "single_usrp::sptr sdev = single_usrp::make(args);\n" +    ); +    return sptr(new simple_usrp_impl(dev_addr)); +} + +}} + +#endif /* INCLUDED_UHD_USRP_SIMPLE_USRP_HPP */ diff --git a/host/include/uhd/usrp/single_usrp.hpp b/host/include/uhd/usrp/single_usrp.hpp new file mode 100644 index 000000000..26303fe10 --- /dev/null +++ b/host/include/uhd/usrp/single_usrp.hpp @@ -0,0 +1,453 @@ +// +// Copyright 2010 Ettus Research LLC +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program.  If not, see <http://www.gnu.org/licenses/>. +// + +#ifndef INCLUDED_UHD_USRP_SINGLE_USRP_HPP +#define INCLUDED_UHD_USRP_SINGLE_USRP_HPP + +#include <uhd/config.hpp> +#include <uhd/device.hpp> +#include <uhd/types/ranges.hpp> +#include <uhd/types/stream_cmd.hpp> +#include <uhd/types/clock_config.hpp> +#include <uhd/types/tune_request.hpp> +#include <uhd/types/tune_result.hpp> +#include <uhd/usrp/subdev_spec.hpp> +#include <uhd/usrp/dboard_iface.hpp> +#include <boost/shared_ptr.hpp> +#include <boost/utility.hpp> +#include <vector> + +namespace uhd{ namespace usrp{ + +/*! + * The single-USRP device class: + * A single-USRP 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. + * This wrapper supports multi-channel configurations per motherboard. + */ +class UHD_API single_usrp : boost::noncopyable{ +public: +    typedef boost::shared_ptr<single_usrp> sptr; + +    //! A wildcard gain element name +    static const std::string ALL_GAINS; + +    /*! +     * Make a new single usrp from the device address. +     * \param dev_addr the device address +     * \return a new single usrp object +     */ +    static sptr make(const device_addr_t &dev_addr); + +    /*! +     * Get the underlying device object. +     * This is needed to get access to the streaming API and properties. +     * \return the device object within this single usrp +     */ +    virtual device::sptr get_device(void) = 0; + +    /******************************************************************* +     * Mboard methods +     ******************************************************************/ +    /*! +     * Get a printable summary for this USRP configuration. +     * \return a printable string +     */ +    virtual std::string get_pp_string(void) = 0; + +    /*! +     * Get canonical name for this USRP motherboard. +     * \return a string representing the name +     */ +    virtual std::string get_mboard_name(void) = 0; + +    /*! +     * Gets the current time in the usrp time registers. +     * \return a timespec representing current usrp time +     */ +    virtual time_spec_t get_time_now(void) = 0; + +    /*! +     * Sets the time registers on the usrp immediately. +     * \param time_spec the time to latch into the usrp device +     */ +    virtual void set_time_now(const time_spec_t &time_spec) = 0; + +    /*! +     * Set the time registers on the usrp at the next pps tick. +     * The values will not be latched in until the pulse occurs. +     * It is recommended that the user sleep(1) after calling to ensure +     * that the time registers will be in a known state prior to use. +     * +     * Note: Because this call sets the time on the "next" pps, +     * the seconds in the time spec should be current seconds + 1. +     * +     * \param time_spec the time to latch into the usrp device +     */ +    virtual void set_time_next_pps(const time_spec_t &time_spec) = 0; + +    /*! +     * Issue a stream command to the usrp device. +     * This tells the usrp to send samples into the host. +     * See the documentation for stream_cmd_t for more info. +     * \param stream_cmd the stream command to issue +     */ +    virtual void issue_stream_cmd(const stream_cmd_t &stream_cmd) = 0; + +    /*! +     * Set the clock configuration for the usrp device. +     * This tells the usrp how to get a 10Mhz reference and PPS clock. +     * See the documentation for clock_config_t for more info. +     * \param clock_config the clock configuration to set +     */ +    virtual void set_clock_config(const clock_config_t &clock_config) = 0; + +    /******************************************************************* +     * RX methods +     ******************************************************************/ +    /*! +     * Set the RX subdevice specification: +     * The subdev spec maps a physical part of a daughter-board to a channel number. +     * Set the subdev spec before calling into any methods with a channel number. +     * \param spec the new subdevice specification +     */ +    virtual void set_rx_subdev_spec(const uhd::usrp::subdev_spec_t &spec) = 0; + +    /*! +     * Get the RX subdevice specification. +     * \return the subdevice specification in use +     */ +    virtual uhd::usrp::subdev_spec_t get_rx_subdev_spec(void) = 0; + +    /*! +     * Get the name of the RX subdevice. +     * \param chan the channel index 0 to N-1 +     * \return the subdevice name +     */ +    virtual std::string get_rx_subdev_name(size_t chan = 0) = 0; + +    /*! +     * Set the RX sample rate across all channels. +     * \param rate the rate in Sps +     */ +    virtual void set_rx_rate(double rate) = 0; + +    /*! +     * Gets the RX sample rate for all channels. +     * \return the rate in Sps +     */ +    virtual double get_rx_rate(void) = 0; + +    /*! +     * Set the RX center frequency. +     * \param tune_request tune request instructions +     * \param chan the channel index 0 to N-1 +     * \return a tune result object +     */ +    virtual tune_result_t set_rx_freq( +        const tune_request_t &tune_request, size_t chan = 0 +    ) = 0; + +    /*! +     * Get the RX center frequency. +     * \param chan the channel index 0 to N-1 +     * \return the frequency in Hz +     */ +    virtual double get_rx_freq(size_t chan = 0) = 0; + +    /*! +     * Get the RX center frequency range. +     * \param chan the channel index 0 to N-1 +     * \return a frequency range object +     */ +    virtual freq_range_t get_rx_freq_range(size_t chan = 0) = 0; + +    /*! +     * Set the RX gain value for the specified gain element. +     * For an empty name, distribute across all gain elements. +     * \param gain the gain in dB +     * \param name the name of the gain element +     * \param chan the channel index 0 to N-1 +     */ +    virtual void set_rx_gain(float gain, const std::string &name, size_t chan = 0) = 0; + +    //! A convenience wrapper for setting overall RX gain +    void set_rx_gain(float gain, size_t chan = 0){ +        return this->set_rx_gain(gain, ALL_GAINS, chan); +    } + +    /*! +     * Get the RX gain value for the specified gain element. +     * For an empty name, sum across all gain elements. +     * \param name the name of the gain element +     * \param chan the channel index 0 to N-1 +     * \return the gain in dB +     */ +    virtual float get_rx_gain(const std::string &name, size_t chan = 0) = 0; + +    //! A convenience wrapper for getting overall RX gain +    float get_rx_gain(size_t chan = 0){ +        return this->get_rx_gain(ALL_GAINS, chan); +    } + +    /*! +     * Get the RX gain range for the specified gain element. +     * For an empty name, calculate the overall gain range. +     * \param name the name of the gain element +     * \param chan the channel index 0 to N-1 +     * \return a gain range object +     */ +    virtual gain_range_t get_rx_gain_range(const std::string &name, size_t chan = 0) = 0; + +    //! A convenience wrapper for getting overall RX gain range +    gain_range_t get_rx_gain_range(size_t chan = 0){ +        return this->get_rx_gain_range(ALL_GAINS, chan); +    } + +    /*! +     * Get the names of the gain elements in the RX chain. +     * Gain elements are ordered from antenna to FPGA. +     * \param chan the channel index 0 to N-1 +     * \return a vector of gain element names +     */ +    virtual std::vector<std::string> get_rx_gain_names(size_t chan = 0) = 0; + +    /*! +     * Select the RX antenna on the subdevice. +     * \param ant the antenna name +     * \param chan the channel index 0 to N-1 +     */ +    virtual void set_rx_antenna(const std::string &ant, size_t chan = 0) = 0; + +    /*! +     * Get the selected RX antenna on the subdevice. +     * \param chan the channel index 0 to N-1 +     * \return the antenna name +     */ +    virtual std::string get_rx_antenna(size_t chan = 0) = 0; + +    /*! +     * Get a list of possible RX antennas on the subdevice. +     * \param chan the channel index 0 to N-1 +     * \return a vector of antenna names +     */ +    virtual std::vector<std::string> get_rx_antennas(size_t chan = 0) = 0; + +    /*! +     * Get the locked status of the LO on the subdevice. +     * \param chan the channel index 0 to N-1 +     * \return true for locked +     */ +    virtual bool get_rx_lo_locked(size_t chan = 0) = 0; + +    /*! +     * Set the RX bandwidth on the subdevice. +     * \param bandwidth the bandwidth in Hz +     * \param chan the channel index 0 to N-1 +     */ +    virtual void set_rx_bandwidth(double bandwidth, size_t chan = 0) = 0; + +    /*! +     * Get the RX bandwidth on the subdevice. +     * \param chan the channel index 0 to N-1 +     * \return the bandwidth in Hz +     */ +    virtual double get_rx_bandwidth(size_t chan = 0) = 0; + +    /*! +     * Read the RSSI value on the RX subdevice. +     * \param chan the channel index 0 to N-1 +     * \return the rssi in dB +     * \throw exception if RSSI readback not supported +     */ +    virtual float read_rssi(size_t chan = 0) = 0; + +    /*! +     * Get the dboard interface object for the RX subdevice. +     * The dboard interface gives access to GPIOs, SPI, I2C, low-speed ADC and DAC. +     * Use at your own risk! +     * \param chan the channel index 0 to N-1 +     * \return the dboard interface sptr +     */ +    virtual dboard_iface::sptr get_rx_dboard_iface(size_t chan = 0) = 0; + +    /******************************************************************* +     * TX methods +     ******************************************************************/ +    /*! +     * Set the TX subdevice specification: +     * The subdev spec maps a physical part of a daughter-board to a channel number. +     * Set the subdev spec before calling into any methods with a channel number. +     * \param spec the new subdevice specification +     */ +    virtual void set_tx_subdev_spec(const uhd::usrp::subdev_spec_t &spec) = 0; + +    /*! +     * Get the TX subdevice specification. +     * \return the subdevice specification in use +     */ +    virtual uhd::usrp::subdev_spec_t get_tx_subdev_spec(void) = 0; + +    /*! +     * Get the name of the TX subdevice. +     * \param chan the channel index 0 to N-1 +     * \return the subdevice name +     */ +    virtual std::string get_tx_subdev_name(size_t chan = 0) = 0; + +    /*! +     * Set the TX sample rate across all channels. +     * \param rate the rate in Sps +     */ +    virtual void set_tx_rate(double rate) = 0; + +    /*! +     * Gets the TX sample rate for all channels. +     * \return the rate in Sps +     */ +    virtual double get_tx_rate(void) = 0; + +    /*! +     * Set the TX center frequency. +     * \param tune_request tune request instructions +     * \param chan the channel index 0 to N-1 +     * \return a tune result object +     */ +    virtual tune_result_t set_tx_freq( +        const tune_request_t &tune_request, size_t chan = 0 +    ) = 0; + +    /*! +     * Get the TX center frequency. +     * \param chan the channel index 0 to N-1 +     * \return the frequency in Hz +     */ +    virtual double get_tx_freq(size_t chan = 0) = 0; + +    /*! +     * Get the TX center frequency range. +     * \param chan the channel index 0 to N-1 +     * \return a frequency range object +     */ +    virtual freq_range_t get_tx_freq_range(size_t chan = 0) = 0; + +    /*! +     * Set the TX gain value for the specified gain element. +     * For an empty name, distribute across all gain elements. +     * \param gain the gain in dB +     * \param name the name of the gain element +     * \param chan the channel index 0 to N-1 +     */ +    virtual void set_tx_gain(float gain, const std::string &name, size_t chan = 0) = 0; + +    //! A convenience wrapper for setting overall TX gain +    void set_tx_gain(float gain, size_t chan = 0){ +        return this->set_tx_gain(gain, ALL_GAINS, chan); +    } + +    /*! +     * Get the TX gain value for the specified gain element. +     * For an empty name, sum across all gain elements. +     * \param name the name of the gain element +     * \param chan the channel index 0 to N-1 +     * \return the gain in dB +     */ +    virtual float get_tx_gain(const std::string &name, size_t chan = 0) = 0; + +    //! A convenience wrapper for getting overall TX gain +    float get_tx_gain(size_t chan = 0){ +        return this->get_tx_gain(ALL_GAINS, chan); +    } + +    /*! +     * Get the TX gain range for the specified gain element. +     * For an empty name, calculate the overall gain range. +     * \param name the name of the gain element +     * \param chan the channel index 0 to N-1 +     * \return a gain range object +     */ +    virtual gain_range_t get_tx_gain_range(const std::string &name, size_t chan = 0) = 0; + +    //! A convenience wrapper for getting overall TX gain range +    gain_range_t get_tx_gain_range(size_t chan = 0){ +        return this->get_tx_gain_range(ALL_GAINS, chan); +    } + +    /*! +     * Get the names of the gain elements in the TX chain. +     * Gain elements are ordered from antenna to FPGA. +     * \param chan the channel index 0 to N-1 +     * \return a vector of gain element names +     */ +    virtual std::vector<std::string> get_tx_gain_names(size_t chan = 0) = 0; + +    /*! +     * Select the TX antenna on the subdevice. +     * \param ant the antenna name +     * \param chan the channel index 0 to N-1 +     */ +    virtual void set_tx_antenna(const std::string &ant, size_t chan = 0) = 0; + +    /*! +     * Get the selected TX antenna on the subdevice. +     * \param chan the channel index 0 to N-1 +     * \return the antenna name +     */ +    virtual std::string get_tx_antenna(size_t chan = 0) = 0; + +    /*! +     * Get a list of possible TX antennas on the subdevice. +     * \param chan the channel index 0 to N-1 +     * \return a vector of antenna names +     */ +    virtual std::vector<std::string> get_tx_antennas(size_t chan = 0) = 0; + +    /*! +     * Get the locked status of the LO on the subdevice. +     * \param chan the channel index 0 to N-1 +     * \return true for locked +     */ +    virtual bool get_tx_lo_locked(size_t chan = 0) = 0; + +    /*! +     * Set the TX bandwidth on the subdevice. +     * \param bandwidth the bandwidth in Hz +     * \param chan the channel index 0 to N-1 +     */ +    virtual void set_tx_bandwidth(double bandwidth, size_t chan = 0) = 0; + +    /*! +     * Get the TX bandwidth on the subdevice. +     * \param chan the channel index 0 to N-1 +     * \return the bandwidth in Hz +     */ +    virtual double get_tx_bandwidth(size_t chan = 0) = 0; + +    /*! +     * Get the dboard interface object for the TX subdevice. +     * The dboard interface gives access to GPIOs, SPI, I2C, low-speed ADC and DAC. +     * Use at your own risk! +     * \param chan the channel index 0 to N-1 +     * \return the dboard interface sptr +     */ +    virtual dboard_iface::sptr get_tx_dboard_iface(size_t chan = 0) = 0; +}; + +}} + +#endif /* INCLUDED_UHD_USRP_SINGLE_USRP_HPP */ diff --git a/host/include/uhd/usrp/subdev_props.hpp b/host/include/uhd/usrp/subdev_props.hpp new file mode 100644 index 000000000..8f096ffe4 --- /dev/null +++ b/host/include/uhd/usrp/subdev_props.hpp @@ -0,0 +1,64 @@ +// +// Copyright 2010 Ettus Research LLC +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program.  If not, see <http://www.gnu.org/licenses/>. +// + +#ifndef INCLUDED_UHD_USRP_SUBDEV_PROPS_HPP +#define INCLUDED_UHD_USRP_SUBDEV_PROPS_HPP + +#include <uhd/utils/props.hpp> + +namespace uhd{ namespace usrp{ + +    /*! +     * Possible subdev connection types: +     * +     * A complex subdevice is physically connected to both channels, +     * which may be connected in one of two ways: IQ or QI (swapped). +     * +     * A real subdevice is only physically connected one channel, +     * either only the I channel or only the Q channel. +     */ +    enum subdev_conn_t{ +        SUBDEV_CONN_COMPLEX_IQ = 'C', +        SUBDEV_CONN_COMPLEX_QI = 'c', +        SUBDEV_CONN_REAL_I     = 'R', +        SUBDEV_CONN_REAL_Q     = 'r' +    }; + +    /*! +     * Possible device subdev properties +     */ +    enum subdev_prop_t{ +        SUBDEV_PROP_NAME              = 'n', //ro, std::string +        SUBDEV_PROP_OTHERS            = 'o', //ro, prop_names_t +        SUBDEV_PROP_GAIN              = 'g', //rw, float +        SUBDEV_PROP_GAIN_RANGE        = 'r', //ro, gain_range_t +        SUBDEV_PROP_GAIN_NAMES        = 'G', //ro, prop_names_t +        SUBDEV_PROP_FREQ              = 'f', //rw, double +        SUBDEV_PROP_FREQ_RANGE        = 'F', //ro, freq_range_t +        SUBDEV_PROP_ANTENNA           = 'a', //rw, std::string +        SUBDEV_PROP_ANTENNA_NAMES     = 'A', //ro, prop_names_t +        SUBDEV_PROP_LO_LOCKED         = 'L', //ro, bool +        SUBDEV_PROP_CONNECTION        = 'c', //ro, subdev_conn_t +        SUBDEV_PROP_ENABLED           = 'e', //rw, bool +        SUBDEV_PROP_USE_LO_OFFSET     = 'l', //ro, bool +        SUBDEV_PROP_RSSI              = 'R', //ro, float +        SUBDEV_PROP_BANDWIDTH         = 'B'  //rw, double +    }; + +}} //namespace + +#endif /* INCLUDED_UHD_USRP_SUBDEV_PROPS_HPP */ diff --git a/host/include/uhd/usrp/subdev_spec.hpp b/host/include/uhd/usrp/subdev_spec.hpp new file mode 100644 index 000000000..5de3bb3b8 --- /dev/null +++ b/host/include/uhd/usrp/subdev_spec.hpp @@ -0,0 +1,91 @@ +// +// Copyright 2010 Ettus Research LLC +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program.  If not, see <http://www.gnu.org/licenses/>. +// + +#ifndef INCLUDED_UHD_USRP_SUBDEV_SPEC_HPP +#define INCLUDED_UHD_USRP_SUBDEV_SPEC_HPP + +#include <uhd/config.hpp> +#include <boost/operators.hpp> +#include <vector> +#include <string> + +namespace uhd{ namespace usrp{ + +    /*! +     * A subdevice specification (daughterboard, subdevice) name pairing. +     */ +    struct UHD_API subdev_spec_pair_t : boost::equality_comparable<subdev_spec_pair_t>{ +        //! The daughterboard name +        std::string db_name; + +        //! The subdevice name +        std::string sd_name; + +        /*! +         * Create a new subdevice specification pair from dboard and subdev names. +         * \param db_name the name of a daughterboard slot +         * \param sd_name the name of a subdevice on that daughterboard +         */ +        subdev_spec_pair_t( +            const std::string &db_name = "", +            const std::string &sd_name = "" +        ); +    }; + +    //! overloaded comparison operator for subdev_spec_pair_t +    UHD_API bool operator==(const subdev_spec_pair_t &, const subdev_spec_pair_t &); + +    /*! +     * A list of (daughterboard name, subdevice name) pairs: +     * +     * A subdevice specification represents a list of subdevices on a motherboard. +     * The subdevices specified may span across multiple daughterboards; +     * Hence the need for a subdevice specification over a simple list of strings. +     * Typically, the user will pass a RX or TX subdevice specification into the API, +     * and the implementation will infer the channel configuration from the specification. +     * +     * The subdevice specification can be represented as a markup-string. +     * The markup-string is a whitespace separated list of dboard:subdev pairs. +     * The first pair represents the subdevice for channel zero, +     * the second pair represents the subdevice for channel one, and so on. +     */ +    class UHD_API subdev_spec_t : public std::vector<subdev_spec_pair_t>{ +    public: + +        /*! +         * Create a subdev specification from a markup string. +         * \param markup the markup string +         */ +        subdev_spec_t(const std::string &markup = ""); + +        /*! +         * Convert a subdev specification into a pretty print string. +         * \return a printable string representing the subdev specification +         */ +        std::string to_pp_string(void) const; + +        /*! +         * Convert the subdevice specification into a markup string. +         * The markup string contains the delimiter symbols. +         * \return a string with delimiter markup +         */ +        std::string to_string(void) const; +    }; + +}} + +#endif /* INCLUDED_UHD_USRP_SUBDEV_SPEC_HPP */ diff --git a/host/include/uhd/usrp/tune_helper.hpp b/host/include/uhd/usrp/tune_helper.hpp new file mode 100644 index 000000000..db12241c1 --- /dev/null +++ b/host/include/uhd/usrp/tune_helper.hpp @@ -0,0 +1,84 @@ +// +// Copyright 2010 Ettus Research LLC +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program.  If not, see <http://www.gnu.org/licenses/>. +// + +#ifndef INCLUDED_UHD_USRP_TUNE_HELPER_HPP +#define INCLUDED_UHD_USRP_TUNE_HELPER_HPP + +#include <uhd/config.hpp> +#include <uhd/wax.hpp> +#include <uhd/types/tune_request.hpp> +#include <uhd/types/tune_result.hpp> + +namespace uhd{ namespace usrp{ + +    /*! +     * Tune a rx chain to the desired frequency: +     * The IF of the subdevice is set as close as possible to +     * the given target frequency + the LO offset (when applicable). +     * The ddc cordic is setup to bring the IF down to baseband. +     * \param subdev the dboard subdevice object with properties +     * \param ddc the mboard dsp object with properties +     * \param chan the channel of the dsp to tune +     * \param tune_request tune request instructions +     * \return a tune result struct +     */ +    UHD_API tune_result_t tune_rx_subdev_and_dsp( +        wax::obj subdev, wax::obj ddc, size_t chan, +        const tune_request_t &tune_request +    ); + +    /*! +     * Calculate the overall frequency from the combination of dboard IF and DDC shift. +     * \param subdev the dboard subdevice object with properties +     * \param ddc the mboard dsp object with properties +     * \param chan the channel of the dsp to tune +     * \return the overall tune frequency of the system in Hz +     */ +    UHD_API double derive_freq_from_rx_subdev_and_dsp( +        wax::obj subdev, wax::obj ddc, size_t chan +    ); + +    /*! +     * Tune a tx chain to the desired frequency: +     * The IF of the subdevice is set as close as possible to +     * the given target frequency + the LO offset (when applicable). +     * The duc cordic is setup to bring the baseband up to IF. +     * \param subdev the dboard subdevice object with properties +     * \param duc the mboard dsp object with properties +     * \param chan the channel of the dsp to tune +     * \param tune_request tune request instructions +     * \return a tune result struct +     */ +    UHD_API tune_result_t tune_tx_subdev_and_dsp( +        wax::obj subdev, wax::obj duc, size_t chan, +        const tune_request_t &tune_request +    ); + +    /*! +     * Calculate the overall frequency from the combination of dboard IF and DUC shift. +     * \param subdev the dboard subdevice object with properties +     * \param duc the mboard dsp object with properties +     * \param chan the channel of the dsp to tune +     * \return the overall tune frequency of the system in Hz +     */ +    UHD_API double derive_freq_from_tx_subdev_and_dsp( +        wax::obj subdev, wax::obj duc, size_t chan +    ); + +}} + +#endif /* INCLUDED_UHD_USRP_TUNE_HELPER_HPP */ diff --git a/host/include/uhd/utils/CMakeLists.txt b/host/include/uhd/utils/CMakeLists.txt new file mode 100644 index 000000000..b39b6083c --- /dev/null +++ b/host/include/uhd/utils/CMakeLists.txt @@ -0,0 +1,34 @@ +# +# 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/>. +# + +INSTALL(FILES +    algorithm.hpp +    assert.hpp +    assert.ipp +    byteswap.hpp +    byteswap.ipp +    exception.hpp +    gain_group.hpp +    images.hpp +    pimpl.hpp +    props.hpp +    safe_main.hpp +    static.hpp +    thread_priority.hpp +    warning.hpp +    DESTINATION ${INCLUDE_DIR}/uhd/utils +) diff --git a/host/include/uhd/utils/algorithm.hpp b/host/include/uhd/utils/algorithm.hpp new file mode 100644 index 000000000..53c571e4e --- /dev/null +++ b/host/include/uhd/utils/algorithm.hpp @@ -0,0 +1,173 @@ +// +// Copyright 2010 Ettus Research LLC +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program.  If not, see <http://www.gnu.org/licenses/>. +// + +#ifndef INCLUDED_UHD_UTILS_ALGORITHM_HPP +#define INCLUDED_UHD_UTILS_ALGORITHM_HPP + +#include <algorithm> +#include <boost/range/begin.hpp> +#include <boost/range/end.hpp> +#include <boost/range/size.hpp> +#include <boost/algorithm/string.hpp> +#include <vector> +#include <string> + +/*! \file algorithm.hpp + * Useful templated functions and classes that I like to pretend are part of stl. + * Many of the range wrapper functions come with recent versions of boost (1.43). + */ +namespace std{ + +    /*! +     * Split a string at the separation characters. +     * \param string the string to split +     * \param sep the separator characters +     * \return a range of strings +     */ +    inline std::vector<std::string> split_string( +        const std::string &string, const std::string &sep = "\t " +    ){ +        std::vector<std::string> strings; +        if (not string.empty()) boost::split( +            // do not split an empty string: +            // let me tell you about the time when boost::split segfaulted... +            strings, string, boost::is_any_of(sep) +        ); +        return strings; +    } + +    /*! +     * A wrapper around std::copy that takes ranges instead of iterators. +     * +     * Copy the elements of the source range into the destination range. +     * The destination range should be at least as large as the source range. +     * +     * \param src the range of elements to copy from +     * \param dst the range of elements to be filled +     */ +    template<typename RangeSrc, typename RangeDst> inline +    void copy(const RangeSrc &src, RangeDst &dst){ +        std::copy(boost::begin(src), boost::end(src), boost::begin(dst)); +    } + +    /*! +     * A wrapper around std::sort that takes a range instead of an iterator. +     * +     * The elements are sorted into ascending order using the less-than operator. +     * +     * \param range the range of elements to be sorted +     */ +    template<typename Range> inline void sort(Range &range){ +        return std::sort(boost::begin(range), boost::end(range)); +    } + +    /*! +     * A wrapper around std::sort that takes a range instead of an iterator. +     * +     * The elements are sorted into ascending order using the less-than operator. +     * This wrapper sorts the elements non-destructively into a new range. +     * Based on the builtin python function sorted(...) +     * +     * \param range the range of elements to be sorted +     * \return a new range with the elements sorted +     */ +    template<typename Range> inline Range sorted(const Range &range){ +        Range srange(range); std::sort(srange); return srange; +    } + +    /*! +     * A wrapper around std::reverse that takes a range instead of an iterator. +     * +     * The elements are reversed into descending order using the less-than operator. +     * +     * \param range the range of elements to be reversed +     */ +    template<typename Range> inline void reverse(Range &range){ +        return std::reverse(boost::begin(range), boost::end(range)); +    } + +    /*! +     * A wrapper around std::reverse that takes a range instead of an iterator. +     * +     * The elements are reversed into descending order using the less-than operator. +     * This wrapper reverses the elements non-destructively into a new range. +     * Based on the builtin python function reversed(...) +     * +     * \param range the range of elements to be reversed +     * \return a new range with the elements reversed +     */ +    template<typename Range> inline Range reversed(const Range &range){ +        Range srange(range); std::reverse(srange); return srange; +    } + +    /*! +     * Is the value found within the elements in this range? +     * +     * Uses std::find to search the iterable for an element. +     * +     * \param range the elements to search through +     * \param value the match to look for in the range +     * \return true when the value is found in the range +     */ +    template<typename Range, typename T> inline +    bool has(const Range &range, const T &value){ +        return boost::end(range) != std::find(boost::begin(range), boost::end(range), value); +    } + +    /*! +     * Count the number of appearances of a value in a range. +     * +     * Uses std::count to count the appearances in the range. +     * +     * \param range the elements to iterate through +     * \param value the value to count in the range +     * \return the number of appearances of the value +     */ +    template<typename Range, typename T> inline +    size_t count(const Range &range, const T &value){ +        return std::count(boost::begin(range), boost::end(range), value); +    } + +    /*! +     * Are the ranges equal (are their elements equivalent)? +     * +     * Uses std::equal to search the iterable for an element. +     * +     * \param range1 the first range of elements +     * \param range2 the second range of elements +     * \return true when the elements are equivalent +     */ +    template<typename Range> inline +    bool equal(const Range &range1, const Range &range2){ +        return (boost::size(range1) == boost::size(range2)) and +        std::equal(boost::begin(range1), boost::end(range1), boost::begin(range2)); +    } + +    /*! +     * A templated clip implementation. +     * \param val the value to clip between an upper and lower limit +     * \param bound1 the upper or lower bound +     * \param bound2 the upper or lower bound +     * \return the value clipped at the bounds +     */ +    template<typename T> inline T clip(T val, T bound1, T bound2){ +        return std::min(std::max(val, std::min(bound1, bound2)), std::max(bound1, bound2)); +    } + +}//namespace std + +#endif /* INCLUDED_UHD_UTILS_ALGORITHM_HPP */ diff --git a/host/include/uhd/utils/assert.hpp b/host/include/uhd/utils/assert.hpp new file mode 100644 index 000000000..7f7b71cfb --- /dev/null +++ b/host/include/uhd/utils/assert.hpp @@ -0,0 +1,59 @@ +// +// Copyright 2010 Ettus Research LLC +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program.  If not, see <http://www.gnu.org/licenses/>. +// + +#ifndef INCLUDED_UHD_UTILS_ASSERT_HPP +#define INCLUDED_UHD_UTILS_ASSERT_HPP + +#include <uhd/config.hpp> +#include <uhd/utils/exception.hpp> +#include <stdexcept> +#include <string> + +namespace uhd{ + +    //! The exception to throw when assertions fail +    struct UHD_API assert_error : std::runtime_error{ +        assert_error(const std::string &what); +    }; + +    //! Throw an assert error with throw-site information +    #define UHD_ASSERT_THROW(_x) if (not (_x)) throw uhd::assert_error( \ +        UHD_THROW_SITE_INFO("assertion failed: " + std::string(#_x)) \ +    ); else void(0) + +    /*! +     * Check that an element is found in a container. +     * If not, throw a meaningful assertion error. +     * The "what" in the error will show what is +     * being set and a list of known good values. +     * +     * \param range a list of possible settings +     * \param value an element that may be in the list +     * \param what a description of what the value is +     * \throw assertion_error when elem not in list +     */ +    template<typename T, typename Range> void assert_has( +        const Range &range, +        const T &value, +        const std::string &what = "unknown" +    ); + +}//namespace uhd + +#include <uhd/utils/assert.ipp> + +#endif /* INCLUDED_UHD_UTILS_ASSERT_HPP */ diff --git a/host/include/uhd/utils/assert.ipp b/host/include/uhd/utils/assert.ipp new file mode 100644 index 000000000..6a8b3e417 --- /dev/null +++ b/host/include/uhd/utils/assert.ipp @@ -0,0 +1,52 @@ +// +// Copyright 2010 Ettus Research LLC +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program.  If not, see <http://www.gnu.org/licenses/>. +// + +#ifndef INCLUDED_UHD_UTILS_ASSERT_IPP +#define INCLUDED_UHD_UTILS_ASSERT_IPP + +#include <uhd/utils/algorithm.hpp> +#include <boost/format.hpp> +#include <boost/foreach.hpp> +#include <boost/lexical_cast.hpp> + +namespace uhd{ + +    template<typename T, typename Range> UHD_INLINE void assert_has( +        const Range &range, +        const T &value, +        const std::string &what +    ){ +        if (std::has(range, value)) return; +        std::string possible_values = ""; +        size_t i = 0; +        BOOST_FOREACH(const T &v, range){ +            if (i++ > 0) possible_values += ", "; +            possible_values += boost::lexical_cast<std::string>(v); +        } +        throw uhd::assert_error(str(boost::format( +                "assertion failed:\n" +                "  %s is not a valid %s.\n" +                "  possible values are: [%s].\n" +            ) +            % boost::lexical_cast<std::string>(value) +            % what % possible_values +        )); +    } + +}//namespace uhd + +#endif /* INCLUDED_UHD_UTILS_ASSERT_IPP */ diff --git a/host/include/uhd/utils/byteswap.hpp b/host/include/uhd/utils/byteswap.hpp new file mode 100644 index 000000000..9a1871210 --- /dev/null +++ b/host/include/uhd/utils/byteswap.hpp @@ -0,0 +1,50 @@ +// +// Copyright 2010 Ettus Research LLC +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program.  If not, see <http://www.gnu.org/licenses/>. +// + +#ifndef INCLUDED_UHD_UTILS_BYTESWAP_HPP +#define INCLUDED_UHD_UTILS_BYTESWAP_HPP + +#include <uhd/config.hpp> +#include <boost/cstdint.hpp> + +/*! \file byteswap.hpp + * Provide fast byteswaping routines for 16, 32, and 64 bit integers, + * by using the system's native routines/intrinsics when available. + */ + +namespace uhd{ + +    //! perform a byteswap on a 16 bit integer +    boost::uint16_t byteswap(boost::uint16_t); + +    //! perform a byteswap on a 32 bit integer +    boost::uint32_t byteswap(boost::uint32_t); + +    //! perform a byteswap on a 64 bit integer +    boost::uint64_t byteswap(boost::uint64_t); + +    //! network to host: short, long, or long-long +    template<typename T> T ntohx(T); + +    //! host to network: short, long, or long-long +    template<typename T> T htonx(T); + +} //namespace uhd + +#include <uhd/utils/byteswap.ipp> + +#endif /* INCLUDED_UHD_UTILS_BYTESWAP_HPP */ diff --git a/host/include/uhd/utils/byteswap.ipp b/host/include/uhd/utils/byteswap.ipp new file mode 100644 index 000000000..a070a7cf5 --- /dev/null +++ b/host/include/uhd/utils/byteswap.ipp @@ -0,0 +1,120 @@ +// +// Copyright 2010 Ettus Research LLC +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program.  If not, see <http://www.gnu.org/licenses/>. +// + +#ifndef INCLUDED_UHD_UTILS_BYTESWAP_IPP +#define INCLUDED_UHD_UTILS_BYTESWAP_IPP + +/*********************************************************************** + * Platform-specific implementation details for byteswap below: + **********************************************************************/ +#if defined(UHD_PLATFORM_WIN32) //http://msdn.microsoft.com/en-us/library/a3140177%28VS.80%29.aspx +    #include <stdlib.h> + +    UHD_INLINE boost::uint16_t uhd::byteswap(boost::uint16_t x){ +        return _byteswap_ushort(x); +    } + +    UHD_INLINE boost::uint32_t uhd::byteswap(boost::uint32_t x){ +        return _byteswap_ulong(x); +    } + +    UHD_INLINE boost::uint64_t uhd::byteswap(boost::uint64_t x){ +        return _byteswap_uint64(x); +    } + +#elif defined(__GNUC__) && __GNUC__ >= 4 && __GNUC_MINOR__ >= 2 + +    UHD_INLINE boost::uint16_t uhd::byteswap(boost::uint16_t x){ +        return (x>>8) | (x<<8); //DNE return __builtin_bswap16(x); +    } + +    UHD_INLINE boost::uint32_t uhd::byteswap(boost::uint32_t x){ +        return __builtin_bswap32(x); +    } + +    UHD_INLINE boost::uint64_t uhd::byteswap(boost::uint64_t x){ +        return __builtin_bswap64(x); +    } + +#elif defined(UHD_PLATFORM_MACOS) +    #include <libkern/OSByteOrder.h> + +    UHD_INLINE boost::uint16_t uhd::byteswap(boost::uint16_t x){ +        return OSSwapInt16(x); +    } + +    UHD_INLINE boost::uint32_t uhd::byteswap(boost::uint32_t x){ +        return OSSwapInt32(x); +    } + +    UHD_INLINE boost::uint64_t uhd::byteswap(boost::uint64_t x){ +        return OSSwapInt64(x); +    } + +#elif defined(UHD_PLATFORM_LINUX) +    #include <byteswap.h> + +    UHD_INLINE boost::uint16_t uhd::byteswap(boost::uint16_t x){ +        return bswap_16(x); +    } + +    UHD_INLINE boost::uint32_t uhd::byteswap(boost::uint32_t x){ +        return bswap_32(x); +    } + +    UHD_INLINE boost::uint64_t uhd::byteswap(boost::uint64_t x){ +        return bswap_64(x); +    } + +#else //http://www.koders.com/c/fidB93B34CD44F0ECF724F1A4EAE3854BA2FE692F59.aspx + +    UHD_INLINE boost::uint16_t uhd::byteswap(boost::uint16_t x){ +        return (x>>8) | (x<<8); +    } + +    UHD_INLINE boost::uint32_t uhd::byteswap(boost::uint32_t x){ +        return (boost::uint32_t(uhd::byteswap(boost::uint16_t(x&0xfffful)))<<16) | (uhd::byteswap(boost::uint16_t(x>>16))); +    } + +    UHD_INLINE boost::uint64_t uhd::byteswap(boost::uint64_t x){ +        return (boost::uint64_t(uhd::byteswap(boost::uint32_t(x&0xffffffffull)))<<32) | (uhd::byteswap(boost::uint32_t(x>>32))); +    } + +#endif + +/*********************************************************************** + * Define the templated network to/from host conversions + **********************************************************************/ +#include <boost/detail/endian.hpp> + +template<typename T> UHD_INLINE T uhd::ntohx(T num){ +    #ifdef BOOST_BIG_ENDIAN +        return num; +    #else +        return uhd::byteswap(num); +    #endif +} + +template<typename T> UHD_INLINE T uhd::htonx(T num){ +    #ifdef BOOST_BIG_ENDIAN +        return num; +    #else +        return uhd::byteswap(num); +    #endif +} + +#endif /* INCLUDED_UHD_UTILS_BYTESWAP_IPP */ diff --git a/host/include/uhd/utils/exception.hpp b/host/include/uhd/utils/exception.hpp new file mode 100644 index 000000000..e74c19b9c --- /dev/null +++ b/host/include/uhd/utils/exception.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/>. +// + +#ifndef INCLUDED_UHD_UTILS_EXCEPTION_HPP +#define INCLUDED_UHD_UTILS_EXCEPTION_HPP + +#include <uhd/config.hpp> +#include <boost/current_function.hpp> +#include <stdexcept> +#include <string> + +/*! + * Create a formated string with throw-site information. + * Fills in the function name, file name, and line number. + * \param what the std::exeption message + * \return the formatted exception message + */ +#define UHD_THROW_SITE_INFO(what) std::string( \ +    std::string(what) + "\n" + \ +    "  in " + std::string(BOOST_CURRENT_FUNCTION) + "\n" + \ +    "  at " + std::string(__FILE__) + ":" + BOOST_STRINGIZE(__LINE__) + "\n" \ +) + +/*! + * Throws an invalid code path exception with throw-site information. + * Use this macro in places that code execution is not supposed to go. + */ +#define UHD_THROW_INVALID_CODE_PATH() \ +    throw std::runtime_error(UHD_THROW_SITE_INFO("invalid code path")) + +#endif /* INCLUDED_UHD_UTILS_EXCEPTION_HPP */ diff --git a/host/include/uhd/utils/gain_group.hpp b/host/include/uhd/utils/gain_group.hpp new file mode 100644 index 000000000..c863248ce --- /dev/null +++ b/host/include/uhd/utils/gain_group.hpp @@ -0,0 +1,108 @@ +// +// Copyright 2010 Ettus Research LLC +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program.  If not, see <http://www.gnu.org/licenses/>. +// + +#ifndef INCLUDED_UHD_UTILS_GAIN_GROUP_HPP +#define INCLUDED_UHD_UTILS_GAIN_GROUP_HPP + +#include <uhd/config.hpp> +#include <uhd/types/ranges.hpp> +#include <boost/shared_ptr.hpp> +#include <boost/function.hpp> +#include <boost/utility.hpp> +#include <vector> +#include <string> + +namespace uhd{ + +/*! + * A set of function to control a gain element. + */ +struct UHD_API gain_fcns_t{ +    boost::function<gain_range_t(void)> get_range; +    boost::function<float(void)>        get_value; +    boost::function<void(float)>        set_value; +}; + +class UHD_API gain_group : boost::noncopyable{ +public: +    typedef boost::shared_ptr<gain_group> sptr; + +    /*! +     * Get the gain range for the gain element specified by name. +     * For an empty name, get the overall gain range for this group. +     * Overall step is defined as the minimum step size. +     * \param name name of the gain element (optional) +     * \return a gain range with overall min, max, step +     */ +    virtual gain_range_t get_range(const std::string &name = "") = 0; + +    /*! +     * Get the gain value for the gain element specified by name. +     * For an empty name, get the overall gain value for this group. +     * \param name name of the gain element (optional) +     * \return a gain value of the element or all elements +     */ +    virtual float get_value(const std::string &name = "") = 0; + +    /*! +     * Set the gain value for the gain element specified by name. +     * For an empty name, set the overall gain value for this group. +     * The power will be distributed across individual gain elements. +     * The semantics of how to do this are determined by the priority. +     * \param gain the gain to set for the lement or across the group +     * \param name name of the gain element (optional) +     */ +    virtual void set_value(float gain, const std::string &name = "") = 0; + +    /*! +     * Get a list of names of registered gain elements. +     * The names are in the order that they were registered. +     * \return a vector of gain name strings +     */ +    virtual const std::vector<std::string> get_names(void) = 0; + +    /*! +     * Register a set of gain functions into this group: +     * +     * The name should be a unique and non-empty name. +     * Othwerwise, the implementation will rename it. +     * +     * Priority determines how power will be distributed +     * with higher priorities getting the power first, +     * and lower priorities getting the remainder power. +     * +     * \param name the name of the gain element +     * \param gain_fcns the set of gain functions +     * \param priority the priority of the gain element +     */ +    virtual void register_fcns( +        const std::string &name, +        const gain_fcns_t &gain_fcns, +        size_t priority = 0 +    ) = 0; + +    /*! +     * Make a new empty gain group. +     * \return a gain group object. +     */ +    static sptr make(void); +}; + +} //namespace uhd + +#endif /* INCLUDED_UHD_UTILS_GAIN_GROUP_HPP */ + diff --git a/host/include/uhd/utils/images.hpp b/host/include/uhd/utils/images.hpp new file mode 100644 index 000000000..8b5a1eedd --- /dev/null +++ b/host/include/uhd/utils/images.hpp @@ -0,0 +1,38 @@ +// +// Copyright 2010 Ettus Research LLC +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program.  If not, see <http://www.gnu.org/licenses/>. +// + +#ifndef INCLUDED_UHD_UTILS_IMAGES_HPP +#define INCLUDED_UHD_UTILS_IMAGES_HPP + +#include <uhd/config.hpp> +#include <string> + +namespace uhd{ + +    /*! +     * Search for an image in the system image paths: +     * Search compiled-in paths and environment variable paths +     * for a specific image file with the provided file name. +     * \param image_name the name of the file +     * \return the full system path to the file +     * \throw exception if the image was not found +     */ +    UHD_API std::string find_image_path(const std::string &image_name); + +} //namespace uhd + +#endif /* INCLUDED_UHD_UTILS_IMAGES_HPP */ diff --git a/host/include/uhd/utils/pimpl.hpp b/host/include/uhd/utils/pimpl.hpp new file mode 100644 index 000000000..09bf0c0a2 --- /dev/null +++ b/host/include/uhd/utils/pimpl.hpp @@ -0,0 +1,55 @@ +// +// Copyright 2010 Ettus Research LLC +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program.  If not, see <http://www.gnu.org/licenses/>. +// + +#ifndef INCLUDED_UHD_UTILS_PIMPL_HPP +#define INCLUDED_UHD_UTILS_PIMPL_HPP + +#include <uhd/config.hpp> +#include <boost/shared_ptr.hpp> + +/*! \file pimpl.hpp + * "Pimpl idiom" (pointer to implementation idiom). + * The UHD_PIMPL_* macros simplify code overhead for declaring and making pimpls. + * + * Each pimpl is implemented as a shared pointer to the implementation: + * - The container class will not have to deallocate the pimpl. + * - The container class will use the pimpl as a regular pointer. + * - Usage: _impl->method(arg0, arg1) + * - Usage: _impl->member = value; + * + * \see http://en.wikipedia.org/wiki/Opaque_pointer + */ + +/*! + * Make a declaration for a pimpl in a header file. + * - Usage: UHD_PIMPL_DECL(impl) _impl; + * \param _name the name of the pimpl class + */ +#define UHD_PIMPL_DECL(_name) \ +    struct _name; boost::shared_ptr<_name> + +/*! + * Make an instance of a pimpl in a source file. + * - Usage: _impl = UHD_PIMPL_MAKE(impl, ()); + * - Usage: _impl = UHD_PIMPL_MAKE(impl, (a0, a1)); + * \param _name the name of the pimpl class + * \param _args the constructor args for the pimpl + */ +#define UHD_PIMPL_MAKE(_name, _args) \ +    boost::shared_ptr<_name>(new _name _args) + +#endif /* INCLUDED_UHD_UTILS_PIMPL_HPP */ diff --git a/host/include/uhd/utils/props.hpp b/host/include/uhd/utils/props.hpp new file mode 100644 index 000000000..fbca03019 --- /dev/null +++ b/host/include/uhd/utils/props.hpp @@ -0,0 +1,82 @@ +// +// Copyright 2010 Ettus Research LLC +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program.  If not, see <http://www.gnu.org/licenses/>. +// + +#ifndef INCLUDED_UHD_UTILS_PROPS_HPP +#define INCLUDED_UHD_UTILS_PROPS_HPP + +#include <uhd/config.hpp> +#include <uhd/wax.hpp> +#include <uhd/utils/exception.hpp> +#include <stdexcept> +#include <vector> +#include <string> + +namespace uhd{ + +    //! The type for a vector of property names +    typedef std::vector<std::string> prop_names_t; + +    /*! +     * A named prop struct holds a key and a name. +     * Allows properties to be sub-sectioned by name. +     */ +    struct UHD_API named_prop_t{ +        const wax::obj key; +        const std::string name; + +        //! Convert the key to the specified type +        template<typename T> inline T as(void){ +            return key.as<T>(); +        } + +        /*! +         * Utility function to convert generic key into a named prop. +         * If the key was already a named prop, the prop will be split. +         * Otherwise, the key will be the key, and the name will be used. +         * \param key a reference to the prop object +         * \param name a reference to the name object +         * \return a named property struct with key and name +         */ +        static named_prop_t extract( +            const wax::obj &key, const std::string &name = "" +        ); + +        /*! +         * Create a new named prop from key and name. +         * \param key the property key +         * \param name the string name +         */ +        named_prop_t(const wax::obj &key, const std::string &name); +    }; + +    /*! +     * Throw when getting a not-implemented or write-only property. +     * Throw-site information will be included with this error. +     */ +    #define UHD_THROW_PROP_GET_ERROR() \ +        throw std::runtime_error(UHD_THROW_SITE_INFO("cannot get this property")) + +    /*! +     * Throw when setting a not-implemented or read-only property. +     * Throw-site information will be included with this error. +     */ +    #define UHD_THROW_PROP_SET_ERROR() \ +        throw std::runtime_error(UHD_THROW_SITE_INFO("cannot set this property")) + +} //namespace uhd + +#endif /* INCLUDED_UHD_UTILS_PROPS_HPP */ diff --git a/host/include/uhd/utils/safe_main.hpp b/host/include/uhd/utils/safe_main.hpp new file mode 100644 index 000000000..b682aa540 --- /dev/null +++ b/host/include/uhd/utils/safe_main.hpp @@ -0,0 +1,44 @@ +// +// Copyright 2010 Ettus Research LLC +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program.  If not, see <http://www.gnu.org/licenses/>. +// + +#ifndef INCLUDED_UHD_UTILS_SAFE_MAIN_HPP +#define INCLUDED_UHD_UTILS_SAFE_MAIN_HPP + +#include <uhd/config.hpp> +#include <iostream> +#include <stdexcept> + +/*! + * Defines a safe wrapper that places a catch-all around main. + * If an exception is thrown, it prints to stderr and returns. + * Usage: int UHD_SAFE_MAIN(int argc, char *argv[]){ main code here } + * \param _argc the declaration for argc + * \param _argv the declaration for argv + */ +#define UHD_SAFE_MAIN(_argc, _argv) _main(int, char*[]); \ +int main(int argc, char *argv[]){ \ +    try { \ +        return _main(argc, argv); \ +    } catch(const std::exception &e) { \ +        std::cerr << "Error: " << e.what() << std::endl; \ +    } catch(...) { \ +        std::cerr << "Error: unknown exception" << std::endl; \ +    } \ +    return ~0; \ +} int _main(_argc, _argv) + +#endif /* INCLUDED_UHD_UTILS_SAFE_MAIN_HPP */ diff --git a/host/include/uhd/utils/static.hpp b/host/include/uhd/utils/static.hpp new file mode 100644 index 000000000..c61f10884 --- /dev/null +++ b/host/include/uhd/utils/static.hpp @@ -0,0 +1,37 @@ +// +// Copyright 2010 Ettus Research LLC +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program.  If not, see <http://www.gnu.org/licenses/>. +// + +#ifndef INCLUDED_UHD_UTILS_STATIC_HPP +#define INCLUDED_UHD_UTILS_STATIC_HPP + +#include <uhd/config.hpp> + +/*! + * Defines a function that implements the "construct on first use" idiom + * \param _t the type definition for the instance + * \param _x the name of the defined function + * \return a reference to the lazy instance + */ +#define UHD_SINGLETON_FCN(_t, _x) static _t &_x(){static _t _x; return _x;} + +/*! + * Defines a static code block that will be called before main() + * \param _x the name of the defined struct (must be unique in file) + */ +#define UHD_STATIC_BLOCK(_x) static struct _x{_x();}_x;_x::_x() + +#endif /* INCLUDED_UHD_UTILS_STATIC_HPP */ diff --git a/host/include/uhd/utils/thread_priority.hpp b/host/include/uhd/utils/thread_priority.hpp new file mode 100644 index 000000000..988fc3012 --- /dev/null +++ b/host/include/uhd/utils/thread_priority.hpp @@ -0,0 +1,58 @@ +// +// Copyright 2010 Ettus Research LLC +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program.  If not, see <http://www.gnu.org/licenses/>. +// + +#ifndef INCLUDED_UHD_UTILS_THREAD_PRIORITY_HPP +#define INCLUDED_UHD_UTILS_THREAD_PRIORITY_HPP + +#include <uhd/config.hpp> + +namespace uhd{ + +    static const float default_thread_priority = float(0.5); + +    /*! +     * Set the scheduling priority on the current thread. +     * +     * A new thread or calling process should make this call +     * with the defailts this to enable realtime scheduling. +     * +     * A priority of zero corresponds to normal priority. +     * Positive priority values are higher than normal. +     * Negative priority values are lower than normal. +     * +     * \param priority a value between -1 and 1 +     * \param realtime true to use realtime mode +     * \throw exception on set priority failure +     */ +    UHD_API void set_thread_priority( +        float priority = default_thread_priority, +        bool realtime = true +    ); + +    /*! +     * Set the scheduling priority on the current thread. +     * Same as set_thread_priority but does not throw on failure. +     * \return true on success, false on failure +     */ +    UHD_API bool set_thread_priority_safe( +        float priority = default_thread_priority, +        bool realtime = true +    ); + +} //namespace uhd + +#endif /* INCLUDED_UHD_UTILS_THREAD_PRIORITY_HPP */ diff --git a/host/include/uhd/utils/warning.hpp b/host/include/uhd/utils/warning.hpp new file mode 100644 index 000000000..a1e3f0d1e --- /dev/null +++ b/host/include/uhd/utils/warning.hpp @@ -0,0 +1,62 @@ +// +// Copyright 2010 Ettus Research LLC +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program.  If not, see <http://www.gnu.org/licenses/>. +// + +#ifndef INCLUDED_UHD_UTILS_WARNING_HPP +#define INCLUDED_UHD_UTILS_WARNING_HPP + +#include <uhd/config.hpp> +#include <boost/function.hpp> +#include <vector> +#include <string> + +namespace uhd{ namespace warning{ + +    //! Callback function type for a message handler +    typedef boost::function<void(std::string)> handler_t; + +    /*! +     * Post a warning message to all registered handlers. +     * \param msg the multiline warning message +     */ +    UHD_API void post(const std::string &msg); + +    /*! +     * Register a new handler with this name. +     * If the name was already registered for this name, +     * the old registered handler will be replaced. +     * \param name a unique name for this handler +     * \param handler the callback handler function +     */ +    UHD_API void register_handler(const std::string &name, const handler_t &handler); + +    /*! +     * Unregister a handler for this name. +     * \param name a unique name for a registered handler +     * \return the handler that was registered +     * \throw error when the name was not found in the registry +     */ +    UHD_API handler_t unregister_handler(const std::string &name); + +    /*! +     * Get a list of registered handler names. +     * \return a vector of unique string names +     */ +    UHD_API const std::vector<std::string> registry_names(void); + +}} //namespace uhd::warning + +#endif /* INCLUDED_UHD_UTILS_WARNING_HPP */ diff --git a/host/include/uhd/version.hpp b/host/include/uhd/version.hpp new file mode 100644 index 000000000..19d672e65 --- /dev/null +++ b/host/include/uhd/version.hpp @@ -0,0 +1,28 @@ +// +// 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_VERSION_HPP +#define INCLUDED_UHD_VERSION_HPP + +#include <uhd/config.hpp> +#include <string> + +namespace uhd{ +    UHD_API std::string get_version_string(void); +} //namespace uhd + +#endif /* INCLUDED_UHD_VERSION_HPP */ diff --git a/host/include/uhd/wax.hpp b/host/include/uhd/wax.hpp new file mode 100644 index 000000000..14e6734a5 --- /dev/null +++ b/host/include/uhd/wax.hpp @@ -0,0 +1,167 @@ +// +// 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_WAX_HPP +#define INCLUDED_WAX_HPP + +#include <uhd/config.hpp> +#include <boost/any.hpp> + +/*! + * WAX - it's a metaphor! + * + * The WAX framework allows an object to have generic/anyobj properties. + * These properties can be addressed through generic/anyobj identifiers. + * + * 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].as<type>(); + * + * 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(). + * + * Note: Do not put a class derived from wax::obj into an stl container. + * MSVC will compile the code, but the binaries will crash at runtime. + * Rather, use pointers or smart pointers to instances of the derived class. + */ + +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: +     *   1) to act as a polymorphic container, just like boost any +     *   2) to provide a nested set/get properties interface +     * +     * Internally, the polymorphic container is handled by a boost any. +     * For properties, a subclass should override the set and get methods. +     * For property nesting, wax obj subclasses return special links +     * to other wax obj subclasses, and the api handles the magic. +     */ +    class UHD_API obj{ +    public: + +        /*! +         * Default constructor: +         * The contents will be empty. +         */ +        obj(void); + +        /*! +         * Copy constructor: +         * The contents will be cloned. +         * \param o another wax::obj +         */ +        obj(const obj &o); + +        /*! +         * Templated any type constructor: +         * The contents can be anything. +         * Uses the boost::any to handle the magic. +         * \param o an object of any type +         */ +        template<class T> obj(const T &o){ +            _contents = o; +        } + +        /*! +         * Destructor. +         */ +        virtual ~obj(void); + +        /*! +         * The chaining operator: +         * This operator allows access objs with properties. +         * A call to the [] operator will return a new proxy obj. +         * The proxy object is an obj with special proxy contents. +         * Assignment and casting can be used on this special object +         * to access the property referenced by the obj key. +         * \param key a key to identify a property within this obj +         * \return a special wax obj that proxies the obj and key +         */ +        obj operator[](const obj &key); + +        /*! +         * The assignment operator: +         * This operator allows for assignment of new contents. +         * In the special case where this obj contains a proxy, +         * the value will be set to the proxy's property reference. +         * \param val the new value to assign to the wax obj +         * \return a reference to this obj (*this) +         */ +        obj & operator=(const obj &val); + +        /*! +         * Get a link in the chain: +         * When a wax obj returns another wax obj as part of a get call, +         * the return value should be set to the result of this method. +         * Doing so will ensure chain-ability of the returned object. +         * \return an obj containing a valid link to a wax obj +         */ +        obj get_link(void) const; + +        /*! +         * Get the type of the contents of this obj. +         * \return a reference to the type_info +         */ +        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 &); +        virtual void set(const obj &, const obj &); + +        /*! +         * Resolve the contents of this obj. +         * In the case where this obj is a proxy, +         * the referenced property will be resolved. +         * Otherwise, just get the private contents. +         * \return a boost any type with contents +         */ +        boost::any resolve(void) const; + +        //private contents of this obj +        boost::any _contents; + +    }; + +} //namespace wax + +#endif /* INCLUDED_WAX_HPP */ | 
