diff options
author | Ashish Chaudhari <ashish@ettus.com> | 2015-03-17 13:52:29 -0700 |
---|---|---|
committer | Ashish Chaudhari <ashish@ettus.com> | 2015-03-17 13:52:29 -0700 |
commit | 6a34824ad10eaa2d2b642b959f278f6c4e326d6d (patch) | |
tree | 1aa582ee8e5cef716b59ec4deb3a8e5f4f532929 /host/include | |
parent | 5682321efa26bb97f5d0c37d8e9921fc11a9b923 (diff) | |
parent | 306b5243e12af0db493856ad8397abac9835db0c (diff) | |
download | uhd-6a34824ad10eaa2d2b642b959f278f6c4e326d6d.tar.gz uhd-6a34824ad10eaa2d2b642b959f278f6c4e326d6d.tar.bz2 uhd-6a34824ad10eaa2d2b642b959f278f6c4e326d6d.zip |
Merge branch 'master' into ashish/vivado
Diffstat (limited to 'host/include')
21 files changed, 917 insertions, 37 deletions
diff --git a/host/include/uhd/config.hpp b/host/include/uhd/config.hpp index 7ecc4924a..23eb9cdb2 100644 --- a/host/include/uhd/config.hpp +++ b/host/include/uhd/config.hpp @@ -1,5 +1,5 @@ // -// Copyright 2010-2011 Ettus Research LLC +// Copyright 2010-2011,2014 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 @@ -56,6 +56,13 @@ typedef ptrdiff_t ssize_t; #define UHD_DEPRECATED __declspec(deprecated) #define UHD_ALIGNED(x) __declspec(align(x)) #define UHD_UNUSED(x) x +#elif defined(__MINGW32__) + #define UHD_EXPORT __declspec(dllexport) + #define UHD_IMPORT __declspec(dllimport) + #define UHD_INLINE inline + #define UHD_DEPRECATED __declspec(deprecated) + #define UHD_ALIGNED(x) __declspec(align(x)) + #define UHD_UNUSED(x) x #elif defined(__GNUG__) && __GNUG__ >= 4 #define UHD_EXPORT __attribute__((visibility("default"))) #define UHD_IMPORT __attribute__((visibility("default"))) diff --git a/host/include/uhd/convert.hpp b/host/include/uhd/convert.hpp index d740d80fb..e42123b20 100644 --- a/host/include/uhd/convert.hpp +++ b/host/include/uhd/convert.hpp @@ -63,12 +63,13 @@ namespace uhd{ namespace convert{ typedef int priority_type; //! Identify a conversion routine in the registry - struct id_type : boost::equality_comparable<id_type>{ + struct UHD_API id_type : boost::equality_comparable<id_type>{ std::string input_format; size_t num_inputs; std::string output_format; size_t num_outputs; std::string to_pp_string(void) const; + std::string to_string(void) const; }; //! Implement equality_comparable interface diff --git a/host/include/uhd/device.hpp b/host/include/uhd/device.hpp index 1e88a4138..5ca48f8e9 100644 --- a/host/include/uhd/device.hpp +++ b/host/include/uhd/device.hpp @@ -77,7 +77,9 @@ public: /*! * \brief Create a new device from the device address hint. * - * The make routine will call find and pick one of the results. + * The method will go through the registered device types and pick one of + * the discovered devices. + * * 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. * diff --git a/host/include/uhd/transport/CMakeLists.txt b/host/include/uhd/transport/CMakeLists.txt index 2118674c6..623c179e9 100644 --- a/host/include/uhd/transport/CMakeLists.txt +++ b/host/include/uhd/transport/CMakeLists.txt @@ -1,5 +1,5 @@ # -# Copyright 2010-2013 Ettus Research LLC +# Copyright 2010-2014 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 @@ -15,11 +15,11 @@ # along with this program. If not, see <http://www.gnu.org/licenses/>. # - UHD_INSTALL(FILES bounded_buffer.hpp bounded_buffer.ipp buffer_pool.hpp + chdr.hpp if_addrs.hpp udp_constants.hpp udp_simple.hpp diff --git a/host/include/uhd/transport/chdr.hpp b/host/include/uhd/transport/chdr.hpp new file mode 100644 index 000000000..5e8cd58a9 --- /dev/null +++ b/host/include/uhd/transport/chdr.hpp @@ -0,0 +1,113 @@ +// +// Copyright 2014 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_CHDR_HPP +#define INCLUDED_UHD_TRANSPORT_CHDR_HPP + +#include <uhd/transport/vrt_if_packet.hpp> + +namespace uhd{ namespace transport{ namespace vrt{ + +/*! \brief CVITA/CHDR related function + * + * See \ref rtp_chdr for details on the CVITA/CHDR protocol. + * + * All packers take the host format into account. Choose the _le functions + * if the transport uses little endian format (e.g. PCIe) and the _be + * functions if the transport uses big endian format (e.g. Ethernet). + * + * Note 1: All packers assume there to be enough space at the address + * provided by \p packet_buff. See also \ref vrt_pack_contract. + * + * Note 2: All these packers assume the following options without checking them: + * - `if_packet_info.link_type == LINK_TYPE_CHDR` + * - `if_packet_info.has_cid == false` + * - `if_packet_info.has_sid == true` + * - `if_packet_info.has_tsi == false` + * - `if_packet_info.has_tlr == false` + * This relaxes some of \ref vrt_pack_contract, but adds the additional + * constraint that the input data must be CHDR. + * + * In the unpacker, these values will be set accordingly. + */ +namespace chdr{ + + //! The maximum number of 64-bit words in a CVITA header + static const size_t max_if_hdr_words64 = 2; // CHDR + tsf (fractional timestamp) + + /*! + * Pack a CHDR header from metadata (big endian format). + * + * See \ref vrt_pack_contract, but `link_type` is assumed to be + * `LINK_TYPE_CHDR`. + * + * \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 CHDR header to metadata (big endian format). + * + * See \ref vrt_unpack_contract, but `link_type` is assumed to be + * `LINK_TYPE_CHDR`. + * + * \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 CHDR header from metadata (little endian format). + * + * See \ref vrt_pack_contract, but `link_type` is assumed to be + * `LINK_TYPE_CHDR`. + * + * \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 CHDR header to metadata (little endian format). + * + * See \ref vrt_unpack_contract, but `link_type` is assumed to be + * `LINK_TYPE_CHDR`. + * + * \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 chdr + +}}} //namespace uhd::transport::vrt + +#endif /* INCLUDED_UHD_TRANSPORT_CHDR_HPP */ + diff --git a/host/include/uhd/transport/nirio/nirio_driver_iface.h b/host/include/uhd/transport/nirio/nirio_driver_iface.h index 83afd816a..3e0e56a7f 100644 --- a/host/include/uhd/transport/nirio/nirio_driver_iface.h +++ b/host/include/uhd/transport/nirio/nirio_driver_iface.h @@ -24,9 +24,9 @@ #include <uhd/transport/nirio/status.h> #include <uhd/config.hpp> #if defined(UHD_PLATFORM_WIN32) - #include <Windows.h> + #include <windows.h> #pragma warning(disable:4201) // nonstandard extension used : nameless struct/union - #include <WinIoCtl.h> + #include <winioctl.h> #pragma warning(default:4201) #elif !defined(UHD_PLATFORM_LINUX) #include <IOKit/IOKitLib.h> diff --git a/host/include/uhd/transport/nirio/nirio_fifo.h b/host/include/uhd/transport/nirio/nirio_fifo.h index c424275fc..5a2e29631 100644 --- a/host/include/uhd/transport/nirio/nirio_fifo.h +++ b/host/include/uhd/transport/nirio/nirio_fifo.h @@ -59,8 +59,8 @@ public: inline const std::string& get_name() const { return _name; } inline uint32_t get_channel() const { return _fifo_channel; } - inline uint32_t get_direction() const { return _fifo_direction; } - inline uint32_t get_scalar_type() const { return _datatype_info.scalar_type; } + inline fifo_direction_t get_direction() const { return _fifo_direction; } + inline nirio_scalar_type_t get_scalar_type() const { return _datatype_info.scalar_type; } nirio_status start(); diff --git a/host/include/uhd/transport/nirio/nirio_fifo.ipp b/host/include/uhd/transport/nirio/nirio_fifo.ipp index ca6486e30..49ce43888 100644 --- a/host/include/uhd/transport/nirio/nirio_fifo.ipp +++ b/host/include/uhd/transport/nirio/nirio_fifo.ipp @@ -15,9 +15,11 @@ // along with this program. If not, see <http://www.gnu.org/licenses/>. // -#ifdef __clang__ - #pragma GCC diagnostic push ignored "-Wmissing-field-initializers" -#elif defined(__GNUC__) +// "push" and "pop" introduced in GCC 4.6; works with all clang +#if defined(__clang__) || defined(__GNUC__) && (__GNUC__ > 3) && (__GNUC_MINOR__ > 5) + #pragma GCC diagnostic push +#endif +#if defined(__clang__) || defined(__GNUC__) #pragma GCC diagnostic ignored "-Wmissing-field-initializers" #endif @@ -375,6 +377,6 @@ inline datatype_info_t nirio_fifo<uint64_t>::_get_datatype_info() return datatype_info_t(RIO_SCALAR_TYPE_UQ, 8); } -#ifdef __GNUC__ +#if defined(__clang__) || defined(__GNUC__) && (__GNUC__ > 3) && (__GNUC_MINOR__ > 5) #pragma GCC diagnostic pop #endif diff --git a/host/include/uhd/transport/usb_device_handle.hpp b/host/include/uhd/transport/usb_device_handle.hpp index fdea9e2be..bf122f549 100644 --- a/host/include/uhd/transport/usb_device_handle.hpp +++ b/host/include/uhd/transport/usb_device_handle.hpp @@ -41,6 +41,7 @@ namespace uhd { namespace transport { class UHD_API usb_device_handle : boost::noncopyable { public: typedef boost::shared_ptr<usb_device_handle> sptr; + typedef std::pair<boost::uint16_t, boost::uint16_t> vid_pid_pair_t; /*! * Return the device's serial number @@ -83,6 +84,8 @@ public: * \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); + static std::vector<usb_device_handle::sptr> get_device_list(const std::vector<usb_device_handle::vid_pid_pair_t>& vid_pid_pair_list); + }; //namespace usb diff --git a/host/include/uhd/transport/vrt_if_packet.hpp b/host/include/uhd/transport/vrt_if_packet.hpp index d16892281..1e54607c1 100644 --- a/host/include/uhd/transport/vrt_if_packet.hpp +++ b/host/include/uhd/transport/vrt_if_packet.hpp @@ -1,5 +1,5 @@ // -// Copyright 2010-2013 Ettus Research LLC +// Copyright 2010-2014 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 @@ -46,15 +46,24 @@ namespace vrt{ { LINK_TYPE_NONE = 0x0, LINK_TYPE_CHDR = 0x1, - LINK_TYPE_VRLP = 0x2, + LINK_TYPE_VRLP = 0x2 } link_type; //packet type enum packet_type_t { + // VRT language: PACKET_TYPE_DATA = 0x0, PACKET_TYPE_IF_EXT = 0x1, PACKET_TYPE_CONTEXT = 0x2, //extension context: has_sid = true + + // CVITA language: + //PACKET_TYPE_DATA = 0x0, // Data + PACKET_TYPE_FC = 0x1, // Flow control + PACKET_TYPE_ACK = 0x1, // Flow control (ack) + PACKET_TYPE_CMD = 0x2, // Command + PACKET_TYPE_RESP = 0x3, // Command response + PACKET_TYPE_ERROR = 0x3 // Command response: Error (the EOB bit is raised in this case) } packet_type; //size fields @@ -65,18 +74,46 @@ namespace vrt{ //header fields size_t packet_count; + //! Asserted for start- or end-of-burst bool sob, eob; + //! This is asserted for command responses that are errors (CHDR only) + bool error; //optional fields + //! Stream ID (SID). See uhd::sid_t bool has_sid; boost::uint32_t sid; + //! Class ID. bool has_cid; boost::uint64_t cid; + //! Integer timestamp bool has_tsi; boost::uint32_t tsi; + //! Fractional timestamp bool has_tsf; boost::uint64_t tsf; + //! Trailer bool has_tlr; boost::uint32_t tlr; }; /*! * Pack a vrt header from metadata (big endian format). + * + * \section vrt_pack_contract Packing contract + * + * \subsection Requirements: + * - packet_buff points to a valid address space with enough space to write + * the entire buffer, regardless of its length. At the very least, it must + * be able to hold an entire header. + * - `if_packet_info` has the following members set to correct values: + * - `has_*` members all set accordingly + * - For every true `has_*` member, the corresponding variable holds a valid + * value (e.g. if `has_sid` is true, `sid` contains a valid SID) + * - `num_payload_bytes` and `num_payload_words32` are both set to the correct values + * + * \subsection Result: + * - `packet_buff` now points to a valid header that can be sent over the transport + * without further modification + * - The following members on `if_packet_info` are set: + * - `num_header_words32` + * - `num_packet_words32` + * * \param packet_buff memory to write the packed vrt header * \param if_packet_info the if packet info (read/write) */ @@ -87,6 +124,34 @@ namespace vrt{ /*! * Unpack a vrt header to metadata (big endian format). + * + * \section vrt_unpack_contract Unpacking contract + * + * \subsection Requirements + * - `packet_buff` points to a readable address space with a + * CHDR packet, starting at the header. `packet_buff[0]` *must* always + * point to a valid first word of the header. This implies that num_packet_words32 + * must be at least 1. + * - `if_packet_info` has the following members set to correct values: + * - `num_packet_words32`. This means all values `packet_buff[0]` + * through `packet_buff[if_packet_info.num_packet_words32-1]` are + * readable words from this packet. + * - `link_type` + * + * \subsection Result + * - `if_packet_info` now has the following values set to correct values: + * - `packet_type` + * - `num_payload_bytes` + * - `num_payload_words32` + * - `num_header_words32` + * - `has_*` + * - `sob`, `eob`, `error`, `cid`, `sid` (if applicable) + * - `tsf`, `tsi` (if applicable) + * + * \subsection Exceptions + * - If the header is invalid, but the requirements are still met, + * will throw a uhd::value_error. + * * \param packet_buff memory to read the packed vrt header * \param if_packet_info the if packet info (read/write) */ @@ -97,6 +162,9 @@ namespace vrt{ /*! * Pack a vrt header from metadata (little endian format). + * + * See \ref vrt_pack_contract. + * * \param packet_buff memory to write the packed vrt header * \param if_packet_info the if packet info (read/write) */ @@ -107,6 +175,9 @@ namespace vrt{ /*! * Unpack a vrt header to metadata (little endian format). + * + * See \ref vrt_unpack_contract. + * * \param packet_buff memory to read the packed vrt header * \param if_packet_info the if packet info (read/write) */ @@ -124,6 +195,7 @@ namespace vrt{ num_packet_words32(0), packet_count(0), sob(false), eob(false), + error(false), has_sid(false), sid(0), has_cid(false), cid(0), has_tsi(false), tsi(0), diff --git a/host/include/uhd/types/CMakeLists.txt b/host/include/uhd/types/CMakeLists.txt index 8bb1de381..b82c2b7f2 100644 --- a/host/include/uhd/types/CMakeLists.txt +++ b/host/include/uhd/types/CMakeLists.txt @@ -31,11 +31,13 @@ UHD_INSTALL(FILES ref_vector.hpp sensors.hpp serial.hpp + sid.hpp stream_cmd.hpp time_spec.hpp tune_request.hpp tune_result.hpp wb_iface.hpp + filters.hpp DESTINATION ${INCLUDE_DIR}/uhd/types COMPONENT headers ) diff --git a/host/include/uhd/types/clock_config.hpp b/host/include/uhd/types/clock_config.hpp index 27b312245..6d5d01ec2 100644 --- a/host/include/uhd/types/clock_config.hpp +++ b/host/include/uhd/types/clock_config.hpp @@ -47,12 +47,12 @@ namespace uhd{ REF_AUTO = int('a'), //automatic (device specific) REF_INT = int('i'), //internal reference REF_SMA = int('s'), //external sma port - REF_MIMO = int('m'), //reference from mimo cable + REF_MIMO = int('m') //reference from mimo cable } ref_source; enum pps_source_t { PPS_INT = int('i'), //there is no internal PPS_SMA = int('s'), //external sma port - PPS_MIMO = int('m'), //time sync from mimo cable + PPS_MIMO = int('m') //time sync from mimo cable } pps_source; enum pps_polarity_t { PPS_NEG = int('n'), //negative edge diff --git a/host/include/uhd/types/dict.hpp b/host/include/uhd/types/dict.hpp index 97fa8f09c..51e3e1814 100644 --- a/host/include/uhd/types/dict.hpp +++ b/host/include/uhd/types/dict.hpp @@ -1,5 +1,5 @@ // -// Copyright 2010-2011 Ettus Research LLC +// Copyright 2010-2011,2015 Ettus Research LLC // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by @@ -117,6 +117,23 @@ namespace uhd{ */ Val pop(const Key &key); + /*! Update this dictionary with values from another. + * + * Basically, this copies all the key/value pairs from \p new_dict + * into this dict. When the key is already present in the current + * dict, it either overwrites the current value (if \p fail_on_conflict + * is false) or it throws (if \p fail_on_conflict is true *and* the + * values differ). + * + * With the exception of \p fail_on_conflict, this behaves analogously + * to Python's dict.update() method. + * + * \param new_args The arguments to copy. + * \param fail_on_conflict If true, throws. + * \throws uhd::value_error + */ + void update(const dict<Key, Val> &new_dict, bool fail_on_conflict=true); + private: typedef std::pair<Key, Val> pair_t; std::list<pair_t> _map; //private container diff --git a/host/include/uhd/types/dict.ipp b/host/include/uhd/types/dict.ipp index 5e9cf97ad..5fd4b536e 100644 --- a/host/include/uhd/types/dict.ipp +++ b/host/include/uhd/types/dict.ipp @@ -135,6 +135,20 @@ namespace uhd{ throw key_not_found<Key, Val>(key); } + template <typename Key, typename Val> + void dict<Key, Val>::update(const dict<Key, Val> &new_dict, bool fail_on_conflict) + { + BOOST_FOREACH(const Key &key, new_dict.keys()) { + if (fail_on_conflict and has_key(key) and get(key) != new_dict[key]) { + throw uhd::value_error(str( + boost::format("Option merge conflict: %s:%s != %s:%s") + % key % get(key) % key % new_dict[key] + )); + } + set(key, new_dict[key]); + } + } + } //namespace uhd #endif /* INCLUDED_UHD_TYPES_DICT_IPP */ diff --git a/host/include/uhd/types/direction.hpp b/host/include/uhd/types/direction.hpp index 0f257de44..59ee9b55f 100644 --- a/host/include/uhd/types/direction.hpp +++ b/host/include/uhd/types/direction.hpp @@ -1,5 +1,5 @@ // -// Copyright 2015 Ettus Research LLC +// Copyright 2014-2015 Ettus Research LLC // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by diff --git a/host/include/uhd/types/filters.hpp b/host/include/uhd/types/filters.hpp new file mode 100644 index 000000000..0cb23b294 --- /dev/null +++ b/host/include/uhd/types/filters.hpp @@ -0,0 +1,286 @@ +// +// Copyright 2015 Ettus Research LLC +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. +// + +#ifndef INCLUDED_UHD_TYPES_FILTERS_HPP +#define INCLUDED_UHD_TYPES_FILTERS_HPP + +#include <uhd/config.hpp> +#include <uhd/utils/log.hpp> +#include <uhd/utils/msg.hpp> +#include <boost/cstdint.hpp> +#include <boost/shared_ptr.hpp> +#include <boost/scoped_array.hpp> +#include <string> +#include <vector> +#include <iostream> +#include <ostream> +#include <sstream> + +namespace uhd{ + + class UHD_API filter_info_base + { + public: + typedef boost::shared_ptr<filter_info_base> sptr; + enum filter_type + { + ANALOG_LOW_PASS, + ANALOG_BAND_PASS, + DIGITAL_I16, + DIGITAL_FIR_I16 + }; + + filter_info_base( + filter_type type, + bool bypass, + size_t position_index + ): + _type(type), _bypass(bypass), + _position_index(position_index) + { + //NOP + } + + inline virtual bool is_bypassed() + { + return _bypass; + } + + inline filter_type get_type() + { + return _type; + } + + virtual ~filter_info_base() + { + //NOP + } + + virtual std::string to_pp_string(); + + protected: + filter_type _type; + bool _bypass; + size_t _position_index; + + }; + + UHD_API std::ostream& operator<<(std::ostream& os, filter_info_base& f); + + class UHD_API analog_filter_base : public filter_info_base + { + std::string _analog_type; + public: + typedef boost::shared_ptr<analog_filter_base> sptr; + analog_filter_base( + filter_type type, + bool bypass, + size_t position_index, + const std::string& analog_type + ): + filter_info_base(type, bypass, position_index), + _analog_type(analog_type) + { + //NOP + } + + inline const std::string& get_analog_type() + { + return _analog_type; + } + + virtual std::string to_pp_string(); + }; + + class UHD_API analog_filter_lp : public analog_filter_base + { + double _cutoff; + double _rolloff; + + public: + typedef boost::shared_ptr<analog_filter_lp> sptr; + analog_filter_lp( + filter_type type, + bool bypass, + size_t position_index, + const std::string& analog_type, + double cutoff, + double rolloff + ): + analog_filter_base(type, bypass, position_index, analog_type), + _cutoff(cutoff), + _rolloff(rolloff) + { + //NOP + } + + inline double get_cutoff() + { + return _cutoff; + } + + inline double get_rolloff() + { + return _cutoff; + } + + inline void set_cutoff(const double cutoff) + { + _cutoff = cutoff; + } + + virtual std::string to_pp_string(); + }; + + template<typename tap_t> + class UHD_API digital_filter_base : public filter_info_base + { + protected: + double _rate; + boost::uint32_t _interpolation; + boost::uint32_t _decimation; + tap_t _tap_full_scale; + boost::uint32_t _max_num_taps; + std::vector<tap_t> _taps; + + public: + typedef boost::shared_ptr<digital_filter_base> sptr; + digital_filter_base( + filter_type type, + bool bypass, + size_t position_index, + double rate, + size_t interpolation, + size_t decimation, + double tap_full_scale, + size_t max_num_taps, + const std::vector<tap_t>& taps + ): + filter_info_base(type, bypass, position_index), + _rate(rate), + _interpolation(interpolation), + _decimation(decimation), + _tap_full_scale(tap_full_scale), + _max_num_taps(max_num_taps), + _taps(taps) + { + //NOP + } + + inline double get_output_rate() + { + return (_bypass ? _rate : (_rate / _decimation * _interpolation)); + } + + inline double get_input_rate() + { + return _rate; + } + + inline double get_interpolation() + { + return _interpolation; + } + + inline double get_decimation() + { + return _decimation; + } + + inline double get_tap_full_scale() + { + return _tap_full_scale; + } + + inline std::vector<tap_t>& get_taps() + { + return _taps; + } + + virtual std::string to_pp_string() + { + std::ostringstream os; + os<<filter_info_base::to_pp_string()<< + "\t[digital_filter_base]"<<std::endl<< + "\tinput rate: "<<_rate<<std::endl<< + "\tinterpolation: "<<_interpolation<<std::endl<< + "\tdecimation: "<<_decimation<<std::endl<< + "\tfull-scale: "<<_tap_full_scale<<std::endl<< + "\tmax num taps: "<<_max_num_taps<<std::endl<< + "\ttaps: "<<std::endl; + + os<<"\t\t"; + for(int i = 0; i < _taps.size(); i++) + { + os<<"(tap "<<i<<": "<<_taps[i]<<")"; + if( ((i%10) == 0) && (i != 0)) + { + os<<std::endl<<"\t\t"; + } + } + os<<std::endl; + return std::string(os.str()); + } + + }; + + template<typename tap_t> + class UHD_API digital_filter_fir : public digital_filter_base<tap_t> + { + public: + typedef boost::shared_ptr<digital_filter_fir<tap_t> > sptr; + + digital_filter_fir( + filter_info_base::filter_type type, + bool bypass, size_t position_index, + double rate, + size_t interpolation, + size_t decimation, + size_t tap_bit_width, + size_t max_num_taps, + const std::vector<tap_t>& taps + ): + digital_filter_base<tap_t>(type, bypass, position_index, rate, interpolation, decimation, tap_bit_width, max_num_taps, taps) + { + //NOP + } + + void set_taps(const std::vector<tap_t>& taps) + { + std::size_t num_taps = taps.size(); + if(num_taps < this->_max_num_taps){ + UHD_MSG(warning) << "digital_filter_fir::set_taps not enough coefficients. Appending zeros"; + std::vector<tap_t> coeffs; + for (size_t i = 0; i < this->_max_num_taps; i++) + { + if(i < num_taps) + { + coeffs.push_back(taps[i]); + } else { + coeffs.push_back(0); + } + } + this->_taps = coeffs; + } else { + this->_taps = taps; + } + } + }; + +} //namespace uhd + +#endif /* INCLUDED_UHD_TYPES_FILTERS_HPP */ diff --git a/host/include/uhd/types/sid.hpp b/host/include/uhd/types/sid.hpp new file mode 100644 index 000000000..95034c7a5 --- /dev/null +++ b/host/include/uhd/types/sid.hpp @@ -0,0 +1,238 @@ +// +// Copyright 2014 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_SID_HPP +#define INCLUDED_UHD_TYPES_SID_HPP + +#include <uhd/config.hpp> +#include <boost/cstdint.hpp> +#include <boost/shared_ptr.hpp> +#include <iostream> + +namespace uhd { + /*! + * \brief Represents a stream ID (SID). + * + * A stream ID (SID) is an identifier for data. + * It is a 32-Bit value which consistst of 16 Bits + * for the source address and 16 Bits for the destination + * address. + * Every address is split into two parts: The _address_, which + * identifies the device used, and the _endpoint_, which identifies + * a specific object inside the given device (e.g., a block). + * *Note:* In the case where there are several crossbars on a single + * device, each crossbar gets its own address. + * Both address and endpoint are 8 bits in length. If a 16-bit address + * is required, we use the combination of the 8-bit address and the 8-bit + * endpoint. + * + * \section sid_str_repr String Representation + * + * The string representation of a SID is of the form + * + * 2.3>0.6 + * + * The '>' symbol shows the direction, so in this case, + * data is flowing from address 2.3 to 0.6. + * + * As a convention, ':' is used instead of '.' when giving the + * SID in hexadecimal numbers, and two characters are used for each + * address part. As an example, the following two SIDs are identical: + * + * 2.3>0.16 (decimal) + * 02:03>00:10 (hexadecimal) + * + * The format is: + * SRC_ADDRESS.SRC_ENDPOINT>DST_ADDRESS.DST_ENDPOINT + * + * + * \section sid_block_ports Block Ports + * + * In the special case where a block on a crossbar is addressed, the + * endpoint is further split up into two parts of four bits each: The + * first four bits specify the port number on the crossbar, whereas the + * lower four bits represent the *block port*. As an example, consider + * the following SID, given in hexadecimal: + * + * 00:10>02:A1 + * + * In this example, assume data is flowing from the host computer to an + * X300. The crossbar address is 02. The endpoint is A1, which means we + * are accessing a block on crossbar port A (the tenth port), and are addressing + * block port 1. + * + */ + class UHD_API sid_t + { + public: + //! Create an unset SID + sid_t(); + //! Create a sid_t object from a 32-Bit SID value + sid_t(boost::uint32_t sid); + //! Create a sid_t object from its four components + sid_t(boost::uint8_t src_addr, boost::uint8_t src_ep, boost::uint8_t dst_addr, boost::uint8_t dst_ep); + //! Convert a string representation of a SID into its numerical representation + sid_t(const std::string &); + + //! Return a decimal string representation of the SID. + std::string to_pp_string() const; + //! Return a hexadecimal string representation of the SID. + std::string to_pp_string_hex() const; + + //! Returns true if this actually holds a valid SID + bool is_set() const { return _set; }; + + // Getters + // + //! Alias for get_sid() + UHD_INLINE boost::uint32_t get() const { return get_sid(); }; + //! Returns a 32-Bit representation of the SID if set, or zero otherwise. + UHD_INLINE boost::uint32_t get_sid() const { return _set ? _sid : 0; }; + //! Return the 16-bit source address of this SID + UHD_INLINE boost::uint32_t get_src() const { + return (_sid >> 16) & 0xFFFF; + } + //! Return the 16-bit destination address of this SID + UHD_INLINE boost::uint32_t get_dst() const { + return _sid & 0xFFFF; + } + //! Return 8-bit address of the source + UHD_INLINE boost::uint32_t get_src_addr() const { + return (get_src() >> 8) & 0xFF; + } + //! Return endpoint of the source + UHD_INLINE boost::uint32_t get_src_endpoint() const { + return get_src() & 0xFF; + } + //! Return crossbar port of the source + UHD_INLINE boost::uint32_t get_src_xbarport() const { + return (get_src_endpoint() >> 4) & 0xF; + } + //! Return block port of the source + UHD_INLINE boost::uint32_t get_src_blockport() const { + return (get_src_endpoint()) & 0xF; + } + //! Return 8-bit address of the destination + UHD_INLINE boost::uint32_t get_dst_addr() const { + return (get_dst() >> 8) & 0xFF; + } + //! Return endpoint of the destination + UHD_INLINE boost::uint32_t get_dst_endpoint() const { + return get_dst() & 0xFF; + } + //! Return crossbar port of the source + UHD_INLINE boost::uint32_t get_dst_xbarport() const { + return (get_dst_endpoint() >> 4) & 0xF; + } + //! Return block port of the source + UHD_INLINE boost::uint32_t get_dst_blockport() const { + return (get_dst_endpoint()) & 0xF; + } + + // Setters + + //! Alias for set_sid() + void set(boost::uint32_t new_sid) { set_sid(new_sid); }; + //! Convert a string representation of a SID into a numerical one + // Throws uhd::value_error if the string is not a valid SID + // representation. + void set_from_str(const std::string &); + void set_sid(boost::uint32_t new_sid); + //! Set the source address of this SID + // (the first 16 Bits) + void set_src(boost::uint32_t new_addr); + //! Set the destination address of this SID + // (the last 16 Bits) + void set_dst(boost::uint32_t new_addr); + void set_src_addr(boost::uint32_t new_addr); + void set_src_endpoint(boost::uint32_t new_addr); + void set_dst_addr(boost::uint32_t new_addr); + void set_dst_endpoint(boost::uint32_t new_addr); + void set_dst_xbarport(boost::uint32_t new_xbarport); + void set_dst_blockport(boost::uint32_t new_blockport); + + // Manipulators + + //! Swaps dst and src address and returns the new SID. + sid_t reversed(); + + //! Swaps dst and src in-place. + void reverse(); + + // Overloaded operators + + sid_t operator = (boost::uint32_t new_sid) { + set_sid(new_sid); + return *this; + } + + sid_t operator = (sid_t &sid) { + set_sid(sid.get_sid()); + return *this; + } + + sid_t operator = (const std::string &sid_str) { + set_from_str(sid_str); + return *this; + } + + bool operator == (const sid_t &sid) const { + return (not _set and not sid.is_set()) or (_sid == sid.get_sid()); + } + + bool operator == (boost::uint32_t sid) const { + return _set and _sid == sid; + } + + bool operator == (const std::string &sid_str) const { + sid_t rhs(sid_str); + return *this == rhs; + } + + // overloaded type casts are tricky, but for now we'll need them + // for backward compatibility. consider them deprecated. + + //! If the SID is not set, always returns zero. + // Use is_set() to check if the return value is valid. + operator boost::uint32_t() const { + return get(); + } + + operator bool() const { + return _set; + } + + private: + boost::uint32_t _sid; + bool _set; + }; + + //! Stream output operator. Honors std::ios::hex. + UHD_INLINE std::ostream& operator<< (std::ostream& out, const sid_t &sid) { + std::ios_base::fmtflags ff = out.flags(); + if (ff & std::ios::hex) { + out << sid.to_pp_string_hex(); + } else { + out << sid.to_pp_string(); + } + return out; + } + +} //namespace uhd + +#endif /* INCLUDED_UHD_TYPES_SID_HPP */ +// vim: sw=4 et: diff --git a/host/include/uhd/usrp/multi_usrp.hpp b/host/include/uhd/usrp/multi_usrp.hpp index 6fd22ff23..1c408d56e 100644 --- a/host/include/uhd/usrp/multi_usrp.hpp +++ b/host/include/uhd/usrp/multi_usrp.hpp @@ -26,6 +26,7 @@ #define UHD_USRP_MULTI_USRP_BW_RANGE_API #define UHD_USRP_MULTI_USRP_USER_REGS_API #define UHD_USRP_MULTI_USRP_GET_USRP_INFO_API +#define UHD_USRP_MULTI_USRP_NORMALIZED_GAIN #include <uhd/config.hpp> #include <uhd/device.hpp> @@ -35,6 +36,7 @@ #include <uhd/types/tune_request.hpp> #include <uhd/types/tune_result.hpp> #include <uhd/types/sensors.hpp> +#include <uhd/types/filters.hpp> #include <uhd/usrp/subdev_spec.hpp> #include <uhd/usrp/dboard_iface.hpp> #include <boost/shared_ptr.hpp> @@ -155,6 +157,11 @@ public: * If the specified rate is not available, this method will throw. * On other devices, this method notifies the software of the rate, * but requires the the user has made the necessary hardware change. + * + * If the device has an 'auto clock rate' setting (e.g. B200, see also + * \ref b200_auto_mcr), this will get disabled and the clock rate will be + * fixed to \p rate. + * * \param rate the new master clock rate in Hz * \param mboard the motherboard index 0 to M-1 */ @@ -490,6 +497,34 @@ public: } /*! + * Set the normalized RX gain value. + * + * The normalized gain is a value in [0, 1], where 0 is the + * smallest gain value available, and 1 is the largest, independent + * of the device. In between, gains are linearly interpolated. + * + * Check the individual device manual for notes on the gain range. + * + * Note that it is not possible to specify a gain name for + * this function, it will always set the overall gain. + * + * \param gain the normalized gain value + * \param chan the channel index 0 to N-1 + * \throws A uhd::runtime_error if the gain value is outside [0, 1]. + */ + virtual void set_normalized_rx_gain(double gain, size_t chan = 0) = 0; + + /*! + * Enable or disable the RX AGC module. + * Once this module is enabled manual gain settings will be ignored. + * The AGC will start in a default configuration which should be good for most use cases. + * Device specific configuration parameters can be found in the property tree. + * \param on Enable or Disable the AGC + * \param chan the channel index 0 to N-1 + */ + virtual void set_rx_agc(bool enable, size_t chan = 0) = 0; + + /*! * 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 @@ -504,6 +539,19 @@ public: } /*! + * Return the normalized RX gain value. + * + * See set_normalized_rx_gain() for a discussion of normalized + * gains. + * + * \param gain the normalized gain value + * \param chan the channel index 0 to N-1 + * \returns The normalized gain (in [0, 1]) + * \throws A uhd::runtime_error if the gain value is outside [0, 1]. + */ + virtual double get_normalized_rx_gain(size_t chan = 0) = 0; + + /*! * 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 @@ -615,6 +663,14 @@ public: virtual void set_rx_dc_offset(const std::complex<double> &offset, size_t chan = ALL_CHANS) = 0; /*! + * Enable/disable the automatic IQ imbalance correction. + * + * \param enb true to enable automatic IQ balance correction + * \param chan the channel index 0 to N-1 + */ + virtual void set_rx_iq_balance(const bool enb, size_t chan) = 0; + + /*! * Set the RX frontend IQ imbalance correction. * Use this to adjust the magnitude and phase of I and Q. * @@ -728,6 +784,18 @@ public: } /*! + * Set the normalized TX gain value. + * + * See set_normalized_rx_gain() for a discussion on normalized + * gains. + * + * \param gain the normalized gain value + * \param chan the channel index 0 to N-1 + * \throws A uhd::runtime_error if the gain value is outside [0, 1]. + */ + virtual void set_normalized_tx_gain(double gain, size_t chan = 0) = 0; + + /*! * 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 @@ -742,6 +810,19 @@ public: } /*! + * Return the normalized TX gain value. + * + * See set_normalized_rx_gain() for a discussion of normalized + * gains. + * + * \param gain the normalized gain value + * \param chan the channel index 0 to N-1 + * \returns The normalized gain (in [0, 1]) + * \throws A uhd::runtime_error if the gain value is outside [0, 1]. + */ + virtual double get_normalized_tx_gain(size_t chan = 0) = 0; + + /*! * 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 @@ -893,6 +974,38 @@ public: */ virtual boost::uint32_t get_gpio_attr(const std::string &bank, const std::string &attr, const size_t mboard = 0) = 0; + /******************************************************************* + * Filter API methods + ******************************************************************/ + + /*! + * Enumerate the available filters in the signal path. + * \param search_mask + * \parblock + * Select only certain filter names by specifying this search mask. + * + * E.g. if search mask is set to "rx_frontends/A" only filter names including that string will be returned. + * \endparblock + * \return a vector of strings representing the selected filter names. + */ + virtual std::vector<std::string> get_filter_names(const std::string &search_mask = "") = 0; + + /*! + * Return the filter object for the given name. + * \param path the name of the filter as returned from get_filter_names(). + * \return a filter_info_base::sptr. + */ + virtual filter_info_base::sptr get_filter(const std::string &path) = 0; + + /*! + * Write back a filter obtained by get_filter() to the signal path. + * This filter can be a modified version of the originally returned one. + * The information about Rx or Tx is contained in the path parameter. + * \param path the name of the filter as returned from get_filter_names(). + * \param filter the filter_info_base::sptr of the filter object to be written + */ + virtual void set_filter(const std::string &path, filter_info_base::sptr filter) = 0; + }; }} diff --git a/host/include/uhd/utils/fp_compare_delta.ipp b/host/include/uhd/utils/fp_compare_delta.ipp index 092ade6e9..49cbc281b 100644 --- a/host/include/uhd/utils/fp_compare_delta.ipp +++ b/host/include/uhd/utils/fp_compare_delta.ipp @@ -100,8 +100,8 @@ namespace uhd { namespace math { namespace fp_compare { template<typename float_t> UHD_INLINE bool operator==(fp_compare_delta<float_t> lhs, double rhs) { - float_t delta = fp_compare_select_delta(double(lhs._delta), - DOUBLE_PRECISION_DELTA); + float_t delta = float_t(fp_compare_select_delta(double(lhs._delta), + DOUBLE_PRECISION_DELTA)); return (std::fabs(lhs._value - rhs) < delta); } @@ -112,8 +112,8 @@ namespace uhd { namespace math { namespace fp_compare { template<typename float_t> UHD_INLINE bool operator<(fp_compare_delta<float_t> lhs, double rhs) { - float_t delta = fp_compare_select_delta(double(lhs._delta), - DOUBLE_PRECISION_DELTA); + float_t delta = float_t(fp_compare_select_delta(double(lhs._delta), + DOUBLE_PRECISION_DELTA)); return ((rhs - lhs._value) > delta); } @@ -124,8 +124,8 @@ namespace uhd { namespace math { namespace fp_compare { template<typename float_t> UHD_INLINE bool operator>(fp_compare_delta<float_t> lhs, double rhs) { - float_t delta = fp_compare_select_delta(double(lhs._delta), - DOUBLE_PRECISION_DELTA); + float_t delta = float_t(fp_compare_select_delta(double(lhs._delta), + DOUBLE_PRECISION_DELTA)); return ((lhs._value - rhs) > delta); } @@ -148,8 +148,8 @@ namespace uhd { namespace math { namespace fp_compare { template<typename float_t> UHD_INLINE bool operator<(double lhs, fp_compare_delta<float_t> rhs) { - float_t delta = fp_compare_select_delta(DOUBLE_PRECISION_DELTA, - double(rhs._delta)); + float_t delta = float_t(fp_compare_select_delta(DOUBLE_PRECISION_DELTA, + double(rhs._delta))); return ((rhs._value - lhs) > delta); } @@ -160,8 +160,8 @@ namespace uhd { namespace math { namespace fp_compare { template<typename float_t> UHD_INLINE bool operator>(double lhs, fp_compare_delta<float_t> rhs) { - float_t delta = fp_compare_select_delta(DOUBLE_PRECISION_DELTA, - double(rhs._delta)); + float_t delta = float_t(fp_compare_select_delta(DOUBLE_PRECISION_DELTA, + double(rhs._delta))); return ((lhs - rhs._value) > delta); } diff --git a/host/include/uhd/utils/log.hpp b/host/include/uhd/utils/log.hpp index 5baa00108..106c0d9d5 100644 --- a/host/include/uhd/utils/log.hpp +++ b/host/include/uhd/utils/log.hpp @@ -76,7 +76,7 @@ namespace uhd{ namespace _log{ regularly = 3, rarely = 4, very_rarely = 5, - never = 6, + never = 6 }; //! Internal logging object (called by UHD_LOG macros) @@ -101,12 +101,12 @@ namespace uhd{ namespace _log{ // General insertion overload template <typename T> - INSERTION_OVERLOAD(T val); + INSERTION_OVERLOAD(T val) // Insertion overloads for std::ostream manipulators - INSERTION_OVERLOAD(std::ostream& (*val)(std::ostream&)); - INSERTION_OVERLOAD(std::ios& (*val)(std::ios&)); - INSERTION_OVERLOAD(std::ios_base& (*val)(std::ios_base&)); + INSERTION_OVERLOAD(std::ostream& (*val)(std::ostream&)) + INSERTION_OVERLOAD(std::ios& (*val)(std::ios&)) + INSERTION_OVERLOAD(std::ios_base& (*val)(std::ios_base&)) private: std::ostringstream _ss; diff --git a/host/include/uhd/utils/math.hpp b/host/include/uhd/utils/math.hpp index 21825c3dc..46a1cf7e4 100644 --- a/host/include/uhd/utils/math.hpp +++ b/host/include/uhd/utils/math.hpp @@ -18,11 +18,11 @@ #ifndef INCLUDED_UHD_UTILS_MATH_HPP #define INCLUDED_UHD_UTILS_MATH_HPP +#include <cmath> #include <uhd/config.hpp> #include <boost/cstdint.hpp> #include <boost/numeric/conversion/bounds.hpp> - namespace uhd { /*! @@ -60,7 +60,7 @@ namespace math { * values, a custom epsilon should be defined for those computations. This * use-case is provided for in the `fp_compare_epsilon` class constructor. */ - static const float SINGLE_PRECISION_EPSILON = 1.19e-7; + static const float SINGLE_PRECISION_EPSILON = 1.19e-7f; static const double DOUBLE_PRECISION_EPSILON = 2.22e-16; namespace fp_compare { @@ -155,7 +155,7 @@ namespace fp_compare { * These are the default deltas used by the 'fp_compare_delta' class for * single and double-precision floating point comparisons. */ - static const float SINGLE_PRECISION_DELTA = 1e-3; + static const float SINGLE_PRECISION_DELTA = 1e-3f; static const double DOUBLE_PRECISION_DELTA = 1e-5; /*! Floating-point delta to use for frequency comparisons. */ @@ -237,6 +237,16 @@ namespace fp_compare { == fp_compare::fp_compare_delta<double>(rhs, FREQ_COMPARISON_DELTA_HZ)); } + //! Portable log2() + template <typename float_t> UHD_INLINE + float_t log2(float_t x) + { + // C++11 defines std::log2(), when that's universally supported + // we can switch over. + return std::log(x) / std::log(float_t(2)); + } + + } // namespace math } // namespace uhd |