diff options
-rw-r--r-- | host/include/uhd/usrp/CMakeLists.txt | 1 | ||||
-rw-r--r-- | host/include/uhd/usrp/subdev_spec.hpp | 77 | ||||
-rw-r--r-- | host/lib/types.cpp | 9 | ||||
-rw-r--r-- | host/lib/usrp/CMakeLists.txt | 1 | ||||
-rw-r--r-- | host/lib/usrp/subdev_spec.cpp | 64 | ||||
-rw-r--r-- | host/test/CMakeLists.txt | 1 | ||||
-rw-r--r-- | host/test/addr_test.cpp | 2 | ||||
-rw-r--r-- | host/test/subdev_spec_test.cpp | 45 |
8 files changed, 196 insertions, 4 deletions
diff --git a/host/include/uhd/usrp/CMakeLists.txt b/host/include/uhd/usrp/CMakeLists.txt index 6f8c1a2d8..ef0696700 100644 --- a/host/include/uhd/usrp/CMakeLists.txt +++ b/host/include/uhd/usrp/CMakeLists.txt @@ -32,6 +32,7 @@ INSTALL(FILES dboard_manager.hpp ### utilities ### + subdev_spec.hpp tune_helper.hpp ### interfaces ### diff --git a/host/include/uhd/usrp/subdev_spec.hpp b/host/include/uhd/usrp/subdev_spec.hpp new file mode 100644 index 000000000..d874a9bd9 --- /dev/null +++ b/host/include/uhd/usrp/subdev_spec.hpp @@ -0,0 +1,77 @@ +// +// Copyright 2010 Ettus Research LLC +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. +// + +#ifndef INCLUDED_UHD_USRP_SUBDEV_SPEC_HPP +#define INCLUDED_UHD_USRP_SUBDEV_SPEC_HPP + +#include <uhd/config.hpp> +#include <utility> //std::pair +#include <vector> +#include <string> + +namespace uhd{ namespace usrp{ + + /*! + * A list of (daughterboard name, subdevice name) pairs: + * + * A subdevice specification represents a list of subdevices on a motherboard. + * The subdevices specified may span across multiple daughterboards; + * Hence the need for a subdevice specification over a simple list of strings. + * Typically, the user will pass a RX or TX subdevice specification into the API, + * and the implementation will infer the channel configuration from the specification. + * + * The subdevice specification can be represented as a markup-string. + * The markup-string is a whitespace separated list of dboard:subdev pairs. + * The "dboard:" part is optional on boards with only one daughterboard slot. + * The first pair represents the subdevice for channel zero, + * the second pair represents the subdevice for channel one, and so on. + * + * Examples: + * - Use subdevice AB on daughterboard A (USRP1): "A:AB" + * - Use subdevice A on daughterboard A for channel zero and subdevice A on daughterboard B for channel one (USRP1): "A:A B:A" + * - Use subdevice AB (USRP2): "AB" or ":AB" + * + * An empty subdevice specification can be used to automatically + * select the first subdevice on the first present daughterboard. + */ + class UHD_API subdev_spec_t : public std::vector<std::pair<std::string, std::string> >{ + public: + typedef std::pair<std::string, std::string> pair_t; + + /*! + * Create a subdev specification from a markup string. + * \param markup the markup string + */ + subdev_spec_t(const std::string &markup = ""); + + /*! + * Convert a subdev specification into a pretty print string. + * \return a printable string representing the subdev specification + */ + std::string to_pp_string(void) const; + + /*! + * Convert the subdevice specification into a markup string. + * The markup string contains the delimiter symbols. + * \return a string with delimiter markup + */ + std::string to_string(void) const; + }; + +}} + +#endif /* INCLUDED_UHD_USRP_SUBDEV_SPEC_HPP */ diff --git a/host/lib/types.cpp b/host/lib/types.cpp index 1cfe84832..5c0fb1f42 100644 --- a/host/lib/types.cpp +++ b/host/lib/types.cpp @@ -36,6 +36,7 @@ #include <boost/thread.hpp> #include <stdexcept> #include <complex> +#include <sstream> using namespace uhd; @@ -190,7 +191,7 @@ device_addr_t::device_addr_t(const std::string &args){ std::vector<std::string> key_val; boost::split(key_val, pair, boost::is_any_of(pair_delim)); if (key_val.size() != 2) throw std::runtime_error("invalid args string: "+args); - (*this)[trim(key_val[0])] = trim(key_val[1]); + (*this)[trim(key_val.front())] = trim(key_val.back()); } } @@ -198,16 +199,18 @@ 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; + 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 += key + pair_delim + (*this)[key] + arg_delim; + args_str += ((count++)? arg_delim : "") + key + pair_delim + (*this)[key]; } return args_str; } diff --git a/host/lib/usrp/CMakeLists.txt b/host/lib/usrp/CMakeLists.txt index 80ac537ee..a403296fa 100644 --- a/host/lib/usrp/CMakeLists.txt +++ b/host/lib/usrp/CMakeLists.txt @@ -25,6 +25,7 @@ LIBUHD_APPEND_SOURCES( ${CMAKE_SOURCE_DIR}/lib/usrp/dsp_utils.hpp ${CMAKE_SOURCE_DIR}/lib/usrp/mimo_usrp.cpp ${CMAKE_SOURCE_DIR}/lib/usrp/simple_usrp.cpp + ${CMAKE_SOURCE_DIR}/lib/usrp/subdev_spec.cpp ${CMAKE_SOURCE_DIR}/lib/usrp/tune_helper.cpp ) diff --git a/host/lib/usrp/subdev_spec.cpp b/host/lib/usrp/subdev_spec.cpp new file mode 100644 index 000000000..69ab6a339 --- /dev/null +++ b/host/lib/usrp/subdev_spec.cpp @@ -0,0 +1,64 @@ +// +// Copyright 2010 Ettus Research LLC +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. +// + +#include <uhd/usrp/subdev_spec.hpp> +#include <boost/algorithm/string.hpp> +#include <boost/format.hpp> +#include <boost/foreach.hpp> +#include <stdexcept> +#include <sstream> + +using namespace uhd; +using namespace uhd::usrp; + +subdev_spec_t::subdev_spec_t(const std::string &markup){ + std::vector<std::string> pairs; + boost::split(pairs, markup, boost::is_any_of("\t ")); + BOOST_FOREACH(const std::string &pair, pairs){ + if (pair == "") continue; + std::vector<std::string> db_sd; + boost::split(db_sd, pair, boost::is_any_of(":")); + switch(db_sd.size()){ + case 1: this->push_back(pair_t("", db_sd.front())); break; + case 2: this->push_back(pair_t(db_sd.front(), db_sd.back())); break; + default: throw std::runtime_error("invalid subdev-spec markup string: "+markup); + } + } +} + +std::string subdev_spec_t::to_pp_string(void) const{ + if (this->size() == 0) return "Empty Subdevice Specification"; + + std::stringstream ss; + size_t count = 0; + ss << "Subdevice Specification:" << std::endl; + BOOST_FOREACH(const pair_t &pair, *this){ + ss << boost::format( + " Channel %d: Daughterboard %s, Subdevice %s" + ) % (count++) % pair.first % pair.second << std::endl; + } + return ss.str(); +} + +std::string subdev_spec_t::to_string(void) const{ + std::string markup; + size_t count = 0; + BOOST_FOREACH(const pair_t &pair, *this){ + markup += ((count++)? " " : "") + pair.first + ":" + pair.second; + } + return markup; +} diff --git a/host/test/CMakeLists.txt b/host/test/CMakeLists.txt index ad2f33a3b..1b909aa39 100644 --- a/host/test/CMakeLists.txt +++ b/host/test/CMakeLists.txt @@ -27,6 +27,7 @@ ADD_EXECUTABLE(main_test dict_test.cpp error_test.cpp gain_handler_test.cpp + subdev_spec_test.cpp tune_helper_test.cpp vrt_test.cpp warning_test.cpp diff --git a/host/test/addr_test.cpp b/host/test/addr_test.cpp index 0c50200d6..d4b45aa1a 100644 --- a/host/test/addr_test.cpp +++ b/host/test/addr_test.cpp @@ -48,7 +48,7 @@ BOOST_AUTO_TEST_CASE(test_device_addr){ uhd::device_addr_t new_dev_addr(args_str); //they should be the same size - BOOST_CHECK_EQUAL(dev_addr.size(), new_dev_addr.size()); + BOOST_REQUIRE_EQUAL(dev_addr.size(), new_dev_addr.size()); //the keys should match std::vector<std::string> old_dev_addr_keys = dev_addr.keys(); diff --git a/host/test/subdev_spec_test.cpp b/host/test/subdev_spec_test.cpp new file mode 100644 index 000000000..ca4b4771b --- /dev/null +++ b/host/test/subdev_spec_test.cpp @@ -0,0 +1,45 @@ +// +// Copyright 2010 Ettus Research LLC +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. +// + +#include <boost/test/unit_test.hpp> +#include <uhd/usrp/subdev_spec.hpp> +#include <boost/foreach.hpp> +#include <iostream> + +BOOST_AUTO_TEST_CASE(test_subdevice_spec){ + std::cout << "Testing subdevice specification..." << std::endl; + + //load the subdev spec with something + uhd::usrp::subdev_spec_t sd_spec; + sd_spec.push_back(uhd::usrp::subdev_spec_t::pair_t("A", "AB")); + sd_spec.push_back(uhd::usrp::subdev_spec_t::pair_t("B", "AB")); + + //convert to and from args string + std::cout << "Pretty Print: " << std::endl << sd_spec.to_pp_string(); + std::string markup_str = sd_spec.to_string(); + std::cout << "Markup String: " << markup_str << std::endl; + uhd::usrp::subdev_spec_t new_sd_spec(markup_str); + + //they should be the same size + BOOST_REQUIRE_EQUAL(sd_spec.size(), new_sd_spec.size()); + + //the contents should match + for (size_t i = 0; i < sd_spec.size(); i++){ + BOOST_CHECK_EQUAL(sd_spec.at(i).first, new_sd_spec.at(i).first); + BOOST_CHECK_EQUAL(sd_spec.at(i).second, new_sd_spec.at(i).second); + } +} |