From e2487eb7311d6bbeec5e6aaeab0a3857d8cada1b Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Sun, 2 Jan 2011 13:10:27 -0800 Subject: uhd: potential fix for explicit template + llvm --- host/lib/types.cpp | 2 ++ 1 file changed, 2 insertions(+) (limited to 'host/lib/types.cpp') diff --git a/host/lib/types.cpp b/host/lib/types.cpp index bea20a4aa..9e4a26c23 100644 --- a/host/lib/types.cpp +++ b/host/lib/types.cpp @@ -43,8 +43,10 @@ using namespace uhd; /*********************************************************************** * ranges template instantiation **********************************************************************/ +#ifdef UHD_USE_EXIM_TMPL template struct uhd::meta_range_t; template struct uhd::meta_range_t; +#endif /*********************************************************************** * tune request -- cgit v1.2.3 From 283067dea28c2082b71793706f582ce96e667370 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Wed, 5 Jan 2011 12:17:06 -0800 Subject: uhd: replaced templated ranges with one range thing using doubles only to avoid trouble with compiler portability --- host/include/uhd/config.hpp | 10 -- host/include/uhd/types/CMakeLists.txt | 1 - host/include/uhd/types/ranges.hpp | 41 ++++---- host/include/uhd/types/ranges.ipp | 188 ---------------------------------- host/include/uhd/utils/gain_group.hpp | 11 +- host/lib/CMakeLists.txt | 1 + host/lib/ranges.cpp | 163 +++++++++++++++++++++++++++++ host/lib/types.cpp | 9 -- host/lib/usrp/dboard/db_xcvr2450.cpp | 10 +- host/lib/utils/gain_group.cpp | 18 ++-- host/test/gain_group_test.cpp | 20 ++-- host/test/ranges_test.cpp | 12 +-- 12 files changed, 219 insertions(+), 265 deletions(-) delete mode 100644 host/include/uhd/types/ranges.ipp create mode 100644 host/lib/ranges.cpp (limited to 'host/lib/types.cpp') diff --git a/host/include/uhd/config.hpp b/host/include/uhd/config.hpp index 62c2504e1..f7ccb62e5 100644 --- a/host/include/uhd/config.hpp +++ b/host/include/uhd/config.hpp @@ -89,14 +89,4 @@ typedef ptrdiff_t ssize_t; #define UHD_PLATFORM_BSD #endif -//On macos platform, explicit templates must be: -// - defined with extern in the header file -// - defined as a symbol in the source file -#if defined(UHD_PLATFORM_MACOS) || defined(UHD_PLATFORM_BSD) - #define UHD_EXIM_TMPL extern - #define UHD_USE_EXIM_TMPL -#else - #define UHD_EXIM_TMPL -#endif - #endif /* INCLUDED_UHD_CONFIG_HPP */ diff --git a/host/include/uhd/types/CMakeLists.txt b/host/include/uhd/types/CMakeLists.txt index 1d2c0c41c..a96976b5e 100644 --- a/host/include/uhd/types/CMakeLists.txt +++ b/host/include/uhd/types/CMakeLists.txt @@ -25,7 +25,6 @@ INSTALL(FILES mac_addr.hpp metadata.hpp otw_type.hpp - ranges.ipp ranges.hpp serial.hpp stream_cmd.hpp diff --git a/host/include/uhd/types/ranges.hpp b/host/include/uhd/types/ranges.hpp index 366efb1f3..5bb74f976 100644 --- a/host/include/uhd/types/ranges.hpp +++ b/host/include/uhd/types/ranges.hpp @@ -30,14 +30,15 @@ namespace uhd{ * A range object describes a set of discrete values of the form: * y = start + step*n, where n is an integer between 0 and (stop - start)/step */ - template class range_t{ + class UHD_API range_t{ public: + /*! * Create a range from a single value. * The step size will be taken as zero. * \param value the only possible value in this range */ - range_t(const T &value = T(0)); + range_t(double value = 0); /*! * Create a range from a full set of values. @@ -46,28 +47,27 @@ namespace uhd{ * \param stop the maximum value for this range * \param step the step size for this range */ - range_t(const T &start, const T &stop, const T &step = T(0)); + range_t(double start, double stop, double step = 0); //! Get the start value for this range. - const T start(void) const; + double start(void) const; //! Get the stop value for this range. - const T stop(void) const; + double stop(void) const; //! Get the step value for this range. - const T step(void) const; + double step(void) const; //! Convert this range to a printable string const std::string to_pp_string(void) const; - private: - UHD_PIMPL_DECL(impl) _impl; + private: UHD_PIMPL_DECL(impl) _impl; }; /*! * A meta-range object holds a list of individual ranges. */ - template struct meta_range_t : std::vector >{ + struct UHD_API meta_range_t : std::vector{ //! A default constructor for an empty meta-range meta_range_t(void); @@ -79,7 +79,8 @@ namespace uhd{ * \param last the end iterator */ template - meta_range_t(InputIterator first, InputIterator last); + meta_range_t(InputIterator first, InputIterator last): + std::vector(first, last){ /* NOP */ } /*! * A convenience constructor for a single range. @@ -88,16 +89,16 @@ namespace uhd{ * \param stop the maximum value for this range * \param step the step size for this range */ - meta_range_t(const T &start, const T &stop, const T &step = T(0)); + meta_range_t(double start, double stop, double step = 0); //! Get the overall start value for this meta-range. - const T start(void) const; + double start(void) const; //! Get the overall stop value for this meta-range. - const T stop(void) const; + double stop(void) const; //! Get the overall step value for this meta-range. - const T step(void) const; + double step(void) const; /*! * Clip the target value to a possible range value. @@ -105,22 +106,16 @@ namespace uhd{ * \param clip_step if true, clip to steps as well * \return a value that is in one of the ranges */ - const T clip(const T &value, bool clip_step = false) const; + double clip(double value, bool clip_step = false) const; //! Convert this meta-range to a printable string const std::string to_pp_string(void) const; }; - //!typedef for a gain meta-range - typedef meta_range_t gain_range_t; - - //!typedef for a frequency meta-range - typedef meta_range_t freq_range_t; - + typedef meta_range_t gain_range_t; + typedef meta_range_t freq_range_t; } //namespace uhd -#include - #endif /* INCLUDED_UHD_TYPES_RANGES_HPP */ diff --git a/host/include/uhd/types/ranges.ipp b/host/include/uhd/types/ranges.ipp deleted file mode 100644 index 944ada51f..000000000 --- a/host/include/uhd/types/ranges.ipp +++ /dev/null @@ -1,188 +0,0 @@ -// -// Copyright 2010 Ettus Research LLC -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// - -#ifndef INCLUDED_UHD_TYPES_RANGES_IPP -#define INCLUDED_UHD_TYPES_RANGES_IPP - -#include -#include -#include -#include -#include - -namespace uhd{ - - /******************************************************************* - * range_t implementation code - ******************************************************************/ - template struct range_t::impl{ - impl(const T &start, const T &stop, const T &step): - start(start), stop(stop), step(step) - { - /* NOP */ - } - const T start, stop, step; - }; - - template range_t::range_t(const T &value): - _impl(UHD_PIMPL_MAKE(impl, (value, value, T(0)))) - { - /* NOP */ - } - - template range_t::range_t( - const T &start, const T &stop, const T &step - ): - _impl(UHD_PIMPL_MAKE(impl, (start, stop, step))) - { - if (stop < start){ - throw std::invalid_argument("cannot make range where stop < start"); - } - } - - template const T range_t::start(void) const{ - return _impl->start; - } - - template const T range_t::stop(void) const{ - return _impl->stop; - } - - template const T range_t::step(void) const{ - return _impl->step; - } - - template const std::string range_t::to_pp_string(void) const{ - std::stringstream ss; - ss << "(" << this->start(); - if (this->start() != this->stop()) ss << ", " << this->stop(); - if (this->step() != T(0)) ss << ", " << this->step(); - ss << ")"; - return ss.str(); - } - - /******************************************************************* - * meta_range_t implementation code - ******************************************************************/ - - namespace /*anon*/{ - template inline - void check_meta_range_monotonic(const meta_range_t &mr){ - if (mr.empty()){ - throw std::runtime_error("meta-range cannot be empty"); - } - for (size_t i = 1; i < mr.size(); i++){ - if (mr.at(i).start() < mr.at(i-1).stop()){ - throw std::runtime_error("meta-range is not monotonic"); - } - } - } - } //namespace /*anon*/ - - - template meta_range_t::meta_range_t(void){ - /* NOP */ - } - - template template - meta_range_t::meta_range_t( - InputIterator first, InputIterator last - ): - std::vector >(first, last) - { - /* NOP */ - } - - template meta_range_t::meta_range_t( - const T &start, const T &stop, const T &step - ): - std::vector > (1, range_t(start, stop, step)) - { - /* NOP */ - } - - template const T meta_range_t::start(void) const{ - check_meta_range_monotonic(*this); - T min_start = this->front().start(); - BOOST_FOREACH(const range_t &r, (*this)){ - min_start = std::min(min_start, r.start()); - } - return min_start; - } - - template const T meta_range_t::stop(void) const{ - check_meta_range_monotonic(*this); - T max_stop = this->front().stop(); - BOOST_FOREACH(const range_t &r, (*this)){ - max_stop = std::max(max_stop, r.stop()); - } - return max_stop; - } - - template const T meta_range_t::step(void) const{ - check_meta_range_monotonic(*this); - std::vector non_zero_steps; - range_t last = this->front(); - BOOST_FOREACH(const range_t &r, (*this)){ - //steps at each range - if (r.step() > T(0)) non_zero_steps.push_back(r.step()); - //and steps in-between ranges - T ibtw_step = r.start() - last.stop(); - if (ibtw_step > T(0)) non_zero_steps.push_back(ibtw_step); - //store ref to last - last = r; - } - if (non_zero_steps.empty()) return T(0); //all zero steps, its zero... - return *std::min_element(non_zero_steps.begin(), non_zero_steps.end()); - } - - template const T meta_range_t::clip( - const T &value, bool clip_step - ) const{ - check_meta_range_monotonic(*this); - T last_stop = this->front().stop(); - BOOST_FOREACH(const range_t &r, (*this)){ - //in-between ranges, clip to nearest - if (value < r.start()){ - return (std::abs(value - r.start()) < std::abs(value - last_stop))? - r.start() : last_stop; - } - //in this range, clip here - if (value <= r.stop()){ - if (not clip_step or r.step() == T(0)) return value; - return boost::math::round((value - r.start())/r.step())*r.step() + r.start(); - } - //continue on to the next range - last_stop = r.stop(); - } - return last_stop; - } - - template const std::string meta_range_t::to_pp_string(void) const{ - std::stringstream ss; - BOOST_FOREACH(const range_t &r, (*this)){ - ss << r.to_pp_string() << std::endl; - } - return ss.str(); - } - - UHD_EXIM_TMPL template struct UHD_API meta_range_t; - UHD_EXIM_TMPL template struct UHD_API meta_range_t; - -} //namespace uhd - -#endif /* INCLUDED_UHD_TYPES_RANGES_IPP */ diff --git a/host/include/uhd/utils/gain_group.hpp b/host/include/uhd/utils/gain_group.hpp index c863248ce..c4115f224 100644 --- a/host/include/uhd/utils/gain_group.hpp +++ b/host/include/uhd/utils/gain_group.hpp @@ -28,13 +28,16 @@ namespace uhd{ +//! the data type that represents a gain +typedef double gain_t; + /*! * A set of function to control a gain element. */ struct UHD_API gain_fcns_t{ boost::function get_range; - boost::function get_value; - boost::function set_value; + boost::function get_value; + boost::function set_value; }; class UHD_API gain_group : boost::noncopyable{ @@ -56,7 +59,7 @@ public: * \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; + virtual gain_t get_value(const std::string &name = "") = 0; /*! * Set the gain value for the gain element specified by name. @@ -66,7 +69,7 @@ public: * \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; + virtual void set_value(gain_t gain, const std::string &name = "") = 0; /*! * Get a list of names of registered gain elements. diff --git a/host/lib/CMakeLists.txt b/host/lib/CMakeLists.txt index 9ab121df5..43a29df59 100644 --- a/host/lib/CMakeLists.txt +++ b/host/lib/CMakeLists.txt @@ -117,6 +117,7 @@ INCLUDE_DIRECTORIES(${CMAKE_CURRENT_BINARY_DIR}) LIBUHD_APPEND_SOURCES( ${CMAKE_CURRENT_BINARY_DIR}/constants.hpp ${CMAKE_CURRENT_SOURCE_DIR}/device.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/ranges.cpp ${CMAKE_CURRENT_SOURCE_DIR}/types.cpp ${CMAKE_CURRENT_SOURCE_DIR}/version.cpp ${CMAKE_CURRENT_SOURCE_DIR}/wax.cpp diff --git a/host/lib/ranges.cpp b/host/lib/ranges.cpp new file mode 100644 index 000000000..0503cc71c --- /dev/null +++ b/host/lib/ranges.cpp @@ -0,0 +1,163 @@ +// +// 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 . +// + +#include +#include +#include +#include +#include +#include + +using namespace uhd; + +/*********************************************************************** + * range_t implementation code + **********************************************************************/ +struct range_t::impl{ + impl(double start, double stop, double step): + start(start), stop(stop), step(step) + { + /* NOP */ + } + double start, stop, step; +}; + +range_t::range_t(double value): + _impl(UHD_PIMPL_MAKE(impl, (value, value, 0))) +{ + /* NOP */ +} + +range_t::range_t( + double start, double stop, double step +): + _impl(UHD_PIMPL_MAKE(impl, (start, stop, step))) +{ + if (stop < start){ + throw std::invalid_argument("cannot make range where stop < start"); + } +} + +double range_t::start(void) const{ + return _impl->start; +} + +double range_t::stop(void) const{ + return _impl->stop; +} + +double range_t::step(void) const{ + return _impl->step; +} + +const std::string range_t::to_pp_string(void) const{ + std::stringstream ss; + ss << "(" << this->start(); + if (this->start() != this->stop()) ss << ", " << this->stop(); + if (this->step() != 0) ss << ", " << this->step(); + ss << ")"; + return ss.str(); +} + +/*********************************************************************** + * meta_range_t implementation code + **********************************************************************/ +void check_meta_range_monotonic(const meta_range_t &mr){ + if (mr.empty()){ + throw std::runtime_error("meta-range cannot be empty"); + } + for (size_t i = 1; i < mr.size(); i++){ + if (mr.at(i).start() < mr.at(i-1).stop()){ + throw std::runtime_error("meta-range is not monotonic"); + } + } +} + +meta_range_t::meta_range_t(void){ + /* NOP */ +} + +meta_range_t::meta_range_t( + double start, double stop, double step +): + std::vector (1, range_t(start, stop, step)) +{ + /* NOP */ +} + +double meta_range_t::start(void) const{ + check_meta_range_monotonic(*this); + double min_start = this->front().start(); + BOOST_FOREACH(const range_t &r, (*this)){ + min_start = std::min(min_start, r.start()); + } + return min_start; +} + +double meta_range_t::stop(void) const{ + check_meta_range_monotonic(*this); + double max_stop = this->front().stop(); + BOOST_FOREACH(const range_t &r, (*this)){ + max_stop = std::max(max_stop, r.stop()); + } + return max_stop; +} + +double meta_range_t::step(void) const{ + check_meta_range_monotonic(*this); + std::vector non_zero_steps; + range_t last = this->front(); + BOOST_FOREACH(const range_t &r, (*this)){ + //steps at each range + if (r.step() > 0) non_zero_steps.push_back(r.step()); + //and steps in-between ranges + double ibtw_step = r.start() - last.stop(); + if (ibtw_step > 0) non_zero_steps.push_back(ibtw_step); + //store ref to last + last = r; + } + if (non_zero_steps.empty()) return 0; //all zero steps, its zero... + return *std::min_element(non_zero_steps.begin(), non_zero_steps.end()); +} + +double meta_range_t::clip(double value, bool clip_step) const{ + check_meta_range_monotonic(*this); + double last_stop = this->front().stop(); + BOOST_FOREACH(const range_t &r, (*this)){ + //in-between ranges, clip to nearest + if (value < r.start()){ + return (std::abs(value - r.start()) < std::abs(value - last_stop))? + r.start() : last_stop; + } + //in this range, clip here + if (value <= r.stop()){ + if (not clip_step or r.step() == 0) return value; + return boost::math::round((value - r.start())/r.step())*r.step() + r.start(); + } + //continue on to the next range + last_stop = r.stop(); + } + return last_stop; +} + +const std::string meta_range_t::to_pp_string(void) const{ + std::stringstream ss; + BOOST_FOREACH(const range_t &r, (*this)){ + ss << r.to_pp_string() << std::endl; + } + return ss.str(); +} diff --git a/host/lib/types.cpp b/host/lib/types.cpp index 9e4a26c23..8ccb664d5 100644 --- a/host/lib/types.cpp +++ b/host/lib/types.cpp @@ -21,7 +21,6 @@ #include #include #include -#include #include #include #include @@ -40,14 +39,6 @@ using namespace uhd; -/*********************************************************************** - * ranges template instantiation - **********************************************************************/ -#ifdef UHD_USE_EXIM_TMPL -template struct uhd::meta_range_t; -template struct uhd::meta_range_t; -#endif - /*********************************************************************** * tune request **********************************************************************/ diff --git a/host/lib/usrp/dboard/db_xcvr2450.cpp b/host/lib/usrp/dboard/db_xcvr2450.cpp index e76727bec..6fdac7c6f 100644 --- a/host/lib/usrp/dboard/db_xcvr2450.cpp +++ b/host/lib/usrp/dboard/db_xcvr2450.cpp @@ -73,8 +73,8 @@ using namespace boost::assign; static const bool xcvr2450_debug = false; static const freq_range_t xcvr_freq_range = list_of - (range_t(2.4e9, 2.5e9)) - (range_t(4.9e9, 6.0e9)) + (range_t(2.4e9, 2.5e9)) + (range_t(4.9e9, 6.0e9)) ; static const prop_names_t xcvr_antennas = list_of("J1")("J2"); @@ -85,9 +85,9 @@ static const uhd::dict xcvr_tx_gain_ranges = map_list ; static const uhd::dict xcvr_rx_gain_ranges = map_list_of ("LNA", gain_range_t(list_of - (range_t(0)) - (range_t(15)) - (range_t(30.5)) + (range_t(0)) + (range_t(15)) + (range_t(30.5)) )) ("VGA", gain_range_t(0, 62, 2.0)) ; diff --git a/host/lib/utils/gain_group.cpp b/host/lib/utils/gain_group.cpp index 11bbb8c0a..cba5056ea 100644 --- a/host/lib/utils/gain_group.cpp +++ b/host/lib/utils/gain_group.cpp @@ -39,7 +39,7 @@ static bool compare_by_step_size( * Get a multiple of step with the following relation: * result = step*floor(num/step) * - * Due to small floating-point inaccuracies: + * Due to small gain_ting-point inaccuracies: * num = n*step + e, where e is a small inaccuracy. * When e is negative, floor would yeild (n-1)*step, * despite that n*step is really the desired result. @@ -66,7 +66,7 @@ public: gain_range_t get_range(const std::string &name){ if (not name.empty()) return _name_to_fcns[name].get_range(); - float overall_min = 0, overall_max = 0, overall_step = 0; + gain_t overall_min = 0, overall_max = 0, overall_step = 0; BOOST_FOREACH(const gain_fcns_t &fcns, get_all_fcns()){ const gain_range_t range = fcns.get_range(); overall_min += range.start(); @@ -78,33 +78,33 @@ public: return gain_range_t(overall_min, overall_max, overall_step); } - float get_value(const std::string &name){ + gain_t get_value(const std::string &name){ if (not name.empty()) return _name_to_fcns[name].get_value(); - float overall_gain = 0; + gain_t overall_gain = 0; BOOST_FOREACH(const gain_fcns_t &fcns, get_all_fcns()){ overall_gain += fcns.get_value(); } return overall_gain; } - void set_value(float gain, const std::string &name){ + void set_value(gain_t gain, const std::string &name){ if (not name.empty()) return _name_to_fcns[name].set_value(gain); std::vector all_fcns = get_all_fcns(); if (all_fcns.size() == 0) return; //nothing to set! //get the max step size among the gains - float max_step = 0; + gain_t max_step = 0; BOOST_FOREACH(const gain_fcns_t &fcns, all_fcns){ max_step = std::max(max_step, fcns.get_range().step()); } //create gain bucket to distribute power - std::vector gain_bucket; + std::vector gain_bucket; //distribute power according to priority (round to max step) - float gain_left_to_distribute = gain; + gain_t gain_left_to_distribute = gain; BOOST_FOREACH(const gain_fcns_t &fcns, all_fcns){ const gain_range_t range = fcns.get_range(); gain_bucket.push_back(floor_step(std::clip( @@ -131,7 +131,7 @@ public: //fill in the largest step sizes first that are less than the remainder BOOST_FOREACH(size_t i, indexes_step_size_dec){ const gain_range_t range = all_fcns.at(i).get_range(); - float additional_gain = floor_step(std::clip( + gain_t additional_gain = floor_step(std::clip( gain_bucket.at(i) + gain_left_to_distribute, range.start(), range.stop() ), range.step()) - gain_bucket.at(i); gain_bucket.at(i) += additional_gain; diff --git a/host/test/gain_group_test.cpp b/host/test/gain_group_test.cpp index dbb585987..79487b2ba 100644 --- a/host/test/gain_group_test.cpp +++ b/host/test/gain_group_test.cpp @@ -52,7 +52,7 @@ class gain_element2{ public: gain_range_t get_range(void){ - return gain_range_t(-20, 10, float(0.1)); + return gain_range_t(-20, 10, 0.1); } float get_value(void){ @@ -94,17 +94,17 @@ static gain_group::sptr get_gain_group(size_t pri1 = 0, size_t pri2 = 0){ /*********************************************************************** * Test cases **********************************************************************/ -static const float tolerance = float(0.001); +static const double tolerance = 0.001; BOOST_AUTO_TEST_CASE(test_gain_group_overall){ gain_group::sptr gg = get_gain_group(); //test the overall stuff gg->set_value(80); - BOOST_CHECK_CLOSE(gg->get_value(), float(80), tolerance); - BOOST_CHECK_CLOSE(gg->get_range().start(), float(-20), tolerance); - BOOST_CHECK_CLOSE(gg->get_range().stop(), float(100), tolerance); - BOOST_CHECK_CLOSE(gg->get_range().step(), float(0.1), tolerance); + BOOST_CHECK_CLOSE(gg->get_value(), 80, tolerance); + BOOST_CHECK_CLOSE(gg->get_range().start(), -20, tolerance); + BOOST_CHECK_CLOSE(gg->get_range().stop(), 100, tolerance); + BOOST_CHECK_CLOSE(gg->get_range().step(), 0.1, tolerance); } BOOST_AUTO_TEST_CASE(test_gain_group_priority){ @@ -112,10 +112,10 @@ BOOST_AUTO_TEST_CASE(test_gain_group_priority){ //test the overall stuff gg->set_value(80); - BOOST_CHECK_CLOSE(gg->get_value(), float(80), tolerance); - BOOST_CHECK_CLOSE(gg->get_range().start(), float(-20), tolerance); - BOOST_CHECK_CLOSE(gg->get_range().stop(), float(100), tolerance); - BOOST_CHECK_CLOSE(gg->get_range().step(), float(0.1), tolerance); + BOOST_CHECK_CLOSE(gg->get_value(), 80, tolerance); + BOOST_CHECK_CLOSE(gg->get_range().start(), -20, tolerance); + BOOST_CHECK_CLOSE(gg->get_range().stop(), 100, tolerance); + BOOST_CHECK_CLOSE(gg->get_range().step(), 0.1, tolerance); //test the the higher priority gain got filled first (gain 2) BOOST_CHECK_CLOSE(g2.get_value(), g2.get_range().stop(), tolerance); diff --git a/host/test/ranges_test.cpp b/host/test/ranges_test.cpp index ad61867e1..bbc7f4661 100644 --- a/host/test/ranges_test.cpp +++ b/host/test/ranges_test.cpp @@ -24,13 +24,13 @@ using namespace uhd; static const double tolerance = 0.001; BOOST_AUTO_TEST_CASE(test_ranges_bounds){ - meta_range_t mr; - mr.push_back(range_t(-1.0, +1.0, 0.1)); + meta_range_t mr; + mr.push_back(range_t(-1.0, +1.0, 0.1)); BOOST_CHECK_CLOSE(mr.start(), -1.0, tolerance); BOOST_CHECK_CLOSE(mr.stop(), +1.0, tolerance); BOOST_CHECK_CLOSE(mr.step(), 0.1, tolerance); - mr.push_back(range_t(40.0, 60.0, 1.0)); + mr.push_back(range_t(40.0, 60.0, 1.0)); BOOST_CHECK_CLOSE(mr.start(), -1.0, tolerance); BOOST_CHECK_CLOSE(mr.stop(), 60.0, tolerance); BOOST_CHECK_CLOSE(mr.step(), 0.1, tolerance); @@ -43,9 +43,9 @@ BOOST_AUTO_TEST_CASE(test_ranges_bounds){ } BOOST_AUTO_TEST_CASE(test_ranges_clip){ - meta_range_t mr; - mr.push_back(range_t(-1.0, +1.0, 0.1)); - mr.push_back(range_t(40.0, 60.0, 1.0)); + meta_range_t mr; + mr.push_back(range_t(-1.0, +1.0, 0.1)); + mr.push_back(range_t(40.0, 60.0, 1.0)); BOOST_CHECK_CLOSE(mr.clip(-30.0), -1.0, tolerance); BOOST_CHECK_CLOSE(mr.clip(70.0), 60.0, tolerance); -- cgit v1.2.3 From 612c84beb6015d7cf0fee918aa01944e20de5472 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Wed, 5 Jan 2011 19:07:08 -0800 Subject: uhd: added convenience factory functions for clock config (external/internal) --- host/include/uhd/types/clock_config.hpp | 7 ++++++- host/lib/types.cpp | 20 ++++++++++++++++++-- 2 files changed, 24 insertions(+), 3 deletions(-) (limited to 'host/lib/types.cpp') diff --git a/host/include/uhd/types/clock_config.hpp b/host/include/uhd/types/clock_config.hpp index 5966dcf3a..a72eb63de 100644 --- a/host/include/uhd/types/clock_config.hpp +++ b/host/include/uhd/types/clock_config.hpp @@ -1,5 +1,5 @@ // -// Copyright 2010 Ettus Research LLC +// Copyright 2010-2011 Ettus Research LLC // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by @@ -28,6 +28,11 @@ namespace uhd{ * The source and polarity for the PPS clock. */ struct UHD_API clock_config_t{ + //------ simple usage --------// + static clock_config_t external(void); + static clock_config_t internal(void); + + //------ advanced usage --------// enum ref_source_t { REF_AUTO = 'a', //automatic (device specific) REF_INT = 'i', //internal reference diff --git a/host/lib/types.cpp b/host/lib/types.cpp index 8ccb664d5..dce8d0828 100644 --- a/host/lib/types.cpp +++ b/host/lib/types.cpp @@ -1,5 +1,5 @@ // -// Copyright 2010 Ettus Research LLC +// Copyright 2010-2011 Ettus Research LLC // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by @@ -78,10 +78,26 @@ std::string tune_result_t::to_pp_string(void) const{ /*********************************************************************** * clock config **********************************************************************/ +clock_config_t clock_config_t::external(void){ + clock_config_t clock_config; + clock_config.ref_source = clock_config_t::REF_SMA; + clock_config.pps_source = clock_config_t::PPS_SMA; + clock_config.pps_polarity = clock_config_t::PPS_POS; + return clock_config; +} + +clock_config_t clock_config_t::internal(void){ + clock_config_t clock_config; + clock_config.ref_source = clock_config_t::REF_INT; + clock_config.pps_source = clock_config_t::PPS_INT; + clock_config.pps_polarity = clock_config_t::PPS_POS; + return clock_config; +} + clock_config_t::clock_config_t(void): ref_source(REF_INT), pps_source(PPS_INT), - pps_polarity(PPS_NEG) + pps_polarity(PPS_POS) { /* NOP */ } -- cgit v1.2.3 From fd9962af9ed6682117c3ab224548298907f59c49 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Thu, 6 Jan 2011 11:56:35 -0800 Subject: uhd: created sensors value, made lib/types and moved files --- host/include/uhd/types/CMakeLists.txt | 1 + host/include/uhd/types/ranges.hpp | 1 - host/include/uhd/types/sensors.hpp | 118 +++++++++++ host/lib/CMakeLists.txt | 3 +- host/lib/ranges.cpp | 163 --------------- host/lib/types.cpp | 359 ---------------------------------- host/lib/types/CMakeLists.txt | 25 +++ host/lib/types/ranges.cpp | 163 +++++++++++++++ host/lib/types/sensors.cpp | 69 +++++++ host/lib/types/types.cpp | 359 ++++++++++++++++++++++++++++++++++ 10 files changed, 736 insertions(+), 525 deletions(-) create mode 100644 host/include/uhd/types/sensors.hpp delete mode 100644 host/lib/ranges.cpp delete mode 100644 host/lib/types.cpp create mode 100644 host/lib/types/CMakeLists.txt create mode 100644 host/lib/types/ranges.cpp create mode 100644 host/lib/types/sensors.cpp create mode 100644 host/lib/types/types.cpp (limited to 'host/lib/types.cpp') diff --git a/host/include/uhd/types/CMakeLists.txt b/host/include/uhd/types/CMakeLists.txt index 316a8e14b..51be164aa 100644 --- a/host/include/uhd/types/CMakeLists.txt +++ b/host/include/uhd/types/CMakeLists.txt @@ -26,6 +26,7 @@ INSTALL(FILES metadata.hpp otw_type.hpp ranges.hpp + sensors.hpp serial.hpp stream_cmd.hpp time_spec.hpp diff --git a/host/include/uhd/types/ranges.hpp b/host/include/uhd/types/ranges.hpp index 253536a42..f0d0e1c0b 100644 --- a/host/include/uhd/types/ranges.hpp +++ b/host/include/uhd/types/ranges.hpp @@ -22,7 +22,6 @@ #include #include #include -#include namespace uhd{ diff --git a/host/include/uhd/types/sensors.hpp b/host/include/uhd/types/sensors.hpp new file mode 100644 index 000000000..d400b8944 --- /dev/null +++ b/host/include/uhd/types/sensors.hpp @@ -0,0 +1,118 @@ +// +// Copyright 2010-2011 Ettus Research LLC +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// + +#ifndef INCLUDED_UHD_TYPES_SENSORS_HPP +#define INCLUDED_UHD_TYPES_SENSORS_HPP + +#include +#include + +namespace uhd{ + + /*! + * A sensor value stores a sensor reading as a string with unit and data type. + * The sensor value class can be used in the following way: + * + * sensor_value_t ref_lock_sensor("Reference", my_lock, "unlocked", "locked"); + * std::cout << ref_lock_sensor.to_pp_string() << std::endl; + * //prints Reference: locked + * + * sensor_value_t temp_sensor("Temperature", my_temp, "C"); + * std::cout << temp_sensor.to_pp_string() << std::endl; + * //prints Temperature: 38.5 C + */ + struct UHD_API sensor_value_t{ + + //! typedef for the signed integer type + typedef signed int_type; + + //! typedef for the real number type + typedef double real_type; + + /*! + * Create a sensor value from a boolean. + * \param name the name of the sensor + * \param value the value true or false + * \param ufalse the unit string when value is false + * \param utrue the unit string when value is true + */ + sensor_value_t( + const std::string &name, + bool value, + const std::string &ufalse, + const std::string &utrue + ); + + /*! + * Create a sensor value from an integer. + * \param name the name of the sensor + * \param value the signed integer value + * \param unit the associated unit type + * \param formatter the formatter string + */ + sensor_value_t( + const std::string &name, + int_type value, + const std::string &unit, + const std::string &formatter = "%d" + ); + + /*! + * Create a sensor value from a real number. + * \param name the name of the sensor + * \param value the real number value + * \param unit the associated unit type + * \param formatter the formatter string + */ + sensor_value_t( + const std::string &name, + real_type value, + const std::string &unit, + const std::string &formatter = "%f" + ); + + //! The name of the sensor value + const std::string name; + + /*! + * The sensor value as a string. + * For integer and real number types, this will be the output of the formatter. + * For boolean types, the value will be the string literal "true" or "false". + */ + const std::string value; + + /*! + * The sensor value's unit type. + * For boolean types, this will be the one of the two units + * depending upon the value of the boolean true or false. + */ + const std::string unit; + + //! The data type of the value + const enum{ + BOOLEAN = 'b', + INTEGER = 'i', + REALNUM = 'r' + } type; + + //! Convert this sensor value into a printable string + std::string to_pp_string(void) const; + }; + +} //namespace uhd + +#endif /* INCLUDED_UHD_TYPES_SENSORS_HPP */ diff --git a/host/lib/CMakeLists.txt b/host/lib/CMakeLists.txt index 43a29df59..0fe137432 100644 --- a/host/lib/CMakeLists.txt +++ b/host/lib/CMakeLists.txt @@ -89,6 +89,7 @@ ENDMACRO(INCLUDE_SUBDIRECTORY) # Include subdirectories (different than add) ######################################################################## INCLUDE_SUBDIRECTORY(ic_reg_maps) +INCLUDE_SUBDIRECTORY(types) INCLUDE_SUBDIRECTORY(convert) INCLUDE_SUBDIRECTORY(transport) INCLUDE_SUBDIRECTORY(usrp) @@ -117,8 +118,6 @@ INCLUDE_DIRECTORIES(${CMAKE_CURRENT_BINARY_DIR}) LIBUHD_APPEND_SOURCES( ${CMAKE_CURRENT_BINARY_DIR}/constants.hpp ${CMAKE_CURRENT_SOURCE_DIR}/device.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/ranges.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/types.cpp ${CMAKE_CURRENT_SOURCE_DIR}/version.cpp ${CMAKE_CURRENT_SOURCE_DIR}/wax.cpp ) diff --git a/host/lib/ranges.cpp b/host/lib/ranges.cpp deleted file mode 100644 index 4a0d05d80..000000000 --- a/host/lib/ranges.cpp +++ /dev/null @@ -1,163 +0,0 @@ -// -// Copyright 2011-2011 Ettus Research LLC -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// - -#include -#include -#include -#include -#include -#include - -using namespace uhd; - -/*********************************************************************** - * range_t implementation code - **********************************************************************/ -struct range_t::impl{ - impl(double start, double stop, double step): - start(start), stop(stop), step(step) - { - /* NOP */ - } - double start, stop, step; -}; - -range_t::range_t(double value): - _impl(UHD_PIMPL_MAKE(impl, (value, value, 0))) -{ - /* NOP */ -} - -range_t::range_t( - double start, double stop, double step -): - _impl(UHD_PIMPL_MAKE(impl, (start, stop, step))) -{ - if (stop < start){ - throw std::invalid_argument("cannot make range where stop < start"); - } -} - -double range_t::start(void) const{ - return _impl->start; -} - -double range_t::stop(void) const{ - return _impl->stop; -} - -double range_t::step(void) const{ - return _impl->step; -} - -const std::string range_t::to_pp_string(void) const{ - std::stringstream ss; - ss << "(" << this->start(); - if (this->start() != this->stop()) ss << ", " << this->stop(); - if (this->step() != 0) ss << ", " << this->step(); - ss << ")"; - return ss.str(); -} - -/*********************************************************************** - * meta_range_t implementation code - **********************************************************************/ -void check_meta_range_monotonic(const meta_range_t &mr){ - if (mr.empty()){ - throw std::runtime_error("meta-range cannot be empty"); - } - for (size_t i = 1; i < mr.size(); i++){ - if (mr.at(i).start() < mr.at(i-1).stop()){ - throw std::runtime_error("meta-range is not monotonic"); - } - } -} - -meta_range_t::meta_range_t(void){ - /* NOP */ -} - -meta_range_t::meta_range_t( - double start, double stop, double step -): - std::vector (1, range_t(start, stop, step)) -{ - /* NOP */ -} - -double meta_range_t::start(void) const{ - check_meta_range_monotonic(*this); - double min_start = this->front().start(); - BOOST_FOREACH(const range_t &r, (*this)){ - min_start = std::min(min_start, r.start()); - } - return min_start; -} - -double meta_range_t::stop(void) const{ - check_meta_range_monotonic(*this); - double max_stop = this->front().stop(); - BOOST_FOREACH(const range_t &r, (*this)){ - max_stop = std::max(max_stop, r.stop()); - } - return max_stop; -} - -double meta_range_t::step(void) const{ - check_meta_range_monotonic(*this); - std::vector non_zero_steps; - range_t last = this->front(); - BOOST_FOREACH(const range_t &r, (*this)){ - //steps at each range - if (r.step() > 0) non_zero_steps.push_back(r.step()); - //and steps in-between ranges - double ibtw_step = r.start() - last.stop(); - if (ibtw_step > 0) non_zero_steps.push_back(ibtw_step); - //store ref to last - last = r; - } - if (non_zero_steps.empty()) return 0; //all zero steps, its zero... - return *std::min_element(non_zero_steps.begin(), non_zero_steps.end()); -} - -double meta_range_t::clip(double value, bool clip_step) const{ - check_meta_range_monotonic(*this); - double last_stop = this->front().stop(); - BOOST_FOREACH(const range_t &r, (*this)){ - //in-between ranges, clip to nearest - if (value < r.start()){ - return (std::abs(value - r.start()) < std::abs(value - last_stop))? - r.start() : last_stop; - } - //in this range, clip here - if (value <= r.stop()){ - if (not clip_step or r.step() == 0) return value; - return boost::math::round((value - r.start())/r.step())*r.step() + r.start(); - } - //continue on to the next range - last_stop = r.stop(); - } - return last_stop; -} - -const std::string meta_range_t::to_pp_string(void) const{ - std::stringstream ss; - BOOST_FOREACH(const range_t &r, (*this)){ - ss << r.to_pp_string() << std::endl; - } - return ss.str(); -} diff --git a/host/lib/types.cpp b/host/lib/types.cpp deleted file mode 100644 index dce8d0828..000000000 --- a/host/lib/types.cpp +++ /dev/null @@ -1,359 +0,0 @@ -// -// Copyright 2010-2011 Ettus Research LLC -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . -// - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -using namespace uhd; - -/*********************************************************************** - * tune request - **********************************************************************/ -tune_request_t::tune_request_t(double target_freq): - target_freq(target_freq), - inter_freq_policy(POLICY_AUTO), - dsp_freq_policy(POLICY_AUTO) -{ - /* NOP */ -} - -tune_request_t::tune_request_t(double target_freq, double lo_off): - target_freq(target_freq), - inter_freq_policy(POLICY_MANUAL), - inter_freq(target_freq + lo_off), - dsp_freq_policy(POLICY_AUTO) -{ - /* NOP */ -} - -/*********************************************************************** - * tune result - **********************************************************************/ -std::string tune_result_t::to_pp_string(void) const{ - return str(boost::format( - "Tune Result:\n" - " Target Intermediate Freq: %f (MHz)\n" - " Actual Intermediate Freq: %f (MHz)\n" - " Target DSP Freq Shift: %f (MHz)\n" - " Actual DSP Freq Shift: %f (MHz)\n" - ) - % (target_inter_freq/1e6) % (actual_inter_freq/1e6) - % (target_dsp_freq/1e6) % (actual_dsp_freq/1e6) - ); -} - -/*********************************************************************** - * clock config - **********************************************************************/ -clock_config_t clock_config_t::external(void){ - clock_config_t clock_config; - clock_config.ref_source = clock_config_t::REF_SMA; - clock_config.pps_source = clock_config_t::PPS_SMA; - clock_config.pps_polarity = clock_config_t::PPS_POS; - return clock_config; -} - -clock_config_t clock_config_t::internal(void){ - clock_config_t clock_config; - clock_config.ref_source = clock_config_t::REF_INT; - clock_config.pps_source = clock_config_t::PPS_INT; - clock_config.pps_polarity = clock_config_t::PPS_POS; - return clock_config; -} - -clock_config_t::clock_config_t(void): - ref_source(REF_INT), - pps_source(PPS_INT), - pps_polarity(PPS_POS) -{ - /* NOP */ -} - -/*********************************************************************** - * stream command - **********************************************************************/ -stream_cmd_t::stream_cmd_t(const stream_mode_t &stream_mode): - stream_mode(stream_mode), - num_samps(0), - stream_now(true) -{ - /* NOP */ -} - -/*********************************************************************** - * metadata - **********************************************************************/ -tx_metadata_t::tx_metadata_t(void): - has_time_spec(false), - time_spec(time_spec_t()), - start_of_burst(false), - end_of_burst(false) -{ - /* NOP */ -} - -/*********************************************************************** - * time spec - **********************************************************************/ -time_spec_t::time_spec_t(double secs): - _full_secs(0), - _frac_secs(secs) -{ - /* NOP */ -} - -time_spec_t::time_spec_t(time_t full_secs, double frac_secs): - _full_secs(full_secs), - _frac_secs(frac_secs) -{ - /* NOP */ -} - -time_spec_t::time_spec_t(time_t full_secs, long tick_count, double tick_rate): - _full_secs(full_secs), - _frac_secs(double(tick_count)/tick_rate) -{ - /* NOP */ -} - -long time_spec_t::get_tick_count(double tick_rate) const{ - return boost::math::iround(this->get_frac_secs()*tick_rate); -} - -double time_spec_t::get_real_secs(void) const{ - return this->_full_secs + this->_frac_secs; -} - -time_t time_spec_t::get_full_secs(void) const{ - double intpart; - std::modf(this->_frac_secs, &intpart); - return this->_full_secs + time_t(intpart); -} - -double time_spec_t::get_frac_secs(void) const{ - return std::fmod(this->_frac_secs, 1.0); -} - -time_spec_t &time_spec_t::operator+=(const time_spec_t &rhs){ - this->_full_secs += rhs.get_full_secs(); - this->_frac_secs += rhs.get_frac_secs(); - return *this; -} - -time_spec_t &time_spec_t::operator-=(const time_spec_t &rhs){ - this->_full_secs -= rhs.get_full_secs(); - this->_frac_secs -= rhs.get_frac_secs(); - return *this; -} - -bool uhd::operator==(const time_spec_t &lhs, const time_spec_t &rhs){ - return - lhs.get_full_secs() == rhs.get_full_secs() and - lhs.get_frac_secs() == rhs.get_frac_secs() - ; -} - -bool uhd::operator<(const time_spec_t &lhs, const time_spec_t &rhs){ - return ( - (lhs.get_full_secs() < rhs.get_full_secs()) or ( - (lhs.get_full_secs() == rhs.get_full_secs()) and - (lhs.get_frac_secs() < rhs.get_frac_secs()) - )); -} - -/*********************************************************************** - * device addr - **********************************************************************/ -static const std::string arg_delim = ","; -static const std::string pair_delim = "="; - -static std::string trim(const std::string &in){ - return boost::algorithm::trim_copy(in); -} - -device_addr_t::device_addr_t(const std::string &args){ - BOOST_FOREACH(const std::string &pair, std::split_string(args, arg_delim)){ - if (trim(pair) == "") continue; - - std::vector key_val = std::split_string(pair, pair_delim); - if (key_val.size() != 2) throw std::runtime_error("invalid args string: "+args); - (*this)[trim(key_val.front())] = trim(key_val.back()); - } -} - -std::string device_addr_t::to_pp_string(void) const{ - if (this->size() == 0) return "Empty Device Address"; - - std::stringstream ss; - ss << "Device Address:" << std::endl; - BOOST_FOREACH(std::string key, this->keys()){ - ss << boost::format(" %s: %s") % key % (*this)[key] << std::endl; - } - return ss.str(); -} - -std::string device_addr_t::to_string(void) const{ - std::string args_str; - size_t count = 0; - BOOST_FOREACH(const std::string &key, this->keys()){ - args_str += ((count++)? arg_delim : "") + key + pair_delim + (*this)[key]; - } - return args_str; -} - -/*********************************************************************** - * mac addr - **********************************************************************/ -mac_addr_t::mac_addr_t(const byte_vector_t &bytes) : _bytes(bytes){ - UHD_ASSERT_THROW(_bytes.size() == 6); -} - -mac_addr_t mac_addr_t::from_bytes(const byte_vector_t &bytes){ - return mac_addr_t(bytes); -} - -mac_addr_t mac_addr_t::from_string(const std::string &mac_addr_str){ - - byte_vector_t bytes; - - try{ - if (mac_addr_str.size() != 17){ - throw std::runtime_error("expected exactly 17 characters"); - } - - //split the mac addr hex string at the colons - BOOST_FOREACH(const std::string &hex_str, std::split_string(mac_addr_str, ":")){ - int hex_num; - std::istringstream iss(hex_str); - iss >> std::hex >> hex_num; - bytes.push_back(boost::uint8_t(hex_num)); - } - - } - catch(std::exception const& e){ - throw std::runtime_error(str( - boost::format("Invalid mac address: %s\n\t%s") % mac_addr_str % e.what() - )); - } - - return mac_addr_t::from_bytes(bytes); -} - -byte_vector_t mac_addr_t::to_bytes(void) const{ - return _bytes; -} - -std::string mac_addr_t::to_string(void) const{ - std::string addr = ""; - BOOST_FOREACH(boost::uint8_t byte, this->to_bytes()){ - addr += str(boost::format("%s%02x") % ((addr == "")?"":":") % int(byte)); - } - return addr; -} - -/*********************************************************************** - * otw type - **********************************************************************/ -size_t otw_type_t::get_sample_size(void) const{ - return (this->width * 2) / 8; -} - -otw_type_t::otw_type_t(void): - width(0), - shift(0), - byteorder(BO_NATIVE) -{ - /* NOP */ -} - -/*********************************************************************** - * io type - **********************************************************************/ -static size_t tid_to_size(io_type_t::tid_t tid){ - switch(tid){ - case io_type_t::COMPLEX_FLOAT32: return sizeof(std::complex); - case io_type_t::COMPLEX_INT16: return sizeof(std::complex); - case io_type_t::COMPLEX_INT8: return sizeof(std::complex); - default: throw std::runtime_error("unknown io type tid"); - } -} - -io_type_t::io_type_t(tid_t tid) -: size(tid_to_size(tid)), tid(tid){ - /* NOP */ -} - -io_type_t::io_type_t(size_t size) -: size(size), tid(CUSTOM_TYPE){ - /* NOP */ -} - -/*********************************************************************** - * serial - **********************************************************************/ -spi_config_t::spi_config_t(edge_t edge): - mosi_edge(edge), - miso_edge(edge) -{ - /* NOP */ -} - -void i2c_iface::write_eeprom( - boost::uint8_t addr, - boost::uint8_t offset, - const byte_vector_t &bytes -){ - for (size_t i = 0; i < bytes.size(); i++){ - //write a byte at a time, its easy that way - byte_vector_t cmd = boost::assign::list_of(offset+i)(bytes[i]); - this->write_i2c(addr, cmd); - boost::this_thread::sleep(boost::posix_time::milliseconds(10)); //worst case write - } -} - -byte_vector_t i2c_iface::read_eeprom( - boost::uint8_t addr, - boost::uint8_t offset, - size_t num_bytes -){ - byte_vector_t bytes; - for (size_t i = 0; i < num_bytes; i++){ - //do a zero byte write to start read cycle - this->write_i2c(addr, byte_vector_t(1, offset+i)); - bytes.push_back(this->read_i2c(addr, 1).at(0)); - } - return bytes; -} diff --git a/host/lib/types/CMakeLists.txt b/host/lib/types/CMakeLists.txt new file mode 100644 index 000000000..7a8093ed5 --- /dev/null +++ b/host/lib/types/CMakeLists.txt @@ -0,0 +1,25 @@ +# +# Copyright 2011 Ettus Research LLC +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# + +######################################################################## +# This file included, use CMake directory variables +######################################################################## +LIBUHD_APPEND_SOURCES( + ${CMAKE_CURRENT_SOURCE_DIR}/ranges.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/sensors.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/types.cpp +) diff --git a/host/lib/types/ranges.cpp b/host/lib/types/ranges.cpp new file mode 100644 index 000000000..4a0d05d80 --- /dev/null +++ b/host/lib/types/ranges.cpp @@ -0,0 +1,163 @@ +// +// Copyright 2011-2011 Ettus Research LLC +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// + +#include +#include +#include +#include +#include +#include + +using namespace uhd; + +/*********************************************************************** + * range_t implementation code + **********************************************************************/ +struct range_t::impl{ + impl(double start, double stop, double step): + start(start), stop(stop), step(step) + { + /* NOP */ + } + double start, stop, step; +}; + +range_t::range_t(double value): + _impl(UHD_PIMPL_MAKE(impl, (value, value, 0))) +{ + /* NOP */ +} + +range_t::range_t( + double start, double stop, double step +): + _impl(UHD_PIMPL_MAKE(impl, (start, stop, step))) +{ + if (stop < start){ + throw std::invalid_argument("cannot make range where stop < start"); + } +} + +double range_t::start(void) const{ + return _impl->start; +} + +double range_t::stop(void) const{ + return _impl->stop; +} + +double range_t::step(void) const{ + return _impl->step; +} + +const std::string range_t::to_pp_string(void) const{ + std::stringstream ss; + ss << "(" << this->start(); + if (this->start() != this->stop()) ss << ", " << this->stop(); + if (this->step() != 0) ss << ", " << this->step(); + ss << ")"; + return ss.str(); +} + +/*********************************************************************** + * meta_range_t implementation code + **********************************************************************/ +void check_meta_range_monotonic(const meta_range_t &mr){ + if (mr.empty()){ + throw std::runtime_error("meta-range cannot be empty"); + } + for (size_t i = 1; i < mr.size(); i++){ + if (mr.at(i).start() < mr.at(i-1).stop()){ + throw std::runtime_error("meta-range is not monotonic"); + } + } +} + +meta_range_t::meta_range_t(void){ + /* NOP */ +} + +meta_range_t::meta_range_t( + double start, double stop, double step +): + std::vector (1, range_t(start, stop, step)) +{ + /* NOP */ +} + +double meta_range_t::start(void) const{ + check_meta_range_monotonic(*this); + double min_start = this->front().start(); + BOOST_FOREACH(const range_t &r, (*this)){ + min_start = std::min(min_start, r.start()); + } + return min_start; +} + +double meta_range_t::stop(void) const{ + check_meta_range_monotonic(*this); + double max_stop = this->front().stop(); + BOOST_FOREACH(const range_t &r, (*this)){ + max_stop = std::max(max_stop, r.stop()); + } + return max_stop; +} + +double meta_range_t::step(void) const{ + check_meta_range_monotonic(*this); + std::vector non_zero_steps; + range_t last = this->front(); + BOOST_FOREACH(const range_t &r, (*this)){ + //steps at each range + if (r.step() > 0) non_zero_steps.push_back(r.step()); + //and steps in-between ranges + double ibtw_step = r.start() - last.stop(); + if (ibtw_step > 0) non_zero_steps.push_back(ibtw_step); + //store ref to last + last = r; + } + if (non_zero_steps.empty()) return 0; //all zero steps, its zero... + return *std::min_element(non_zero_steps.begin(), non_zero_steps.end()); +} + +double meta_range_t::clip(double value, bool clip_step) const{ + check_meta_range_monotonic(*this); + double last_stop = this->front().stop(); + BOOST_FOREACH(const range_t &r, (*this)){ + //in-between ranges, clip to nearest + if (value < r.start()){ + return (std::abs(value - r.start()) < std::abs(value - last_stop))? + r.start() : last_stop; + } + //in this range, clip here + if (value <= r.stop()){ + if (not clip_step or r.step() == 0) return value; + return boost::math::round((value - r.start())/r.step())*r.step() + r.start(); + } + //continue on to the next range + last_stop = r.stop(); + } + return last_stop; +} + +const std::string meta_range_t::to_pp_string(void) const{ + std::stringstream ss; + BOOST_FOREACH(const range_t &r, (*this)){ + ss << r.to_pp_string() << std::endl; + } + return ss.str(); +} diff --git a/host/lib/types/sensors.cpp b/host/lib/types/sensors.cpp new file mode 100644 index 000000000..497f4bfd5 --- /dev/null +++ b/host/lib/types/sensors.cpp @@ -0,0 +1,69 @@ +// +// Copyright 2011-2011 Ettus Research LLC +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// + +#include +#include +#include + +using namespace uhd; + +sensor_value_t::sensor_value_t( + const std::string &name, + bool value, + const std::string &ufalse, + const std::string &utrue +): + name(name), value(value?"true":"false"), + unit(value?utrue:ufalse), type(BOOLEAN) +{ + /* NOP */ +} + +sensor_value_t::sensor_value_t( + const std::string &name, + int_type value, + const std::string &unit, + const std::string &formatter +): + name(name), value(str(boost::format(formatter) % value)), + unit(unit), type(INTEGER) +{ + /* NOP */ +} + +sensor_value_t::sensor_value_t( + const std::string &name, + real_type value, + const std::string &unit, + const std::string &formatter +): + name(name), value(str(boost::format(formatter) % value)), + unit(unit), type(REALNUM) +{ + /* NOP */ +} + +std::string sensor_value_t::to_pp_string(void) const{ + switch(type){ + case BOOLEAN: + return str(boost::format("%s: %s") % name % unit); + case INTEGER: + case REALNUM: + return str(boost::format("%s: %s %s") % name % value % unit); + } + UHD_THROW_INVALID_CODE_PATH(); +} diff --git a/host/lib/types/types.cpp b/host/lib/types/types.cpp new file mode 100644 index 000000000..dce8d0828 --- /dev/null +++ b/host/lib/types/types.cpp @@ -0,0 +1,359 @@ +// +// Copyright 2010-2011 Ettus Research LLC +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . +// + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace uhd; + +/*********************************************************************** + * tune request + **********************************************************************/ +tune_request_t::tune_request_t(double target_freq): + target_freq(target_freq), + inter_freq_policy(POLICY_AUTO), + dsp_freq_policy(POLICY_AUTO) +{ + /* NOP */ +} + +tune_request_t::tune_request_t(double target_freq, double lo_off): + target_freq(target_freq), + inter_freq_policy(POLICY_MANUAL), + inter_freq(target_freq + lo_off), + dsp_freq_policy(POLICY_AUTO) +{ + /* NOP */ +} + +/*********************************************************************** + * tune result + **********************************************************************/ +std::string tune_result_t::to_pp_string(void) const{ + return str(boost::format( + "Tune Result:\n" + " Target Intermediate Freq: %f (MHz)\n" + " Actual Intermediate Freq: %f (MHz)\n" + " Target DSP Freq Shift: %f (MHz)\n" + " Actual DSP Freq Shift: %f (MHz)\n" + ) + % (target_inter_freq/1e6) % (actual_inter_freq/1e6) + % (target_dsp_freq/1e6) % (actual_dsp_freq/1e6) + ); +} + +/*********************************************************************** + * clock config + **********************************************************************/ +clock_config_t clock_config_t::external(void){ + clock_config_t clock_config; + clock_config.ref_source = clock_config_t::REF_SMA; + clock_config.pps_source = clock_config_t::PPS_SMA; + clock_config.pps_polarity = clock_config_t::PPS_POS; + return clock_config; +} + +clock_config_t clock_config_t::internal(void){ + clock_config_t clock_config; + clock_config.ref_source = clock_config_t::REF_INT; + clock_config.pps_source = clock_config_t::PPS_INT; + clock_config.pps_polarity = clock_config_t::PPS_POS; + return clock_config; +} + +clock_config_t::clock_config_t(void): + ref_source(REF_INT), + pps_source(PPS_INT), + pps_polarity(PPS_POS) +{ + /* NOP */ +} + +/*********************************************************************** + * stream command + **********************************************************************/ +stream_cmd_t::stream_cmd_t(const stream_mode_t &stream_mode): + stream_mode(stream_mode), + num_samps(0), + stream_now(true) +{ + /* NOP */ +} + +/*********************************************************************** + * metadata + **********************************************************************/ +tx_metadata_t::tx_metadata_t(void): + has_time_spec(false), + time_spec(time_spec_t()), + start_of_burst(false), + end_of_burst(false) +{ + /* NOP */ +} + +/*********************************************************************** + * time spec + **********************************************************************/ +time_spec_t::time_spec_t(double secs): + _full_secs(0), + _frac_secs(secs) +{ + /* NOP */ +} + +time_spec_t::time_spec_t(time_t full_secs, double frac_secs): + _full_secs(full_secs), + _frac_secs(frac_secs) +{ + /* NOP */ +} + +time_spec_t::time_spec_t(time_t full_secs, long tick_count, double tick_rate): + _full_secs(full_secs), + _frac_secs(double(tick_count)/tick_rate) +{ + /* NOP */ +} + +long time_spec_t::get_tick_count(double tick_rate) const{ + return boost::math::iround(this->get_frac_secs()*tick_rate); +} + +double time_spec_t::get_real_secs(void) const{ + return this->_full_secs + this->_frac_secs; +} + +time_t time_spec_t::get_full_secs(void) const{ + double intpart; + std::modf(this->_frac_secs, &intpart); + return this->_full_secs + time_t(intpart); +} + +double time_spec_t::get_frac_secs(void) const{ + return std::fmod(this->_frac_secs, 1.0); +} + +time_spec_t &time_spec_t::operator+=(const time_spec_t &rhs){ + this->_full_secs += rhs.get_full_secs(); + this->_frac_secs += rhs.get_frac_secs(); + return *this; +} + +time_spec_t &time_spec_t::operator-=(const time_spec_t &rhs){ + this->_full_secs -= rhs.get_full_secs(); + this->_frac_secs -= rhs.get_frac_secs(); + return *this; +} + +bool uhd::operator==(const time_spec_t &lhs, const time_spec_t &rhs){ + return + lhs.get_full_secs() == rhs.get_full_secs() and + lhs.get_frac_secs() == rhs.get_frac_secs() + ; +} + +bool uhd::operator<(const time_spec_t &lhs, const time_spec_t &rhs){ + return ( + (lhs.get_full_secs() < rhs.get_full_secs()) or ( + (lhs.get_full_secs() == rhs.get_full_secs()) and + (lhs.get_frac_secs() < rhs.get_frac_secs()) + )); +} + +/*********************************************************************** + * device addr + **********************************************************************/ +static const std::string arg_delim = ","; +static const std::string pair_delim = "="; + +static std::string trim(const std::string &in){ + return boost::algorithm::trim_copy(in); +} + +device_addr_t::device_addr_t(const std::string &args){ + BOOST_FOREACH(const std::string &pair, std::split_string(args, arg_delim)){ + if (trim(pair) == "") continue; + + std::vector key_val = std::split_string(pair, pair_delim); + if (key_val.size() != 2) throw std::runtime_error("invalid args string: "+args); + (*this)[trim(key_val.front())] = trim(key_val.back()); + } +} + +std::string device_addr_t::to_pp_string(void) const{ + if (this->size() == 0) return "Empty Device Address"; + + std::stringstream ss; + ss << "Device Address:" << std::endl; + BOOST_FOREACH(std::string key, this->keys()){ + ss << boost::format(" %s: %s") % key % (*this)[key] << std::endl; + } + return ss.str(); +} + +std::string device_addr_t::to_string(void) const{ + std::string args_str; + size_t count = 0; + BOOST_FOREACH(const std::string &key, this->keys()){ + args_str += ((count++)? arg_delim : "") + key + pair_delim + (*this)[key]; + } + return args_str; +} + +/*********************************************************************** + * mac addr + **********************************************************************/ +mac_addr_t::mac_addr_t(const byte_vector_t &bytes) : _bytes(bytes){ + UHD_ASSERT_THROW(_bytes.size() == 6); +} + +mac_addr_t mac_addr_t::from_bytes(const byte_vector_t &bytes){ + return mac_addr_t(bytes); +} + +mac_addr_t mac_addr_t::from_string(const std::string &mac_addr_str){ + + byte_vector_t bytes; + + try{ + if (mac_addr_str.size() != 17){ + throw std::runtime_error("expected exactly 17 characters"); + } + + //split the mac addr hex string at the colons + BOOST_FOREACH(const std::string &hex_str, std::split_string(mac_addr_str, ":")){ + int hex_num; + std::istringstream iss(hex_str); + iss >> std::hex >> hex_num; + bytes.push_back(boost::uint8_t(hex_num)); + } + + } + catch(std::exception const& e){ + throw std::runtime_error(str( + boost::format("Invalid mac address: %s\n\t%s") % mac_addr_str % e.what() + )); + } + + return mac_addr_t::from_bytes(bytes); +} + +byte_vector_t mac_addr_t::to_bytes(void) const{ + return _bytes; +} + +std::string mac_addr_t::to_string(void) const{ + std::string addr = ""; + BOOST_FOREACH(boost::uint8_t byte, this->to_bytes()){ + addr += str(boost::format("%s%02x") % ((addr == "")?"":":") % int(byte)); + } + return addr; +} + +/*********************************************************************** + * otw type + **********************************************************************/ +size_t otw_type_t::get_sample_size(void) const{ + return (this->width * 2) / 8; +} + +otw_type_t::otw_type_t(void): + width(0), + shift(0), + byteorder(BO_NATIVE) +{ + /* NOP */ +} + +/*********************************************************************** + * io type + **********************************************************************/ +static size_t tid_to_size(io_type_t::tid_t tid){ + switch(tid){ + case io_type_t::COMPLEX_FLOAT32: return sizeof(std::complex); + case io_type_t::COMPLEX_INT16: return sizeof(std::complex); + case io_type_t::COMPLEX_INT8: return sizeof(std::complex); + default: throw std::runtime_error("unknown io type tid"); + } +} + +io_type_t::io_type_t(tid_t tid) +: size(tid_to_size(tid)), tid(tid){ + /* NOP */ +} + +io_type_t::io_type_t(size_t size) +: size(size), tid(CUSTOM_TYPE){ + /* NOP */ +} + +/*********************************************************************** + * serial + **********************************************************************/ +spi_config_t::spi_config_t(edge_t edge): + mosi_edge(edge), + miso_edge(edge) +{ + /* NOP */ +} + +void i2c_iface::write_eeprom( + boost::uint8_t addr, + boost::uint8_t offset, + const byte_vector_t &bytes +){ + for (size_t i = 0; i < bytes.size(); i++){ + //write a byte at a time, its easy that way + byte_vector_t cmd = boost::assign::list_of(offset+i)(bytes[i]); + this->write_i2c(addr, cmd); + boost::this_thread::sleep(boost::posix_time::milliseconds(10)); //worst case write + } +} + +byte_vector_t i2c_iface::read_eeprom( + boost::uint8_t addr, + boost::uint8_t offset, + size_t num_bytes +){ + byte_vector_t bytes; + for (size_t i = 0; i < num_bytes; i++){ + //do a zero byte write to start read cycle + this->write_i2c(addr, byte_vector_t(1, offset+i)); + bytes.push_back(this->read_i2c(addr, 1).at(0)); + } + return bytes; +} -- cgit v1.2.3