From bf5aba2dc1b32c8eb0d016e98f942fb7119fdfde Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Sun, 2 Oct 2011 14:45:44 -0700 Subject: uhd: moved wax API into deprecated files --- host/include/uhd/CMakeLists.txt | 1 + host/include/uhd/deprecated.hpp | 173 ++++++++++++++++++++++++++++++++++++++++ host/include/uhd/device.hpp | 3 +- host/include/uhd/wax.hpp | 171 +-------------------------------------- host/lib/CMakeLists.txt | 2 +- host/lib/deprecated.cpp | 155 +++++++++++++++++++++++++++++++++++ host/lib/wax.cpp | 151 ----------------------------------- host/tests/CMakeLists.txt | 1 - host/tests/wax_test.cpp | 104 ------------------------ 9 files changed, 333 insertions(+), 428 deletions(-) create mode 100644 host/include/uhd/deprecated.hpp create mode 100644 host/lib/deprecated.cpp delete mode 100644 host/lib/wax.cpp delete mode 100644 host/tests/wax_test.cpp (limited to 'host') diff --git a/host/include/uhd/CMakeLists.txt b/host/include/uhd/CMakeLists.txt index 49562a7a0..6ca6d43cc 100644 --- a/host/include/uhd/CMakeLists.txt +++ b/host/include/uhd/CMakeLists.txt @@ -24,6 +24,7 @@ ADD_SUBDIRECTORY(utils) INSTALL(FILES config.hpp convert.hpp + deprecated.hpp device.hpp exception.hpp property_tree.ipp diff --git a/host/include/uhd/deprecated.hpp b/host/include/uhd/deprecated.hpp new file mode 100644 index 000000000..0a49cc423 --- /dev/null +++ b/host/include/uhd/deprecated.hpp @@ -0,0 +1,173 @@ +//---------------------------------------------------------------------- +//-- deprecated interfaces below, to be removed when the API is changed +//---------------------------------------------------------------------- + +// +// 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_WAX_HPP +#define INCLUDED_WAX_HPP + +#include +#include +#include +#include +#include + +/*! + * WAX - it's a metaphor! + * + * The WAX framework allows an object to have generic/anyobj properties. + * These properties can be addressed through generic/anyobj identifiers. + * + * The WAX object itself is an anytype container much like boost::any. + * To retrieve the value of the appropriate type, use my_obj.as(). + * + * Proprties may be referenced though the [] overloaded operator. + * The [] operator returns a special proxy that allows for assigment. + * Also, the [] operators may be chained as in the folowing examples: + * my_obj[prop1][prop2][prop3] = value; + * value = my_obj[prop1][prop2][prop3].as(); + * + * Property nesting occurs when a WAX object gets another object's link. + * This special link is obtained through a call to my_obj.get_link(). + * + * Note: Do not put a class derived from wax::obj into an stl container. + * MSVC will compile the code, but the binaries will crash at runtime. + * Rather, use pointers or smart pointers to instances of the derived class. + */ + +namespace wax{ + + /*! + * WAX object base class: + * + * A wax obj has two major purposes: + * 1) to act as a polymorphic container, just like boost any + * 2) to provide a nested set/get properties interface + * + * Internally, the polymorphic container is handled by a boost any. + * For properties, a subclass should override the set and get methods. + * For property nesting, wax obj subclasses return special links + * to other wax obj subclasses, and the api handles the magic. + */ + class UHD_API obj{ + public: + + /*! + * Default constructor: + * The contents will be empty. + */ + obj(void); + + /*! + * Copy constructor: + * The contents will be cloned. + * \param o another wax::obj + */ + obj(const obj &o); + + /*! + * Templated any type constructor: + * The contents can be anything. + * Uses the boost::any to handle the magic. + * \param o an object of any type + */ + template obj(const T &o){ + _contents = o; + } + + /*! + * Destructor. + */ + virtual ~obj(void); + + /*! + * The chaining operator: + * This operator allows access objs with properties. + * A call to the [] operator will return a new proxy obj. + * The proxy object is an obj with special proxy contents. + * Assignment and casting can be used on this special object + * to access the property referenced by the obj key. + * \param key a key to identify a property within this obj + * \return a special wax obj that proxies the obj and key + */ + obj operator[](const obj &key); + + /*! + * The assignment operator: + * This operator allows for assignment of new contents. + * In the special case where this obj contains a proxy, + * the value will be set to the proxy's property reference. + * \param val the new value to assign to the wax obj + * \return a reference to this obj (*this) + */ + obj & operator=(const obj &val); + + /*! + * Get a link in the chain: + * When a wax obj returns another wax obj as part of a get call, + * the return value should be set to the result of this method. + * Doing so will ensure chain-ability of the returned object. + * \return an obj containing a valid link to a wax obj + */ + obj get_link(void) const; + + /*! + * Get the type of the contents of this obj. + * \return a reference to the type_info + */ + const std::type_info & type(void) const; + + /*! + * Cast this obj into the desired type. + * Usage: myobj.as() + * + * \return an object of the desired type + * \throw wax::bad_cast when the cast fails + */ + template T as(void) const{ + try{ + return boost::any_cast(resolve()); + } + catch(const boost::bad_any_cast &e){ + throw uhd::type_error(std::string("") + "Cannot wax cast " + type().name() + " to " + typeid(T).name() + " " + e.what()); + } + } + + private: + //private interface (override in subclasses) + virtual void get(const obj &, obj &); + virtual void set(const obj &, const obj &); + + /*! + * Resolve the contents of this obj. + * In the case where this obj is a proxy, + * the referenced property will be resolved. + * Otherwise, just get the private contents. + * \return a boost any type with contents + */ + boost::any resolve(void) const; + + //private contents of this obj + boost::any _contents; + + }; + +} //namespace wax + +#endif /* INCLUDED_WAX_HPP */ diff --git a/host/include/uhd/device.hpp b/host/include/uhd/device.hpp index a6571d027..18545427c 100644 --- a/host/include/uhd/device.hpp +++ b/host/include/uhd/device.hpp @@ -23,7 +23,6 @@ #include #include #include -#include #include #include #include @@ -36,7 +35,7 @@ class property_tree; //forward declaration * The usrp device interface represents the usrp hardware. * The api allows for discovery, configuration, and streaming. */ -class UHD_API device : boost::noncopyable, public wax::obj{ +class UHD_API device : boost::noncopyable{ public: typedef boost::shared_ptr sptr; diff --git a/host/include/uhd/wax.hpp b/host/include/uhd/wax.hpp index 6fd2b8652..a55e5465d 100644 --- a/host/include/uhd/wax.hpp +++ b/host/include/uhd/wax.hpp @@ -1,169 +1,2 @@ -// -// 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_WAX_HPP -#define INCLUDED_WAX_HPP - -#include -#include -#include -#include -#include - -/*! - * WAX - it's a metaphor! - * - * The WAX framework allows an object to have generic/anyobj properties. - * These properties can be addressed through generic/anyobj identifiers. - * - * The WAX object itself is an anytype container much like boost::any. - * To retrieve the value of the appropriate type, use my_obj.as(). - * - * Proprties may be referenced though the [] overloaded operator. - * The [] operator returns a special proxy that allows for assigment. - * Also, the [] operators may be chained as in the folowing examples: - * my_obj[prop1][prop2][prop3] = value; - * value = my_obj[prop1][prop2][prop3].as(); - * - * Property nesting occurs when a WAX object gets another object's link. - * This special link is obtained through a call to my_obj.get_link(). - * - * Note: Do not put a class derived from wax::obj into an stl container. - * MSVC will compile the code, but the binaries will crash at runtime. - * Rather, use pointers or smart pointers to instances of the derived class. - */ - -namespace wax{ - - /*! - * WAX object base class: - * - * A wax obj has two major purposes: - * 1) to act as a polymorphic container, just like boost any - * 2) to provide a nested set/get properties interface - * - * Internally, the polymorphic container is handled by a boost any. - * For properties, a subclass should override the set and get methods. - * For property nesting, wax obj subclasses return special links - * to other wax obj subclasses, and the api handles the magic. - */ - class UHD_API obj{ - public: - - /*! - * Default constructor: - * The contents will be empty. - */ - obj(void); - - /*! - * Copy constructor: - * The contents will be cloned. - * \param o another wax::obj - */ - obj(const obj &o); - - /*! - * Templated any type constructor: - * The contents can be anything. - * Uses the boost::any to handle the magic. - * \param o an object of any type - */ - template obj(const T &o){ - _contents = o; - } - - /*! - * Destructor. - */ - virtual ~obj(void); - - /*! - * The chaining operator: - * This operator allows access objs with properties. - * A call to the [] operator will return a new proxy obj. - * The proxy object is an obj with special proxy contents. - * Assignment and casting can be used on this special object - * to access the property referenced by the obj key. - * \param key a key to identify a property within this obj - * \return a special wax obj that proxies the obj and key - */ - obj operator[](const obj &key); - - /*! - * The assignment operator: - * This operator allows for assignment of new contents. - * In the special case where this obj contains a proxy, - * the value will be set to the proxy's property reference. - * \param val the new value to assign to the wax obj - * \return a reference to this obj (*this) - */ - obj & operator=(const obj &val); - - /*! - * Get a link in the chain: - * When a wax obj returns another wax obj as part of a get call, - * the return value should be set to the result of this method. - * Doing so will ensure chain-ability of the returned object. - * \return an obj containing a valid link to a wax obj - */ - obj get_link(void) const; - - /*! - * Get the type of the contents of this obj. - * \return a reference to the type_info - */ - const std::type_info & type(void) const; - - /*! - * Cast this obj into the desired type. - * Usage: myobj.as() - * - * \return an object of the desired type - * \throw wax::bad_cast when the cast fails - */ - template T as(void) const{ - try{ - return boost::any_cast(resolve()); - } - catch(const boost::bad_any_cast &e){ - throw uhd::type_error(std::string("") + "Cannot wax cast " + type().name() + " to " + typeid(T).name() + " " + e.what()); - } - } - - private: - //private interface (override in subclasses) - virtual void get(const obj &, obj &); - virtual void set(const obj &, const obj &); - - /*! - * Resolve the contents of this obj. - * In the case where this obj is a proxy, - * the referenced property will be resolved. - * Otherwise, just get the private contents. - * \return a boost any type with contents - */ - boost::any resolve(void) const; - - //private contents of this obj - boost::any _contents; - - }; - -} //namespace wax - -#endif /* INCLUDED_WAX_HPP */ +//The wax API has been deprecated in favor of the properties interface +#include diff --git a/host/lib/CMakeLists.txt b/host/lib/CMakeLists.txt index 2b0210e6e..7a76ebd53 100644 --- a/host/lib/CMakeLists.txt +++ b/host/lib/CMakeLists.txt @@ -86,11 +86,11 @@ CONFIGURE_FILE( # Append to the list of sources for lib uhd ######################################################################## LIBUHD_APPEND_SOURCES( + ${CMAKE_CURRENT_SOURCE_DIR}/deprecated.cpp ${CMAKE_CURRENT_SOURCE_DIR}/device.cpp ${CMAKE_CURRENT_SOURCE_DIR}/exception.cpp ${CMAKE_CURRENT_SOURCE_DIR}/property_tree.cpp ${CMAKE_CURRENT_BINARY_DIR}/version.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/wax.cpp ) ######################################################################## diff --git a/host/lib/deprecated.cpp b/host/lib/deprecated.cpp new file mode 100644 index 000000000..eeaba03cb --- /dev/null +++ b/host/lib/deprecated.cpp @@ -0,0 +1,155 @@ +//---------------------------------------------------------------------- +//-- deprecated interfaces below, to be removed when the API is changed +//---------------------------------------------------------------------- + +// +// 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 + +/*! + * The link args for internal use within this cpp file: + * + * It contains a link (in this case a pointer) to a wax object. + * Only the methods in this file may create or parse link args. + * The get_link method is the creator of a link args object. + * The [] operator will resolve the link and make the [] call. + * + * TODO: register the link args with the wax obj that it links to. + * That way, if the obj destructs, the link can be invalidated. + * The operator() will throw, rather than dereferencing bad memory. + */ +class link_args_t{ +public: + link_args_t(const wax::obj *obj_ptr) : _obj_ptr(obj_ptr){ + /* NOP */ + } + wax::obj & operator()(void) const{ + //recursively resolve link args to get at original pointer + if (_obj_ptr->type() == typeid(link_args_t)){ + return _obj_ptr->as()(); + } + return *const_cast(_obj_ptr); + } +private: + const wax::obj *_obj_ptr; +}; + +/*! + * The proxy args for internal use within this cpp file: + * + * It contains a link and a key for setting/getting a property. + * Only the methods in this file may create or parse proxy args. + * Class methods have special handling for the case when the + * wax obj contains an instance of the proxy args. + */ +class proxy_args_t{ +public: + proxy_args_t(const wax::obj *obj_ptr, const wax::obj &key) : _key(key){ + _obj_link = obj_ptr->get_link(); + } + wax::obj & operator()(void) const{ + return _obj_link.as()(); + } + const wax::obj & key(void) const{ + return _key; + } +private: + wax::obj _obj_link; + const wax::obj _key; +}; + +/*********************************************************************** + * Structors + **********************************************************************/ +wax::obj::obj(void){ + /* NOP */ +} + +wax::obj::obj(const obj &o){ + _contents = o._contents; +} + +wax::obj::~obj(void){ + /* NOP */ +} + +/*********************************************************************** + * Special Operators + **********************************************************************/ +wax::obj wax::obj::operator[](const obj &key){ + if (_contents.type() == typeid(proxy_args_t)){ + obj val = resolve(); + //check if its a special link and call + if (val.type() == typeid(link_args_t)){ + return val.as()()[key]; + } + //unknown obj + throw uhd::type_error("cannot use [] on non wax::obj link"); + } + else{ + return proxy_args_t(this, key); + } +} + +wax::obj & wax::obj::operator=(const obj &val){ + if (_contents.type() == typeid(proxy_args_t)){ + proxy_args_t proxy_args = boost::any_cast(_contents); + proxy_args().set(proxy_args.key(), val); + } + else{ + _contents = val._contents; + } + return *this; +} + +/*********************************************************************** + * Public Methods + **********************************************************************/ +wax::obj wax::obj::get_link(void) const{ + return link_args_t(this); +} + +const std::type_info & wax::obj::type(void) const{ + return resolve().type(); +} + +/*********************************************************************** + * Private Methods + **********************************************************************/ +boost::any wax::obj::resolve(void) const{ + if (_contents.type() == typeid(proxy_args_t)){ + obj val; + proxy_args_t proxy_args = boost::any_cast(_contents); + proxy_args().get(proxy_args.key(), val); + return val.resolve(); + } + else{ + return _contents; + } +} + +void wax::obj::get(const obj &, obj &){ + throw uhd::type_error("Cannot call get on wax obj base class"); +} + +void wax::obj::set(const obj &, const obj &){ + throw uhd::type_error("Cannot call set on wax obj base class"); +} diff --git a/host/lib/wax.cpp b/host/lib/wax.cpp deleted file mode 100644 index 5f658acd8..000000000 --- a/host/lib/wax.cpp +++ /dev/null @@ -1,151 +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 - -/*! - * The link args for internal use within this cpp file: - * - * It contains a link (in this case a pointer) to a wax object. - * Only the methods in this file may create or parse link args. - * The get_link method is the creator of a link args object. - * The [] operator will resolve the link and make the [] call. - * - * TODO: register the link args with the wax obj that it links to. - * That way, if the obj destructs, the link can be invalidated. - * The operator() will throw, rather than dereferencing bad memory. - */ -class link_args_t{ -public: - link_args_t(const wax::obj *obj_ptr) : _obj_ptr(obj_ptr){ - /* NOP */ - } - wax::obj & operator()(void) const{ - //recursively resolve link args to get at original pointer - if (_obj_ptr->type() == typeid(link_args_t)){ - return _obj_ptr->as()(); - } - return *const_cast(_obj_ptr); - } -private: - const wax::obj *_obj_ptr; -}; - -/*! - * The proxy args for internal use within this cpp file: - * - * It contains a link and a key for setting/getting a property. - * Only the methods in this file may create or parse proxy args. - * Class methods have special handling for the case when the - * wax obj contains an instance of the proxy args. - */ -class proxy_args_t{ -public: - proxy_args_t(const wax::obj *obj_ptr, const wax::obj &key) : _key(key){ - _obj_link = obj_ptr->get_link(); - } - wax::obj & operator()(void) const{ - return _obj_link.as()(); - } - const wax::obj & key(void) const{ - return _key; - } -private: - wax::obj _obj_link; - const wax::obj _key; -}; - -/*********************************************************************** - * Structors - **********************************************************************/ -wax::obj::obj(void){ - /* NOP */ -} - -wax::obj::obj(const obj &o){ - _contents = o._contents; -} - -wax::obj::~obj(void){ - /* NOP */ -} - -/*********************************************************************** - * Special Operators - **********************************************************************/ -wax::obj wax::obj::operator[](const obj &key){ - if (_contents.type() == typeid(proxy_args_t)){ - obj val = resolve(); - //check if its a special link and call - if (val.type() == typeid(link_args_t)){ - return val.as()()[key]; - } - //unknown obj - throw uhd::type_error("cannot use [] on non wax::obj link"); - } - else{ - return proxy_args_t(this, key); - } -} - -wax::obj & wax::obj::operator=(const obj &val){ - if (_contents.type() == typeid(proxy_args_t)){ - proxy_args_t proxy_args = boost::any_cast(_contents); - proxy_args().set(proxy_args.key(), val); - } - else{ - _contents = val._contents; - } - return *this; -} - -/*********************************************************************** - * Public Methods - **********************************************************************/ -wax::obj wax::obj::get_link(void) const{ - return link_args_t(this); -} - -const std::type_info & wax::obj::type(void) const{ - return resolve().type(); -} - -/*********************************************************************** - * Private Methods - **********************************************************************/ -boost::any wax::obj::resolve(void) const{ - if (_contents.type() == typeid(proxy_args_t)){ - obj val; - proxy_args_t proxy_args = boost::any_cast(_contents); - proxy_args().get(proxy_args.key(), val); - return val.resolve(); - } - else{ - return _contents; - } -} - -void wax::obj::get(const obj &, obj &){ - throw uhd::type_error("Cannot call get on wax obj base class"); -} - -void wax::obj::set(const obj &, const obj &){ - throw uhd::type_error("Cannot call set on wax obj base class"); -} diff --git a/host/tests/CMakeLists.txt b/host/tests/CMakeLists.txt index c97116233..28cc1c5da 100644 --- a/host/tests/CMakeLists.txt +++ b/host/tests/CMakeLists.txt @@ -34,7 +34,6 @@ SET(test_sources subdev_spec_test.cpp time_spec_test.cpp vrt_test.cpp - wax_test.cpp ) #turn each test cpp file into an executable with an int main() function diff --git a/host/tests/wax_test.cpp b/host/tests/wax_test.cpp deleted file mode 100644 index 18730e0c2..000000000 --- a/host/tests/wax_test.cpp +++ /dev/null @@ -1,104 +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 - -enum opt_a_t{OPTION_A_0, OPTION_A_1}; -enum opt_b_t{OPTION_B_0, OPTION_B_1}; - -BOOST_AUTO_TEST_CASE(test_enums){ - wax::obj opta = OPTION_A_0; - BOOST_CHECK_THROW(opta.as(), std::exception); - BOOST_CHECK_EQUAL(opta.as(), OPTION_A_0); -} - -/*********************************************************************** - * demo class for wax framework - **********************************************************************/ -class wax_demo : public wax::obj{ -public: - typedef boost::shared_ptr sptr; - - wax_demo(size_t sub_demos, size_t len){ - d_nums = std::vector(len); - if (sub_demos != 0){ - for (size_t i = 0; i < len; i++){ - d_subs.push_back(sptr(new wax_demo(sub_demos-1, len))); - } - } - } - ~wax_demo(void){ - /* NOP */ - } -private: - std::vector d_nums; - std::vector d_subs; - - void get(const wax::obj &key, wax::obj &value){ - if (d_subs.size() == 0){ - value = d_nums[key.as()]; - }else{ - value = d_subs[key.as()]->get_link(); - } - } - void set(const wax::obj &key, const wax::obj &value){ - if (d_subs.size() == 0){ - d_nums[key.as()] = value.as(); - }else{ - throw std::runtime_error("cant set to a wax demo with sub demos"); - } - } -}; - -BOOST_AUTO_TEST_CASE(test_chaining){ - wax_demo wd(2, 1); - std::cout << "chain 1" << std::endl; - wd[size_t(0)]; - std::cout << "chain 2" << std::endl; - wd[size_t(0)][size_t(0)]; - std::cout << "chain 3" << std::endl; - wd[size_t(0)][size_t(0)][size_t(0)]; -} - -BOOST_AUTO_TEST_CASE(test_set_get){ - wax_demo wd(2, 10); - std::cout << "set and get all" << std::endl; - for (size_t i = 0; i < 10; i++){ - for (size_t j = 0; j < 10; j++){ - for (size_t k = 0; k < 10; k++){ - float val = float(i * j * k + i + j + k); - //std::cout << i << " " << j << " " << k << std::endl; - wd[i][j][k] = val; - BOOST_CHECK_EQUAL(val, wd[i][j][k].as()); - } - } - } -} - -BOOST_AUTO_TEST_CASE(test_proxy){ - wax_demo wd(2, 1); - std::cout << "store proxy" << std::endl; - wax::obj p = wd[size_t(0)][size_t(0)]; - p[size_t(0)] = float(5); - - std::cout << "assign proxy" << std::endl; - wax::obj a = p[size_t(0)]; - BOOST_CHECK_EQUAL(a.as(), float(5)); -} -- cgit v1.2.3 From 8c182d75e7adc20ff12cbc1065debd8dd4f2ef9d Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Mon, 3 Oct 2011 11:35:16 -0700 Subject: uhd: removed unsed interfaces, deprecated otw and io type --- host/include/uhd/CMakeLists.txt | 1 + host/include/uhd/deprecated.hpp | 148 +++++++++++++++++++++++++++++++++ host/include/uhd/device.hpp | 2 +- host/include/uhd/types/io_type.hpp | 78 +---------------- host/include/uhd/types/otw_type.hpp | 71 +--------------- host/include/uhd/usrp/CMakeLists.txt | 2 - host/include/uhd/usrp/mboard_iface.hpp | 71 ---------------- host/include/uhd/usrp/single_usrp.hpp | 30 ------- host/lib/deprecated.cpp | 50 +++++++++++ host/lib/types/types.cpp | 47 ----------- 10 files changed, 204 insertions(+), 296 deletions(-) delete mode 100644 host/include/uhd/usrp/mboard_iface.hpp delete mode 100644 host/include/uhd/usrp/single_usrp.hpp (limited to 'host') diff --git a/host/include/uhd/CMakeLists.txt b/host/include/uhd/CMakeLists.txt index 6ca6d43cc..08483346c 100644 --- a/host/include/uhd/CMakeLists.txt +++ b/host/include/uhd/CMakeLists.txt @@ -29,6 +29,7 @@ INSTALL(FILES exception.hpp property_tree.ipp property_tree.hpp + streamer.hpp version.hpp wax.hpp DESTINATION ${INCLUDE_DIR}/uhd diff --git a/host/include/uhd/deprecated.hpp b/host/include/uhd/deprecated.hpp index 0a49cc423..0f4965bc6 100644 --- a/host/include/uhd/deprecated.hpp +++ b/host/include/uhd/deprecated.hpp @@ -171,3 +171,151 @@ namespace wax{ } //namespace wax #endif /* INCLUDED_WAX_HPP */ + +// +// 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_OTW_TYPE_HPP +#define INCLUDED_UHD_TYPES_OTW_TYPE_HPP + +#include + +namespace uhd{ + + /*! + * Description for over-the-wire integers: + * The DSP units in the FPGA deal with signed 16-bit integers. + * The width and shift define the translation between OTW and DSP, + * defined by the following relation: otw_int = dsp_int >> shift + * + * Note: possible combinations of width, shift, and byteorder + * depend on the internals of the FPGA. Not all are supported! + */ + struct UHD_API otw_type_t{ + + /*! + * Width of an over-the-wire integer in bits. + */ + size_t width; //in bits + + /*! + * Shift of an over-the-wire integer in bits. + * otw_int = dsp_int >> shift + * dsp_int = otw_int << shift + */ + size_t shift; //in bits + + /*! + * Constants for byte order (borrowed from numpy's dtype) + */ + enum /*bo_t*/ { + BO_NATIVE = int('='), + BO_LITTLE_ENDIAN = int('<'), + BO_BIG_ENDIAN = int('>'), + BO_NOT_APPLICABLE = int('|') + } byteorder; + + /*! + * Get the sample size of this otw type. + * \return the size of a sample in bytes + */ + size_t get_sample_size(void) const; + + otw_type_t(void); + }; + +} //namespace uhd + +#endif /* INCLUDED_UHD_TYPES_OTW_TYPE_HPP */ + +// +// 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_IO_TYPE_HPP +#define INCLUDED_UHD_TYPES_IO_TYPE_HPP + +#include + +namespace uhd{ + + /*! + * The Input/Output configuration struct: + * Used to specify the IO type with device send/recv. + */ + class UHD_API io_type_t{ + public: + + /*! + * Built in IO types known to the system. + */ + enum tid_t{ + //! Custom type (technically unsupported by implementation) + CUSTOM_TYPE = int('?'), + //! Complex floating point (64-bit floats) range [-1.0, +1.0] + COMPLEX_FLOAT64 = int('d'), + //! Complex floating point (32-bit floats) range [-1.0, +1.0] + COMPLEX_FLOAT32 = int('f'), + //! Complex signed integer (16-bit integers) range [-32768, +32767] + COMPLEX_INT16 = int('s'), + //! Complex signed integer (8-bit integers) range [-128, 127] + COMPLEX_INT8 = int('b') + }; + + /*! + * The size of this io type in bytes. + */ + const size_t size; + + /*! + * The type id of this io type. + * Good for using with switch statements. + */ + const tid_t tid; + + /*! + * Create an io type from a built-in type id. + * \param tid a type id known to the system + */ + io_type_t(tid_t tid); + + /*! + * Create an io type from attributes. + * The tid will be set to custom. + * \param size the size in bytes + */ + io_type_t(size_t size); + + }; + +} //namespace uhd + +#endif /* INCLUDED_UHD_TYPES_IO_TYPE_HPP */ + diff --git a/host/include/uhd/device.hpp b/host/include/uhd/device.hpp index 18545427c..0ea5259b5 100644 --- a/host/include/uhd/device.hpp +++ b/host/include/uhd/device.hpp @@ -19,9 +19,9 @@ #define INCLUDED_UHD_DEVICE_HPP #include +#include #include #include -#include #include #include #include diff --git a/host/include/uhd/types/io_type.hpp b/host/include/uhd/types/io_type.hpp index ace643abc..e0ee4187b 100644 --- a/host/include/uhd/types/io_type.hpp +++ b/host/include/uhd/types/io_type.hpp @@ -1,76 +1,2 @@ -// -// 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_IO_TYPE_HPP -#define INCLUDED_UHD_TYPES_IO_TYPE_HPP - -#include - -namespace uhd{ - - /*! - * The Input/Output configuration struct: - * Used to specify the IO type with device send/recv. - */ - class UHD_API io_type_t{ - public: - - /*! - * Built in IO types known to the system. - */ - enum tid_t{ - //! Custom type (technically unsupported by implementation) - CUSTOM_TYPE = int('?'), - //! Complex floating point (64-bit floats) range [-1.0, +1.0] - COMPLEX_FLOAT64 = int('d'), - //! Complex floating point (32-bit floats) range [-1.0, +1.0] - COMPLEX_FLOAT32 = int('f'), - //! Complex signed integer (16-bit integers) range [-32768, +32767] - COMPLEX_INT16 = int('s'), - //! Complex signed integer (8-bit integers) range [-128, 127] - COMPLEX_INT8 = int('b') - }; - - /*! - * The size of this io type in bytes. - */ - const size_t size; - - /*! - * The type id of this io type. - * Good for using with switch statements. - */ - const tid_t tid; - - /*! - * Create an io type from a built-in type id. - * \param tid a type id known to the system - */ - io_type_t(tid_t tid); - - /*! - * Create an io type from attributes. - * The tid will be set to custom. - * \param size the size in bytes - */ - io_type_t(size_t size); - - }; - -} //namespace uhd - -#endif /* INCLUDED_UHD_TYPES_IO_TYPE_HPP */ +//The IO type API has been deprecated in favor of the streamer interface +#include diff --git a/host/include/uhd/types/otw_type.hpp b/host/include/uhd/types/otw_type.hpp index 11a6af38e..6dc634fc8 100644 --- a/host/include/uhd/types/otw_type.hpp +++ b/host/include/uhd/types/otw_type.hpp @@ -1,69 +1,2 @@ -// -// 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_OTW_TYPE_HPP -#define INCLUDED_UHD_TYPES_OTW_TYPE_HPP - -#include - -namespace uhd{ - - /*! - * Description for over-the-wire integers: - * The DSP units in the FPGA deal with signed 16-bit integers. - * The width and shift define the translation between OTW and DSP, - * defined by the following relation: otw_int = dsp_int >> shift - * - * Note: possible combinations of width, shift, and byteorder - * depend on the internals of the FPGA. Not all are supported! - */ - struct UHD_API otw_type_t{ - - /*! - * Width of an over-the-wire integer in bits. - */ - size_t width; //in bits - - /*! - * Shift of an over-the-wire integer in bits. - * otw_int = dsp_int >> shift - * dsp_int = otw_int << shift - */ - size_t shift; //in bits - - /*! - * Constants for byte order (borrowed from numpy's dtype) - */ - enum /*bo_t*/ { - BO_NATIVE = int('='), - BO_LITTLE_ENDIAN = int('<'), - BO_BIG_ENDIAN = int('>'), - BO_NOT_APPLICABLE = int('|') - } byteorder; - - /*! - * Get the sample size of this otw type. - * \return the size of a sample in bytes - */ - size_t get_sample_size(void) const; - - otw_type_t(void); - }; - -} //namespace uhd - -#endif /* INCLUDED_UHD_TYPES_OTW_TYPE_HPP */ +//The OTW type API has been deprecated in favor of the streamer interface +#include diff --git a/host/include/uhd/usrp/CMakeLists.txt b/host/include/uhd/usrp/CMakeLists.txt index ba38a67ea..d7b936fc2 100644 --- a/host/include/uhd/usrp/CMakeLists.txt +++ b/host/include/uhd/usrp/CMakeLists.txt @@ -31,9 +31,7 @@ INSTALL(FILES subdev_spec.hpp ### interfaces ### - single_usrp.hpp multi_usrp.hpp - mboard_iface.hpp DESTINATION ${INCLUDE_DIR}/uhd/usrp COMPONENT headers diff --git a/host/include/uhd/usrp/mboard_iface.hpp b/host/include/uhd/usrp/mboard_iface.hpp deleted file mode 100644 index bbee8f2de..000000000 --- a/host/include/uhd/usrp/mboard_iface.hpp +++ /dev/null @@ -1,71 +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 . -// - -#ifndef INCLUDED_UHD_USRP_MBOARD_IFACE_HPP -#define INCLUDED_UHD_USRP_MBOARD_IFACE_HPP - -#include -#include -#include -#include -#include -#include -#include - -namespace uhd{ namespace usrp{ - -/*! - * The mboard interface class: - * Provides a set of functions to implementation layer. - * Including spi, peek, poke, control... - */ -class mboard_iface : public uhd::i2c_iface, public uhd::spi_iface, public uhd::uart_iface { -public: - typedef boost::shared_ptr sptr; - /*! - * Write a register (32 bits) - * \param addr the address - * \param data the 32bit data - */ - virtual void poke32(boost::uint32_t addr, boost::uint32_t data) = 0; - - /*! - * Read a register (32 bits) - * \param addr the address - * \return the 32bit data - */ - virtual boost::uint32_t peek32(boost::uint32_t addr) = 0; - - /*! - * Write a register (16 bits) - * \param addr the address - * \param data the 16bit data - */ - virtual void poke16(boost::uint32_t addr, boost::uint16_t data) = 0; - - /*! - * Read a register (16 bits) - * \param addr the address - * \return the 16bit data - */ - virtual boost::uint16_t peek16(boost::uint32_t addr) = 0; - -}; - -}} - -#endif //INCLUDED_UHD_USRP_DBOARD_IFACE_HPP diff --git a/host/include/uhd/usrp/single_usrp.hpp b/host/include/uhd/usrp/single_usrp.hpp deleted file mode 100644 index 0520db162..000000000 --- a/host/include/uhd/usrp/single_usrp.hpp +++ /dev/null @@ -1,30 +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 . -// - -#ifndef INCLUDED_UHD_USRP_SINGLE_USRP_HPP -#define INCLUDED_UHD_USRP_SINGLE_USRP_HPP - -#include - -namespace uhd{ namespace usrp{ - - //! Multi-USRP is a superset of Single-USRP - typedef multi_usrp single_usrp; - -}} - -#endif /* INCLUDED_UHD_USRP_SINGLE_USRP_HPP */ diff --git a/host/lib/deprecated.cpp b/host/lib/deprecated.cpp index eeaba03cb..dd4cc02ad 100644 --- a/host/lib/deprecated.cpp +++ b/host/lib/deprecated.cpp @@ -153,3 +153,53 @@ void wax::obj::get(const obj &, obj &){ void wax::obj::set(const obj &, const obj &){ throw uhd::type_error("Cannot call set on wax obj base class"); } + +#include +#include +#include +#include +#include +#include + +using namespace uhd; + +/*********************************************************************** + * 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 std::vector get_tid_size_table(void){ + std::vector table(128, 0); + table[size_t(io_type_t::COMPLEX_FLOAT64)] = sizeof(std::complex); + table[size_t(io_type_t::COMPLEX_FLOAT32)] = sizeof(std::complex); + table[size_t(io_type_t::COMPLEX_INT16)] = sizeof(std::complex); + table[size_t(io_type_t::COMPLEX_INT8)] = sizeof(std::complex); + return table; +} + +static const std::vector tid_size_table(get_tid_size_table()); + +io_type_t::io_type_t(tid_t tid): + size(tid_size_table[size_t(tid) & 0x7f]), tid(tid) +{ + /* NOP */ +} + +io_type_t::io_type_t(size_t size): + size(size), tid(CUSTOM_TYPE) +{ + /* NOP */ +} diff --git a/host/lib/types/types.cpp b/host/lib/types/types.cpp index 7c65d2997..1a3e7e860 100644 --- a/host/lib/types/types.cpp +++ b/host/lib/types/types.cpp @@ -17,12 +17,6 @@ #include #include -#include -#include -#include -#include -#include -#include using namespace uhd; @@ -48,44 +42,3 @@ tx_metadata_t::tx_metadata_t(void): { /* NOP */ } - -/*********************************************************************** - * 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 std::vector get_tid_size_table(void){ - std::vector table(128, 0); - table[size_t(io_type_t::COMPLEX_FLOAT64)] = sizeof(std::complex); - table[size_t(io_type_t::COMPLEX_FLOAT32)] = sizeof(std::complex); - table[size_t(io_type_t::COMPLEX_INT16)] = sizeof(std::complex); - table[size_t(io_type_t::COMPLEX_INT8)] = sizeof(std::complex); - return table; -} - -static const std::vector tid_size_table(get_tid_size_table()); - -io_type_t::io_type_t(tid_t tid): - size(tid_size_table[size_t(tid) & 0x7f]), tid(tid) -{ - /* NOP */ -} - -io_type_t::io_type_t(size_t size): - size(size), tid(CUSTOM_TYPE) -{ - /* NOP */ -} -- cgit v1.2.3 From c480414fea7948dedd9428f545dfff90f4c8f2c8 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Mon, 3 Oct 2011 13:54:35 -0700 Subject: uhd: work on streamer interface, lots of docstrings --- host/include/uhd/streamer.hpp | 170 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 170 insertions(+) create mode 100644 host/include/uhd/streamer.hpp (limited to 'host') diff --git a/host/include/uhd/streamer.hpp b/host/include/uhd/streamer.hpp new file mode 100644 index 000000000..eed18e773 --- /dev/null +++ b/host/include/uhd/streamer.hpp @@ -0,0 +1,170 @@ +// +// 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 . +// + +#ifndef INCLUDED_UHD_STREAMER_HPP +#define INCLUDED_UHD_STREAMER_HPP + +#include +#include +#include +#include + +namespace uhd{ + +/*! + * A streamer is the host interface to RX or TX samples. + * It represents the layer between the samples on the host + * and samples inside the device's DSP processing. + */ +class UHD_API streamer : boost::noncopyable{ +public: + //! Get the number of channels associated with this streamer + virtual size_t get_num_channels(void) const = 0; + + /*! + * \brief Set the format for all channels in this streamer. + * + * The CPU format is a string that describes the format of host memory. + * Common CPU formats are: + * - fc32 - complex + * - fc64 - complex + * - sc16 - complex + * - sc8 - complex + * - f32 - float + * - f64 - double + * - s16 - int16_t + * - s8 - int8_t + * + * The OTW format is a string that describes the format over-the-wire. + * Common OTW format are: + * - sc16 - Q16 I16 + * - sc8 - Q8_1 I8_1 Q8_0 I8_0 + * - s16 - R16_1 R16_0 + * - s8 - R8_3 R8_2 R8_1 R8_0 + * + * The args parameter is currently unused. Leave it blank. + * The intention is that a user with a custom DSP design + * may want to pass args and do something special with it. + * + * Note: + * Not all combinations of CPU and OTW format have conversion support. + * You may however write and register your own conversion routines. + * + * \param cpu_format the data format for samples used on the host + * \param otw_format the data format of the samples over the wire + * \param args optional arguments to augment the format + */ + virtual void set_format( + const std::string &cpu_format, + const std::string &otw_format, + const std::string &args = "" + ) = 0; + + //! Get the number of bytes per CPU item/sample + virtual size_t get_bytes_per_cpu_item(void) const = 0; + + //! Get the number of bytes per OTW item/sample + virtual size_t get_bytes_per_otw_item(void) const = 0; + + //! Get the max number of items/samples per packet + virtual size_t get_items_per_packet(void) const = 0; + + //TODO enumerate cpu and otw format options + +}; + +//! A RX streamer to receive host samples +class UHD_API rx_streamer : public streamer{ +public: + typedef boost::shared_ptr sptr; + + //! Typedef for a pointer to a single, or a collection of recv buffers + typedef ref_vector recv_buffs_type; + + /*! + * Receive buffers containing samples described by the metadata. + * + * Receive handles fragmentation as follows: + * If the buffer has insufficient space to hold all samples + * that were received in a single packet over-the-wire, + * then the buffer will be completely filled and the implementation + * will hold a pointer into the remaining portion of the packet. + * Subsequent calls will load from the remainder of the packet, + * and will flag the metadata to show that this is a fragment. + * The next call to receive, after the remainder becomes exahausted, + * will perform an over-the-wire receive as usual. + * See the rx metadata fragment flags and offset fields for details. + * + * This is a blocking call and will not return until the number + * of samples returned have been written into each buffer. + * Under a timeout condition, the number of samples returned + * may be less than the number of samples specified. + * + * \param buffs a vector of writable memory to fill with samples + * \param nsamps_per_buff the size of each buffer in number of samples + * \param metadata data to fill describing the buffer + * \param timeout the timeout in seconds to wait for a packet + * \return the number of samples received or 0 on error + */ + virtual size_t recv( + const recv_buffs_type &buffs, + size_t nsamps_per_buff, + rx_metadata_t &metadata, + double timeout = 0.1 + ) = 0; +}; + +//! A TX streamer to transmit host samples +class UHD_API rx_streamer : public streamer{ +public: + typedef boost::shared_ptr sptr; + + //! Typedef for a pointer to a single, or a collection of send buffers + typedef ref_vector send_buffs_type; + + /*! + * Send buffers containing samples described by the metadata. + * + * Send handles fragmentation as follows: + * If the buffer has more items than the maximum per packet, + * the send method will fragment the samples across several packets. + * Send will respect the burst flags when fragmenting to ensure + * that start of burst can only be set on the first fragment and + * that end of burst can only be set on the final fragment. + * + * This is a blocking call and will not return until the number + * of samples returned have been read out of each buffer. + * Under a timeout condition, the number of samples returned + * may be less than the number of samples specified. + * + * \param buffs a vector of read-only memory containing samples + * \param nsamps_per_buff the number of samples to send, per buffer + * \param metadata data describing the buffer's contents + * \param timeout the timeout in seconds to wait on a packet + * \return the number of samples sent + */ + virtual size_t send( + const send_buffs_type &buffs, + size_t nsamps_per_buff, + const tx_metadata_t &metadata, + double timeout = 0.1 + ) = 0; +}; + +} //namespace uhd + +#endif /* INCLUDED_UHD_STREAMER_HPP */ -- cgit v1.2.3 From 75b7967fac3ec72fb35c542da23491215d53a8bb Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Mon, 3 Oct 2011 16:46:00 -0700 Subject: convert: reworked convert to use new identification standard --- host/include/uhd/convert.hpp | 59 +++++---- host/lib/convert/CMakeLists.txt | 11 -- host/lib/convert/convert_common.hpp | 27 +++- host/lib/convert/convert_fc32_with_sse2.cpp | 8 +- host/lib/convert/convert_fc64_with_sse2.cpp | 8 +- host/lib/convert/convert_impl.cpp | 117 +++++++++++------- host/lib/convert/gen_convert_general.py | 23 ++-- host/lib/convert/gen_convert_pred.py | 185 ---------------------------- 8 files changed, 146 insertions(+), 292 deletions(-) delete mode 100644 host/lib/convert/gen_convert_pred.py (limited to 'host') diff --git a/host/include/uhd/convert.hpp b/host/include/uhd/convert.hpp index 99f1860ae..a0b502ab0 100644 --- a/host/include/uhd/convert.hpp +++ b/host/include/uhd/convert.hpp @@ -19,17 +19,18 @@ #define INCLUDED_UHD_CONVERT_HPP #include -#include -#include #include #include +#include #include namespace uhd{ namespace convert{ typedef uhd::ref_vector output_type; typedef uhd::ref_vector input_type; - typedef boost::function function_type; + + //! input vectors, output vectors, num samples, scale factor + typedef boost::function function_type; /*! * Describe the priority of a converter function. @@ -45,46 +46,50 @@ namespace uhd{ namespace convert{ PRIORITY_EMPTY = -1, }; + //! Identify a conversion routine in the registry + struct id_type : boost::equality_comparable{ + std::string input_markup; + size_t num_inputs; + std::string output_markup; + size_t num_outputs; + std::string args; + std::string to_pp_string(void) const; + }; + + //! Implement equality_comparable interface + UHD_API bool operator==(const id_type &, const id_type &); + /*! - * Register a converter function that converts cpu type to/from otw type. - * \param markup representing the signature + * Register a converter function. + * \param id identify the conversion * \param fcn a pointer to the converter * \param prio the function priority */ UHD_API void register_converter( - const std::string &markup, + const id_type &id, function_type fcn, priority_type prio ); /*! - * Get a converter function that converts cpu to otw. - * \param io_type the type of the input samples - * \param otw_type the type of the output samples - * \param num_input_buffs the number of inputs - * \param num_output_buffs the number of outputs + * Get a converter function. + * \param id identify the conversion + * \return the converter function */ - UHD_API const function_type &get_converter_cpu_to_otw( - const io_type_t &io_type, - const otw_type_t &otw_type, - size_t num_input_buffs, - size_t num_output_buffs - ); + UHD_API function_type get_converter(const id_type &id); /*! - * Get a converter function that converts otw to cpu. - * \param io_type the type of the input samples - * \param otw_type the type of the output samples - * \param num_input_buffs the number of inputs - * \param num_output_buffs the number of outputs + * Register the size of a particular item. + * \param markup the item markup + * \param size the size in bytes */ - UHD_API const function_type &get_converter_otw_to_cpu( - const io_type_t &io_type, - const otw_type_t &otw_type, - size_t num_input_buffs, - size_t num_output_buffs + UHD_API void register_bytes_per_item( + const std::string &markup, const size_t size ); + //! Convert an item markup to a size in bytes + UHD_API size_t get_bytes_per_item(const std::string &markup); + }} //namespace #endif /* INCLUDED_UHD_CONVERT_HPP */ diff --git a/host/lib/convert/CMakeLists.txt b/host/lib/convert/CMakeLists.txt index b260cb247..4cc421884 100644 --- a/host/lib/convert/CMakeLists.txt +++ b/host/lib/convert/CMakeLists.txt @@ -111,17 +111,6 @@ ENDIF() INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}) INCLUDE_DIRECTORIES(${CMAKE_CURRENT_BINARY_DIR}) -LIBUHD_PYTHON_GEN_SOURCE( - ${CMAKE_CURRENT_SOURCE_DIR}/gen_convert_pred.py - ${CMAKE_CURRENT_BINARY_DIR}/convert_pred.hpp -) - -INCLUDE(AddFileDependencies) -ADD_FILE_DEPENDENCIES( - ${CMAKE_CURRENT_SOURCE_DIR}/convert_impl.cpp - ${CMAKE_CURRENT_BINARY_DIR}/convert_pred.hpp -) - LIBUHD_PYTHON_GEN_SOURCE( ${CMAKE_CURRENT_SOURCE_DIR}/gen_convert_general.py ${CMAKE_CURRENT_BINARY_DIR}/convert_general.cpp diff --git a/host/lib/convert/convert_common.hpp b/host/lib/convert/convert_common.hpp index 7f513b124..8c8cc88b0 100644 --- a/host/lib/convert/convert_common.hpp +++ b/host/lib/convert/convert_common.hpp @@ -23,28 +23,45 @@ #include #include -#define DECLARE_CONVERTER(fcn, prio) \ +#define _DECLARE_CONVERTER(fcn, in_mark, num_in, out_mark, num_out, prio) \ static void fcn( \ const uhd::convert::input_type &inputs, \ const uhd::convert::output_type &outputs, \ - size_t nsamps, double scale_factor \ + const size_t nsamps, \ + const double scale_factor \ ); \ - UHD_STATIC_BLOCK(register_##fcn##_##prio){ \ - uhd::convert::register_converter(#fcn, fcn, prio); \ + UHD_STATIC_BLOCK(__register_##fcn##_##prio){ \ + uhd::convert::id_type id; \ + id.input_markup = #in_mark; \ + id.num_inputs = num_in; \ + id.output_markup = #out_mark; \ + id.num_outputs = num_out; \ + uhd::convert::register_converter(id, fcn, prio); \ } \ static void fcn( \ const uhd::convert::input_type &inputs, \ const uhd::convert::output_type &outputs, \ - size_t nsamps, double scale_factor \ + const size_t nsamps, \ + const double scale_factor \ ) +#define DECLARE_CONVERTER(in_mark, num_in, out_mark, num_out, prio) \ + _DECLARE_CONVERTER(__convert_##in_mark##_##num_in##_##out_mark##_##num_out, in_mark, num_in, out_mark, num_out, prio) + /*********************************************************************** * Typedefs **********************************************************************/ typedef std::complex fc64_t; typedef std::complex fc32_t; +typedef std::complex sc32_t; typedef std::complex sc16_t; typedef std::complex sc8_t; +typedef double f64_t; +typedef float f32_t; +typedef boost::int32_t s32_t; +typedef boost::int16_t s16_t; +typedef boost::int8_t s8_t; + typedef boost::uint32_t item32_t; /*********************************************************************** diff --git a/host/lib/convert/convert_fc32_with_sse2.cpp b/host/lib/convert/convert_fc32_with_sse2.cpp index 676e1561c..34c85db80 100644 --- a/host/lib/convert/convert_fc32_with_sse2.cpp +++ b/host/lib/convert/convert_fc32_with_sse2.cpp @@ -21,7 +21,7 @@ using namespace uhd::convert; -DECLARE_CONVERTER(convert_fc32_1_to_item32_1_nswap, PRIORITY_CUSTOM){ +DECLARE_CONVERTER(fc32, 1, sc16_item32_le, 1, PRIORITY_CUSTOM){ const fc32_t *input = reinterpret_cast(inputs[0]); item32_t *output = reinterpret_cast(outputs[0]); @@ -64,7 +64,7 @@ DECLARE_CONVERTER(convert_fc32_1_to_item32_1_nswap, PRIORITY_CUSTOM){ } } -DECLARE_CONVERTER(convert_fc32_1_to_item32_1_bswap, PRIORITY_CUSTOM){ +DECLARE_CONVERTER(fc32, 1, sc16_item32_be, 1, PRIORITY_CUSTOM){ const fc32_t *input = reinterpret_cast(inputs[0]); item32_t *output = reinterpret_cast(outputs[0]); @@ -106,7 +106,7 @@ DECLARE_CONVERTER(convert_fc32_1_to_item32_1_bswap, PRIORITY_CUSTOM){ } } -DECLARE_CONVERTER(convert_item32_1_to_fc32_1_nswap, PRIORITY_CUSTOM){ +DECLARE_CONVERTER(sc16_item32_le, 1, fc32, 1, PRIORITY_CUSTOM){ const item32_t *input = reinterpret_cast(inputs[0]); fc32_t *output = reinterpret_cast(outputs[0]); @@ -151,7 +151,7 @@ DECLARE_CONVERTER(convert_item32_1_to_fc32_1_nswap, PRIORITY_CUSTOM){ } } -DECLARE_CONVERTER(convert_item32_1_to_fc32_1_bswap, PRIORITY_CUSTOM){ +DECLARE_CONVERTER(sc16_item32_be, 1, fc32, 1, PRIORITY_CUSTOM){ const item32_t *input = reinterpret_cast(inputs[0]); fc32_t *output = reinterpret_cast(outputs[0]); diff --git a/host/lib/convert/convert_fc64_with_sse2.cpp b/host/lib/convert/convert_fc64_with_sse2.cpp index 4d28396a4..2093cf476 100644 --- a/host/lib/convert/convert_fc64_with_sse2.cpp +++ b/host/lib/convert/convert_fc64_with_sse2.cpp @@ -21,7 +21,7 @@ using namespace uhd::convert; -DECLARE_CONVERTER(convert_fc64_1_to_item32_1_nswap, PRIORITY_CUSTOM){ +DECLARE_CONVERTER(fc64, 1, sc16_item32_le, 1, PRIORITY_CUSTOM){ const fc64_t *input = reinterpret_cast(inputs[0]); item32_t *output = reinterpret_cast(outputs[0]); @@ -68,7 +68,7 @@ DECLARE_CONVERTER(convert_fc64_1_to_item32_1_nswap, PRIORITY_CUSTOM){ } } -DECLARE_CONVERTER(convert_fc64_1_to_item32_1_bswap, PRIORITY_CUSTOM){ +DECLARE_CONVERTER(fc64, 1, sc16_item32_be, 1, PRIORITY_CUSTOM){ const fc64_t *input = reinterpret_cast(inputs[0]); item32_t *output = reinterpret_cast(outputs[0]); @@ -114,7 +114,7 @@ DECLARE_CONVERTER(convert_fc64_1_to_item32_1_bswap, PRIORITY_CUSTOM){ } } -DECLARE_CONVERTER(convert_item32_1_to_fc64_1_nswap, PRIORITY_CUSTOM){ +DECLARE_CONVERTER(sc16_item32_le, 1, fc64, 1, PRIORITY_CUSTOM){ const item32_t *input = reinterpret_cast(inputs[0]); fc64_t *output = reinterpret_cast(outputs[0]); @@ -163,7 +163,7 @@ DECLARE_CONVERTER(convert_item32_1_to_fc64_1_nswap, PRIORITY_CUSTOM){ } } -DECLARE_CONVERTER(convert_item32_1_to_fc64_1_bswap, PRIORITY_CUSTOM){ +DECLARE_CONVERTER(sc16_item32_be, 1, fc64, 1, PRIORITY_CUSTOM){ const item32_t *input = reinterpret_cast(inputs[0]); fc64_t *output = reinterpret_cast(outputs[0]); diff --git a/host/lib/convert/convert_impl.cpp b/host/lib/convert/convert_impl.cpp index 9b2cdcdc9..2ead2f5b4 100644 --- a/host/lib/convert/convert_impl.cpp +++ b/host/lib/convert/convert_impl.cpp @@ -18,11 +18,40 @@ #include #include #include +#include #include +#include +#include +#include using namespace uhd; -#include "convert_pred.hpp" +bool convert::operator==(const convert::id_type &lhs, const convert::id_type &rhs){ + return + (lhs.input_markup == rhs.input_markup) and + (lhs.num_inputs == rhs.num_inputs) and + (lhs.output_markup == rhs.output_markup) and + (lhs.num_outputs == rhs.num_outputs) and + (lhs.args == rhs.args) + ; +} + +std::string convert::id_type::to_pp_string(void) const{ + return str(boost::format( + "conversion ID\n" + " Input markup: %s\n" + " Num inputs: %d\n" + " Output markup: %s\n" + " Num outputs: %d\n" + " Optional args: %s\n" + ) + % this->input_markup + % this->num_inputs + % this->output_markup + % this->num_outputs + % this->args + ); +} /*********************************************************************** * Define types for the function tables @@ -30,56 +59,34 @@ using namespace uhd; struct fcn_table_entry_type{ convert::priority_type prio; convert::function_type fcn; - fcn_table_entry_type(void) - : prio(convert::PRIORITY_EMPTY), fcn(NULL){ - /* NOP */ - } }; -typedef std::vector fcn_table_type; /*********************************************************************** * Setup the table registry **********************************************************************/ -UHD_SINGLETON_FCN(fcn_table_type, get_cpu_to_otw_table); -UHD_SINGLETON_FCN(fcn_table_type, get_otw_to_cpu_table); - -fcn_table_type &get_table(dir_type dir){ - switch(dir){ - case DIR_OTW_TO_CPU: return get_otw_to_cpu_table(); - case DIR_CPU_TO_OTW: return get_cpu_to_otw_table(); - } - UHD_THROW_INVALID_CODE_PATH(); -} +typedef uhd::dict fcn_table_type; +UHD_SINGLETON_FCN(fcn_table_type, get_table); /*********************************************************************** * The registry functions **********************************************************************/ void uhd::convert::register_converter( - const std::string &markup, + const id_type &id, function_type fcn, priority_type prio ){ - //extract the predicate and direction from the markup - dir_type dir; - pred_type pred = make_pred(markup, dir); - //get a reference to the function table - fcn_table_type &table = get_table(dir); - - //resize the table so that its at least pred+1 - if (table.size() <= pred) table.resize(pred+1); + fcn_table_type &table = get_table(); //register the function if higher priority - if (table[pred].prio < prio){ - table[pred].fcn = fcn; - table[pred].prio = prio; + if (not table.has_key(id) or table[id].prio < prio){ + table[id].fcn = fcn; + table[id].prio = prio; } //----------------------------------------------------------------// - UHD_LOGV(always) << "register_converter: " << markup << std::endl + UHD_LOGV(always) << "register_converter: " << id.to_pp_string() << std::endl << " prio: " << prio << std::endl - << " pred: " << pred << std::endl - << " dir: " << dir << std::endl << std::endl ; //----------------------------------------------------------------// @@ -88,22 +95,40 @@ void uhd::convert::register_converter( /*********************************************************************** * The converter functions **********************************************************************/ -const convert::function_type &convert::get_converter_cpu_to_otw( - const io_type_t &io_type, - const otw_type_t &otw_type, - size_t num_input_buffs, - size_t num_output_buffs -){ - pred_type pred = make_pred(io_type, otw_type, num_input_buffs, num_output_buffs); - return get_cpu_to_otw_table().at(pred).fcn; +convert::function_type convert::get_converter(const id_type &id){ + if (get_table().has_key(id)) return get_table()[id].fcn; + throw uhd::key_error("Cannot find a conversion routine for " + id.to_pp_string()); } -const convert::function_type &convert::get_converter_otw_to_cpu( - const io_type_t &io_type, - const otw_type_t &otw_type, - size_t num_input_buffs, - size_t num_output_buffs +/*********************************************************************** + * Mappings for item markup to byte size for all items we can + **********************************************************************/ +typedef uhd::dict item_size_type; +UHD_SINGLETON_FCN(item_size_type, get_item_size_table); + +void register_bytes_per_item( + const std::string &markup, const size_t size ){ - pred_type pred = make_pred(io_type, otw_type, num_input_buffs, num_output_buffs); - return get_otw_to_cpu_table().at(pred).fcn; + get_item_size_table()[markup] = size; +} + +size_t convert::get_bytes_per_item(const std::string &markup){ + if (get_item_size_table().has_key(markup)) return get_item_size_table()[markup]; + throw uhd::key_error("Cannot find an item size " + markup); +} + +UHD_STATIC_BLOCK(convert_register_item_sizes){ + //register standard complex types + get_item_size_table()["fc64"] = sizeof(std::complex); + get_item_size_table()["fc32"] = sizeof(std::complex); + get_item_size_table()["sc32"] = sizeof(std::complex); + get_item_size_table()["sc16"] = sizeof(std::complex); + get_item_size_table()["sc8"] = sizeof(std::complex); + + //register standard real types + get_item_size_table()["f64"] = sizeof(double); + get_item_size_table()["f32"] = sizeof(float); + get_item_size_table()["s32"] = sizeof(boost::int32_t); + get_item_size_table()["s16"] = sizeof(boost::int16_t); + get_item_size_table()["s8"] = sizeof(boost::int8_t); } diff --git a/host/lib/convert/gen_convert_general.py b/host/lib/convert/gen_convert_general.py index 8c3138bda..0d68a4dd3 100644 --- a/host/lib/convert/gen_convert_general.py +++ b/host/lib/convert/gen_convert_general.py @@ -29,26 +29,26 @@ using namespace uhd::convert; """ TMPL_CONV_TO_FROM_ITEM32_1 = """ -DECLARE_CONVERTER(convert_$(cpu_type)_1_to_item32_1_$(swap), PRIORITY_GENERAL){ +DECLARE_CONVERTER($(cpu_type), 1, sc16_item32_$(end), 1, PRIORITY_GENERAL){ const $(cpu_type)_t *input = reinterpret_cast(inputs[0]); item32_t *output = reinterpret_cast(outputs[0]); for (size_t i = 0; i < nsamps; i++){ - output[i] = $(swap_fcn)($(cpu_type)_to_item32(input[i], float(scale_factor))); + output[i] = $(to_wire)($(cpu_type)_to_item32(input[i], float(scale_factor))); } } -DECLARE_CONVERTER(convert_item32_1_to_$(cpu_type)_1_$(swap), PRIORITY_GENERAL){ +DECLARE_CONVERTER(sc16_item32_$(end), 1, $(cpu_type), 1, PRIORITY_GENERAL){ const item32_t *input = reinterpret_cast(inputs[0]); $(cpu_type)_t *output = reinterpret_cast<$(cpu_type)_t *>(outputs[0]); for (size_t i = 0; i < nsamps; i++){ - output[i] = item32_to_$(cpu_type)($(swap_fcn)(input[i]), float(scale_factor)); + output[i] = item32_to_$(cpu_type)($(to_host)(input[i]), float(scale_factor)); } } """ TMPL_CONV_TO_FROM_ITEM32_X = """ -DECLARE_CONVERTER(convert_$(cpu_type)_$(width)_to_item32_1_$(swap), PRIORITY_GENERAL){ +DECLARE_CONVERTER($(cpu_type), $(width), sc16_item32_$(end), 1, PRIORITY_GENERAL){ #for $w in range($width) const $(cpu_type)_t *input$(w) = reinterpret_cast(inputs[$(w)]); #end for @@ -56,12 +56,12 @@ DECLARE_CONVERTER(convert_$(cpu_type)_$(width)_to_item32_1_$(swap), PRIORITY_GEN for (size_t i = 0, j = 0; i < nsamps; i++){ #for $w in range($width) - output[j++] = $(swap_fcn)($(cpu_type)_to_item32(input$(w)[i], float(scale_factor))); + output[j++] = $(to_wire)($(cpu_type)_to_item32(input$(w)[i], float(scale_factor))); #end for } } -DECLARE_CONVERTER(convert_item32_1_to_$(cpu_type)_$(width)_$(swap), PRIORITY_GENERAL){ +DECLARE_CONVERTER(sc16_item32_$(end), 1, $(cpu_type), $(width), PRIORITY_GENERAL){ const item32_t *input = reinterpret_cast(inputs[0]); #for $w in range($width) $(cpu_type)_t *output$(w) = reinterpret_cast<$(cpu_type)_t *>(outputs[$(w)]); @@ -69,7 +69,7 @@ DECLARE_CONVERTER(convert_item32_1_to_$(cpu_type)_$(width)_$(swap), PRIORITY_GEN for (size_t i = 0, j = 0; i < nsamps; i++){ #for $w in range($width) - output$(w)[i] = item32_to_$(cpu_type)($(swap_fcn)(input[j++]), float(scale_factor)); + output$(w)[i] = item32_to_$(cpu_type)($(to_host)(input[j++]), float(scale_factor)); #end for } } @@ -84,10 +84,13 @@ if __name__ == '__main__': file = os.path.basename(__file__) output = parse_tmpl(TMPL_HEADER, file=file) for width in 1, 2, 3, 4: - for swap, swap_fcn in (('nswap', ''), ('bswap', 'uhd::byteswap')): + for end, to_host, to_wire in ( + ('be', 'uhd::ntohx', 'uhd::htonx'), + ('le', 'uhd::wtohx', 'uhd::htowx'), + ): for cpu_type in 'fc64', 'fc32', 'sc16': output += parse_tmpl( TMPL_CONV_TO_FROM_ITEM32_1 if width == 1 else TMPL_CONV_TO_FROM_ITEM32_X, - width=width, swap=swap, swap_fcn=swap_fcn, cpu_type=cpu_type + width=width, end=end, to_host=to_host, to_wire=to_wire, cpu_type=cpu_type ) open(sys.argv[1], 'w').write(output) diff --git a/host/lib/convert/gen_convert_pred.py b/host/lib/convert/gen_convert_pred.py deleted file mode 100644 index 360fbcf44..000000000 --- a/host/lib/convert/gen_convert_pred.py +++ /dev/null @@ -1,185 +0,0 @@ -#!/usr/bin/env python -# -# 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 . -# - -TMPL_TEXT = """ -#import time -/*********************************************************************** - * This file was generated by $file on $time.strftime("%c") - **********************************************************************/ -\#include -\#include -\#include -\#include -\#include -\#include -\#include - -typedef size_t pred_type; -typedef std::vector pred_vector_type; - -enum dir_type{ - DIR_OTW_TO_CPU = 0, - DIR_CPU_TO_OTW = 1 -}; - -struct pred_error : uhd::value_error{ - pred_error(const std::string &what): - uhd::value_error("convert::make_pred: " + what) - { - /* NOP */ - } -}; - -pred_type make_pred(const std::string &markup, dir_type &dir){ - pred_type pred = 0; - - try{ - boost::tokenizer > tokenizer(markup, boost::char_separator("_")); - std::vector tokens(tokenizer.begin(), tokenizer.end()); - //token 0 is - std::string inp_type = tokens.at(1); - std::string num_inps = tokens.at(2); - //token 3 is - std::string out_type = tokens.at(4); - std::string num_outs = tokens.at(5); - std::string swap_type = tokens.at(6); - - std::string cpu_type, otw_type; - if (inp_type.find("item") == std::string::npos){ - cpu_type = inp_type; - otw_type = out_type; - dir = DIR_CPU_TO_OTW; - } - else{ - cpu_type = out_type; - otw_type = inp_type; - dir = DIR_OTW_TO_CPU; - } - - if (cpu_type == "fc64") pred |= $ph.fc64_p; - else if (cpu_type == "fc32") pred |= $ph.fc32_p; - else if (cpu_type == "sc16") pred |= $ph.sc16_p; - else if (cpu_type == "sc8") pred |= $ph.sc8_p; - else throw pred_error("unhandled io type " + cpu_type); - - if (otw_type == "item32") pred |= $ph.item32_p; - else throw pred_error("unhandled otw type " + otw_type); - - int num_inputs = boost::lexical_cast(num_inps); - int num_outputs = boost::lexical_cast(num_outs); - - switch(num_inputs*num_outputs){ //FIXME treated as one value - case 1: pred |= $ph.chan1_p; break; - case 2: pred |= $ph.chan2_p; break; - case 3: pred |= $ph.chan3_p; break; - case 4: pred |= $ph.chan4_p; break; - default: throw pred_error("unhandled number of channels"); - } - - if (swap_type == "bswap") pred |= $ph.bswap_p; - else if (swap_type == "nswap") pred |= $ph.nswap_p; - else throw pred_error("unhandled swap type"); - - } - catch(...){ - throw pred_error("could not parse markup: " + markup); - } - - return pred; -} - -#define pred_table_wildcard pred_type(~0) -#define pred_table_max_size size_t(128) -#define pred_table_index(e) (pred_type(e) & 0x7f) - -static pred_vector_type get_pred_byte_order_table(void){ - pred_vector_type table(pred_table_max_size, pred_table_wildcard); - \#ifdef BOOST_BIG_ENDIAN - table[pred_table_index(otw_type_t::BO_BIG_ENDIAN)] = $ph.nswap_p; - table[pred_table_index(otw_type_t::BO_LITTLE_ENDIAN)] = $ph.bswap_p; - \#else - table[pred_table_index(otw_type_t::BO_BIG_ENDIAN)] = $ph.bswap_p; - table[pred_table_index(otw_type_t::BO_LITTLE_ENDIAN)] = $ph.nswap_p; - \#endif - table[pred_table_index(otw_type_t::BO_NATIVE)] = $ph.nswap_p; - return table; -} - -static pred_vector_type get_pred_io_type_table(void){ - pred_vector_type table(pred_table_max_size, pred_table_wildcard); - table[pred_table_index(io_type_t::COMPLEX_FLOAT64)] = $ph.fc64_p; - table[pred_table_index(io_type_t::COMPLEX_FLOAT32)] = $ph.fc32_p; - table[pred_table_index(io_type_t::COMPLEX_INT16)] = $ph.sc16_p; - return table; -} - -static pred_vector_type get_pred_num_io_table(void){ - pred_vector_type table(pred_table_max_size, pred_table_wildcard); - table[1] = $ph.chan1_p; - table[2] = $ph.chan2_p; - table[3] = $ph.chan3_p; - table[4] = $ph.chan4_p; - return table; -} - -UHD_INLINE pred_type make_pred( - const io_type_t &io_type, - const otw_type_t &otw_type, - size_t num_inputs, - size_t num_outputs -){ - pred_type pred = $ph.item32_p; //only item32 supported as of now - - static const pred_vector_type pred_byte_order_table(get_pred_byte_order_table()); - pred |= pred_byte_order_table[pred_table_index(otw_type.byteorder)]; - - static const pred_vector_type pred_io_type_table(get_pred_io_type_table()); - pred |= pred_io_type_table[pred_table_index(io_type.tid)]; - - static const pred_vector_type pred_num_io_table(get_pred_num_io_table()); - pred |= pred_num_io_table[pred_table_index(num_inputs*num_outputs)]; - - if (pred == pred_table_wildcard) throw pred_error( - "unhanded input combination for make_pred()" - ); - - return pred; -} -""" - -def parse_tmpl(_tmpl_text, **kwargs): - from Cheetah.Template import Template - return str(Template(_tmpl_text, kwargs)) - -class ph: - bswap_p = 0b00001 - nswap_p = 0b00000 - item32_p = 0b00000 - sc8_p = 0b00000 - sc16_p = 0b00010 - fc32_p = 0b00100 - fc64_p = 0b00110 - chan1_p = 0b00000 - chan2_p = 0b01000 - chan3_p = 0b10000 - chan4_p = 0b11000 - -if __name__ == '__main__': - import sys, os - file = os.path.basename(__file__) - open(sys.argv[1], 'w').write(parse_tmpl(TMPL_TEXT, file=file, ph=ph)) -- cgit v1.2.3 From 839b9379d436adc1a6b0f876d0d03f11e41dbee6 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Mon, 3 Oct 2011 17:07:45 -0700 Subject: convert: restored unit test functionality --- host/tests/CMakeLists.txt | 4 +- host/tests/convert_test.cpp | 148 +++++++++++++++++++++++--------------------- 2 files changed, 80 insertions(+), 72 deletions(-) (limited to 'host') diff --git a/host/tests/CMakeLists.txt b/host/tests/CMakeLists.txt index 28cc1c5da..25679a33e 100644 --- a/host/tests/CMakeLists.txt +++ b/host/tests/CMakeLists.txt @@ -29,8 +29,8 @@ SET(test_sources msg_test.cpp property_test.cpp ranges_test.cpp - sph_recv_test.cpp - sph_send_test.cpp + #TODO restore sph_recv_test.cpp + #TODO restore sph_send_test.cpp subdev_spec_test.cpp time_spec_test.cpp vrt_test.cpp diff --git a/host/tests/convert_test.cpp b/host/tests/convert_test.cpp index d828ed64a..9dabcf54e 100644 --- a/host/tests/convert_test.cpp +++ b/host/tests/convert_test.cpp @@ -41,8 +41,8 @@ typedef std::complex fc64_t; **********************************************************************/ template static void loopback( size_t nsamps, - const io_type_t &io_type, - const otw_type_t &otw_type, + convert::id_type &in_id, + convert::id_type &out_id, const Range &input, Range &output ){ @@ -53,23 +53,17 @@ template static void loopback( std::vector output0(1, &interm[0]), output1(1, &output[0]); //convert to intermediate type - convert::get_converter_cpu_to_otw( - io_type, otw_type, input0.size(), output0.size() - )(input0, output0, nsamps, 32767.); + convert::get_converter(in_id)(input0, output0, nsamps, 32767.); //convert back to host type - convert::get_converter_otw_to_cpu( - io_type, otw_type, input1.size(), output1.size() - )(input1, output1, nsamps, 1/32767.); + convert::get_converter(out_id)(input1, output1, nsamps, 1/32767.); } /*********************************************************************** * Test short conversion **********************************************************************/ static void test_convert_types_sc16( - size_t nsamps, - const io_type_t &io_type, - const otw_type_t &otw_type + size_t nsamps, convert::id_type &id ){ //fill the input samples std::vector input(nsamps), output(nsamps); @@ -79,31 +73,37 @@ static void test_convert_types_sc16( ); //run the loopback and test - loopback(nsamps, io_type, otw_type, input, output); + convert::id_type in_id = id; + convert::id_type out_id = id; + std::swap(out_id.input_markup, out_id.output_markup); + std::swap(out_id.num_inputs, out_id.num_outputs); + loopback(nsamps, in_id, out_id, input, output); BOOST_CHECK_EQUAL_COLLECTIONS(input.begin(), input.end(), output.begin(), output.end()); } BOOST_AUTO_TEST_CASE(test_convert_types_be_sc16){ - io_type_t io_type(io_type_t::COMPLEX_INT16); - otw_type_t otw_type; - otw_type.byteorder = otw_type_t::BO_BIG_ENDIAN; - otw_type.width = 16; + convert::id_type id; + id.input_markup = "sc16"; + id.num_inputs = 1; + id.output_markup = "sc16_item32_be"; + id.num_outputs = 1; //try various lengths to test edge cases for (size_t nsamps = 1; nsamps < 16; nsamps++){ - test_convert_types_sc16(nsamps, io_type, otw_type); + test_convert_types_sc16(nsamps, id); } } BOOST_AUTO_TEST_CASE(test_convert_types_le_sc16){ - io_type_t io_type(io_type_t::COMPLEX_INT16); - otw_type_t otw_type; - otw_type.byteorder = otw_type_t::BO_LITTLE_ENDIAN; - otw_type.width = 16; + convert::id_type id; + id.input_markup = "sc16"; + id.num_inputs = 1; + id.output_markup = "sc16_item32_le"; + id.num_outputs = 1; //try various lengths to test edge cases for (size_t nsamps = 1; nsamps < 16; nsamps++){ - test_convert_types_sc16(nsamps, io_type, otw_type); + test_convert_types_sc16(nsamps, id); } } @@ -112,9 +112,7 @@ BOOST_AUTO_TEST_CASE(test_convert_types_le_sc16){ **********************************************************************/ template static void test_convert_types_for_floats( - size_t nsamps, - const io_type_t &io_type, - const otw_type_t &otw_type + size_t nsamps, convert::id_type &id ){ typedef typename data_type::value_type value_type; @@ -126,7 +124,11 @@ static void test_convert_types_for_floats( ); //run the loopback and test - loopback(nsamps, io_type, otw_type, input, output); + convert::id_type in_id = id; + convert::id_type out_id = id; + std::swap(out_id.input_markup, out_id.output_markup); + std::swap(out_id.num_inputs, out_id.num_outputs); + loopback(nsamps, in_id, out_id, input, output); for (size_t i = 0; i < nsamps; i++){ MY_CHECK_CLOSE(input[i].real(), output[i].real(), value_type(0.01)); MY_CHECK_CLOSE(input[i].imag(), output[i].imag(), value_type(0.01)); @@ -134,50 +136,54 @@ static void test_convert_types_for_floats( } BOOST_AUTO_TEST_CASE(test_convert_types_be_fc32){ - io_type_t io_type(io_type_t::COMPLEX_FLOAT32); - otw_type_t otw_type; - otw_type.byteorder = otw_type_t::BO_BIG_ENDIAN; - otw_type.width = 16; + convert::id_type id; + id.input_markup = "fc32"; + id.num_inputs = 1; + id.output_markup = "sc16_item32_be"; + id.num_outputs = 1; //try various lengths to test edge cases for (size_t nsamps = 1; nsamps < 16; nsamps++){ - test_convert_types_for_floats(nsamps, io_type, otw_type); + test_convert_types_for_floats(nsamps, id); } } BOOST_AUTO_TEST_CASE(test_convert_types_le_fc32){ - io_type_t io_type(io_type_t::COMPLEX_FLOAT32); - otw_type_t otw_type; - otw_type.byteorder = otw_type_t::BO_LITTLE_ENDIAN; - otw_type.width = 16; + convert::id_type id; + id.input_markup = "fc32"; + id.num_inputs = 1; + id.output_markup = "sc16_item32_le"; + id.num_outputs = 1; //try various lengths to test edge cases for (size_t nsamps = 1; nsamps < 16; nsamps++){ - test_convert_types_for_floats(nsamps, io_type, otw_type); + test_convert_types_for_floats(nsamps, id); } } BOOST_AUTO_TEST_CASE(test_convert_types_be_fc64){ - io_type_t io_type(io_type_t::COMPLEX_FLOAT64); - otw_type_t otw_type; - otw_type.byteorder = otw_type_t::BO_BIG_ENDIAN; - otw_type.width = 16; + convert::id_type id; + id.input_markup = "fc64"; + id.num_inputs = 1; + id.output_markup = "sc16_item32_be"; + id.num_outputs = 1; //try various lengths to test edge cases for (size_t nsamps = 1; nsamps < 16; nsamps++){ - test_convert_types_for_floats(nsamps, io_type, otw_type); + test_convert_types_for_floats(nsamps, id); } } BOOST_AUTO_TEST_CASE(test_convert_types_le_fc64){ - io_type_t io_type(io_type_t::COMPLEX_FLOAT64); - otw_type_t otw_type; - otw_type.byteorder = otw_type_t::BO_LITTLE_ENDIAN; - otw_type.width = 16; + convert::id_type id; + id.input_markup = "fc64"; + id.num_inputs = 1; + id.output_markup = "sc16_item32_le"; + id.num_outputs = 1; //try various lengths to test edge cases for (size_t nsamps = 1; nsamps < 16; nsamps++){ - test_convert_types_for_floats(nsamps, io_type, otw_type); + test_convert_types_for_floats(nsamps, id); } } @@ -185,12 +191,17 @@ BOOST_AUTO_TEST_CASE(test_convert_types_le_fc64){ * Test float to short conversion loopback **********************************************************************/ BOOST_AUTO_TEST_CASE(test_convert_types_fc32_to_sc16){ - io_type_t io_type_in(io_type_t::COMPLEX_FLOAT32); - io_type_t io_type_out(io_type_t::COMPLEX_INT16); - - otw_type_t otw_type; - otw_type.byteorder = otw_type_t::BO_NATIVE; - otw_type.width = 16; + convert::id_type in_id; + in_id.input_markup = "fc32"; + in_id.num_inputs = 1; + in_id.output_markup = "sc16_item32_le"; + in_id.num_outputs = 1; + + convert::id_type out_id; + out_id.input_markup = "sc16_item32_le"; + out_id.num_inputs = 1; + out_id.output_markup = "sc16"; + out_id.num_outputs = 1; const size_t nsamps = 13; std::vector input(nsamps); @@ -205,14 +216,10 @@ BOOST_AUTO_TEST_CASE(test_convert_types_fc32_to_sc16){ std::vector output0(1, &interm[0]), output1(1, &output[0]); //convert float to intermediate - convert::get_converter_cpu_to_otw( - io_type_in, otw_type, input0.size(), output0.size() - )(input0, output0, nsamps, 32767.); + convert::get_converter(in_id)(input0, output0, nsamps, 32767.); //convert intermediate to short - convert::get_converter_otw_to_cpu( - io_type_out, otw_type, input1.size(), output1.size() - )(input1, output1, nsamps, 1/32767.); + convert::get_converter(out_id)(input1, output1, nsamps, 1/32767.); //test that the inputs and outputs match for (size_t i = 0; i < nsamps; i++){ @@ -225,12 +232,17 @@ BOOST_AUTO_TEST_CASE(test_convert_types_fc32_to_sc16){ * Test short to float conversion loopback **********************************************************************/ BOOST_AUTO_TEST_CASE(test_convert_types_sc16_to_fc32){ - io_type_t io_type_in(io_type_t::COMPLEX_INT16); - io_type_t io_type_out(io_type_t::COMPLEX_FLOAT32); - - otw_type_t otw_type; - otw_type.byteorder = otw_type_t::BO_NATIVE; - otw_type.width = 16; + convert::id_type in_id; + in_id.input_markup = "sc16"; + in_id.num_inputs = 1; + in_id.output_markup = "sc16_item32_le"; + in_id.num_outputs = 1; + + convert::id_type out_id; + out_id.input_markup = "sc16_item32_le"; + out_id.num_inputs = 1; + out_id.output_markup = "fc32"; + out_id.num_outputs = 1; const size_t nsamps = 13; std::vector input(nsamps); @@ -245,14 +257,10 @@ BOOST_AUTO_TEST_CASE(test_convert_types_sc16_to_fc32){ std::vector output0(1, &interm[0]), output1(1, &output[0]); //convert short to intermediate - convert::get_converter_cpu_to_otw( - io_type_in, otw_type, input0.size(), output0.size() - )(input0, output0, nsamps, 32767.); + convert::get_converter(in_id)(input0, output0, nsamps, 32767.); //convert intermediate to float - convert::get_converter_otw_to_cpu( - io_type_out, otw_type, input1.size(), output1.size() - )(input1, output1, nsamps, 1/32767.); + convert::get_converter(out_id)(input1, output1, nsamps, 1/32767.); //test that the inputs and outputs match for (size_t i = 0; i < nsamps; i++){ -- cgit v1.2.3 From 6c13ef7855dcfe9c825e819f69f219851387da25 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Mon, 3 Oct 2011 18:11:21 -0700 Subject: uhd: created backwards compatible send/recv implementation --- host/include/uhd/CMakeLists.txt | 1 + host/include/uhd/device.hpp | 118 ++------------------- host/include/uhd/device_deprecated.ipp | 181 +++++++++++++++++++++++++++++++++ host/include/uhd/streamer.hpp | 14 +-- 4 files changed, 197 insertions(+), 117 deletions(-) create mode 100644 host/include/uhd/device_deprecated.ipp (limited to 'host') diff --git a/host/include/uhd/CMakeLists.txt b/host/include/uhd/CMakeLists.txt index 08483346c..6b277654d 100644 --- a/host/include/uhd/CMakeLists.txt +++ b/host/include/uhd/CMakeLists.txt @@ -26,6 +26,7 @@ INSTALL(FILES convert.hpp deprecated.hpp device.hpp + device_deprecated.ipp exception.hpp property_tree.ipp property_tree.hpp diff --git a/host/include/uhd/device.hpp b/host/include/uhd/device.hpp index 0ea5259b5..47afe7dc6 100644 --- a/host/include/uhd/device.hpp +++ b/host/include/uhd/device.hpp @@ -19,10 +19,9 @@ #define INCLUDED_UHD_DEVICE_HPP #include +#include #include #include -#include -#include #include #include #include @@ -77,116 +76,11 @@ public: */ static sptr make(const device_addr_t &hint, size_t which = 0); - /*! - * Send modes for the device send routine. - */ - enum send_mode_t{ - //! Tells the send routine to send the entire buffer - SEND_MODE_FULL_BUFF = 0, - //! Tells the send routine to return after one packet - SEND_MODE_ONE_PACKET = 1 - }; - - /*! - * Recv modes for the device recv routine. - */ - enum recv_mode_t{ - //! Tells the recv routine to recv the entire buffer - RECV_MODE_FULL_BUFF = 0, - //! Tells the recv routine to return after one packet - RECV_MODE_ONE_PACKET = 1 - }; - - //! Typedef for a pointer to a single, or a collection of send buffers - typedef ref_vector send_buffs_type; - - //! Typedef for a pointer to a single, or a collection of recv buffers - typedef ref_vector recv_buffs_type; - - /*! - * Send buffers containing IF data described by the metadata. - * - * Send handles fragmentation as follows: - * If the buffer has more samples than the maximum per packet, - * the send method will fragment the samples across several packets. - * Send will respect the burst flags when fragmenting to ensure - * that start of burst can only be set on the first fragment and - * that end of burst can only be set on the final fragment. - * Fragmentation only applies in the full buffer send mode. - * - * This is a blocking call and will not return until the number - * of samples returned have been read out of each buffer. - * Under a timeout condition, the number of samples returned - * may be less than the number of samples specified. - * - * \param buffs a vector of read-only memory containing IF data - * \param nsamps_per_buff the number of samples to send, per buffer - * \param metadata data describing the buffer's contents - * \param io_type the type of data loaded in the buffer - * \param send_mode tells send how to unload the buffer - * \param timeout the timeout in seconds to wait on a packet - * \return the number of samples sent - */ - virtual size_t send( - const send_buffs_type &buffs, - size_t nsamps_per_buff, - const tx_metadata_t &metadata, - const io_type_t &io_type, - send_mode_t send_mode, - double timeout = 0.1 - ) = 0; + //! Make a new receive streamer given the list of channels + virtual recv_streamer::sptr get_recv_streamer(const std::vector &channels) = 0; - /*! - * Receive buffers containing IF data described by the metadata. - * - * Receive handles fragmentation as follows: - * If the buffer has insufficient space to hold all samples - * that were received in a single packet over-the-wire, - * then the buffer will be completely filled and the implementation - * will hold a pointer into the remaining portion of the packet. - * Subsequent calls will load from the remainder of the packet, - * and will flag the metadata to show that this is a fragment. - * The next call to receive, after the remainder becomes exahausted, - * will perform an over-the-wire receive as usual. - * See the rx metadata fragment flags and offset fields for details. - * - * This is a blocking call and will not return until the number - * of samples returned have been written into each buffer. - * Under a timeout condition, the number of samples returned - * may be less than the number of samples specified. - * - * When using the full buffer recv mode, the metadata only applies - * to the first packet received and written into the recv buffers. - * Use the one packet recv mode to get per packet metadata. - * - * \param buffs a vector of writable memory to fill with IF data - * \param nsamps_per_buff the size of each buffer in number of samples - * \param metadata data to fill describing the buffer - * \param io_type the type of data to fill into the buffer - * \param recv_mode tells recv how to load the buffer - * \param timeout the timeout in seconds to wait for a packet - * \return the number of samples received or 0 on error - */ - virtual size_t recv( - const recv_buffs_type &buffs, - size_t nsamps_per_buff, - rx_metadata_t &metadata, - const io_type_t &io_type, - recv_mode_t recv_mode, - double timeout = 0.1 - ) = 0; - - /*! - * Get the maximum number of samples per packet on send. - * \return the number of samples - */ - virtual size_t get_max_send_samps_per_packet(void) const = 0; - - /*! - * Get the maximum number of samples per packet on recv. - * \return the number of samples - */ - virtual size_t get_max_recv_samps_per_packet(void) const = 0; + //! Make a new transmit streamer given the list of channels + virtual send_streamer::sptr get_send_streamer(const std::vector &channels) = 0; /*! * Receive and asynchronous message from the device. @@ -201,6 +95,8 @@ public: //! Get access to the underlying property structure virtual boost::shared_ptr get_tree(void) const = 0; + #include + }; } //namespace uhd diff --git a/host/include/uhd/device_deprecated.ipp b/host/include/uhd/device_deprecated.ipp new file mode 100644 index 000000000..4b8ec0037 --- /dev/null +++ b/host/include/uhd/device_deprecated.ipp @@ -0,0 +1,181 @@ +// +// 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 . +// + +//this file is included inside device class +//it supports the old send/recv functions +//this was replaced by the streamer API + +/*! + * Send modes for the device send routine. + */ +enum send_mode_t{ + //! Tells the send routine to send the entire buffer + SEND_MODE_FULL_BUFF = 0, + //! Tells the send routine to return after one packet + SEND_MODE_ONE_PACKET = 1 +}; + +/*! + * Recv modes for the device recv routine. + */ +enum recv_mode_t{ + //! Tells the recv routine to recv the entire buffer + RECV_MODE_FULL_BUFF = 0, + //! Tells the recv routine to return after one packet + RECV_MODE_ONE_PACKET = 1 +}; + +//! Typedef for a pointer to a single, or a collection of send buffers +typedef ref_vector send_buffs_type; + +//! Typedef for a pointer to a single, or a collection of recv buffers +typedef ref_vector recv_buffs_type; + +/*! + * Send buffers containing IF data described by the metadata. + * + * Send handles fragmentation as follows: + * If the buffer has more samples than the maximum per packet, + * the send method will fragment the samples across several packets. + * Send will respect the burst flags when fragmenting to ensure + * that start of burst can only be set on the first fragment and + * that end of burst can only be set on the final fragment. + * Fragmentation only applies in the full buffer send mode. + * + * This is a blocking call and will not return until the number + * of samples returned have been read out of each buffer. + * Under a timeout condition, the number of samples returned + * may be less than the number of samples specified. + * + * \param buffs a vector of read-only memory containing IF data + * \param nsamps_per_buff the number of samples to send, per buffer + * \param metadata data describing the buffer's contents + * \param io_type the type of data loaded in the buffer + * \param send_mode tells send how to unload the buffer + * \param timeout the timeout in seconds to wait on a packet + * \return the number of samples sent + */ +size_t send( + const send_buffs_type &buffs, + size_t nsamps_per_buff, + const tx_metadata_t &metadata, + const io_type_t &io_type, + send_mode_t send_mode, + double timeout = 0.1 +){ + if (_send_streamer.get() == NULL or _send_streamer->get_num_channels() != buffs.size()){ + std::vector chans(buffs.size()); + for (size_t ch = 0; ch < chans.size(); ch++) chans[ch] = ch; + _send_streamer.reset(); //cleanup possible old one + _send_streamer = get_send_streamer(chans); + _send_tid = io_type_t::CUSTOM_TYPE; + } + if (io_type.tid != _send_tid){ + _send_tid = io_type.tid; + _send_streamer->set_format((_send_tid == io_type_t::COMPLEX_FLOAT32)? "fc32" : "sc16", "sc16"); + } + const size_t nsamps = (send_mode == SEND_MODE_ONE_PACKET)? + std::min(nsamps_per_buff, get_max_send_samps_per_packet()) : + nsamps_per_buff; + return _send_streamer->send(buffs, nsamps, metadata, timeout); +} + +/*! + * Receive buffers containing IF data described by the metadata. + * + * Receive handles fragmentation as follows: + * If the buffer has insufficient space to hold all samples + * that were received in a single packet over-the-wire, + * then the buffer will be completely filled and the implementation + * will hold a pointer into the remaining portion of the packet. + * Subsequent calls will load from the remainder of the packet, + * and will flag the metadata to show that this is a fragment. + * The next call to receive, after the remainder becomes exahausted, + * will perform an over-the-wire receive as usual. + * See the rx metadata fragment flags and offset fields for details. + * + * This is a blocking call and will not return until the number + * of samples returned have been written into each buffer. + * Under a timeout condition, the number of samples returned + * may be less than the number of samples specified. + * + * When using the full buffer recv mode, the metadata only applies + * to the first packet received and written into the recv buffers. + * Use the one packet recv mode to get per packet metadata. + * + * \param buffs a vector of writable memory to fill with IF data + * \param nsamps_per_buff the size of each buffer in number of samples + * \param metadata data to fill describing the buffer + * \param io_type the type of data to fill into the buffer + * \param recv_mode tells recv how to load the buffer + * \param timeout the timeout in seconds to wait for a packet + * \return the number of samples received or 0 on error + */ +size_t recv( + const recv_buffs_type &buffs, + size_t nsamps_per_buff, + rx_metadata_t &metadata, + const io_type_t &io_type, + recv_mode_t recv_mode, + double timeout = 0.1 +){ + if (_recv_streamer.get() == NULL or _recv_streamer->get_num_channels() != buffs.size()){ + std::vector chans(buffs.size()); + for (size_t ch = 0; ch < chans.size(); ch++) chans[ch] = ch; + _recv_streamer.reset(); //cleanup possible old one + _recv_streamer = get_recv_streamer(chans); + _recv_tid = io_type_t::CUSTOM_TYPE; + } + if (io_type.tid != _recv_tid){ + _recv_tid = io_type.tid; + _recv_streamer->set_format((_recv_tid == io_type_t::COMPLEX_FLOAT32)? "fc32" : "sc16", "sc16"); + } + const size_t nsamps = (recv_mode == RECV_MODE_ONE_PACKET)? + std::min(nsamps_per_buff, get_max_recv_samps_per_packet()) : + nsamps_per_buff; + return _recv_streamer->recv(buffs, nsamps, metadata, timeout); +} + +/*! + * Get the maximum number of samples per packet on send. + * \return the number of samples + */ +size_t get_max_send_samps_per_packet(void){ + if (_send_streamer.get() == NULL){ + std::vector chans(1, 0); + _send_streamer = get_send_streamer(chans); + } + return _send_streamer->get_items_per_packet(); +} + +/*! + * Get the maximum number of samples per packet on recv. + * \return the number of samples + */ +size_t get_max_recv_samps_per_packet(void){ + if (_recv_streamer.get() == NULL){ + std::vector chans(1, 0); + _recv_streamer = get_recv_streamer(chans); + } + return _recv_streamer->get_items_per_packet(); +} + +private: + recv_streamer::sptr _recv_streamer; + io_type_t::tid_t _recv_tid; + send_streamer::sptr _send_streamer; + io_type_t::tid_t _send_tid; diff --git a/host/include/uhd/streamer.hpp b/host/include/uhd/streamer.hpp index eed18e773..dfbe15ec3 100644 --- a/host/include/uhd/streamer.hpp +++ b/host/include/uhd/streamer.hpp @@ -19,6 +19,8 @@ #define INCLUDED_UHD_STREAMER_HPP #include +#include +#include #include #include #include @@ -87,10 +89,10 @@ public: }; -//! A RX streamer to receive host samples -class UHD_API rx_streamer : public streamer{ +//! A receive streamer to receive host samples +class UHD_API recv_streamer : public streamer{ public: - typedef boost::shared_ptr sptr; + typedef boost::shared_ptr sptr; //! Typedef for a pointer to a single, or a collection of recv buffers typedef ref_vector recv_buffs_type; @@ -128,10 +130,10 @@ public: ) = 0; }; -//! A TX streamer to transmit host samples -class UHD_API rx_streamer : public streamer{ +//! A transmit streamer to send host samples +class UHD_API send_streamer : public streamer{ public: - typedef boost::shared_ptr sptr; + typedef boost::shared_ptr sptr; //! Typedef for a pointer to a single, or a collection of send buffers typedef ref_vector send_buffs_type; -- cgit v1.2.3 From abed04b3c6d70c260d8725831b8aa6e944f52749 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Tue, 4 Oct 2011 09:56:11 -0700 Subject: uhd: restored super packet handler functionality --- host/include/uhd/device.hpp | 4 +- host/include/uhd/device_deprecated.ipp | 36 ++--- host/include/uhd/streamer.hpp | 16 +-- host/lib/convert/convert_impl.cpp | 10 ++ host/lib/transport/super_recv_packet_handler.hpp | 99 +++++--------- host/lib/transport/super_send_packet_handler.hpp | 121 ++++++----------- host/tests/CMakeLists.txt | 4 +- host/tests/sph_recv_test.cpp | 166 ++++++++++------------- host/tests/sph_send_test.cpp | 44 +++--- 9 files changed, 212 insertions(+), 288 deletions(-) (limited to 'host') diff --git a/host/include/uhd/device.hpp b/host/include/uhd/device.hpp index 47afe7dc6..f76739907 100644 --- a/host/include/uhd/device.hpp +++ b/host/include/uhd/device.hpp @@ -77,10 +77,10 @@ public: static sptr make(const device_addr_t &hint, size_t which = 0); //! Make a new receive streamer given the list of channels - virtual recv_streamer::sptr get_recv_streamer(const std::vector &channels) = 0; + virtual rx_streamer::sptr get_rx_streamer(const std::vector &channels) = 0; //! Make a new transmit streamer given the list of channels - virtual send_streamer::sptr get_send_streamer(const std::vector &channels) = 0; + virtual tx_streamer::sptr get_tx_streamer(const std::vector &channels) = 0; /*! * Receive and asynchronous message from the device. diff --git a/host/include/uhd/device_deprecated.ipp b/host/include/uhd/device_deprecated.ipp index 4b8ec0037..ba0edb1bc 100644 --- a/host/include/uhd/device_deprecated.ipp +++ b/host/include/uhd/device_deprecated.ipp @@ -77,21 +77,21 @@ size_t send( send_mode_t send_mode, double timeout = 0.1 ){ - if (_send_streamer.get() == NULL or _send_streamer->get_num_channels() != buffs.size()){ + if (_tx_streamer.get() == NULL or _tx_streamer->get_num_channels() != buffs.size()){ std::vector chans(buffs.size()); for (size_t ch = 0; ch < chans.size(); ch++) chans[ch] = ch; - _send_streamer.reset(); //cleanup possible old one - _send_streamer = get_send_streamer(chans); + _tx_streamer.reset(); //cleanup possible old one + _tx_streamer = get_tx_streamer(chans); _send_tid = io_type_t::CUSTOM_TYPE; } if (io_type.tid != _send_tid){ _send_tid = io_type.tid; - _send_streamer->set_format((_send_tid == io_type_t::COMPLEX_FLOAT32)? "fc32" : "sc16", "sc16"); + _tx_streamer->set_format((_send_tid == io_type_t::COMPLEX_FLOAT32)? "fc32" : "sc16", "sc16"); } const size_t nsamps = (send_mode == SEND_MODE_ONE_PACKET)? std::min(nsamps_per_buff, get_max_send_samps_per_packet()) : nsamps_per_buff; - return _send_streamer->send(buffs, nsamps, metadata, timeout); + return _tx_streamer->send(buffs, nsamps, metadata, timeout); } /*! @@ -133,21 +133,21 @@ size_t recv( recv_mode_t recv_mode, double timeout = 0.1 ){ - if (_recv_streamer.get() == NULL or _recv_streamer->get_num_channels() != buffs.size()){ + if (_rx_streamer.get() == NULL or _rx_streamer->get_num_channels() != buffs.size()){ std::vector chans(buffs.size()); for (size_t ch = 0; ch < chans.size(); ch++) chans[ch] = ch; - _recv_streamer.reset(); //cleanup possible old one - _recv_streamer = get_recv_streamer(chans); + _rx_streamer.reset(); //cleanup possible old one + _rx_streamer = get_rx_streamer(chans); _recv_tid = io_type_t::CUSTOM_TYPE; } if (io_type.tid != _recv_tid){ _recv_tid = io_type.tid; - _recv_streamer->set_format((_recv_tid == io_type_t::COMPLEX_FLOAT32)? "fc32" : "sc16", "sc16"); + _rx_streamer->set_format((_recv_tid == io_type_t::COMPLEX_FLOAT32)? "fc32" : "sc16", "sc16"); } const size_t nsamps = (recv_mode == RECV_MODE_ONE_PACKET)? std::min(nsamps_per_buff, get_max_recv_samps_per_packet()) : nsamps_per_buff; - return _recv_streamer->recv(buffs, nsamps, metadata, timeout); + return _rx_streamer->recv(buffs, nsamps, metadata, timeout); } /*! @@ -155,11 +155,11 @@ size_t recv( * \return the number of samples */ size_t get_max_send_samps_per_packet(void){ - if (_send_streamer.get() == NULL){ + if (_tx_streamer.get() == NULL){ std::vector chans(1, 0); - _send_streamer = get_send_streamer(chans); + _tx_streamer = get_tx_streamer(chans); } - return _send_streamer->get_items_per_packet(); + return _tx_streamer->get_items_per_packet(); } /*! @@ -167,15 +167,15 @@ size_t get_max_send_samps_per_packet(void){ * \return the number of samples */ size_t get_max_recv_samps_per_packet(void){ - if (_recv_streamer.get() == NULL){ + if (_rx_streamer.get() == NULL){ std::vector chans(1, 0); - _recv_streamer = get_recv_streamer(chans); + _rx_streamer = get_rx_streamer(chans); } - return _recv_streamer->get_items_per_packet(); + return _rx_streamer->get_items_per_packet(); } private: - recv_streamer::sptr _recv_streamer; + rx_streamer::sptr _rx_streamer; io_type_t::tid_t _recv_tid; - send_streamer::sptr _send_streamer; + tx_streamer::sptr _tx_streamer; io_type_t::tid_t _send_tid; diff --git a/host/include/uhd/streamer.hpp b/host/include/uhd/streamer.hpp index dfbe15ec3..d96eeb2b7 100644 --- a/host/include/uhd/streamer.hpp +++ b/host/include/uhd/streamer.hpp @@ -90,12 +90,12 @@ public: }; //! A receive streamer to receive host samples -class UHD_API recv_streamer : public streamer{ +class UHD_API rx_streamer : public streamer{ public: - typedef boost::shared_ptr sptr; + typedef boost::shared_ptr sptr; //! Typedef for a pointer to a single, or a collection of recv buffers - typedef ref_vector recv_buffs_type; + typedef ref_vector buffs_type; /*! * Receive buffers containing samples described by the metadata. @@ -123,7 +123,7 @@ public: * \return the number of samples received or 0 on error */ virtual size_t recv( - const recv_buffs_type &buffs, + const buffs_type &buffs, size_t nsamps_per_buff, rx_metadata_t &metadata, double timeout = 0.1 @@ -131,12 +131,12 @@ public: }; //! A transmit streamer to send host samples -class UHD_API send_streamer : public streamer{ +class UHD_API tx_streamer : public streamer{ public: - typedef boost::shared_ptr sptr; + typedef boost::shared_ptr sptr; //! Typedef for a pointer to a single, or a collection of send buffers - typedef ref_vector send_buffs_type; + typedef ref_vector buffs_type; /*! * Send buffers containing samples described by the metadata. @@ -160,7 +160,7 @@ public: * \return the number of samples sent */ virtual size_t send( - const send_buffs_type &buffs, + const buffs_type &buffs, size_t nsamps_per_buff, const tx_metadata_t &metadata, double timeout = 0.1 diff --git a/host/lib/convert/convert_impl.cpp b/host/lib/convert/convert_impl.cpp index 2ead2f5b4..5c9e77e93 100644 --- a/host/lib/convert/convert_impl.cpp +++ b/host/lib/convert/convert_impl.cpp @@ -114,6 +114,16 @@ void register_bytes_per_item( size_t convert::get_bytes_per_item(const std::string &markup){ if (get_item_size_table().has_key(markup)) return get_item_size_table()[markup]; + + //OK. I am sorry about this. + //We didnt find a match, so lets find a match for the first term. + //This is partially a hack because of the way I append strings. + //But as long as life is kind, we can keep this. + const size_t pos = markup.find("_"); + if (pos != std::string::npos){ + return get_bytes_per_item(markup.substr(0, pos)); + } + throw uhd::key_error("Cannot find an item size " + markup); } diff --git a/host/lib/transport/super_recv_packet_handler.hpp b/host/lib/transport/super_recv_packet_handler.hpp index 541c588e6..4ae51e146 100644 --- a/host/lib/transport/super_recv_packet_handler.hpp +++ b/host/lib/transport/super_recv_packet_handler.hpp @@ -21,11 +21,9 @@ #include #include #include -#include +#include #include #include -#include -#include #include #include #include @@ -124,24 +122,12 @@ public: _props.at(xport_chan).get_buff = get_buff; } - /*! - * Setup the conversion functions (homogeneous across transports). - * Here, we load a table of converters for all possible io types. - * This makes the converter look-up an O(1) operation. - * \param otw_type the channel data type - * \param width the streams per channel (usually 1) - */ - void set_converter(const uhd::otw_type_t &otw_type, const size_t width = 1){ - _io_buffs.resize(width); - _converters.resize(128); - for (size_t io_type = 0; io_type < _converters.size(); io_type++){ - try{ - _converters[io_type] = uhd::convert::get_converter_otw_to_cpu( - io_type_t::tid_t(io_type), otw_type, 1, width - ); - }catch(const uhd::value_error &){} //we expect this, not all io_types valid... - } - _bytes_per_item = otw_type.get_sample_size(); + //! Set the conversion routine for all channels + void set_converter(const uhd::convert::id_type &id){ + _io_buffs.resize(id.num_inputs); + _converter = uhd::convert::get_converter(id); + _bytes_per_otw_item = uhd::convert::get_bytes_per_item(id.input_markup); + _bytes_per_cpu_item = uhd::convert::get_bytes_per_item(id.output_markup); } //! Set the transport channel's overflow handler @@ -165,11 +151,9 @@ public: * Dispatch into combinations of single packet receive calls. ******************************************************************/ UHD_INLINE size_t recv( - const uhd::device::recv_buffs_type &buffs, + const uhd::rx_streamer::buffs_type &buffs, const size_t nsamps_per_buff, uhd::rx_metadata_t &metadata, - const uhd::io_type_t &io_type, - uhd::device::recv_mode_t recv_mode, double timeout ){ boost::mutex::scoped_lock lock(_mutex); @@ -183,43 +167,32 @@ public: if (_queue_metadata.error_code != rx_metadata_t::ERROR_CODE_TIMEOUT) return 0; } - switch(recv_mode){ - - //////////////////////////////////////////////////////////////// - case uhd::device::RECV_MODE_ONE_PACKET:{ - //////////////////////////////////////////////////////////////// - return recv_one_packet(buffs, nsamps_per_buff, metadata, io_type, timeout); - } + size_t accum_num_samps = recv_one_packet( + buffs, nsamps_per_buff, metadata, timeout + ); - //////////////////////////////////////////////////////////////// - case uhd::device::RECV_MODE_FULL_BUFF:{ - //////////////////////////////////////////////////////////////// - size_t accum_num_samps = recv_one_packet( - buffs, nsamps_per_buff, metadata, io_type, timeout - ); + #ifdef SRPH_TEST_MODE_ONE_PACKET + return accum_num_samps; + #endif - //first recv had an error code set, return immediately - if (metadata.error_code != rx_metadata_t::ERROR_CODE_NONE) return accum_num_samps; + //first recv had an error code set, return immediately + if (metadata.error_code != rx_metadata_t::ERROR_CODE_NONE) return accum_num_samps; - //loop until buffer is filled or error code - while(accum_num_samps < nsamps_per_buff){ - size_t num_samps = recv_one_packet( - buffs, nsamps_per_buff - accum_num_samps, _queue_metadata, - io_type, timeout, accum_num_samps*io_type.size - ); + //loop until buffer is filled or error code + while(accum_num_samps < nsamps_per_buff){ + size_t num_samps = recv_one_packet( + buffs, nsamps_per_buff - accum_num_samps, _queue_metadata, + timeout, accum_num_samps*_bytes_per_cpu_item + ); - //metadata had an error code set, store for next call and return - if (_queue_metadata.error_code != rx_metadata_t::ERROR_CODE_NONE){ - _queue_error_for_next_call = true; - break; - } - accum_num_samps += num_samps; + //metadata had an error code set, store for next call and return + if (_queue_metadata.error_code != rx_metadata_t::ERROR_CODE_NONE){ + _queue_error_for_next_call = true; + break; } - return accum_num_samps; + accum_num_samps += num_samps; } - - default: throw uhd::value_error("unknown recv mode"); - }//switch(recv_mode) + return accum_num_samps; } private: @@ -242,8 +215,9 @@ private: }; std::vector _props; std::vector _io_buffs; //used in conversion - size_t _bytes_per_item; //used in conversion - std::vector _converters; //used in conversion + size_t _bytes_per_otw_item; //used in conversion + size_t _bytes_per_cpu_item; //used in conversion + uhd::convert::function_type _converter; //used in conversion double _scale_factor; //! information stored for a received buffer @@ -471,7 +445,7 @@ private: std::swap(curr_info, next_info); //save progress from curr -> next curr_info.metadata.has_time_spec = prev_info.metadata.has_time_spec; curr_info.metadata.time_spec = prev_info.metadata.time_spec + time_spec_t(0, - prev_info[index].ifpi.num_payload_words32*sizeof(boost::uint32_t)/_bytes_per_item, _samp_rate); + prev_info[index].ifpi.num_payload_words32*sizeof(boost::uint32_t)/_bytes_per_otw_item, _samp_rate); curr_info.metadata.more_fragments = false; curr_info.metadata.fragment_offset = 0; curr_info.metadata.start_of_burst = false; @@ -525,10 +499,9 @@ private: * Then copy-convert available data into the user's IO buffers. ******************************************************************/ UHD_INLINE size_t recv_one_packet( - const uhd::device::recv_buffs_type &buffs, + const uhd::rx_streamer::buffs_type &buffs, const size_t nsamps_per_buff, uhd::rx_metadata_t &metadata, - const uhd::io_type_t &io_type, double timeout, const size_t buffer_offset_bytes = 0 ){ @@ -551,9 +524,9 @@ private: metadata.time_spec += time_spec_t(0, info.fragment_offset_in_samps, _samp_rate); //extract the number of samples available to copy - const size_t nsamps_available = info.data_bytes_to_copy/_bytes_per_item; + const size_t nsamps_available = info.data_bytes_to_copy/_bytes_per_otw_item; const size_t nsamps_to_copy = std::min(nsamps_per_buff*_io_buffs.size(), nsamps_available); - const size_t bytes_to_copy = nsamps_to_copy*_bytes_per_item; + const size_t bytes_to_copy = nsamps_to_copy*_bytes_per_otw_item; const size_t nsamps_to_copy_per_io_buff = nsamps_to_copy/_io_buffs.size(); size_t buff_index = 0; @@ -565,7 +538,7 @@ private: } //copy-convert the samples from the recv buffer - _converters[io_type.tid](buff_info.copy_buff, _io_buffs, nsamps_to_copy_per_io_buff, _scale_factor); + _converter(buff_info.copy_buff, _io_buffs, nsamps_to_copy_per_io_buff, _scale_factor); //update the rx copy buffer to reflect the bytes copied buff_info.copy_buff += bytes_to_copy; diff --git a/host/lib/transport/super_send_packet_handler.hpp b/host/lib/transport/super_send_packet_handler.hpp index a99adcb5f..6950abb73 100644 --- a/host/lib/transport/super_send_packet_handler.hpp +++ b/host/lib/transport/super_send_packet_handler.hpp @@ -21,11 +21,9 @@ #include #include #include -#include +#include #include #include -#include -#include #include #include #include @@ -100,24 +98,12 @@ public: _props.at(xport_chan).get_buff = get_buff; } - /*! - * Setup the conversion functions (homogeneous across transports). - * Here, we load a table of converters for all possible io types. - * This makes the converter look-up an O(1) operation. - * \param otw_type the channel data type - * \param width the streams per channel (usually 1) - */ - void set_converter(const uhd::otw_type_t &otw_type, const size_t width = 1){ - _io_buffs.resize(width); - _converters.resize(128); - for (size_t io_type = 0; io_type < _converters.size(); io_type++){ - try{ - _converters[io_type] = uhd::convert::get_converter_cpu_to_otw( - io_type_t::tid_t(io_type), otw_type, 1, width - ); - }catch(const uhd::value_error &){} //we expect this, not all io_types valid... - } - _bytes_per_item = otw_type.get_sample_size(); + //! Set the conversion routine for all channels + void set_converter(const uhd::convert::id_type &id){ + _io_buffs.resize(id.num_outputs); + _converter = uhd::convert::get_converter(id); + _bytes_per_otw_item = uhd::convert::get_bytes_per_item(id.output_markup); + _bytes_per_cpu_item = uhd::convert::get_bytes_per_item(id.input_markup); } /*! @@ -145,11 +131,9 @@ public: * Dispatch into combinations of single packet send calls. ******************************************************************/ UHD_INLINE size_t send( - const uhd::device::send_buffs_type &buffs, + const uhd::tx_streamer::buffs_type &buffs, const size_t nsamps_per_buff, const uhd::tx_metadata_t &metadata, - const uhd::io_type_t &io_type, - uhd::device::send_mode_t send_mode, double timeout ){ boost::mutex::scoped_lock lock(_mutex); @@ -166,69 +150,52 @@ public: if_packet_info.sob = metadata.start_of_burst; if_packet_info.eob = metadata.end_of_burst; - if (nsamps_per_buff <= _max_samples_per_packet) send_mode = uhd::device::SEND_MODE_ONE_PACKET; - switch(send_mode){ - - //////////////////////////////////////////////////////////////// - case uhd::device::SEND_MODE_ONE_PACKET:{ - //////////////////////////////////////////////////////////////// + if (nsamps_per_buff <= _max_samples_per_packet){ //TODO remove this code when sample counts of zero are supported by hardware #ifndef SSPH_DONT_PAD_TO_ONE if (nsamps_per_buff == 0) return send_one_packet( - _zero_buffs, 1, if_packet_info, io_type, timeout + _zero_buffs, 1, if_packet_info, timeout ) & 0x0; #endif - return send_one_packet( - buffs, - std::min(nsamps_per_buff, _max_samples_per_packet), - if_packet_info, io_type, timeout - ); + return send_one_packet(buffs, nsamps_per_buff, if_packet_info, timeout); } + size_t total_num_samps_sent = 0; - //////////////////////////////////////////////////////////////// - case uhd::device::SEND_MODE_FULL_BUFF:{ - //////////////////////////////////////////////////////////////// - size_t total_num_samps_sent = 0; + //false until final fragment + if_packet_info.eob = false; - //false until final fragment - if_packet_info.eob = false; + const size_t num_fragments = (nsamps_per_buff-1)/_max_samples_per_packet; + const size_t final_length = ((nsamps_per_buff-1)%_max_samples_per_packet)+1; - const size_t num_fragments = (nsamps_per_buff-1)/_max_samples_per_packet; - const size_t final_length = ((nsamps_per_buff-1)%_max_samples_per_packet)+1; + //loop through the following fragment indexes + for (size_t i = 0; i < num_fragments; i++){ - //loop through the following fragment indexes - for (size_t i = 0; i < num_fragments; i++){ - - //send a fragment with the helper function - const size_t num_samps_sent = send_one_packet( - buffs, _max_samples_per_packet, - if_packet_info, io_type, timeout, - total_num_samps_sent*io_type.size - ); - total_num_samps_sent += num_samps_sent; - if (num_samps_sent == 0) return total_num_samps_sent; + //send a fragment with the helper function + const size_t num_samps_sent = send_one_packet( + buffs, _max_samples_per_packet, + if_packet_info, timeout, + total_num_samps_sent*_bytes_per_cpu_item + ); + total_num_samps_sent += num_samps_sent; + if (num_samps_sent == 0) return total_num_samps_sent; - //setup metadata for the next fragment - const time_spec_t time_spec = metadata.time_spec + time_spec_t(0, total_num_samps_sent, _samp_rate); - if_packet_info.tsi = boost::uint32_t(time_spec.get_full_secs()); - if_packet_info.tsf = boost::uint64_t(time_spec.get_tick_count(_tick_rate)); - if_packet_info.sob = false; + //setup metadata for the next fragment + const time_spec_t time_spec = metadata.time_spec + time_spec_t(0, total_num_samps_sent, _samp_rate); + if_packet_info.tsi = boost::uint32_t(time_spec.get_full_secs()); + if_packet_info.tsf = boost::uint64_t(time_spec.get_tick_count(_tick_rate)); + if_packet_info.sob = false; - } - - //send the final fragment with the helper function - if_packet_info.eob = metadata.end_of_burst; - return total_num_samps_sent + send_one_packet( - buffs, final_length, - if_packet_info, io_type, timeout, - total_num_samps_sent*io_type.size - ); } - default: throw uhd::value_error("unknown send mode"); - }//switch(send_mode) + //send the final fragment with the helper function + if_packet_info.eob = metadata.end_of_burst; + return total_num_samps_sent + send_one_packet( + buffs, final_length, + if_packet_info, timeout, + total_num_samps_sent*_bytes_per_cpu_item + ); } private: @@ -242,8 +209,9 @@ private: }; std::vector _props; std::vector _io_buffs; //used in conversion - size_t _bytes_per_item; //used in conversion - std::vector _converters; //used in conversion + size_t _bytes_per_otw_item; //used in conversion + size_t _bytes_per_cpu_item; //used in conversion + uhd::convert::function_type _converter; //used in conversion size_t _max_samples_per_packet; std::vector _zero_buffs; size_t _next_packet_seq; @@ -253,15 +221,14 @@ private: * Send a single packet: ******************************************************************/ UHD_INLINE size_t send_one_packet( - const uhd::device::send_buffs_type &buffs, + const uhd::tx_streamer::buffs_type &buffs, const size_t nsamps_per_buff, vrt::if_packet_info_t &if_packet_info, - const uhd::io_type_t &io_type, double timeout, const size_t buffer_offset_bytes = 0 ){ //load the rest of the if_packet_info in here - if_packet_info.num_payload_words32 = (nsamps_per_buff*_io_buffs.size()*_bytes_per_item)/sizeof(boost::uint32_t); + if_packet_info.num_payload_words32 = (nsamps_per_buff*_io_buffs.size()*_bytes_per_otw_item)/sizeof(boost::uint32_t); if_packet_info.packet_count = _next_packet_seq; size_t buff_index = 0; @@ -280,7 +247,7 @@ private: otw_mem += if_packet_info.num_header_words32; //copy-convert the samples into the send buffer - _converters[io_type.tid](_io_buffs, otw_mem, nsamps_per_buff, _scale_factor); + _converter(_io_buffs, otw_mem, nsamps_per_buff, _scale_factor); //commit the samples to the zero-copy interface size_t num_bytes_total = (_header_offset_words32+if_packet_info.num_packet_words32)*sizeof(boost::uint32_t); diff --git a/host/tests/CMakeLists.txt b/host/tests/CMakeLists.txt index 25679a33e..28cc1c5da 100644 --- a/host/tests/CMakeLists.txt +++ b/host/tests/CMakeLists.txt @@ -29,8 +29,8 @@ SET(test_sources msg_test.cpp property_test.cpp ranges_test.cpp - #TODO restore sph_recv_test.cpp - #TODO restore sph_send_test.cpp + sph_recv_test.cpp + sph_send_test.cpp subdev_spec_test.cpp time_spec_test.cpp vrt_test.cpp diff --git a/host/tests/sph_recv_test.cpp b/host/tests/sph_recv_test.cpp index 1387e3b66..3ca123ef2 100644 --- a/host/tests/sph_recv_test.cpp +++ b/host/tests/sph_recv_test.cpp @@ -16,6 +16,7 @@ // #include +#define SRPH_TEST_MODE_ONE_PACKET #include "../lib/transport/super_recv_packet_handler.hpp" #include #include @@ -67,8 +68,8 @@ private: **********************************************************************/ class dummy_recv_xport_class{ public: - dummy_recv_xport_class(const uhd::otw_type_t &otw_type){ - _otw_type = otw_type; + dummy_recv_xport_class(const std::string &end){ + _end = end; } void push_back_packet( @@ -77,10 +78,10 @@ public: ){ const size_t max_pkt_len = (ifpi.num_payload_words32 + uhd::transport::vrt::max_if_hdr_words32 + 1/*tlr*/)*sizeof(boost::uint32_t); _mems.push_back(boost::shared_array(new char[max_pkt_len])); - if (_otw_type.byteorder == uhd::otw_type_t::BO_BIG_ENDIAN){ + if (_end == "big"){ uhd::transport::vrt::if_hdr_pack_be(reinterpret_cast(_mems.back().get()), ifpi); } - if (_otw_type.byteorder == uhd::otw_type_t::BO_LITTLE_ENDIAN){ + if (_end == "little"){ uhd::transport::vrt::if_hdr_pack_le(reinterpret_cast(_mems.back().get()), ifpi); } (reinterpret_cast(_mems.back().get()) + ifpi.num_header_words32)[0] = optional_msg_word | uhd::byteswap(optional_msg_word); @@ -100,18 +101,19 @@ private: std::list > _mems; std::list _lens; std::list _mrbs; //list means no-realloc - uhd::otw_type_t _otw_type; + std::string _end; }; //////////////////////////////////////////////////////////////////////// BOOST_AUTO_TEST_CASE(test_sph_recv_one_channel_normal){ //////////////////////////////////////////////////////////////////////// - uhd::otw_type_t otw_type; - otw_type.width = 16; - otw_type.shift = 0; - otw_type.byteorder = uhd::otw_type_t::BO_BIG_ENDIAN; + uhd::convert::id_type id; + id.input_markup = "sc16_item32_be"; + id.num_inputs = 1; + id.output_markup = "fc32"; + id.num_outputs = 1; - dummy_recv_xport_class dummy_recv_xport(otw_type); + dummy_recv_xport_class dummy_recv_xport("big"); uhd::transport::vrt::if_packet_info_t ifpi; ifpi.packet_type = uhd::transport::vrt::if_packet_info_t::PACKET_TYPE_DATA; ifpi.num_payload_words32 = 0; @@ -144,7 +146,7 @@ BOOST_AUTO_TEST_CASE(test_sph_recv_one_channel_normal){ handler.set_tick_rate(TICK_RATE); handler.set_samp_rate(SAMP_RATE); handler.set_xport_chan_get_buff(0, boost::bind(&dummy_recv_xport_class::get_recv_buff, &dummy_recv_xport, _1)); - handler.set_converter(otw_type); + handler.set_converter(id); //check the received packets size_t num_accum_samps = 0; @@ -153,9 +155,7 @@ BOOST_AUTO_TEST_CASE(test_sph_recv_one_channel_normal){ for (size_t i = 0; i < NUM_PKTS_TO_TEST; i++){ std::cout << "data check " << i << std::endl; size_t num_samps_ret = handler.recv( - &buff.front(), buff.size(), metadata, - uhd::io_type_t::COMPLEX_FLOAT32, - uhd::device::RECV_MODE_ONE_PACKET, 1.0 + &buff.front(), buff.size(), metadata, 1.0 ); BOOST_CHECK_EQUAL(metadata.error_code, uhd::rx_metadata_t::ERROR_CODE_NONE); BOOST_CHECK(not metadata.more_fragments); @@ -169,9 +169,7 @@ BOOST_AUTO_TEST_CASE(test_sph_recv_one_channel_normal){ for (size_t i = 0; i < 3; i++){ std::cout << "timeout check " << i << std::endl; handler.recv( - &buff.front(), buff.size(), metadata, - uhd::io_type_t::COMPLEX_FLOAT32, - uhd::device::RECV_MODE_ONE_PACKET, 1.0 + &buff.front(), buff.size(), metadata, 1.0 ); BOOST_CHECK_EQUAL(metadata.error_code, uhd::rx_metadata_t::ERROR_CODE_TIMEOUT); } @@ -180,12 +178,13 @@ BOOST_AUTO_TEST_CASE(test_sph_recv_one_channel_normal){ //////////////////////////////////////////////////////////////////////// BOOST_AUTO_TEST_CASE(test_sph_recv_one_channel_sequence_error){ //////////////////////////////////////////////////////////////////////// - uhd::otw_type_t otw_type; - otw_type.width = 16; - otw_type.shift = 0; - otw_type.byteorder = uhd::otw_type_t::BO_BIG_ENDIAN; + uhd::convert::id_type id; + id.input_markup = "sc16_item32_be"; + id.num_inputs = 1; + id.output_markup = "fc32"; + id.num_outputs = 1; - dummy_recv_xport_class dummy_recv_xport(otw_type); + dummy_recv_xport_class dummy_recv_xport("big"); uhd::transport::vrt::if_packet_info_t ifpi; ifpi.packet_type = uhd::transport::vrt::if_packet_info_t::PACKET_TYPE_DATA; ifpi.num_payload_words32 = 0; @@ -220,7 +219,7 @@ BOOST_AUTO_TEST_CASE(test_sph_recv_one_channel_sequence_error){ handler.set_tick_rate(TICK_RATE); handler.set_samp_rate(SAMP_RATE); handler.set_xport_chan_get_buff(0, boost::bind(&dummy_recv_xport_class::get_recv_buff, &dummy_recv_xport, _1)); - handler.set_converter(otw_type); + handler.set_converter(id); //check the received packets size_t num_accum_samps = 0; @@ -229,9 +228,7 @@ BOOST_AUTO_TEST_CASE(test_sph_recv_one_channel_sequence_error){ for (size_t i = 0; i < NUM_PKTS_TO_TEST; i++){ std::cout << "data check " << i << std::endl; size_t num_samps_ret = handler.recv( - &buff.front(), buff.size(), metadata, - uhd::io_type_t::COMPLEX_FLOAT32, - uhd::device::RECV_MODE_ONE_PACKET, 1.0 + &buff.front(), buff.size(), metadata, 1.0 ); if (i == NUM_PKTS_TO_TEST/2){ //must get the soft overflow here @@ -253,9 +250,7 @@ BOOST_AUTO_TEST_CASE(test_sph_recv_one_channel_sequence_error){ for (size_t i = 0; i < 3; i++){ std::cout << "timeout check " << i << std::endl; handler.recv( - &buff.front(), buff.size(), metadata, - uhd::io_type_t::COMPLEX_FLOAT32, - uhd::device::RECV_MODE_ONE_PACKET, 1.0 + &buff.front(), buff.size(), metadata, 1.0 ); BOOST_CHECK_EQUAL(metadata.error_code, uhd::rx_metadata_t::ERROR_CODE_TIMEOUT); } @@ -264,12 +259,13 @@ BOOST_AUTO_TEST_CASE(test_sph_recv_one_channel_sequence_error){ //////////////////////////////////////////////////////////////////////// BOOST_AUTO_TEST_CASE(test_sph_recv_one_channel_inline_message){ //////////////////////////////////////////////////////////////////////// - uhd::otw_type_t otw_type; - otw_type.width = 16; - otw_type.shift = 0; - otw_type.byteorder = uhd::otw_type_t::BO_BIG_ENDIAN; + uhd::convert::id_type id; + id.input_markup = "sc16_item32_be"; + id.num_inputs = 1; + id.output_markup = "fc32"; + id.num_outputs = 1; - dummy_recv_xport_class dummy_recv_xport(otw_type); + dummy_recv_xport_class dummy_recv_xport("big"); uhd::transport::vrt::if_packet_info_t ifpi; ifpi.packet_type = uhd::transport::vrt::if_packet_info_t::PACKET_TYPE_DATA; ifpi.num_payload_words32 = 0; @@ -310,7 +306,7 @@ BOOST_AUTO_TEST_CASE(test_sph_recv_one_channel_inline_message){ handler.set_tick_rate(TICK_RATE); handler.set_samp_rate(SAMP_RATE); handler.set_xport_chan_get_buff(0, boost::bind(&dummy_recv_xport_class::get_recv_buff, &dummy_recv_xport, _1)); - handler.set_converter(otw_type); + handler.set_converter(id); //create an overflow handler overflow_handler_type overflow_handler; @@ -323,9 +319,7 @@ BOOST_AUTO_TEST_CASE(test_sph_recv_one_channel_inline_message){ for (size_t i = 0; i < NUM_PKTS_TO_TEST; i++){ std::cout << "data check " << i << std::endl; size_t num_samps_ret = handler.recv( - &buff.front(), buff.size(), metadata, - uhd::io_type_t::COMPLEX_FLOAT32, - uhd::device::RECV_MODE_ONE_PACKET, 1.0 + &buff.front(), buff.size(), metadata, 1.0 ); BOOST_CHECK_EQUAL(metadata.error_code, uhd::rx_metadata_t::ERROR_CODE_NONE); BOOST_CHECK(not metadata.more_fragments); @@ -335,9 +329,7 @@ BOOST_AUTO_TEST_CASE(test_sph_recv_one_channel_inline_message){ num_accum_samps += num_samps_ret; if (i == NUM_PKTS_TO_TEST/2){ handler.recv( - &buff.front(), buff.size(), metadata, - uhd::io_type_t::COMPLEX_FLOAT32, - uhd::device::RECV_MODE_ONE_PACKET, 1.0 + &buff.front(), buff.size(), metadata, 1.0 ); std::cout << "metadata.error_code " << metadata.error_code << std::endl; BOOST_REQUIRE(metadata.error_code == uhd::rx_metadata_t::ERROR_CODE_OVERFLOW); @@ -350,9 +342,7 @@ BOOST_AUTO_TEST_CASE(test_sph_recv_one_channel_inline_message){ for (size_t i = 0; i < 3; i++){ std::cout << "timeout check " << i << std::endl; handler.recv( - &buff.front(), buff.size(), metadata, - uhd::io_type_t::COMPLEX_FLOAT32, - uhd::device::RECV_MODE_ONE_PACKET, 1.0 + &buff.front(), buff.size(), metadata, 1.0 ); BOOST_CHECK_EQUAL(metadata.error_code, uhd::rx_metadata_t::ERROR_CODE_TIMEOUT); } @@ -361,10 +351,11 @@ BOOST_AUTO_TEST_CASE(test_sph_recv_one_channel_inline_message){ //////////////////////////////////////////////////////////////////////// BOOST_AUTO_TEST_CASE(test_sph_recv_multi_channel_normal){ //////////////////////////////////////////////////////////////////////// - uhd::otw_type_t otw_type; - otw_type.width = 16; - otw_type.shift = 0; - otw_type.byteorder = uhd::otw_type_t::BO_BIG_ENDIAN; + uhd::convert::id_type id; + id.input_markup = "sc16_item32_be"; + id.num_inputs = 1; + id.output_markup = "fc32"; + id.num_outputs = 1; uhd::transport::vrt::if_packet_info_t ifpi; ifpi.packet_type = uhd::transport::vrt::if_packet_info_t::PACKET_TYPE_DATA; @@ -386,7 +377,7 @@ BOOST_AUTO_TEST_CASE(test_sph_recv_multi_channel_normal){ static const size_t NUM_SAMPS_PER_BUFF = 20; static const size_t NCHANNELS = 4; - std::vector dummy_recv_xports(NCHANNELS, dummy_recv_xport_class(otw_type)); + std::vector dummy_recv_xports(NCHANNELS, dummy_recv_xport_class("big")); //generate a bunch of packets for (size_t i = 0; i < NUM_PKTS_TO_TEST; i++){ @@ -406,7 +397,7 @@ BOOST_AUTO_TEST_CASE(test_sph_recv_multi_channel_normal){ for (size_t ch = 0; ch < NCHANNELS; ch++){ handler.set_xport_chan_get_buff(ch, boost::bind(&dummy_recv_xport_class::get_recv_buff, &dummy_recv_xports[ch], _1)); } - handler.set_converter(otw_type); + handler.set_converter(id); //check the received packets size_t num_accum_samps = 0; @@ -419,9 +410,7 @@ BOOST_AUTO_TEST_CASE(test_sph_recv_multi_channel_normal){ for (size_t i = 0; i < NUM_PKTS_TO_TEST; i++){ std::cout << "data check " << i << std::endl; size_t num_samps_ret = handler.recv( - buffs, NUM_SAMPS_PER_BUFF, metadata, - uhd::io_type_t::COMPLEX_FLOAT32, - uhd::device::RECV_MODE_ONE_PACKET, 1.0 + buffs, NUM_SAMPS_PER_BUFF, metadata, 1.0 ); BOOST_CHECK_EQUAL(metadata.error_code, uhd::rx_metadata_t::ERROR_CODE_NONE); BOOST_CHECK(not metadata.more_fragments); @@ -435,9 +424,7 @@ BOOST_AUTO_TEST_CASE(test_sph_recv_multi_channel_normal){ for (size_t i = 0; i < 3; i++){ std::cout << "timeout check " << i << std::endl; handler.recv( - buffs, NUM_SAMPS_PER_BUFF, metadata, - uhd::io_type_t::COMPLEX_FLOAT32, - uhd::device::RECV_MODE_ONE_PACKET, 1.0 + buffs, NUM_SAMPS_PER_BUFF, metadata, 1.0 ); BOOST_CHECK_EQUAL(metadata.error_code, uhd::rx_metadata_t::ERROR_CODE_TIMEOUT); } @@ -447,10 +434,11 @@ BOOST_AUTO_TEST_CASE(test_sph_recv_multi_channel_normal){ //////////////////////////////////////////////////////////////////////// BOOST_AUTO_TEST_CASE(test_sph_recv_multi_channel_sequence_error){ //////////////////////////////////////////////////////////////////////// - uhd::otw_type_t otw_type; - otw_type.width = 16; - otw_type.shift = 0; - otw_type.byteorder = uhd::otw_type_t::BO_BIG_ENDIAN; + uhd::convert::id_type id; + id.input_markup = "sc16_item32_be"; + id.num_inputs = 1; + id.output_markup = "fc32"; + id.num_outputs = 1; uhd::transport::vrt::if_packet_info_t ifpi; ifpi.packet_type = uhd::transport::vrt::if_packet_info_t::PACKET_TYPE_DATA; @@ -472,7 +460,7 @@ BOOST_AUTO_TEST_CASE(test_sph_recv_multi_channel_sequence_error){ static const size_t NUM_SAMPS_PER_BUFF = 20; static const size_t NCHANNELS = 4; - std::vector dummy_recv_xports(NCHANNELS, dummy_recv_xport_class(otw_type)); + std::vector dummy_recv_xports(NCHANNELS, dummy_recv_xport_class("big")); //generate a bunch of packets for (size_t i = 0; i < NUM_PKTS_TO_TEST; i++){ @@ -495,7 +483,7 @@ BOOST_AUTO_TEST_CASE(test_sph_recv_multi_channel_sequence_error){ for (size_t ch = 0; ch < NCHANNELS; ch++){ handler.set_xport_chan_get_buff(ch, boost::bind(&dummy_recv_xport_class::get_recv_buff, &dummy_recv_xports[ch], _1)); } - handler.set_converter(otw_type); + handler.set_converter(id); //check the received packets size_t num_accum_samps = 0; @@ -508,9 +496,7 @@ BOOST_AUTO_TEST_CASE(test_sph_recv_multi_channel_sequence_error){ for (size_t i = 0; i < NUM_PKTS_TO_TEST; i++){ std::cout << "data check " << i << std::endl; size_t num_samps_ret = handler.recv( - buffs, NUM_SAMPS_PER_BUFF, metadata, - uhd::io_type_t::COMPLEX_FLOAT32, - uhd::device::RECV_MODE_ONE_PACKET, 1.0 + buffs, NUM_SAMPS_PER_BUFF, metadata, 1.0 ); if (i == NUM_PKTS_TO_TEST/2){ //must get the soft overflow here @@ -532,9 +518,7 @@ BOOST_AUTO_TEST_CASE(test_sph_recv_multi_channel_sequence_error){ for (size_t i = 0; i < 3; i++){ std::cout << "timeout check " << i << std::endl; handler.recv( - buffs, NUM_SAMPS_PER_BUFF, metadata, - uhd::io_type_t::COMPLEX_FLOAT32, - uhd::device::RECV_MODE_ONE_PACKET, 1.0 + buffs, NUM_SAMPS_PER_BUFF, metadata, 1.0 ); BOOST_CHECK_EQUAL(metadata.error_code, uhd::rx_metadata_t::ERROR_CODE_TIMEOUT); } @@ -543,10 +527,11 @@ BOOST_AUTO_TEST_CASE(test_sph_recv_multi_channel_sequence_error){ //////////////////////////////////////////////////////////////////////// BOOST_AUTO_TEST_CASE(test_sph_recv_multi_channel_time_error){ //////////////////////////////////////////////////////////////////////// - uhd::otw_type_t otw_type; - otw_type.width = 16; - otw_type.shift = 0; - otw_type.byteorder = uhd::otw_type_t::BO_BIG_ENDIAN; + uhd::convert::id_type id; + id.input_markup = "sc16_item32_be"; + id.num_inputs = 1; + id.output_markup = "fc32"; + id.num_outputs = 1; uhd::transport::vrt::if_packet_info_t ifpi; ifpi.packet_type = uhd::transport::vrt::if_packet_info_t::PACKET_TYPE_DATA; @@ -568,7 +553,7 @@ BOOST_AUTO_TEST_CASE(test_sph_recv_multi_channel_time_error){ static const size_t NUM_SAMPS_PER_BUFF = 20; static const size_t NCHANNELS = 4; - std::vector dummy_recv_xports(NCHANNELS, dummy_recv_xport_class(otw_type)); + std::vector dummy_recv_xports(NCHANNELS, dummy_recv_xport_class("big")); //generate a bunch of packets for (size_t i = 0; i < NUM_PKTS_TO_TEST; i++){ @@ -591,7 +576,7 @@ BOOST_AUTO_TEST_CASE(test_sph_recv_multi_channel_time_error){ for (size_t ch = 0; ch < NCHANNELS; ch++){ handler.set_xport_chan_get_buff(ch, boost::bind(&dummy_recv_xport_class::get_recv_buff, &dummy_recv_xports[ch], _1)); } - handler.set_converter(otw_type); + handler.set_converter(id); //check the received packets size_t num_accum_samps = 0; @@ -604,9 +589,7 @@ BOOST_AUTO_TEST_CASE(test_sph_recv_multi_channel_time_error){ for (size_t i = 0; i < NUM_PKTS_TO_TEST; i++){ std::cout << "data check " << i << std::endl; size_t num_samps_ret = handler.recv( - buffs, NUM_SAMPS_PER_BUFF, metadata, - uhd::io_type_t::COMPLEX_FLOAT32, - uhd::device::RECV_MODE_ONE_PACKET, 1.0 + buffs, NUM_SAMPS_PER_BUFF, metadata, 1.0 ); BOOST_CHECK_EQUAL(metadata.error_code, uhd::rx_metadata_t::ERROR_CODE_NONE); BOOST_CHECK(not metadata.more_fragments); @@ -623,9 +606,7 @@ BOOST_AUTO_TEST_CASE(test_sph_recv_multi_channel_time_error){ for (size_t i = 0; i < 3; i++){ std::cout << "timeout check " << i << std::endl; handler.recv( - buffs, NUM_SAMPS_PER_BUFF, metadata, - uhd::io_type_t::COMPLEX_FLOAT32, - uhd::device::RECV_MODE_ONE_PACKET, 1.0 + buffs, NUM_SAMPS_PER_BUFF, metadata, 1.0 ); BOOST_CHECK_EQUAL(metadata.error_code, uhd::rx_metadata_t::ERROR_CODE_TIMEOUT); } @@ -634,10 +615,11 @@ BOOST_AUTO_TEST_CASE(test_sph_recv_multi_channel_time_error){ //////////////////////////////////////////////////////////////////////// BOOST_AUTO_TEST_CASE(test_sph_recv_multi_channel_fragment){ //////////////////////////////////////////////////////////////////////// - uhd::otw_type_t otw_type; - otw_type.width = 16; - otw_type.shift = 0; - otw_type.byteorder = uhd::otw_type_t::BO_BIG_ENDIAN; + uhd::convert::id_type id; + id.input_markup = "sc16_item32_be"; + id.num_inputs = 1; + id.output_markup = "fc32"; + id.num_outputs = 1; uhd::transport::vrt::if_packet_info_t ifpi; ifpi.packet_type = uhd::transport::vrt::if_packet_info_t::PACKET_TYPE_DATA; @@ -659,7 +641,7 @@ BOOST_AUTO_TEST_CASE(test_sph_recv_multi_channel_fragment){ static const size_t NUM_SAMPS_PER_BUFF = 10; static const size_t NCHANNELS = 4; - std::vector dummy_recv_xports(NCHANNELS, dummy_recv_xport_class(otw_type)); + std::vector dummy_recv_xports(NCHANNELS, dummy_recv_xport_class("big")); //generate a bunch of packets for (size_t i = 0; i < NUM_PKTS_TO_TEST; i++){ @@ -679,7 +661,7 @@ BOOST_AUTO_TEST_CASE(test_sph_recv_multi_channel_fragment){ for (size_t ch = 0; ch < NCHANNELS; ch++){ handler.set_xport_chan_get_buff(ch, boost::bind(&dummy_recv_xport_class::get_recv_buff, &dummy_recv_xports[ch], _1)); } - handler.set_converter(otw_type); + handler.set_converter(id); //check the received packets size_t num_accum_samps = 0; @@ -692,9 +674,7 @@ BOOST_AUTO_TEST_CASE(test_sph_recv_multi_channel_fragment){ for (size_t i = 0; i < NUM_PKTS_TO_TEST; i++){ std::cout << "data check " << i << std::endl; size_t num_samps_ret = handler.recv( - buffs, NUM_SAMPS_PER_BUFF, metadata, - uhd::io_type_t::COMPLEX_FLOAT32, - uhd::device::RECV_MODE_ONE_PACKET, 1.0 + buffs, NUM_SAMPS_PER_BUFF, metadata, 1.0 ); BOOST_CHECK_EQUAL(metadata.error_code, uhd::rx_metadata_t::ERROR_CODE_NONE); BOOST_CHECK(metadata.has_time_spec); @@ -705,9 +685,7 @@ BOOST_AUTO_TEST_CASE(test_sph_recv_multi_channel_fragment){ if (not metadata.more_fragments) continue; num_samps_ret = handler.recv( - buffs, NUM_SAMPS_PER_BUFF, metadata, - uhd::io_type_t::COMPLEX_FLOAT32, - uhd::device::RECV_MODE_ONE_PACKET, 1.0 + buffs, NUM_SAMPS_PER_BUFF, metadata, 1.0 ); BOOST_CHECK_EQUAL(metadata.error_code, uhd::rx_metadata_t::ERROR_CODE_NONE); BOOST_CHECK(not metadata.more_fragments); @@ -722,9 +700,7 @@ BOOST_AUTO_TEST_CASE(test_sph_recv_multi_channel_fragment){ for (size_t i = 0; i < 3; i++){ std::cout << "timeout check " << i << std::endl; handler.recv( - buffs, NUM_SAMPS_PER_BUFF, metadata, - uhd::io_type_t::COMPLEX_FLOAT32, - uhd::device::RECV_MODE_ONE_PACKET, 1.0 + buffs, NUM_SAMPS_PER_BUFF, metadata, 1.0 ); BOOST_CHECK_EQUAL(metadata.error_code, uhd::rx_metadata_t::ERROR_CODE_TIMEOUT); } diff --git a/host/tests/sph_send_test.cpp b/host/tests/sph_send_test.cpp index ed2f54371..9a91008af 100644 --- a/host/tests/sph_send_test.cpp +++ b/host/tests/sph_send_test.cpp @@ -55,18 +55,18 @@ private: **********************************************************************/ class dummy_send_xport_class{ public: - dummy_send_xport_class(const uhd::otw_type_t &otw_type){ - _otw_type = otw_type; + dummy_send_xport_class(const std::string &end){ + _end = end; } void pop_front_packet( uhd::transport::vrt::if_packet_info_t &ifpi ){ ifpi.num_packet_words32 = _lens.front()/sizeof(boost::uint32_t); - if (_otw_type.byteorder == uhd::otw_type_t::BO_BIG_ENDIAN){ + if (_end == "big"){ uhd::transport::vrt::if_hdr_unpack_be(reinterpret_cast(_mems.front().get()), ifpi); } - if (_otw_type.byteorder == uhd::otw_type_t::BO_LITTLE_ENDIAN){ + if (_end == "little"){ uhd::transport::vrt::if_hdr_unpack_le(reinterpret_cast(_mems.front().get()), ifpi); } _mems.pop_front(); @@ -85,18 +85,19 @@ private: std::list > _mems; std::list _lens; std::list _msbs; //list means no-realloc - uhd::otw_type_t _otw_type; + std::string _end; }; //////////////////////////////////////////////////////////////////////// BOOST_AUTO_TEST_CASE(test_sph_send_one_channel_one_packet_mode){ //////////////////////////////////////////////////////////////////////// - uhd::otw_type_t otw_type; - otw_type.width = 16; - otw_type.shift = 0; - otw_type.byteorder = uhd::otw_type_t::BO_BIG_ENDIAN; + uhd::convert::id_type id; + id.input_markup = "fc32"; + id.num_inputs = 1; + id.output_markup = "sc16_item32_be"; + id.num_outputs = 1; - dummy_send_xport_class dummy_send_xport(otw_type); + dummy_send_xport_class dummy_send_xport("big"); static const double TICK_RATE = 100e6; static const double SAMP_RATE = 10e6; @@ -108,7 +109,7 @@ BOOST_AUTO_TEST_CASE(test_sph_send_one_channel_one_packet_mode){ handler.set_tick_rate(TICK_RATE); handler.set_samp_rate(SAMP_RATE); handler.set_xport_chan_get_buff(0, boost::bind(&dummy_send_xport_class::get_send_buff, &dummy_send_xport, _1)); - handler.set_converter(otw_type); + handler.set_converter(id); handler.set_max_samples_per_packet(20); //allocate metadata and buffer @@ -122,9 +123,7 @@ BOOST_AUTO_TEST_CASE(test_sph_send_one_channel_one_packet_mode){ metadata.start_of_burst = (i == 0); metadata.end_of_burst = (i == NUM_PKTS_TO_TEST-1); const size_t num_sent = handler.send( - &buff.front(), 10 + i%10, metadata, - uhd::io_type_t::COMPLEX_FLOAT32, - uhd::device::SEND_MODE_ONE_PACKET, 1.0 + &buff.front(), 10 + i%10, metadata, 1.0 ); BOOST_CHECK_EQUAL(num_sent, 10 + i%10); metadata.time_spec += uhd::time_spec_t(0, num_sent, SAMP_RATE); @@ -150,12 +149,13 @@ BOOST_AUTO_TEST_CASE(test_sph_send_one_channel_one_packet_mode){ //////////////////////////////////////////////////////////////////////// BOOST_AUTO_TEST_CASE(test_sph_send_one_channel_full_buffer_mode){ //////////////////////////////////////////////////////////////////////// - uhd::otw_type_t otw_type; - otw_type.width = 16; - otw_type.shift = 0; - otw_type.byteorder = uhd::otw_type_t::BO_BIG_ENDIAN; + uhd::convert::id_type id; + id.input_markup = "fc32"; + id.num_inputs = 1; + id.output_markup = "sc16_item32_be"; + id.num_outputs = 1; - dummy_send_xport_class dummy_send_xport(otw_type); + dummy_send_xport_class dummy_send_xport("big"); static const double TICK_RATE = 100e6; static const double SAMP_RATE = 10e6; @@ -167,7 +167,7 @@ BOOST_AUTO_TEST_CASE(test_sph_send_one_channel_full_buffer_mode){ handler.set_tick_rate(TICK_RATE); handler.set_samp_rate(SAMP_RATE); handler.set_xport_chan_get_buff(0, boost::bind(&dummy_send_xport_class::get_send_buff, &dummy_send_xport, _1)); - handler.set_converter(otw_type); + handler.set_converter(id); handler.set_max_samples_per_packet(20); //allocate metadata and buffer @@ -180,9 +180,7 @@ BOOST_AUTO_TEST_CASE(test_sph_send_one_channel_full_buffer_mode){ //generate the test data const size_t num_sent = handler.send( - &buff.front(), buff.size(), metadata, - uhd::io_type_t::COMPLEX_FLOAT32, - uhd::device::SEND_MODE_FULL_BUFF, 1.0 + &buff.front(), buff.size(), metadata, 1.0 ); BOOST_CHECK_EQUAL(num_sent, buff.size()); -- cgit v1.2.3 From 66c95c12a1d2f7b79bdf5b9b871d1b957c56606f Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Tue, 4 Oct 2011 18:08:47 -0700 Subject: uhd: lots of work releated to streamer work and usrp2 implementation --- host/include/uhd/device.hpp | 8 +- host/include/uhd/device_deprecated.ipp | 46 ++-- host/include/uhd/streamer.hpp | 81 ++++--- host/lib/transport/super_recv_packet_handler.hpp | 27 +++ host/lib/transport/super_send_packet_handler.hpp | 27 +++ host/lib/usrp/usrp2/io_impl.cpp | 270 +++++++++++++---------- host/lib/usrp/usrp2/usrp2_impl.cpp | 20 +- host/lib/usrp/usrp2/usrp2_impl.hpp | 27 +-- 8 files changed, 302 insertions(+), 204 deletions(-) (limited to 'host') diff --git a/host/include/uhd/device.hpp b/host/include/uhd/device.hpp index f76739907..c96139858 100644 --- a/host/include/uhd/device.hpp +++ b/host/include/uhd/device.hpp @@ -76,11 +76,11 @@ public: */ static sptr make(const device_addr_t &hint, size_t which = 0); - //! Make a new receive streamer given the list of channels - virtual rx_streamer::sptr get_rx_streamer(const std::vector &channels) = 0; + //! Make a new receive streamer from the streamer arguments + virtual rx_streamer::sptr get_rx_streamer(const streamer_args &args) = 0; - //! Make a new transmit streamer given the list of channels - virtual tx_streamer::sptr get_tx_streamer(const std::vector &channels) = 0; + //! Make a new transmit streamer from the streamer arguments + virtual tx_streamer::sptr get_tx_streamer(const streamer_args &args) = 0; /*! * Receive and asynchronous message from the device. diff --git a/host/include/uhd/device_deprecated.ipp b/host/include/uhd/device_deprecated.ipp index ba0edb1bc..4647a050e 100644 --- a/host/include/uhd/device_deprecated.ipp +++ b/host/include/uhd/device_deprecated.ipp @@ -77,16 +77,16 @@ size_t send( send_mode_t send_mode, double timeout = 0.1 ){ - if (_tx_streamer.get() == NULL or _tx_streamer->get_num_channels() != buffs.size()){ + if (_tx_streamer.get() == NULL or _tx_streamer->get_num_channels() != buffs.size() or _send_tid != io_type.tid){ + _send_tid = io_type.tid; std::vector chans(buffs.size()); for (size_t ch = 0; ch < chans.size(); ch++) chans[ch] = ch; _tx_streamer.reset(); //cleanup possible old one - _tx_streamer = get_tx_streamer(chans); - _send_tid = io_type_t::CUSTOM_TYPE; - } - if (io_type.tid != _send_tid){ - _send_tid = io_type.tid; - _tx_streamer->set_format((_send_tid == io_type_t::COMPLEX_FLOAT32)? "fc32" : "sc16", "sc16"); + streamer_args args; + args.cpu_format = (_send_tid == io_type_t::COMPLEX_FLOAT32)? "fc32" : "sc16"; + args.otw_format = "sc16"; + args.channels = chans; + _tx_streamer = get_tx_streamer(args); } const size_t nsamps = (send_mode == SEND_MODE_ONE_PACKET)? std::min(nsamps_per_buff, get_max_send_samps_per_packet()) : @@ -133,16 +133,16 @@ size_t recv( recv_mode_t recv_mode, double timeout = 0.1 ){ - if (_rx_streamer.get() == NULL or _rx_streamer->get_num_channels() != buffs.size()){ + if (_rx_streamer.get() == NULL or _rx_streamer->get_num_channels() != buffs.size() or _recv_tid != io_type.tid){ + _recv_tid = io_type.tid; std::vector chans(buffs.size()); for (size_t ch = 0; ch < chans.size(); ch++) chans[ch] = ch; _rx_streamer.reset(); //cleanup possible old one - _rx_streamer = get_rx_streamer(chans); - _recv_tid = io_type_t::CUSTOM_TYPE; - } - if (io_type.tid != _recv_tid){ - _recv_tid = io_type.tid; - _rx_streamer->set_format((_recv_tid == io_type_t::COMPLEX_FLOAT32)? "fc32" : "sc16", "sc16"); + streamer_args args; + args.cpu_format = (_send_tid == io_type_t::COMPLEX_FLOAT32)? "fc32" : "sc16"; + args.otw_format = "sc16"; + args.channels = chans; + _rx_streamer = get_rx_streamer(args); } const size_t nsamps = (recv_mode == RECV_MODE_ONE_PACKET)? std::min(nsamps_per_buff, get_max_recv_samps_per_packet()) : @@ -156,10 +156,13 @@ size_t recv( */ size_t get_max_send_samps_per_packet(void){ if (_tx_streamer.get() == NULL){ - std::vector chans(1, 0); - _tx_streamer = get_tx_streamer(chans); + streamer_args args; + args.cpu_format = "fc32"; + args.otw_format = "sc16"; + _tx_streamer = get_tx_streamer(args); + _send_tid = io_type_t::COMPLEX_FLOAT32; } - return _tx_streamer->get_items_per_packet(); + return _tx_streamer->get_max_num_samps(); } /*! @@ -168,10 +171,13 @@ size_t get_max_send_samps_per_packet(void){ */ size_t get_max_recv_samps_per_packet(void){ if (_rx_streamer.get() == NULL){ - std::vector chans(1, 0); - _rx_streamer = get_rx_streamer(chans); + streamer_args args; + args.cpu_format = "fc32"; + args.otw_format = "sc16"; + _rx_streamer = get_rx_streamer(args); + _recv_tid = io_type_t::COMPLEX_FLOAT32; } - return _rx_streamer->get_items_per_packet(); + return _rx_streamer->get_max_num_samps(); } private: diff --git a/host/include/uhd/streamer.hpp b/host/include/uhd/streamer.hpp index d96eeb2b7..7a80d0f36 100644 --- a/host/include/uhd/streamer.hpp +++ b/host/include/uhd/streamer.hpp @@ -23,23 +23,30 @@ #include #include #include +#include #include namespace uhd{ /*! - * A streamer is the host interface to RX or TX samples. - * It represents the layer between the samples on the host - * and samples inside the device's DSP processing. + * A struct of parameters to construct a streamer. + * + * Note: + * Not all combinations of CPU and OTW format have conversion support. + * You may however write and register your own conversion routines. */ -class UHD_API streamer : boost::noncopyable{ -public: - //! Get the number of channels associated with this streamer - virtual size_t get_num_channels(void) const = 0; +struct UHD_API streamer_args{ + + //! Convenience constructor for streamer args + streamer_args( + const std::string &cpu = "fc32", + const std::string &otw = "sc16" + ){ + cpu_format = cpu; + otw_format = otw; + } /*! - * \brief Set the format for all channels in this streamer. - * * The CPU format is a string that describes the format of host memory. * Common CPU formats are: * - fc32 - complex @@ -50,43 +57,47 @@ public: * - f64 - double * - s16 - int16_t * - s8 - int8_t - * + */ + std::string cpu_format; + + /*! * The OTW format is a string that describes the format over-the-wire. * Common OTW format are: * - sc16 - Q16 I16 * - sc8 - Q8_1 I8_1 Q8_0 I8_0 * - s16 - R16_1 R16_0 * - s8 - R8_3 R8_2 R8_1 R8_0 - * + */ + std::string otw_format; + + /*! * The args parameter is currently unused. Leave it blank. * The intention is that a user with a custom DSP design * may want to pass args and do something special with it. - * - * Note: - * Not all combinations of CPU and OTW format have conversion support. - * You may however write and register your own conversion routines. - * - * \param cpu_format the data format for samples used on the host - * \param otw_format the data format of the samples over the wire - * \param args optional arguments to augment the format */ - virtual void set_format( - const std::string &cpu_format, - const std::string &otw_format, - const std::string &args = "" - ) = 0; - - //! Get the number of bytes per CPU item/sample - virtual size_t get_bytes_per_cpu_item(void) const = 0; - - //! Get the number of bytes per OTW item/sample - virtual size_t get_bytes_per_otw_item(void) const = 0; + std::string args; - //! Get the max number of items/samples per packet - virtual size_t get_items_per_packet(void) const = 0; + /*! + * The channels is a list of channel numbers. + * Leave this blank to default to channel 0. + * Set channels for a multi-channel application. + * Channel mapping depends on the front-end selection. + */ + std::vector channels; +}; - //TODO enumerate cpu and otw format options +/*! + * A streamer is the host interface to RX or TX samples. + * It represents the layer between the samples on the host + * and samples inside the device's DSP processing. + */ +class UHD_API streamer : boost::noncopyable{ +public: + //! Get the number of channels associated with this streamer + virtual size_t get_num_channels(void) const = 0; + //! Get the max number of samples per buffer per packet + virtual size_t get_max_num_samps(void) const = 0; }; //! A receive streamer to receive host samples @@ -124,7 +135,7 @@ public: */ virtual size_t recv( const buffs_type &buffs, - size_t nsamps_per_buff, + const size_t nsamps_per_buff, rx_metadata_t &metadata, double timeout = 0.1 ) = 0; @@ -161,7 +172,7 @@ public: */ virtual size_t send( const buffs_type &buffs, - size_t nsamps_per_buff, + const size_t nsamps_per_buff, const tx_metadata_t &metadata, double timeout = 0.1 ) = 0; diff --git a/host/lib/transport/super_recv_packet_handler.hpp b/host/lib/transport/super_recv_packet_handler.hpp index 4ae51e146..f0b053473 100644 --- a/host/lib/transport/super_recv_packet_handler.hpp +++ b/host/lib/transport/super_recv_packet_handler.hpp @@ -562,6 +562,33 @@ private: } }; +class recv_packet_streamer : public recv_packet_handler, public rx_streamer{ +public: + recv_packet_streamer(const size_t max_num_samps){ + _max_num_samps = max_num_samps; + } + + size_t get_num_channels(void) const{ + return this->size(); + } + + size_t get_max_num_samps(void) const{ + return _max_num_samps; + } + + size_t recv( + const rx_streamer::buffs_type &buffs, + const size_t nsamps_per_buff, + uhd::rx_metadata_t &metadata, + double timeout + ){ + return recv_packet_handler::recv(buffs, nsamps_per_buff, metadata, timeout); + } + +private: + size_t _max_num_samps; +}; + }}} //namespace #endif /* INCLUDED_LIBUHD_TRANSPORT_SUPER_RECV_PACKET_HANDLER_HPP */ diff --git a/host/lib/transport/super_send_packet_handler.hpp b/host/lib/transport/super_send_packet_handler.hpp index 6950abb73..edfe9bd13 100644 --- a/host/lib/transport/super_send_packet_handler.hpp +++ b/host/lib/transport/super_send_packet_handler.hpp @@ -259,6 +259,33 @@ private: } }; +class send_packet_streamer : public send_packet_handler, public tx_streamer{ +public: + send_packet_streamer(const size_t max_num_samps){ + _max_num_samps = max_num_samps; + } + + size_t get_num_channels(void) const{ + return this->size(); + } + + size_t get_max_num_samps(void) const{ + return _max_num_samps; + } + + size_t send( + const tx_streamer::buffs_type &buffs, + const size_t nsamps_per_buff, + const uhd::tx_metadata_t &metadata, + double timeout + ){ + return send_packet_handler::send(buffs, nsamps_per_buff, metadata, timeout); + } + +private: + size_t _max_num_samps; +}; + }}} //namespace #endif /* INCLUDED_LIBUHD_TRANSPORT_SUPER_SEND_PACKET_HANDLER_HPP */ diff --git a/host/lib/usrp/usrp2/io_impl.cpp b/host/lib/usrp/usrp2/io_impl.cpp index 70331e536..98bfcdd3b 100644 --- a/host/lib/usrp/usrp2/io_impl.cpp +++ b/host/lib/usrp/usrp2/io_impl.cpp @@ -31,6 +31,7 @@ #include #include #include +#include #include using namespace uhd; @@ -158,10 +159,6 @@ struct usrp2_impl::io_impl{ std::vector tx_xports; std::vector fc_mons; - //state management for the vrt packet handler code - sph::recv_packet_handler recv_handler; - sph::send_packet_handler send_handler; - //methods and variables for the pirate crew void recv_pirate_loop(zero_copy_if::sptr, size_t); std::list pirate_tasks; @@ -237,17 +234,6 @@ void usrp2_impl::io_impl::recv_pirate_loop( * Helper Functions **********************************************************************/ void usrp2_impl::io_init(void){ - - //setup rx otw type - _rx_otw_type.width = 16; - _rx_otw_type.shift = 0; - _rx_otw_type.byteorder = uhd::otw_type_t::BO_BIG_ENDIAN; - - //setup tx otw type - _tx_otw_type.width = 16; - _tx_otw_type.shift = 0; - _tx_otw_type.byteorder = uhd::otw_type_t::BO_BIG_ENDIAN; - //create new io impl _io_impl = UHD_PIMPL_MAKE(io_impl, ()); @@ -260,6 +246,12 @@ void usrp2_impl::io_init(void){ ))); } + //allocate streamer weak ptrs containers + BOOST_FOREACH(const std::string &mb, _mbc.keys()){ + _mbc[mb].rx_streamers.resize(_mbc[mb].rx_dsps.size()); + _mbc[mb].tx_streamers.resize(1/*known to be 1 dsp*/); + } + //create a new pirate thread for each zc if (yarr!!) size_t index = 0; BOOST_FOREACH(const std::string &mb, _mbc.keys()){ @@ -269,58 +261,68 @@ void usrp2_impl::io_init(void){ _mbc[mb].tx_dsp_xport, index++ ))); } - - //init some handler stuff - _io_impl->recv_handler.set_vrt_unpacker(&vrt::if_hdr_unpack_be); - _io_impl->recv_handler.set_converter(_rx_otw_type); - _io_impl->send_handler.set_vrt_packer(&vrt::if_hdr_pack_be, vrt_send_header_offset_words32); - _io_impl->send_handler.set_converter(_tx_otw_type); - _io_impl->send_handler.set_max_samples_per_packet(get_max_send_samps_per_packet()); - - //set the packet threshold to be an entire socket buffer's worth - const size_t packets_per_sock_buff = size_t(50e6/_mbc[_mbc.keys().front()].rx_dsp_xports[0]->get_recv_frame_size()); - _io_impl->recv_handler.set_alignment_failure_threshold(packets_per_sock_buff); } void usrp2_impl::update_tick_rate(const double rate){ - _io_impl->tick_rate = rate; - boost::mutex::scoped_lock recv_lock = _io_impl->recv_handler.get_scoped_lock(); - _io_impl->recv_handler.set_tick_rate(rate); - boost::mutex::scoped_lock send_lock = _io_impl->send_handler.get_scoped_lock(); - _io_impl->send_handler.set_tick_rate(rate); + _io_impl->tick_rate = rate; //shadow for async msg + + //update the tick rate on all existing streamers -> thread safe + BOOST_FOREACH(const std::string &mb, _mbc.keys()){ + for (size_t i = 0; i < _mbc[mb].rx_streamers.size(); i++){ + boost::shared_ptr my_streamer = + boost::dynamic_pointer_cast(_mbc[mb].rx_streamers[i].lock()); + if (my_streamer.get() == NULL) continue; + boost::mutex::scoped_lock lock = my_streamer->get_scoped_lock(); + my_streamer->set_tick_rate(rate); + } + for (size_t i = 0; i < _mbc[mb].tx_streamers.size(); i++){ + boost::shared_ptr my_streamer = + boost::dynamic_pointer_cast(_mbc[mb].tx_streamers[i].lock()); + if (my_streamer.get() == NULL) continue; + boost::mutex::scoped_lock lock = my_streamer->get_scoped_lock(); + my_streamer->set_tick_rate(rate); + } + } } -void usrp2_impl::update_rx_samp_rate(const double rate){ - boost::mutex::scoped_lock recv_lock = _io_impl->recv_handler.get_scoped_lock(); - _io_impl->recv_handler.set_samp_rate(rate); - const double adj = _mbc[_mbc.keys().front()].rx_dsps.front()->get_scaling_adjustment(); - _io_impl->recv_handler.set_scale_factor(adj/32767.); +void usrp2_impl::update_rx_samp_rate(const std::string &mb, const size_t dsp, const double rate){ + boost::shared_ptr my_streamer = + boost::dynamic_pointer_cast(_mbc[mb].rx_streamers[dsp].lock()); + if (my_streamer.get() == NULL) return; + + boost::mutex::scoped_lock lock = my_streamer->get_scoped_lock(); + + my_streamer->set_samp_rate(rate); + const double adj = _mbc[mb].rx_dsps[dsp]->get_scaling_adjustment(); + my_streamer->set_scale_factor(adj/32767.); } -void usrp2_impl::update_tx_samp_rate(const double rate){ - boost::mutex::scoped_lock send_lock = _io_impl->send_handler.get_scoped_lock(); - _io_impl->send_handler.set_samp_rate(rate); +void usrp2_impl::update_tx_samp_rate(const std::string &mb, const size_t dsp, const double rate){ + boost::shared_ptr my_streamer = + boost::dynamic_pointer_cast(_mbc[mb].tx_streamers[dsp].lock()); + if (my_streamer.get() == NULL) return; + + boost::mutex::scoped_lock lock = my_streamer->get_scoped_lock(); + + my_streamer->set_samp_rate(rate); } -static subdev_spec_t replace_zero_in_spec(const std::string &type, const subdev_spec_t &spec){ - subdev_spec_t new_spec; - BOOST_FOREACH(const subdev_spec_pair_t &pair, spec){ - if (pair.db_name == "0"){ - UHD_MSG(warning) - << boost::format("In the %s subdevice specification: %s") % type % spec.to_string() << std::endl - << "Accepting dboard slot name \"0\" for backward compatibility." << std::endl - << "The official name of the dboard slot on USRP2/N-Series is \"A\"." << std::endl - ; - new_spec.push_back(subdev_spec_pair_t("A", pair.sd_name)); +void usrp2_impl::update_rates(void){ + BOOST_FOREACH(const std::string &mb, _mbc.keys()){ + fs_path root = "/mboards/" + mb; + _tree->access(root / "tick_rate").update(); + + //and now that the tick rate is set, init the host rates to something + BOOST_FOREACH(const std::string &name, _tree->list(root / "rx_dsps")){ + _tree->access(root / "rx_dsps" / name / "rate" / "value").update(); + } + BOOST_FOREACH(const std::string &name, _tree->list(root / "tx_dsps")){ + _tree->access(root / "tx_dsps" / name / "rate" / "value").update(); } - else new_spec.push_back(pair); } - return new_spec; } -subdev_spec_t usrp2_impl::update_rx_subdev_spec(const std::string &which_mb, const subdev_spec_t &spec_){ - const subdev_spec_t spec = replace_zero_in_spec("RX", spec_); - boost::mutex::scoped_lock recv_lock = _io_impl->recv_handler.get_scoped_lock(); +void usrp2_impl::update_rx_subdev_spec(const std::string &which_mb, const subdev_spec_t &spec){ fs_path root = "/mboards/" + which_mb + "/dboards"; //sanity checking @@ -339,24 +341,9 @@ subdev_spec_t usrp2_impl::update_rx_subdev_spec(const std::string &which_mb, con _mbc[which_mb].rx_chan_occ = spec.size(); size_t nchan = 0; BOOST_FOREACH(const std::string &mb, _mbc.keys()) nchan += _mbc[mb].rx_chan_occ; - _io_impl->recv_handler.resize(nchan); - - //bind new callbacks for the handler - size_t chan = 0; - BOOST_FOREACH(const std::string &mb, _mbc.keys()){ - for (size_t dsp = 0; dsp < _mbc[mb].rx_chan_occ; dsp++){ - _mbc[mb].rx_dsps[dsp]->set_nsamps_per_packet(get_max_recv_samps_per_packet()); //seems to be a good place to set this - _io_impl->recv_handler.set_xport_chan_get_buff(chan++, boost::bind( - &zero_copy_if::get_recv_buff, _mbc[mb].rx_dsp_xports[dsp], _1 - )); - } - } - return spec; } -subdev_spec_t usrp2_impl::update_tx_subdev_spec(const std::string &which_mb, const subdev_spec_t &spec_){ - const subdev_spec_t spec = replace_zero_in_spec("TX", spec_); - boost::mutex::scoped_lock send_lock = _io_impl->send_handler.get_scoped_lock(); +void usrp2_impl::update_tx_subdev_spec(const std::string &which_mb, const subdev_spec_t &spec){ fs_path root = "/mboards/" + which_mb + "/dboards"; //sanity checking @@ -370,18 +357,6 @@ subdev_spec_t usrp2_impl::update_tx_subdev_spec(const std::string &which_mb, con _mbc[which_mb].tx_chan_occ = spec.size(); size_t nchan = 0; BOOST_FOREACH(const std::string &mb, _mbc.keys()) nchan += _mbc[mb].tx_chan_occ; - _io_impl->send_handler.resize(nchan); - - //bind new callbacks for the handler - size_t chan = 0, i = 0; - BOOST_FOREACH(const std::string &mb, _mbc.keys()){ - for (size_t dsp = 0; dsp < _mbc[mb].tx_chan_occ; dsp++){ - _io_impl->send_handler.set_xport_chan_get_buff(chan++, boost::bind( - &usrp2_impl::io_impl::get_send_buff, _io_impl.get(), i++, _1 - )); - } - } - return spec; } /*********************************************************************** @@ -395,51 +370,118 @@ bool usrp2_impl::recv_async_msg( } /*********************************************************************** - * Send Data + * Receive streamer **********************************************************************/ -size_t usrp2_impl::get_max_send_samps_per_packet(void) const{ +rx_streamer::sptr usrp2_impl::get_rx_streamer(const uhd::streamer_args &args){ + //map an empty channel set to chan0 + const std::vector channels = args.channels.empty()? std::vector(1, 0) : args.channels; + + //calculate packet size static const size_t hdr_size = 0 + vrt::max_if_hdr_words32*sizeof(boost::uint32_t) - + vrt_send_header_offset_words32*sizeof(boost::uint32_t) + + sizeof(vrt::if_packet_info_t().tlr) //forced to have trailer - sizeof(vrt::if_packet_info_t().cid) //no class id ever used ; - const size_t bpp = _mbc[_mbc.keys().front()].tx_dsp_xport->get_send_frame_size() - hdr_size; - return bpp/_tx_otw_type.get_sample_size(); -} + const size_t bpp = _mbc[_mbc.keys().front()].rx_dsp_xports[0]->get_recv_frame_size() - hdr_size; + const size_t spp = bpp/convert::get_bytes_per_item(args.otw_format); + + //make the new streamer given the samples per packet + boost::shared_ptr my_streamer = boost::make_shared(spp); + + //init some streamer stuff + my_streamer->resize(channels.size()); + my_streamer->set_vrt_unpacker(&vrt::if_hdr_unpack_be); + + //set the converter + uhd::convert::id_type id; + id.input_markup = args.otw_format + "_item32_be"; + id.num_inputs = 1; + id.output_markup = args.cpu_format; + id.num_outputs = 1; + id.args = args.args; + my_streamer->set_converter(id); + + //bind callbacks for the handler + for (size_t chan_i = 0; chan_i < channels.size(); chan_i++){ + const size_t chan = channels[chan_i]; + size_t num_chan_so_far = 0; + BOOST_FOREACH(const std::string &mb, _mbc.keys()){ + num_chan_so_far += _mbc[mb].rx_chan_occ; + if (chan < num_chan_so_far){ + const size_t dsp = num_chan_so_far - chan - 1; + _mbc[mb].rx_dsps[dsp]->set_nsamps_per_packet(spp); //seems to be a good place to set this + my_streamer->set_xport_chan_get_buff(chan_i, boost::bind( + &zero_copy_if::get_recv_buff, _mbc[mb].rx_dsp_xports[dsp], _1 + )); + _mbc[mb].rx_streamers[dsp] = my_streamer; //store weak pointer + break; + } + } + } -size_t usrp2_impl::send( - const send_buffs_type &buffs, size_t nsamps_per_buff, - const tx_metadata_t &metadata, const io_type_t &io_type, - send_mode_t send_mode, double timeout -){ - return _io_impl->send_handler.send( - buffs, nsamps_per_buff, - metadata, io_type, - send_mode, timeout - ); + //set the packet threshold to be an entire socket buffer's worth + const size_t packets_per_sock_buff = size_t(50e6/_mbc[_mbc.keys().front()].rx_dsp_xports[0]->get_recv_frame_size()); + my_streamer->set_alignment_failure_threshold(packets_per_sock_buff); + + //sets all tick and samp rates on this streamer + this->update_rates(); + + return my_streamer; } /*********************************************************************** - * Receive Data + * Transmit streamer **********************************************************************/ -size_t usrp2_impl::get_max_recv_samps_per_packet(void) const{ +tx_streamer::sptr usrp2_impl::get_tx_streamer(const uhd::streamer_args &args){ + //map an empty channel set to chan0 + const std::vector channels = args.channels.empty()? std::vector(1, 0) : args.channels; + + //calculate packet size static const size_t hdr_size = 0 + vrt::max_if_hdr_words32*sizeof(boost::uint32_t) - + sizeof(vrt::if_packet_info_t().tlr) //forced to have trailer + + vrt_send_header_offset_words32*sizeof(boost::uint32_t) - sizeof(vrt::if_packet_info_t().cid) //no class id ever used ; - const size_t bpp = _mbc[_mbc.keys().front()].rx_dsp_xports[0]->get_recv_frame_size() - hdr_size; - return bpp/_rx_otw_type.get_sample_size(); -} + const size_t bpp = _mbc[_mbc.keys().front()].tx_dsp_xport->get_send_frame_size() - hdr_size; + const size_t spp = bpp/convert::get_bytes_per_item(args.otw_format); + + //make the new streamer given the samples per packet + boost::shared_ptr my_streamer = boost::make_shared(spp); + + //init some streamer stuff + my_streamer->resize(channels.size()); + my_streamer->set_vrt_packer(&vrt::if_hdr_pack_be); + + //set the converter + uhd::convert::id_type id; + id.input_markup = args.cpu_format; + id.num_inputs = 1; + id.output_markup = args.otw_format + "_item32_be"; + id.num_outputs = 1; + id.args = args.args; + my_streamer->set_converter(id); + + //bind callbacks for the handler + for (size_t chan_i = 0; chan_i < channels.size(); chan_i++){ + const size_t chan = channels[chan_i]; + size_t num_chan_so_far = 0; + size_t abs = 0; + BOOST_FOREACH(const std::string &mb, _mbc.keys()){ + num_chan_so_far += _mbc[mb].tx_chan_occ; + if (chan < num_chan_so_far){ + const size_t dsp = num_chan_so_far - chan - 1; + my_streamer->set_xport_chan_get_buff(chan_i, boost::bind( + &usrp2_impl::io_impl::get_send_buff, _io_impl.get(), abs, _1 + )); + _mbc[mb].tx_streamers[dsp] = my_streamer; //store weak pointer + break; + } + abs += 1; //assume 1 tx dsp + } + } -size_t usrp2_impl::recv( - const recv_buffs_type &buffs, size_t nsamps_per_buff, - rx_metadata_t &metadata, const io_type_t &io_type, - recv_mode_t recv_mode, double timeout -){ - return _io_impl->recv_handler.recv( - buffs, nsamps_per_buff, - metadata, io_type, - recv_mode, timeout - ); + //sets all tick and samp rates on this streamer + this->update_rates(); + + return my_streamer; } diff --git a/host/lib/usrp/usrp2/usrp2_impl.cpp b/host/lib/usrp/usrp2/usrp2_impl.cpp index 2b541bcf0..2d89ddaf4 100644 --- a/host/lib/usrp/usrp2/usrp2_impl.cpp +++ b/host/lib/usrp/usrp2/usrp2_impl.cpp @@ -458,9 +458,9 @@ usrp2_impl::usrp2_impl(const device_addr_t &_device_addr){ ); //TODO lots of properties to expose here for frontends _tree->create(mb_path / "rx_subdev_spec") - .coerce(boost::bind(&usrp2_impl::update_rx_subdev_spec, this, mb, _1)); + .subscribe(boost::bind(&usrp2_impl::update_rx_subdev_spec, this, mb, _1)); _tree->create(mb_path / "tx_subdev_spec") - .coerce(boost::bind(&usrp2_impl::update_tx_subdev_spec, this, mb, _1)); + .subscribe(boost::bind(&usrp2_impl::update_tx_subdev_spec, this, mb, _1)); //////////////////////////////////////////////////////////////// // create rx dsp control objects @@ -481,8 +481,9 @@ usrp2_impl::usrp2_impl(const device_addr_t &_device_addr){ _mbc[mb].rx_dsp_xports[dspno]->get_recv_buff(0.01).get(); //recv with timeout for expected fs_path rx_dsp_path = mb_path / str(boost::format("rx_dsps/%u") % dspno); _tree->create(rx_dsp_path / "rate/value") + .set(1e6) //some default .coerce(boost::bind(&rx_dsp_core_200::set_host_rate, _mbc[mb].rx_dsps[dspno], _1)) - .subscribe(boost::bind(&usrp2_impl::update_rx_samp_rate, this, _1)); + .subscribe(boost::bind(&usrp2_impl::update_rx_samp_rate, this, mb, dspno, _1)); _tree->create(rx_dsp_path / "freq/value") .coerce(boost::bind(&rx_dsp_core_200::set_freq, _mbc[mb].rx_dsps[dspno], _1)); _tree->create(rx_dsp_path / "freq/range") @@ -501,8 +502,9 @@ usrp2_impl::usrp2_impl(const device_addr_t &_device_addr){ _tree->access(mb_path / "tick_rate") .subscribe(boost::bind(&tx_dsp_core_200::set_tick_rate, _mbc[mb].tx_dsp, _1)); _tree->create(mb_path / "tx_dsps/0/rate/value") + .set(1e6) //some default .coerce(boost::bind(&tx_dsp_core_200::set_host_rate, _mbc[mb].tx_dsp, _1)) - .subscribe(boost::bind(&usrp2_impl::update_tx_samp_rate, this, _1)); + .subscribe(boost::bind(&usrp2_impl::update_tx_samp_rate, this, mb, 0, _1)); _tree->create(mb_path / "tx_dsps/0/freq/value") .coerce(boost::bind(&usrp2_impl::set_tx_dsp_freq, this, mb, _1)); _tree->create(mb_path / "tx_dsps/0/freq/range") @@ -594,17 +596,9 @@ usrp2_impl::usrp2_impl(const device_addr_t &_device_addr){ this->io_init(); //do some post-init tasks + this->update_rates(); BOOST_FOREACH(const std::string &mb, _mbc.keys()){ fs_path root = "/mboards/" + mb; - _tree->access(root / "tick_rate").update(); - - //and now that the tick rate is set, init the host rates to something - BOOST_FOREACH(const std::string &name, _tree->list(root / "rx_dsps")){ - _tree->access(root / "rx_dsps" / name / "rate" / "value").set(1e6); - } - BOOST_FOREACH(const std::string &name, _tree->list(root / "tx_dsps")){ - _tree->access(root / "tx_dsps" / name / "rate" / "value").set(1e6); - } _tree->access(root / "rx_subdev_spec").set(subdev_spec_t("A:"+_mbc[mb].dboard_manager->get_rx_subdev_names()[0])); _tree->access(root / "tx_subdev_spec").set(subdev_spec_t("A:"+_mbc[mb].dboard_manager->get_tx_subdev_names()[0])); diff --git a/host/lib/usrp/usrp2/usrp2_impl.hpp b/host/lib/usrp/usrp2/usrp2_impl.hpp index 6f133f411..566c93853 100644 --- a/host/lib/usrp/usrp2/usrp2_impl.hpp +++ b/host/lib/usrp/usrp2/usrp2_impl.hpp @@ -31,7 +31,6 @@ #include #include #include -#include #include #include #include @@ -73,18 +72,8 @@ public: ~usrp2_impl(void); //the io interface - size_t send( - const send_buffs_type &, size_t, - const uhd::tx_metadata_t &, const uhd::io_type_t &, - uhd::device::send_mode_t, double - ); - size_t recv( - const recv_buffs_type &, size_t, - uhd::rx_metadata_t &, const uhd::io_type_t &, - uhd::device::recv_mode_t, double - ); - size_t get_max_send_samps_per_packet(void) const; - size_t get_max_recv_samps_per_packet(void) const; + uhd::rx_streamer::sptr get_rx_streamer(const uhd::streamer_args &args); + uhd::tx_streamer::sptr get_tx_streamer(const uhd::streamer_args &args); bool recv_async_msg(uhd::async_metadata_t &, double); private: @@ -97,6 +86,8 @@ private: rx_frontend_core_200::sptr rx_fe; tx_frontend_core_200::sptr tx_fe; std::vector rx_dsps; + std::vector > rx_streamers; + std::vector > tx_streamers; tx_dsp_core_200::sptr tx_dsp; time64_core_200::sptr time64; std::vector rx_dsp_xports; @@ -120,15 +111,15 @@ private: } //io impl methods and members - uhd::otw_type_t _rx_otw_type, _tx_otw_type; UHD_PIMPL_DECL(io_impl) _io_impl; void io_init(void); void update_tick_rate(const double rate); - void update_rx_samp_rate(const double rate); - void update_tx_samp_rate(const double rate); + void update_rx_samp_rate(const std::string &, const size_t, const double rate); + void update_tx_samp_rate(const std::string &, const size_t, const double rate); + void update_rates(void); //update spec methods are coercers until we only accept db_name == A - uhd::usrp::subdev_spec_t update_rx_subdev_spec(const std::string &, const uhd::usrp::subdev_spec_t &); - uhd::usrp::subdev_spec_t update_tx_subdev_spec(const std::string &, const uhd::usrp::subdev_spec_t &); + void update_rx_subdev_spec(const std::string &, const uhd::usrp::subdev_spec_t &); + void update_tx_subdev_spec(const std::string &, const uhd::usrp::subdev_spec_t &); double set_tx_dsp_freq(const std::string &, const double); uhd::meta_range_t get_tx_dsp_freq_range(const std::string &); void update_clock_source(const std::string &, const std::string &); -- cgit v1.2.3 From fbe2aefe299a4d3ddf8cceb0eb5866136f48744d Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Wed, 5 Oct 2011 11:54:36 -0700 Subject: usrp2: additional corrections for streaming to work --- host/lib/transport/super_send_packet_handler.hpp | 1 + host/lib/usrp/usrp2/io_impl.cpp | 6 +++--- host/lib/usrp/usrp2/usrp2_impl.hpp | 4 ++-- 3 files changed, 6 insertions(+), 5 deletions(-) (limited to 'host') diff --git a/host/lib/transport/super_send_packet_handler.hpp b/host/lib/transport/super_send_packet_handler.hpp index edfe9bd13..87ae01d47 100644 --- a/host/lib/transport/super_send_packet_handler.hpp +++ b/host/lib/transport/super_send_packet_handler.hpp @@ -263,6 +263,7 @@ class send_packet_streamer : public send_packet_handler, public tx_streamer{ public: send_packet_streamer(const size_t max_num_samps){ _max_num_samps = max_num_samps; + this->set_max_samples_per_packet(_max_num_samps); } size_t get_num_channels(void) const{ diff --git a/host/lib/usrp/usrp2/io_impl.cpp b/host/lib/usrp/usrp2/io_impl.cpp index 98bfcdd3b..44217c36c 100644 --- a/host/lib/usrp/usrp2/io_impl.cpp +++ b/host/lib/usrp/usrp2/io_impl.cpp @@ -298,8 +298,8 @@ void usrp2_impl::update_rx_samp_rate(const std::string &mb, const size_t dsp, co } void usrp2_impl::update_tx_samp_rate(const std::string &mb, const size_t dsp, const double rate){ - boost::shared_ptr my_streamer = - boost::dynamic_pointer_cast(_mbc[mb].tx_streamers[dsp].lock()); + boost::shared_ptr my_streamer = + boost::dynamic_pointer_cast(_mbc[mb].tx_streamers[dsp].lock()); if (my_streamer.get() == NULL) return; boost::mutex::scoped_lock lock = my_streamer->get_scoped_lock(); @@ -450,7 +450,7 @@ tx_streamer::sptr usrp2_impl::get_tx_streamer(const uhd::streamer_args &args){ //init some streamer stuff my_streamer->resize(channels.size()); - my_streamer->set_vrt_packer(&vrt::if_hdr_pack_be); + my_streamer->set_vrt_packer(&vrt::if_hdr_pack_be, vrt_send_header_offset_words32); //set the converter uhd::convert::id_type id; diff --git a/host/lib/usrp/usrp2/usrp2_impl.hpp b/host/lib/usrp/usrp2/usrp2_impl.hpp index 566c93853..a67c704c8 100644 --- a/host/lib/usrp/usrp2/usrp2_impl.hpp +++ b/host/lib/usrp/usrp2/usrp2_impl.hpp @@ -86,8 +86,8 @@ private: rx_frontend_core_200::sptr rx_fe; tx_frontend_core_200::sptr tx_fe; std::vector rx_dsps; - std::vector > rx_streamers; - std::vector > tx_streamers; + std::vector > rx_streamers; + std::vector > tx_streamers; tx_dsp_core_200::sptr tx_dsp; time64_core_200::sptr time64; std::vector rx_dsp_xports; -- cgit v1.2.3 From e89b20da1511f02d887435d093d8efef3e4df261 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Wed, 5 Oct 2011 11:59:10 -0700 Subject: uhd: tweaks to streamer interface and multi-usrp convenience interface --- host/include/uhd/streamer.hpp | 28 +++++++++++++++++----------- host/include/uhd/usrp/multi_usrp.hpp | 10 ++++++++++ 2 files changed, 27 insertions(+), 11 deletions(-) (limited to 'host') diff --git a/host/include/uhd/streamer.hpp b/host/include/uhd/streamer.hpp index 7a80d0f36..c9c6fef89 100644 --- a/host/include/uhd/streamer.hpp +++ b/host/include/uhd/streamer.hpp @@ -87,23 +87,19 @@ struct UHD_API streamer_args{ }; /*! - * A streamer is the host interface to RX or TX samples. + * The RX streamer is the host interface to receiving samples. * It represents the layer between the samples on the host - * and samples inside the device's DSP processing. + * and samples inside the device's receive DSP processing. */ -class UHD_API streamer : boost::noncopyable{ +class UHD_API rx_streamer : boost::noncopyable{ public: + typedef boost::shared_ptr sptr; + //! Get the number of channels associated with this streamer virtual size_t get_num_channels(void) const = 0; //! Get the max number of samples per buffer per packet virtual size_t get_max_num_samps(void) const = 0; -}; - -//! A receive streamer to receive host samples -class UHD_API rx_streamer : public streamer{ -public: - typedef boost::shared_ptr sptr; //! Typedef for a pointer to a single, or a collection of recv buffers typedef ref_vector buffs_type; @@ -141,11 +137,21 @@ public: ) = 0; }; -//! A transmit streamer to send host samples -class UHD_API tx_streamer : public streamer{ +/*! + * The TX streamer is the host interface to transmitting samples. + * It represents the layer between the samples on the host + * and samples inside the device's transmit DSP processing. + */ +class UHD_API tx_streamer : boost::noncopyable{ public: typedef boost::shared_ptr sptr; + //! Get the number of channels associated with this streamer + virtual size_t get_num_channels(void) const = 0; + + //! Get the max number of samples per buffer per packet + virtual size_t get_max_num_samps(void) const = 0; + //! Typedef for a pointer to a single, or a collection of send buffers typedef ref_vector buffs_type; diff --git a/host/include/uhd/usrp/multi_usrp.hpp b/host/include/uhd/usrp/multi_usrp.hpp index 00d5dfe7c..303af7ef9 100644 --- a/host/include/uhd/usrp/multi_usrp.hpp +++ b/host/include/uhd/usrp/multi_usrp.hpp @@ -108,6 +108,16 @@ public: */ virtual device::sptr get_device(void) = 0; + //! Convenience method to get a RX streamer + rx_streamer::sptr get_rx_streamer(const streamer_args &args){ + return this->get_device()->get_rx_streamer(args); + } + + //! Convenience method to get a TX streamer + tx_streamer::sptr get_tx_streamer(const streamer_args &args){ + return this->get_device()->get_tx_streamer(args); + } + /******************************************************************* * Mboard methods ******************************************************************/ -- cgit v1.2.3 From a629bbe7e3c39a10bdc3a981f6badb85a436b443 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Wed, 5 Oct 2011 11:59:27 -0700 Subject: uhd: updated examples to use new streamer interface --- host/examples/benchmark_rate.cpp | 31 +++++++------- host/examples/latency_test.cpp | 17 ++++---- host/examples/rx_ascii_art_dft.cpp | 10 +++-- host/examples/rx_multi_samples.cpp | 15 ++++--- host/examples/rx_samples_to_file.cpp | 17 ++++---- host/examples/rx_samples_to_udp.cpp | 12 +++--- host/examples/rx_timed_samples.cpp | 12 +++--- host/examples/test_messages.cpp | 75 ++++++++++++++-------------------- host/examples/tx_bursts.cpp | 14 ++++--- host/examples/tx_samples_from_file.cpp | 17 ++++---- host/examples/tx_timed_samples.cpp | 17 ++++---- host/examples/tx_waveforms.cpp | 18 ++++---- 12 files changed, 128 insertions(+), 127 deletions(-) (limited to 'host') diff --git a/host/examples/benchmark_rate.cpp b/host/examples/benchmark_rate.cpp index 774b240d4..7862bd44b 100644 --- a/host/examples/benchmark_rate.cpp +++ b/host/examples/benchmark_rate.cpp @@ -43,6 +43,10 @@ unsigned long long num_seq_errors = 0; void benchmark_rx_rate(uhd::usrp::multi_usrp::sptr usrp){ uhd::set_thread_priority_safe(); + //create a receive streamer + uhd::streamer_args stream_args("fc32"); //complex floats + uhd::rx_streamer::sptr rx_stream = usrp->get_rx_streamer(stream_args); + //print pre-test summary std::cout << boost::format( "Testing receive rate %f Msps" @@ -50,7 +54,7 @@ void benchmark_rx_rate(uhd::usrp::multi_usrp::sptr usrp){ //setup variables and allocate buffer uhd::rx_metadata_t md; - const size_t max_samps_per_packet = usrp->get_device()->get_max_recv_samps_per_packet(); + const size_t max_samps_per_packet = rx_stream->get_max_num_samps(); std::vector > buff(max_samps_per_packet); bool had_an_overflow = false; uhd::time_spec_t last_time; @@ -58,10 +62,8 @@ void benchmark_rx_rate(uhd::usrp::multi_usrp::sptr usrp){ usrp->issue_stream_cmd(uhd::stream_cmd_t::STREAM_MODE_START_CONTINUOUS); while (not boost::this_thread::interruption_requested()){ - num_rx_samps += usrp->get_device()->recv( - &buff.front(), buff.size(), md, - uhd::io_type_t::COMPLEX_FLOAT32, - uhd::device::RECV_MODE_ONE_PACKET + num_rx_samps += rx_stream->recv( + &buff.front(), buff.size(), md ); //handle the error codes @@ -95,6 +97,10 @@ void benchmark_rx_rate(uhd::usrp::multi_usrp::sptr usrp){ void benchmark_tx_rate(uhd::usrp::multi_usrp::sptr usrp){ uhd::set_thread_priority_safe(); + //create a transmit streamer + uhd::streamer_args stream_args("fc32"); //complex floats + uhd::tx_streamer::sptr tx_stream = usrp->get_tx_streamer(stream_args); + //print pre-test summary std::cout << boost::format( "Testing transmit rate %f Msps" @@ -103,23 +109,16 @@ void benchmark_tx_rate(uhd::usrp::multi_usrp::sptr usrp){ //setup variables and allocate buffer uhd::tx_metadata_t md; md.has_time_spec = false; - const size_t max_samps_per_packet = usrp->get_device()->get_max_send_samps_per_packet(); + const size_t max_samps_per_packet = tx_stream->get_max_num_samps(); std::vector > buff(max_samps_per_packet); while (not boost::this_thread::interruption_requested()){ - num_tx_samps += usrp->get_device()->send( - &buff.front(), buff.size(), md, - uhd::io_type_t::COMPLEX_FLOAT32, - uhd::device::SEND_MODE_ONE_PACKET - ); + num_tx_samps += tx_stream->send(&buff.front(), buff.size(), md); } //send a mini EOB packet - md.end_of_burst = true; - usrp->get_device()->send("", 0, md, - uhd::io_type_t::COMPLEX_FLOAT32, - uhd::device::SEND_MODE_FULL_BUFF - ); + md.end_of_burst = true; + tx_stream->send("", 0, md); } void benchmark_tx_rate_async_helper(uhd::usrp::multi_usrp::sptr usrp){ diff --git a/host/examples/latency_test.cpp b/host/examples/latency_test.cpp index 85ac73567..b995b0433 100644 --- a/host/examples/latency_test.cpp +++ b/host/examples/latency_test.cpp @@ -83,6 +83,11 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){ //allocate a buffer to use std::vector > buffer(nsamps); + //create RX and TX streamers + uhd::streamer_args stream_args("fc32"); //complex floats + uhd::rx_streamer::sptr rx_stream = usrp->get_rx_streamer(stream_args); + uhd::tx_streamer::sptr tx_stream = usrp->get_tx_streamer(stream_args); + //initialize result counts int time_error = 0; int ack = 0; @@ -104,10 +109,8 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){ * Receive the requested packet **************************************************************/ uhd::rx_metadata_t rx_md; - size_t num_rx_samps = usrp->get_device()->recv( - &buffer.front(), buffer.size(), rx_md, - uhd::io_type_t::COMPLEX_FLOAT32, - uhd::device::RECV_MODE_FULL_BUFF + size_t num_rx_samps = rx_stream->recv( + &buffer.front(), buffer.size(), rx_md ); if(verbose) std::cout << boost::format("Got packet: %u samples, %u full secs, %f frac secs") @@ -121,10 +124,8 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){ tx_md.end_of_burst = true; tx_md.has_time_spec = true; tx_md.time_spec = rx_md.time_spec + uhd::time_spec_t(rtt); - size_t num_tx_samps = usrp->get_device()->send( - &buffer.front(), buffer.size(), tx_md, - uhd::io_type_t::COMPLEX_FLOAT32, - uhd::device::SEND_MODE_FULL_BUFF + size_t num_tx_samps = tx_stream->send( + &buffer.front(), buffer.size(), tx_md ); if(verbose) std::cout << boost::format("Sent %d samples") % num_tx_samps << std::endl; diff --git a/host/examples/rx_ascii_art_dft.cpp b/host/examples/rx_ascii_art_dft.cpp index 11a0ccc24..14b83fb65 100644 --- a/host/examples/rx_ascii_art_dft.cpp +++ b/host/examples/rx_ascii_art_dft.cpp @@ -147,6 +147,10 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){ UHD_ASSERT_THROW(ref_locked.to_bool()); } + //create a receive streamer + uhd::streamer_args stream_args("fc32"); //complex floats + uhd::rx_streamer::sptr rx_stream = usrp->get_rx_streamer(stream_args); + //allocate recv buffer and metatdata uhd::rx_metadata_t md; std::vector > buff(num_bins); @@ -162,10 +166,8 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){ //------------------------------------------------------------------ while (true){ //read a buffer's worth of samples every iteration - size_t num_rx_samps = usrp->get_device()->recv( - &buff.front(), buff.size(), md, - uhd::io_type_t::COMPLEX_FLOAT32, - uhd::device::RECV_MODE_FULL_BUFF + size_t num_rx_samps = rx_stream->recv( + &buff.front(), buff.size(), md ); if (num_rx_samps != buff.size()) continue; diff --git a/host/examples/rx_multi_samples.cpp b/host/examples/rx_multi_samples.cpp index 8f6d7c939..56aed60af 100644 --- a/host/examples/rx_multi_samples.cpp +++ b/host/examples/rx_multi_samples.cpp @@ -111,6 +111,13 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){ boost::this_thread::sleep(boost::posix_time::milliseconds(100)); } + //create a receive streamer + //linearly map channels (index0 = channel0, index1 = channel1, ...) + uhd::streamer_args stream_args("fc32"); //complex floats + for (size_t chan = 0; chan < usrp->get_rx_num_channels(); chan++) + stream_args.channels.push_back(chan); //linear mapping + uhd::rx_streamer::sptr rx_stream = usrp->get_rx_streamer(stream_args); + //setup streaming std::cout << std::endl; std::cout << boost::format( @@ -126,7 +133,7 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){ uhd::rx_metadata_t md; //allocate buffers to receive with samples (one buffer per channel) - size_t samps_per_buff = usrp->get_device()->get_max_recv_samps_per_packet(); + const size_t samps_per_buff = rx_stream->get_max_num_samps(); std::vector > > buffs( usrp->get_rx_num_channels(), std::vector >(samps_per_buff) ); @@ -141,10 +148,8 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){ size_t num_acc_samps = 0; //number of accumulated samples while(num_acc_samps < total_num_samps){ //receive a single packet - size_t num_rx_samps = usrp->get_device()->recv( - buff_ptrs, samps_per_buff, md, - uhd::io_type_t::COMPLEX_FLOAT32, - uhd::device::RECV_MODE_ONE_PACKET, timeout + size_t num_rx_samps = rx_stream->recv( + buff_ptrs, samps_per_buff, md, timeout ); //use a small timeout for subsequent packets diff --git a/host/examples/rx_samples_to_file.cpp b/host/examples/rx_samples_to_file.cpp index 1e213c83a..58bd158a5 100644 --- a/host/examples/rx_samples_to_file.cpp +++ b/host/examples/rx_samples_to_file.cpp @@ -34,20 +34,21 @@ void sig_int_handler(int){stop_signal_called = true;} template void recv_to_file( uhd::usrp::multi_usrp::sptr usrp, - const uhd::io_type_t &io_type, + const std::string &cpu_format, const std::string &file, size_t samps_per_buff ){ + //create a receive streamer + uhd::streamer_args stream_args(cpu_format); + uhd::rx_streamer::sptr rx_stream = usrp->get_rx_streamer(stream_args); + uhd::rx_metadata_t md; std::vector buff(samps_per_buff); std::ofstream outfile(file.c_str(), std::ofstream::binary); bool overflow_message = true; while(not stop_signal_called){ - size_t num_rx_samps = usrp->get_device()->recv( - &buff.front(), buff.size(), md, io_type, - uhd::device::RECV_MODE_FULL_BUFF - ); + size_t num_rx_samps = rx_stream->recv(&buff.front(), buff.size(), md); if (md.error_code == uhd::rx_metadata_t::ERROR_CODE_TIMEOUT) break; if (md.error_code == uhd::rx_metadata_t::ERROR_CODE_OVERFLOW){ @@ -205,9 +206,9 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){ } //recv to file - if (type == "double") recv_to_file >(usrp, uhd::io_type_t::COMPLEX_FLOAT64, file, spb); - else if (type == "float") recv_to_file >(usrp, uhd::io_type_t::COMPLEX_FLOAT32, file, spb); - else if (type == "short") recv_to_file >(usrp, uhd::io_type_t::COMPLEX_INT16, file, spb); + if (type == "double") recv_to_file >(usrp, "fc64", file, spb); + else if (type == "float") recv_to_file >(usrp, "fc32", file, spb); + else if (type == "short") recv_to_file >(usrp, "sc16", file, spb); else throw std::runtime_error("Unknown type " + type); //finished diff --git a/host/examples/rx_samples_to_udp.cpp b/host/examples/rx_samples_to_udp.cpp index d06f1bc6e..3db436ad5 100644 --- a/host/examples/rx_samples_to_udp.cpp +++ b/host/examples/rx_samples_to_udp.cpp @@ -130,6 +130,10 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){ UHD_ASSERT_THROW(ref_locked.to_bool()); } + //create a receive streamer + uhd::streamer_args stream_args("fc32"); //complex floats + uhd::rx_streamer::sptr rx_stream = usrp->get_rx_streamer(stream_args); + //setup streaming uhd::stream_cmd_t stream_cmd(uhd::stream_cmd_t::STREAM_MODE_NUM_SAMPS_AND_DONE); stream_cmd.num_samps = total_num_samps; @@ -139,14 +143,12 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){ //loop until total number of samples reached size_t num_acc_samps = 0; //number of accumulated samples uhd::rx_metadata_t md; - std::vector > buff(usrp->get_device()->get_max_recv_samps_per_packet()); + std::vector > buff(rx_stream->get_max_num_samps()); uhd::transport::udp_simple::sptr udp_xport = uhd::transport::udp_simple::make_connected(addr, port); while(num_acc_samps < total_num_samps){ - size_t num_rx_samps = usrp->get_device()->recv( - &buff.front(), buff.size(), md, - uhd::io_type_t::COMPLEX_FLOAT32, - uhd::device::RECV_MODE_ONE_PACKET + size_t num_rx_samps = rx_stream->recv( + &buff.front(), buff.size(), md ); //handle the error codes diff --git a/host/examples/rx_timed_samples.cpp b/host/examples/rx_timed_samples.cpp index 05cc0717b..6389375d9 100644 --- a/host/examples/rx_timed_samples.cpp +++ b/host/examples/rx_timed_samples.cpp @@ -70,6 +70,10 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){ std::cout << boost::format("Setting device timestamp to 0...") << std::endl; usrp->set_time_now(uhd::time_spec_t(0.0)); + //create a receive streamer + uhd::streamer_args stream_args("fc32"); //complex floats + uhd::rx_streamer::sptr rx_stream = usrp->get_rx_streamer(stream_args); + //setup streaming std::cout << std::endl; std::cout << boost::format( @@ -85,7 +89,7 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){ uhd::rx_metadata_t md; //allocate buffer to receive with samples - std::vector > buff(usrp->get_device()->get_max_recv_samps_per_packet()); + std::vector > buff(rx_stream->get_max_num_samps()); //the first call to recv() will block this many seconds before receiving double timeout = seconds_in_future + 0.1; //timeout (delay before receive + padding) @@ -93,10 +97,8 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){ size_t num_acc_samps = 0; //number of accumulated samples while(num_acc_samps < total_num_samps){ //receive a single packet - size_t num_rx_samps = usrp->get_device()->recv( - &buff.front(), buff.size(), md, - uhd::io_type_t::COMPLEX_FLOAT32, - uhd::device::RECV_MODE_ONE_PACKET, timeout + size_t num_rx_samps = rx_stream->recv( + &buff.front(), buff.size(), md, timeout ); //use a small timeout for subsequent packets diff --git a/host/examples/test_messages.cpp b/host/examples/test_messages.cpp index 60d108184..668f25ef3 100644 --- a/host/examples/test_messages.cpp +++ b/host/examples/test_messages.cpp @@ -36,24 +36,22 @@ namespace po = boost::program_options; * Issue a stream command with a time that is in the past. * We expect to get an inline late command message. */ -bool test_late_command_message(uhd::usrp::multi_usrp::sptr usrp){ +bool test_late_command_message(uhd::usrp::multi_usrp::sptr usrp, uhd::rx_streamer::sptr rx_stream, uhd::tx_streamer::sptr){ std::cout << "Test late command message... " << std::flush; usrp->set_time_now(uhd::time_spec_t(200.0)); //set time uhd::stream_cmd_t stream_cmd(uhd::stream_cmd_t::STREAM_MODE_NUM_SAMPS_AND_DONE); - stream_cmd.num_samps = usrp->get_device()->get_max_recv_samps_per_packet(); + stream_cmd.num_samps = rx_stream->get_max_num_samps(); stream_cmd.stream_now = false; stream_cmd.time_spec = uhd::time_spec_t(100.0); //time in the past usrp->issue_stream_cmd(stream_cmd); - std::vector > buff(usrp->get_device()->get_max_recv_samps_per_packet()); + std::vector > buff(rx_stream->get_max_num_samps()); uhd::rx_metadata_t md; - const size_t nsamps = usrp->get_device()->recv( - &buff.front(), buff.size(), md, - uhd::io_type_t::COMPLEX_FLOAT32, - uhd::device::RECV_MODE_FULL_BUFF + const size_t nsamps = rx_stream->recv( + &buff.front(), buff.size(), md ); switch(md.error_code){ @@ -85,27 +83,23 @@ bool test_late_command_message(uhd::usrp::multi_usrp::sptr usrp){ * Issue a stream command with num samps and more. * We expect to get an inline broken chain message. */ -bool test_broken_chain_message(uhd::usrp::multi_usrp::sptr usrp){ +bool test_broken_chain_message(uhd::usrp::multi_usrp::sptr usrp, uhd::rx_streamer::sptr rx_stream, uhd::tx_streamer::sptr){ std::cout << "Test broken chain message... " << std::flush; uhd::stream_cmd_t stream_cmd(uhd::stream_cmd_t::STREAM_MODE_NUM_SAMPS_AND_MORE); stream_cmd.stream_now = true; - stream_cmd.num_samps = usrp->get_device()->get_max_recv_samps_per_packet(); + stream_cmd.num_samps = rx_stream->get_max_num_samps(); usrp->issue_stream_cmd(stream_cmd); - std::vector > buff(usrp->get_device()->get_max_recv_samps_per_packet()); + std::vector > buff(rx_stream->get_max_num_samps()); uhd::rx_metadata_t md; - usrp->get_device()->recv( //once for the requested samples - &buff.front(), buff.size(), md, - uhd::io_type_t::COMPLEX_FLOAT32, - uhd::device::RECV_MODE_FULL_BUFF + rx_stream->recv( //once for the requested samples + &buff.front(), buff.size(), md ); - usrp->get_device()->recv( //again for the inline message - &buff.front(), buff.size(), md, - uhd::io_type_t::COMPLEX_FLOAT32, - uhd::device::RECV_MODE_FULL_BUFF + rx_stream->recv( //again for the inline message + &buff.front(), buff.size(), md ); switch(md.error_code){ @@ -137,7 +131,7 @@ bool test_broken_chain_message(uhd::usrp::multi_usrp::sptr usrp){ * Send a burst of many samples that will fragment internally. * We expect to get an burst ack async message. */ -bool test_burst_ack_message(uhd::usrp::multi_usrp::sptr usrp){ +bool test_burst_ack_message(uhd::usrp::multi_usrp::sptr usrp, uhd::rx_streamer::sptr, uhd::tx_streamer::sptr tx_stream){ std::cout << "Test burst ack message... " << std::flush; uhd::tx_metadata_t md; @@ -146,12 +140,10 @@ bool test_burst_ack_message(uhd::usrp::multi_usrp::sptr usrp){ md.has_time_spec = false; //3 times max-sps guarantees a SOB, no burst, and EOB packet - std::vector > buff(usrp->get_device()->get_max_send_samps_per_packet()*3); + std::vector > buff(tx_stream->get_max_num_samps()*3); - usrp->get_device()->send( - &buff.front(), buff.size(), md, - uhd::io_type_t::COMPLEX_FLOAT32, - uhd::device::SEND_MODE_FULL_BUFF + tx_stream->send( + &buff.front(), buff.size(), md ); uhd::async_metadata_t async_md; @@ -185,7 +177,7 @@ bool test_burst_ack_message(uhd::usrp::multi_usrp::sptr usrp){ * Send a start of burst packet with no following end of burst. * We expect to get an underflow(within a burst) async message. */ -bool test_underflow_message(uhd::usrp::multi_usrp::sptr usrp){ +bool test_underflow_message(uhd::usrp::multi_usrp::sptr usrp, uhd::rx_streamer::sptr, uhd::tx_streamer::sptr tx_stream){ std::cout << "Test underflow message... " << std::flush; uhd::tx_metadata_t md; @@ -193,10 +185,7 @@ bool test_underflow_message(uhd::usrp::multi_usrp::sptr usrp){ md.end_of_burst = false; md.has_time_spec = false; - usrp->get_device()->send("", 0, md, - uhd::io_type_t::COMPLEX_FLOAT32, - uhd::device::SEND_MODE_FULL_BUFF - ); + tx_stream->send("", 0, md); uhd::async_metadata_t async_md; if (not usrp->get_device()->recv_async_msg(async_md, 1)){ @@ -229,7 +218,7 @@ bool test_underflow_message(uhd::usrp::multi_usrp::sptr usrp){ * Send a burst packet that occurs at a time in the past. * We expect to get a time error async message. */ -bool test_time_error_message(uhd::usrp::multi_usrp::sptr usrp){ +bool test_time_error_message(uhd::usrp::multi_usrp::sptr usrp, uhd::rx_streamer::sptr, uhd::tx_streamer::sptr tx_stream){ std::cout << "Test time error message... " << std::flush; uhd::tx_metadata_t md; @@ -240,10 +229,7 @@ bool test_time_error_message(uhd::usrp::multi_usrp::sptr usrp){ usrp->set_time_now(uhd::time_spec_t(200.0)); //time at 200s - usrp->get_device()->send("", 0, md, - uhd::io_type_t::COMPLEX_FLOAT32, - uhd::device::SEND_MODE_FULL_BUFF - ); + tx_stream->send("", 0, md); uhd::async_metadata_t async_md; if (not usrp->get_device()->recv_async_msg(async_md)){ @@ -276,16 +262,12 @@ void flush_async(uhd::usrp::multi_usrp::sptr usrp){ while (usrp->get_device()->recv_async_msg(async_md)){} } -void flush_recv(uhd::usrp::multi_usrp::sptr usrp){ - std::vector > buff(usrp->get_device()->get_max_recv_samps_per_packet()); +void flush_recv(uhd::rx_streamer::sptr rx_stream){ + std::vector > buff(rx_stream->get_max_num_samps()); uhd::rx_metadata_t md; do{ - usrp->get_device()->recv( - &buff.front(), buff.size(), md, - uhd::io_type_t::COMPLEX_FLOAT32, - uhd::device::RECV_MODE_FULL_BUFF - ); + rx_stream->recv(&buff.front(), buff.size(), md); } while (md.error_code != uhd::rx_metadata_t::ERROR_CODE_TIMEOUT); } @@ -319,10 +301,15 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){ uhd::usrp::multi_usrp::sptr usrp = uhd::usrp::multi_usrp::make(args); std::cout << boost::format("Using Device: %s") % usrp->get_pp_string() << std::endl; + //create RX and TX streamers + uhd::streamer_args stream_args("fc32"); //complex floats + uhd::rx_streamer::sptr rx_stream = usrp->get_rx_streamer(stream_args); + uhd::tx_streamer::sptr tx_stream = usrp->get_tx_streamer(stream_args); + //------------------------------------------------------------------ // begin messages test //------------------------------------------------------------------ - static const uhd::dict > + static const uhd::dict > tests = boost::assign::map_list_of ("Test Burst ACK ", &test_burst_ack_message) ("Test Underflow ", &test_underflow_message) @@ -342,9 +329,9 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){ std::srand(uhd::time_spec_t::get_system_time().get_full_secs()); for (size_t n = 0; n < ntests; n++){ std::string key = tests.keys()[std::rand() % tests.size()]; - bool pass = tests[key](usrp); + bool pass = tests[key](usrp, rx_stream, tx_stream); flush_async(usrp); - flush_recv(usrp); + flush_recv(rx_stream); //store result if (pass) successes[key]++; diff --git a/host/examples/tx_bursts.cpp b/host/examples/tx_bursts.cpp index a66fb85b6..98853ce20 100644 --- a/host/examples/tx_bursts.cpp +++ b/host/examples/tx_bursts.cpp @@ -93,15 +93,19 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){ std::cout << boost::format("Setting device timestamp to 0...") << std::endl; usrp->set_time_now(uhd::time_spec_t(0.0)); + //create a transmit streamer + uhd::streamer_args stream_args("fc32"); //complex floats + uhd::tx_streamer::sptr tx_stream = usrp->get_tx_streamer(stream_args); + //allocate buffer with data to send - size_t spb = usrp->get_device()->get_max_send_samps_per_packet(); + const size_t spb = tx_stream->get_max_num_samps(); std::vector *> buffs; for(size_t i=0; i < usrp->get_num_mboards(); i++) { buffs.push_back(new std::complex[spb]); for(size_t n=0; n < spb; n++) buffs.back()[n] = std::complex(ampl, ampl); - } + }; std::signal(SIGINT, &sig_int_handler); if(repeat) std::cout << "Press Ctrl + C to quit..." << std::endl; @@ -127,10 +131,8 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){ md.end_of_burst = samps_to_send < spb; //send a single packet - size_t num_tx_samps = usrp->get_device()->send( - buffs, samps_to_send, md, - uhd::io_type_t::COMPLEX_FLOAT32, - uhd::device::SEND_MODE_ONE_PACKET, timeout + size_t num_tx_samps = tx_stream->send( + buffs, samps_to_send, md, timeout ); //do not use time spec for subsequent packets diff --git a/host/examples/tx_samples_from_file.cpp b/host/examples/tx_samples_from_file.cpp index 03fc4c8d4..09939183b 100644 --- a/host/examples/tx_samples_from_file.cpp +++ b/host/examples/tx_samples_from_file.cpp @@ -29,10 +29,14 @@ namespace po = boost::program_options; template void send_from_file( uhd::usrp::multi_usrp::sptr usrp, - const uhd::io_type_t &io_type, + const std::string &cpu_format, const std::string &file, size_t samps_per_buff ){ + //create a transmit streamer + uhd::streamer_args stream_args(cpu_format); + uhd::tx_streamer::sptr tx_stream = usrp->get_tx_streamer(stream_args); + uhd::tx_metadata_t md; md.start_of_burst = false; md.end_of_burst = false; @@ -47,10 +51,7 @@ template void send_from_file( md.end_of_burst = infile.eof(); - usrp->get_device()->send( - &buff.front(), num_tx_samps, md, io_type, - uhd::device::SEND_MODE_FULL_BUFF - ); + tx_stream->send(&buff.front(), num_tx_samps, md); } infile.close(); @@ -172,9 +173,9 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){ } //send from file - if (type == "double") send_from_file >(usrp, uhd::io_type_t::COMPLEX_FLOAT64, file, spb); - else if (type == "float") send_from_file >(usrp, uhd::io_type_t::COMPLEX_FLOAT32, file, spb); - else if (type == "short") send_from_file >(usrp, uhd::io_type_t::COMPLEX_INT16, file, spb); + if (type == "double") send_from_file >(usrp, "fc64", file, spb); + else if (type == "float") send_from_file >(usrp, "fc32", file, spb); + else if (type == "short") send_from_file >(usrp, "sc16", file, spb); else throw std::runtime_error("Unknown type " + type); //finished diff --git a/host/examples/tx_timed_samples.cpp b/host/examples/tx_timed_samples.cpp index 1c222d414..3daf1974a 100644 --- a/host/examples/tx_timed_samples.cpp +++ b/host/examples/tx_timed_samples.cpp @@ -73,8 +73,12 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){ std::cout << boost::format("Setting device timestamp to 0...") << std::endl; usrp->set_time_now(uhd::time_spec_t(0.0)); + //create a transmit streamer + uhd::streamer_args stream_args("fc32"); //complex floats + uhd::tx_streamer::sptr tx_stream = usrp->get_tx_streamer(stream_args); + //allocate buffer with data to send - std::vector > buff(usrp->get_device()->get_max_send_samps_per_packet(), std::complex(ampl, ampl)); + std::vector > buff(tx_stream->get_max_num_samps(), std::complex(ampl, ampl)); //setup metadata for the first packet uhd::tx_metadata_t md; @@ -91,10 +95,8 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){ size_t samps_to_send = std::min(total_num_samps - num_acc_samps, buff.size()); //send a single packet - size_t num_tx_samps = usrp->get_device()->send( - &buff.front(), samps_to_send, md, - uhd::io_type_t::COMPLEX_FLOAT32, - uhd::device::SEND_MODE_ONE_PACKET, timeout + size_t num_tx_samps = tx_stream->send( + &buff.front(), samps_to_send, md, timeout ); //do not use time spec for subsequent packets @@ -108,10 +110,7 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){ //send a mini EOB packet md.end_of_burst = true; - usrp->get_device()->send("", 0, md, - uhd::io_type_t::COMPLEX_FLOAT32, - uhd::device::SEND_MODE_FULL_BUFF - ); + tx_stream->send("", 0, md); std::cout << std::endl << "Waiting for async burst ACK... " << std::flush; uhd::async_metadata_t async_md; diff --git a/host/examples/tx_waveforms.cpp b/host/examples/tx_waveforms.cpp index 6e5c53642..9aa3ec71f 100644 --- a/host/examples/tx_waveforms.cpp +++ b/host/examples/tx_waveforms.cpp @@ -202,6 +202,13 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){ const double cps = wave_freq/usrp->get_tx_rate(); double theta = 0; + //create a transmit streamer + //linearly map channels (index0 = channel0, index1 = channel1, ...) + uhd::streamer_args stream_args("fc32"); + for (size_t chan = 0; chan < usrp->get_tx_num_channels(); chan++) + stream_args.channels.push_back(chan); //linear mapping + uhd::tx_streamer::sptr tx_stream = usrp->get_tx_streamer(stream_args); + //allocate a buffer which we re-use for each channel std::vector > buff(spb); std::vector *> buffs(usrp->get_tx_num_channels(), &buff.front()); @@ -250,11 +257,7 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){ theta = std::fmod(theta, 1); //send the entire contents of the buffer - usrp->get_device()->send( - buffs, buff.size(), md, - uhd::io_type_t::COMPLEX_FLOAT32, - uhd::device::SEND_MODE_FULL_BUFF - ); + tx_stream->send(buffs, buff.size(), md); md.start_of_burst = false; md.has_time_spec = false; @@ -262,10 +265,7 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){ //send a mini EOB packet md.end_of_burst = true; - usrp->get_device()->send("", 0, md, - uhd::io_type_t::COMPLEX_FLOAT32, - uhd::device::SEND_MODE_FULL_BUFF - ); + tx_stream->send("", 0, md); //finished std::cout << std::endl << "Done!" << std::endl << std::endl; -- cgit v1.2.3 From e4561a18cd4bbcf8a20799704c42bfb4c2543dc2 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Wed, 5 Oct 2011 14:41:57 -0700 Subject: usrp1: did work for stream interface on usrp1 --- host/lib/transport/super_recv_packet_handler.hpp | 9 - host/lib/transport/super_send_packet_handler.hpp | 9 - host/lib/usrp/usrp1/io_impl.cpp | 271 +++++++++++++++-------- host/lib/usrp/usrp1/usrp1_impl.cpp | 11 +- host/lib/usrp/usrp1/usrp1_impl.hpp | 25 +-- host/lib/usrp/usrp2/io_impl.cpp | 6 - 6 files changed, 195 insertions(+), 136 deletions(-) (limited to 'host') diff --git a/host/lib/transport/super_recv_packet_handler.hpp b/host/lib/transport/super_recv_packet_handler.hpp index f0b053473..f4dbc5531 100644 --- a/host/lib/transport/super_recv_packet_handler.hpp +++ b/host/lib/transport/super_recv_packet_handler.hpp @@ -27,7 +27,6 @@ #include #include #include -#include #include #include #include @@ -135,11 +134,6 @@ public: _props.at(xport_chan).handle_overflow = handle_overflow; } - //! Get a scoped lock object for this instance - boost::mutex::scoped_lock get_scoped_lock(void){ - return boost::mutex::scoped_lock(_mutex); - } - //! Set the scale factor used in float conversion void set_scale_factor(const double scale_factor){ _scale_factor = scale_factor; @@ -156,8 +150,6 @@ public: uhd::rx_metadata_t &metadata, double timeout ){ - boost::mutex::scoped_lock lock(_mutex); - //handle metadata queued from a previous receive if (_queue_error_for_next_call){ _queue_error_for_next_call = false; @@ -197,7 +189,6 @@ public: private: - boost::mutex _mutex; vrt_unpacker_type _vrt_unpacker; size_t _header_offset_words32; double _tick_rate, _samp_rate; diff --git a/host/lib/transport/super_send_packet_handler.hpp b/host/lib/transport/super_send_packet_handler.hpp index 87ae01d47..079fea11e 100644 --- a/host/lib/transport/super_send_packet_handler.hpp +++ b/host/lib/transport/super_send_packet_handler.hpp @@ -28,7 +28,6 @@ #include #include #include -#include #include #include #include @@ -115,11 +114,6 @@ public: _max_samples_per_packet = num_samps; } - //! Get a scoped lock object for this instance - boost::mutex::scoped_lock get_scoped_lock(void){ - return boost::mutex::scoped_lock(_mutex); - } - //! Set the scale factor used in float conversion void set_scale_factor(const double scale_factor){ _scale_factor = scale_factor; @@ -136,8 +130,6 @@ public: const uhd::tx_metadata_t &metadata, double timeout ){ - boost::mutex::scoped_lock lock(_mutex); - //translate the metadata to vrt if packet info vrt::if_packet_info_t if_packet_info; if_packet_info.has_sid = false; @@ -200,7 +192,6 @@ public: private: - boost::mutex _mutex; vrt_packer_type _vrt_packer; size_t _header_offset_words32; double _tick_rate, _samp_rate; diff --git a/host/lib/usrp/usrp1/io_impl.cpp b/host/lib/usrp/usrp1/io_impl.cpp index de325ea5d..7d4fe2ec7 100644 --- a/host/lib/usrp/usrp1/io_impl.cpp +++ b/host/lib/usrp/usrp1/io_impl.cpp @@ -33,6 +33,7 @@ #include #include #include +#include using namespace uhd; using namespace uhd::usrp; @@ -138,10 +139,6 @@ struct usrp1_impl::io_impl{ zero_copy_if::sptr data_transport; - //state management for the vrt packet handler code - sph::recv_packet_handler recv_handler; - sph::send_packet_handler send_handler; - //wrapper around the actual send buffer interface //all of this to ensure only aligned lengths are committed //NOTE: you must commit before getting a new buffer @@ -219,13 +216,6 @@ void usrp1_impl::io_impl::flush_send_buff(void){ * Initialize internals within this file **********************************************************************/ void usrp1_impl::io_init(void){ - _rx_otw_type.width = 16; - _rx_otw_type.shift = 0; - _rx_otw_type.byteorder = otw_type_t::BO_LITTLE_ENDIAN; - - _tx_otw_type.width = 16; - _tx_otw_type.shift = 0; - _tx_otw_type.byteorder = otw_type_t::BO_LITTLE_ENDIAN; _io_impl = UHD_PIMPL_MAKE(io_impl, (_data_transport)); @@ -234,18 +224,6 @@ void usrp1_impl::io_init(void){ &usrp1_impl::vandal_conquest_loop, this )); - //init some handler stuff - _io_impl->recv_handler.set_tick_rate(_master_clock_rate); - _io_impl->recv_handler.set_vrt_unpacker(&usrp1_bs_vrt_unpacker); - _io_impl->recv_handler.set_xport_chan_get_buff(0, boost::bind( - &uhd::transport::zero_copy_if::get_recv_buff, _io_impl->data_transport, _1 - )); - _io_impl->send_handler.set_tick_rate(_master_clock_rate); - _io_impl->send_handler.set_vrt_packer(&usrp1_bs_vrt_packer); - _io_impl->send_handler.set_xport_chan_get_buff(0, boost::bind( - &usrp1_impl::io_impl::get_send_buff, _io_impl.get(), _1 - )); - //init as disabled, then call the real function (uses restore) this->enable_rx(false); this->enable_tx(false); @@ -324,18 +302,108 @@ void usrp1_impl::vandal_conquest_loop(void){ } } +/*********************************************************************** + * RX streamer wrapper that talks to soft time control + **********************************************************************/ +class usrp1_recv_packet_streamer : public sph::recv_packet_handler, public rx_streamer{ +public: + usrp1_recv_packet_streamer(const size_t max_num_samps, soft_time_ctrl::sptr stc){ + _max_num_samps = max_num_samps; + _stc = stc; + } + + size_t get_num_channels(void) const{ + return this->size(); + } + + size_t get_max_num_samps(void) const{ + return _max_num_samps; + } + + size_t recv( + const rx_streamer::buffs_type &buffs, + const size_t nsamps_per_buff, + uhd::rx_metadata_t &metadata, + double timeout + ){ + //interleave a "soft" inline message into the receive stream: + if (_stc->get_inline_queue().pop_with_haste(metadata)) return 0; + + size_t num_samps_recvd = sph::recv_packet_handler::recv( + buffs, nsamps_per_buff, metadata, timeout + ); + + return _stc->recv_post(metadata, num_samps_recvd); + } + +private: + size_t _max_num_samps; + soft_time_ctrl::sptr _stc; +}; + +/*********************************************************************** + * TX streamer wrapper that talks to soft time control + **********************************************************************/ +class usrp1_send_packet_streamer : public sph::send_packet_handler, public tx_streamer{ +public: + usrp1_send_packet_streamer(const size_t max_num_samps, soft_time_ctrl::sptr stc, boost::function tx_enb_fcn){ + _max_num_samps = max_num_samps; + this->set_max_samples_per_packet(_max_num_samps); + _stc = stc; + _tx_enb_fcn = tx_enb_fcn; + } + + size_t get_num_channels(void) const{ + return this->size(); + } + + size_t get_max_num_samps(void) const{ + return _max_num_samps; + } + + size_t send( + const tx_streamer::buffs_type &buffs, + const size_t nsamps_per_buff, + const uhd::tx_metadata_t &metadata, + double timeout + ){ + if (_stc->send_pre(metadata, timeout)) return 0; + + _tx_enb_fcn(true); //always enable (it will do the right thing) + size_t num_samps_sent = sph::send_packet_handler::send( + buffs, nsamps_per_buff, metadata, timeout + ); + + //handle eob flag (commit the buffer, //disable the DACs) + //check num samps sent to avoid flush on incomplete/timeout + if (metadata.end_of_burst and num_samps_sent == nsamps_per_buff){ + async_metadata_t metadata; + metadata.channel = 0; + metadata.has_time_spec = true; + metadata.time_spec = _stc->get_time(); + metadata.event_code = async_metadata_t::EVENT_CODE_BURST_ACK; + _stc->get_async_queue().push_with_pop_on_full(metadata); + _tx_enb_fcn(false); + } + + return num_samps_sent; + } + +private: + size_t _max_num_samps; + soft_time_ctrl::sptr _stc; + boost::function _tx_enb_fcn; +}; + /*********************************************************************** * Properties callback methods below **********************************************************************/ void usrp1_impl::update_rx_subdev_spec(const uhd::usrp::subdev_spec_t &spec){ - boost::mutex::scoped_lock lock = _io_impl->recv_handler.get_scoped_lock(); //sanity checking validate_subdev_spec(_tree, spec, "rx"); _rx_subdev_spec = spec; //shadow - //_io_impl->recv_handler.resize(spec.size()); //always 1 - _io_impl->recv_handler.set_converter(_rx_otw_type, spec.size()); //set the mux and set the number of rx channels std::vector mapping; @@ -351,14 +419,11 @@ void usrp1_impl::update_rx_subdev_spec(const uhd::usrp::subdev_spec_t &spec){ } void usrp1_impl::update_tx_subdev_spec(const uhd::usrp::subdev_spec_t &spec){ - boost::mutex::scoped_lock lock = _io_impl->send_handler.get_scoped_lock(); //sanity checking validate_subdev_spec(_tree, spec, "tx"); _tx_subdev_spec = spec; //shadow - //_io_impl->send_handler.resize(spec.size()); //always 1 - _io_impl->send_handler.set_converter(_tx_otw_type, spec.size()); //set the mux and set the number of tx channels std::vector mapping; @@ -371,13 +436,9 @@ void usrp1_impl::update_tx_subdev_spec(const uhd::usrp::subdev_spec_t &spec){ bool s = this->disable_tx(); _iface->poke32(FR_TX_MUX, calc_tx_mux(mapping)); this->restore_tx(s); - - //if the spec changes size, so does the max samples per packet... - _io_impl->send_handler.set_max_samples_per_packet(get_max_send_samps_per_packet()); } double usrp1_impl::update_rx_samp_rate(const double samp_rate){ - boost::mutex::scoped_lock lock = _io_impl->recv_handler.get_scoped_lock(); const size_t rate = uhd::clip( boost::math::iround(_master_clock_rate / samp_rate), size_t(std::ceil(_master_clock_rate / 8e6)), 256 @@ -387,12 +448,17 @@ double usrp1_impl::update_rx_samp_rate(const double samp_rate){ _iface->poke32(FR_DECIM_RATE, rate/2 - 1); this->restore_rx(s); - _io_impl->recv_handler.set_samp_rate(_master_clock_rate / rate); + //update the streamer if created + boost::shared_ptr my_streamer = + boost::dynamic_pointer_cast(_rx_streamer.lock()); + if (my_streamer.get() != NULL){ + my_streamer->set_samp_rate(_master_clock_rate / rate); + } + return _master_clock_rate / rate; } double usrp1_impl::update_tx_samp_rate(const double samp_rate){ - boost::mutex::scoped_lock lock = _io_impl->send_handler.get_scoped_lock(); const size_t rate = uhd::clip( boost::math::iround(_master_clock_rate / samp_rate), size_t(std::ceil(_master_clock_rate / 8e6)), 256 @@ -402,10 +468,26 @@ double usrp1_impl::update_tx_samp_rate(const double samp_rate){ _iface->poke32(FR_INTERP_RATE, rate/2 - 1); this->restore_tx(s); - _io_impl->send_handler.set_samp_rate(_master_clock_rate / rate); + //update the streamer if created + boost::shared_ptr my_streamer = + boost::dynamic_pointer_cast(_tx_streamer.lock()); + if (my_streamer.get() != NULL){ + my_streamer->set_samp_rate(_master_clock_rate / rate); + } + return _master_clock_rate / rate; } +void usrp1_impl::update_rates(void){ + const fs_path mb_path = "/mboards/0"; + BOOST_FOREACH(const std::string &name, _tree->list(mb_path / "rx_dsps")){ + _tree->access(mb_path / "rx_dsps" / name / "rate" / "value").update(); + } + BOOST_FOREACH(const std::string &name, _tree->list(mb_path / "tx_dsps")){ + _tree->access(mb_path / "tx_dsps" / name / "rate" / "value").update(); + } +} + double usrp1_impl::update_rx_dsp_freq(const size_t dspno, const double freq_){ //correct for outside of rate (wrap around) @@ -443,67 +525,82 @@ bool usrp1_impl::recv_async_msg( } /*********************************************************************** - * Data send + helper functions + * Receive streamer **********************************************************************/ -size_t usrp1_impl::get_max_send_samps_per_packet(void) const { - return (_data_transport->get_send_frame_size() - alignment_padding) - / _tx_otw_type.get_sample_size() - / _tx_subdev_spec.size() - ; -} +rx_streamer::sptr usrp1_impl::get_rx_streamer(const uhd::streamer_args &args){ + //map an empty channel set to chan0 + const std::vector channels = args.channels.empty()? std::vector(1, 0) : args.channels; + + //calculate packet size + const size_t bpp = _data_transport->get_recv_frame_size()/channels.size(); + const size_t spp = bpp/convert::get_bytes_per_item(args.otw_format); + + //make the new streamer given the samples per packet + boost::shared_ptr my_streamer = + boost::make_shared(spp, _soft_time_ctrl); + + //init some streamer stuff + my_streamer->set_tick_rate(_master_clock_rate); + my_streamer->set_vrt_unpacker(&usrp1_bs_vrt_unpacker); + my_streamer->set_xport_chan_get_buff(0, boost::bind( + &uhd::transport::zero_copy_if::get_recv_buff, _io_impl->data_transport, _1 + )); -size_t usrp1_impl::send( - const send_buffs_type &buffs, size_t nsamps_per_buff, - const tx_metadata_t &metadata, const io_type_t &io_type, - send_mode_t send_mode, double timeout -){ - if (_soft_time_ctrl->send_pre(metadata, timeout)) return 0; + //set the converter + uhd::convert::id_type id; + id.input_markup = args.otw_format + "_item32_le"; + id.num_inputs = channels.size(); + id.output_markup = args.cpu_format; + id.num_outputs = 1; + id.args = args.args; + my_streamer->set_converter(id); - this->tx_stream_on_off(true); //always enable (it will do the right thing) - size_t num_samps_sent = _io_impl->send_handler.send( - buffs, nsamps_per_buff, - metadata, io_type, - send_mode, timeout - ); + //save as weak ptr for update access + _rx_streamer = my_streamer; - //handle eob flag (commit the buffer, /*disable the DACs*/) - //check num samps sent to avoid flush on incomplete/timeout - if (metadata.end_of_burst and num_samps_sent == nsamps_per_buff){ - async_metadata_t metadata; - metadata.channel = 0; - metadata.has_time_spec = true; - metadata.time_spec = _soft_time_ctrl->get_time(); - metadata.event_code = async_metadata_t::EVENT_CODE_BURST_ACK; - _soft_time_ctrl->get_async_queue().push_with_pop_on_full(metadata); - this->tx_stream_on_off(false); - } + //sets all tick and samp rates on this streamer + this->update_rates(); - return num_samps_sent; + return my_streamer; } /*********************************************************************** - * Data recv + helper functions + * Transmit streamer **********************************************************************/ -size_t usrp1_impl::get_max_recv_samps_per_packet(void) const { - return _data_transport->get_recv_frame_size() - / _rx_otw_type.get_sample_size() - / _rx_subdev_spec.size() - ; -} +tx_streamer::sptr usrp1_impl::get_tx_streamer(const uhd::streamer_args &args){ + //map an empty channel set to chan0 + const std::vector channels = args.channels.empty()? std::vector(1, 0) : args.channels; + + //calculate packet size + const size_t bpp = _data_transport->get_send_frame_size()/channels.size(); + const size_t spp = bpp/convert::get_bytes_per_item(args.otw_format); + + //make the new streamer given the samples per packet + boost::function tx_fcn = boost::bind(&usrp1_impl::tx_stream_on_off, this, _1); + boost::shared_ptr my_streamer = + boost::make_shared(spp, _soft_time_ctrl, tx_fcn); + + //init some streamer stuff + my_streamer->set_tick_rate(_master_clock_rate); + my_streamer->set_vrt_packer(&usrp1_bs_vrt_packer); + my_streamer->set_xport_chan_get_buff(0, boost::bind( + &usrp1_impl::io_impl::get_send_buff, _io_impl.get(), _1 + )); -size_t usrp1_impl::recv( - const recv_buffs_type &buffs, size_t nsamps_per_buff, - rx_metadata_t &metadata, const io_type_t &io_type, - recv_mode_t recv_mode, double timeout -){ - //interleave a "soft" inline message into the receive stream: - if (_soft_time_ctrl->get_inline_queue().pop_with_haste(metadata)) return 0; + //set the converter + uhd::convert::id_type id; + id.input_markup = args.cpu_format; + id.num_inputs = 1; + id.output_markup = args.otw_format + "_item32_le"; + id.num_outputs = channels.size(); + id.args = args.args; + my_streamer->set_converter(id); - size_t num_samps_recvd = _io_impl->recv_handler.recv( - buffs, nsamps_per_buff, - metadata, io_type, - recv_mode, timeout - ); + //save as weak ptr for update access + _tx_streamer = my_streamer; + + //sets all tick and samp rates on this streamer + this->update_rates(); - return _soft_time_ctrl->recv_post(metadata, num_samps_recvd); + return my_streamer; } diff --git a/host/lib/usrp/usrp1/usrp1_impl.cpp b/host/lib/usrp/usrp1/usrp1_impl.cpp index fe4541d38..d169c4823 100644 --- a/host/lib/usrp/usrp1/usrp1_impl.cpp +++ b/host/lib/usrp/usrp1/usrp1_impl.cpp @@ -281,6 +281,7 @@ usrp1_impl::usrp1_impl(const device_addr_t &device_addr){ for (size_t dspno = 0; dspno < get_num_ddcs(); dspno++){ fs_path rx_dsp_path = mb_path / str(boost::format("rx_dsps/%u") % dspno); _tree->create(rx_dsp_path / "rate/value") + .set(1e6) .coerce(boost::bind(&usrp1_impl::update_rx_samp_rate, this, _1)); _tree->create(rx_dsp_path / "freq/value") .coerce(boost::bind(&usrp1_impl::update_rx_dsp_freq, this, dspno, _1)); @@ -301,6 +302,7 @@ usrp1_impl::usrp1_impl(const device_addr_t &device_addr){ for (size_t dspno = 0; dspno < get_num_ducs(); dspno++){ fs_path tx_dsp_path = mb_path / str(boost::format("tx_dsps/%u") % dspno); _tree->create(tx_dsp_path / "rate/value") + .set(1e6) .coerce(boost::bind(&usrp1_impl::update_tx_samp_rate, this, _1)); _tree->create(tx_dsp_path / "freq/value") .coerce(boost::bind(&usrp1_impl::update_tx_dsp_freq, this, dspno, _1)); @@ -382,14 +384,7 @@ usrp1_impl::usrp1_impl(const device_addr_t &device_addr){ //////////////////////////////////////////////////////////////////// // do some post-init tasks //////////////////////////////////////////////////////////////////// - //and now that the tick rate is set, init the host rates to something - BOOST_FOREACH(const std::string &name, _tree->list(mb_path / "rx_dsps")){ - _tree->access(mb_path / "rx_dsps" / name / "rate" / "value").set(1e6); - } - BOOST_FOREACH(const std::string &name, _tree->list(mb_path / "tx_dsps")){ - _tree->access(mb_path / "tx_dsps" / name / "rate" / "value").set(1e6); - } - + this->update_rates(); if (_tree->list(mb_path / "rx_dsps").size() > 0) _tree->access(mb_path / "rx_subdev_spec").set(_rx_subdev_spec); if (_tree->list(mb_path / "tx_dsps").size() > 0) diff --git a/host/lib/usrp/usrp1/usrp1_impl.hpp b/host/lib/usrp/usrp1/usrp1_impl.hpp index 68ce31a54..7776ea8d6 100644 --- a/host/lib/usrp/usrp1/usrp1_impl.hpp +++ b/host/lib/usrp/usrp1/usrp1_impl.hpp @@ -55,21 +55,8 @@ public: ~usrp1_impl(void); //the io interface - size_t send(const send_buffs_type &, - size_t, - const uhd::tx_metadata_t &, - const uhd::io_type_t &, - send_mode_t, double); - - size_t recv(const recv_buffs_type &, - size_t, uhd::rx_metadata_t &, - const uhd::io_type_t &, - recv_mode_t, double); - - size_t get_max_send_samps_per_packet(void) const; - - size_t get_max_recv_samps_per_packet(void) const; - + uhd::rx_streamer::sptr get_rx_streamer(const uhd::streamer_args &args); + uhd::tx_streamer::sptr get_tx_streamer(const uhd::streamer_args &args); bool recv_async_msg(uhd::async_metadata_t &, double); private: @@ -94,6 +81,10 @@ private: double _master_clock_rate; //clock rate shadow + //weak pointers to streamers for update purposes + boost::weak_ptr _rx_streamer; + boost::weak_ptr _tx_streamer; + void set_mb_eeprom(const uhd::usrp::mboard_eeprom_t &); void set_db_eeprom(const std::string &, const std::string &, const uhd::usrp::dboard_eeprom_t &); double update_rx_codec_gain(const std::string &, const double); //sets A and B at once @@ -101,6 +92,7 @@ private: void update_tx_subdev_spec(const uhd::usrp::subdev_spec_t &); double update_rx_samp_rate(const double); double update_tx_samp_rate(const double); + void update_rates(void); double update_rx_dsp_freq(const size_t, const double); double update_tx_dsp_freq(const size_t, const double); @@ -119,8 +111,7 @@ private: void tx_stream_on_off(bool); void handle_overrun(size_t); - //otw types - uhd::otw_type_t _rx_otw_type, _tx_otw_type; + //channel mapping shadows uhd::usrp::subdev_spec_t _rx_subdev_spec, _tx_subdev_spec; //capabilities diff --git a/host/lib/usrp/usrp2/io_impl.cpp b/host/lib/usrp/usrp2/io_impl.cpp index 44217c36c..f271d480a 100644 --- a/host/lib/usrp/usrp2/io_impl.cpp +++ b/host/lib/usrp/usrp2/io_impl.cpp @@ -272,14 +272,12 @@ void usrp2_impl::update_tick_rate(const double rate){ boost::shared_ptr my_streamer = boost::dynamic_pointer_cast(_mbc[mb].rx_streamers[i].lock()); if (my_streamer.get() == NULL) continue; - boost::mutex::scoped_lock lock = my_streamer->get_scoped_lock(); my_streamer->set_tick_rate(rate); } for (size_t i = 0; i < _mbc[mb].tx_streamers.size(); i++){ boost::shared_ptr my_streamer = boost::dynamic_pointer_cast(_mbc[mb].tx_streamers[i].lock()); if (my_streamer.get() == NULL) continue; - boost::mutex::scoped_lock lock = my_streamer->get_scoped_lock(); my_streamer->set_tick_rate(rate); } } @@ -290,8 +288,6 @@ void usrp2_impl::update_rx_samp_rate(const std::string &mb, const size_t dsp, co boost::dynamic_pointer_cast(_mbc[mb].rx_streamers[dsp].lock()); if (my_streamer.get() == NULL) return; - boost::mutex::scoped_lock lock = my_streamer->get_scoped_lock(); - my_streamer->set_samp_rate(rate); const double adj = _mbc[mb].rx_dsps[dsp]->get_scaling_adjustment(); my_streamer->set_scale_factor(adj/32767.); @@ -302,8 +298,6 @@ void usrp2_impl::update_tx_samp_rate(const std::string &mb, const size_t dsp, co boost::dynamic_pointer_cast(_mbc[mb].tx_streamers[dsp].lock()); if (my_streamer.get() == NULL) return; - boost::mutex::scoped_lock lock = my_streamer->get_scoped_lock(); - my_streamer->set_samp_rate(rate); } -- cgit v1.2.3 From 371c555ed45aa14747a5701913bd5af97e970d83 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Wed, 5 Oct 2011 16:11:35 -0700 Subject: uhd: restore io type header for swig backwards compat --- host/include/uhd/deprecated.hpp | 78 +------------------------------- host/include/uhd/device_deprecated.ipp | 10 ++--- host/include/uhd/types/io_type.hpp | 81 +++++++++++++++++++++++++++++++++- 3 files changed, 84 insertions(+), 85 deletions(-) (limited to 'host') diff --git a/host/include/uhd/deprecated.hpp b/host/include/uhd/deprecated.hpp index 0f4965bc6..e4112fa66 100644 --- a/host/include/uhd/deprecated.hpp +++ b/host/include/uhd/deprecated.hpp @@ -242,80 +242,4 @@ namespace uhd{ #endif /* INCLUDED_UHD_TYPES_OTW_TYPE_HPP */ -// -// 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_IO_TYPE_HPP -#define INCLUDED_UHD_TYPES_IO_TYPE_HPP - -#include - -namespace uhd{ - - /*! - * The Input/Output configuration struct: - * Used to specify the IO type with device send/recv. - */ - class UHD_API io_type_t{ - public: - - /*! - * Built in IO types known to the system. - */ - enum tid_t{ - //! Custom type (technically unsupported by implementation) - CUSTOM_TYPE = int('?'), - //! Complex floating point (64-bit floats) range [-1.0, +1.0] - COMPLEX_FLOAT64 = int('d'), - //! Complex floating point (32-bit floats) range [-1.0, +1.0] - COMPLEX_FLOAT32 = int('f'), - //! Complex signed integer (16-bit integers) range [-32768, +32767] - COMPLEX_INT16 = int('s'), - //! Complex signed integer (8-bit integers) range [-128, 127] - COMPLEX_INT8 = int('b') - }; - - /*! - * The size of this io type in bytes. - */ - const size_t size; - - /*! - * The type id of this io type. - * Good for using with switch statements. - */ - const tid_t tid; - - /*! - * Create an io type from a built-in type id. - * \param tid a type id known to the system - */ - io_type_t(tid_t tid); - - /*! - * Create an io type from attributes. - * The tid will be set to custom. - * \param size the size in bytes - */ - io_type_t(size_t size); - - }; - -} //namespace uhd - -#endif /* INCLUDED_UHD_TYPES_IO_TYPE_HPP */ - +#include //wish it was in here diff --git a/host/include/uhd/device_deprecated.ipp b/host/include/uhd/device_deprecated.ipp index 4647a050e..ad84a1a6b 100644 --- a/host/include/uhd/device_deprecated.ipp +++ b/host/include/uhd/device_deprecated.ipp @@ -79,13 +79,12 @@ size_t send( ){ if (_tx_streamer.get() == NULL or _tx_streamer->get_num_channels() != buffs.size() or _send_tid != io_type.tid){ _send_tid = io_type.tid; - std::vector chans(buffs.size()); - for (size_t ch = 0; ch < chans.size(); ch++) chans[ch] = ch; _tx_streamer.reset(); //cleanup possible old one streamer_args args; args.cpu_format = (_send_tid == io_type_t::COMPLEX_FLOAT32)? "fc32" : "sc16"; args.otw_format = "sc16"; - args.channels = chans; + for (size_t ch = 0; ch < buffs.size(); ch++) + args.channels.push_back(ch); //linear mapping _tx_streamer = get_tx_streamer(args); } const size_t nsamps = (send_mode == SEND_MODE_ONE_PACKET)? @@ -135,13 +134,12 @@ size_t recv( ){ if (_rx_streamer.get() == NULL or _rx_streamer->get_num_channels() != buffs.size() or _recv_tid != io_type.tid){ _recv_tid = io_type.tid; - std::vector chans(buffs.size()); - for (size_t ch = 0; ch < chans.size(); ch++) chans[ch] = ch; _rx_streamer.reset(); //cleanup possible old one streamer_args args; args.cpu_format = (_send_tid == io_type_t::COMPLEX_FLOAT32)? "fc32" : "sc16"; args.otw_format = "sc16"; - args.channels = chans; + for (size_t ch = 0; ch < buffs.size(); ch++) + args.channels.push_back(ch); //linear mapping _rx_streamer = get_rx_streamer(args); } const size_t nsamps = (recv_mode == RECV_MODE_ONE_PACKET)? diff --git a/host/include/uhd/types/io_type.hpp b/host/include/uhd/types/io_type.hpp index e0ee4187b..967ad7908 100644 --- a/host/include/uhd/types/io_type.hpp +++ b/host/include/uhd/types/io_type.hpp @@ -1,2 +1,79 @@ -//The IO type API has been deprecated in favor of the streamer interface -#include +// +// 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_IO_TYPE_HPP +#define INCLUDED_UHD_TYPES_IO_TYPE_HPP + +#include + +namespace uhd{ + + /*! + * The DEPRECATED Input/Output configuration struct: + * Used to specify the IO type with device send/recv. + * + * Deprecated in favor of streamer interface. + * Its still in this file for the sake of gr-uhd swig. + */ + class UHD_API io_type_t{ + public: + + /*! + * Built in IO types known to the system. + */ + enum tid_t{ + //! Custom type (technically unsupported by implementation) + CUSTOM_TYPE = int('?'), + //! Complex floating point (64-bit floats) range [-1.0, +1.0] + COMPLEX_FLOAT64 = int('d'), + //! Complex floating point (32-bit floats) range [-1.0, +1.0] + COMPLEX_FLOAT32 = int('f'), + //! Complex signed integer (16-bit integers) range [-32768, +32767] + COMPLEX_INT16 = int('s'), + //! Complex signed integer (8-bit integers) range [-128, 127] + COMPLEX_INT8 = int('b') + }; + + /*! + * The size of this io type in bytes. + */ + const size_t size; + + /*! + * The type id of this io type. + * Good for using with switch statements. + */ + const tid_t tid; + + /*! + * Create an io type from a built-in type id. + * \param tid a type id known to the system + */ + io_type_t(tid_t tid); + + /*! + * Create an io type from attributes. + * The tid will be set to custom. + * \param size the size in bytes + */ + io_type_t(size_t size); + + }; + +} //namespace uhd + +#endif /* INCLUDED_UHD_TYPES_IO_TYPE_HPP */ -- cgit v1.2.3 From fa6d1380918e655a66cd209d7be3b0b31c61e907 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Wed, 5 Oct 2011 17:39:21 -0700 Subject: uhd: device_deprecated.ipp typo fix --- host/include/uhd/device_deprecated.ipp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'host') diff --git a/host/include/uhd/device_deprecated.ipp b/host/include/uhd/device_deprecated.ipp index ad84a1a6b..7afaaca2d 100644 --- a/host/include/uhd/device_deprecated.ipp +++ b/host/include/uhd/device_deprecated.ipp @@ -136,7 +136,7 @@ size_t recv( _recv_tid = io_type.tid; _rx_streamer.reset(); //cleanup possible old one streamer_args args; - args.cpu_format = (_send_tid == io_type_t::COMPLEX_FLOAT32)? "fc32" : "sc16"; + args.cpu_format = (_recv_tid == io_type_t::COMPLEX_FLOAT32)? "fc32" : "sc16"; args.otw_format = "sc16"; for (size_t ch = 0; ch < buffs.size(); ch++) args.channels.push_back(ch); //linear mapping -- cgit v1.2.3 From fac15db5d77c5196badb4a06f2f5fec34eb57337 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Thu, 6 Oct 2011 09:25:54 -0700 Subject: uhd: renamed some of the stream types and functions --- host/examples/benchmark_rate.cpp | 8 +- host/examples/latency_test.cpp | 6 +- host/examples/rx_ascii_art_dft.cpp | 4 +- host/examples/rx_multi_samples.cpp | 4 +- host/examples/rx_samples_to_file.cpp | 4 +- host/examples/rx_samples_to_udp.cpp | 4 +- host/examples/rx_timed_samples.cpp | 4 +- host/examples/test_messages.cpp | 6 +- host/examples/tx_bursts.cpp | 4 +- host/examples/tx_samples_from_file.cpp | 4 +- host/examples/tx_timed_samples.cpp | 4 +- host/examples/tx_waveforms.cpp | 4 +- host/include/uhd/CMakeLists.txt | 2 +- host/include/uhd/device.hpp | 6 +- host/include/uhd/device_deprecated.ipp | 16 +- host/include/uhd/stream.hpp | 189 +++++++++++++++++++++++ host/include/uhd/streamer.hpp | 189 ----------------------- host/include/uhd/usrp/multi_usrp.hpp | 8 +- host/lib/transport/super_recv_packet_handler.hpp | 2 +- host/lib/transport/super_send_packet_handler.hpp | 2 +- host/lib/usrp/usrp1/io_impl.cpp | 4 +- host/lib/usrp/usrp1/usrp1_impl.hpp | 4 +- host/lib/usrp/usrp2/io_impl.cpp | 4 +- host/lib/usrp/usrp2/usrp2_impl.hpp | 4 +- 24 files changed, 243 insertions(+), 243 deletions(-) create mode 100644 host/include/uhd/stream.hpp delete mode 100644 host/include/uhd/streamer.hpp (limited to 'host') diff --git a/host/examples/benchmark_rate.cpp b/host/examples/benchmark_rate.cpp index 7862bd44b..fce184514 100644 --- a/host/examples/benchmark_rate.cpp +++ b/host/examples/benchmark_rate.cpp @@ -44,8 +44,8 @@ void benchmark_rx_rate(uhd::usrp::multi_usrp::sptr usrp){ uhd::set_thread_priority_safe(); //create a receive streamer - uhd::streamer_args stream_args("fc32"); //complex floats - uhd::rx_streamer::sptr rx_stream = usrp->get_rx_streamer(stream_args); + uhd::stream_args_t stream_args("fc32"); //complex floats + uhd::rx_streamer::sptr rx_stream = usrp->get_rx_stream(stream_args); //print pre-test summary std::cout << boost::format( @@ -98,8 +98,8 @@ void benchmark_tx_rate(uhd::usrp::multi_usrp::sptr usrp){ uhd::set_thread_priority_safe(); //create a transmit streamer - uhd::streamer_args stream_args("fc32"); //complex floats - uhd::tx_streamer::sptr tx_stream = usrp->get_tx_streamer(stream_args); + uhd::stream_args_t stream_args("fc32"); //complex floats + uhd::tx_streamer::sptr tx_stream = usrp->get_tx_stream(stream_args); //print pre-test summary std::cout << boost::format( diff --git a/host/examples/latency_test.cpp b/host/examples/latency_test.cpp index b995b0433..518d2383a 100644 --- a/host/examples/latency_test.cpp +++ b/host/examples/latency_test.cpp @@ -84,9 +84,9 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){ std::vector > buffer(nsamps); //create RX and TX streamers - uhd::streamer_args stream_args("fc32"); //complex floats - uhd::rx_streamer::sptr rx_stream = usrp->get_rx_streamer(stream_args); - uhd::tx_streamer::sptr tx_stream = usrp->get_tx_streamer(stream_args); + uhd::stream_args_t stream_args("fc32"); //complex floats + uhd::rx_streamer::sptr rx_stream = usrp->get_rx_stream(stream_args); + uhd::tx_streamer::sptr tx_stream = usrp->get_tx_stream(stream_args); //initialize result counts int time_error = 0; diff --git a/host/examples/rx_ascii_art_dft.cpp b/host/examples/rx_ascii_art_dft.cpp index 14b83fb65..2e5bbba9d 100644 --- a/host/examples/rx_ascii_art_dft.cpp +++ b/host/examples/rx_ascii_art_dft.cpp @@ -148,8 +148,8 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){ } //create a receive streamer - uhd::streamer_args stream_args("fc32"); //complex floats - uhd::rx_streamer::sptr rx_stream = usrp->get_rx_streamer(stream_args); + uhd::stream_args_t stream_args("fc32"); //complex floats + uhd::rx_streamer::sptr rx_stream = usrp->get_rx_stream(stream_args); //allocate recv buffer and metatdata uhd::rx_metadata_t md; diff --git a/host/examples/rx_multi_samples.cpp b/host/examples/rx_multi_samples.cpp index 56aed60af..7561f1285 100644 --- a/host/examples/rx_multi_samples.cpp +++ b/host/examples/rx_multi_samples.cpp @@ -113,10 +113,10 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){ //create a receive streamer //linearly map channels (index0 = channel0, index1 = channel1, ...) - uhd::streamer_args stream_args("fc32"); //complex floats + uhd::stream_args_t stream_args("fc32"); //complex floats for (size_t chan = 0; chan < usrp->get_rx_num_channels(); chan++) stream_args.channels.push_back(chan); //linear mapping - uhd::rx_streamer::sptr rx_stream = usrp->get_rx_streamer(stream_args); + uhd::rx_streamer::sptr rx_stream = usrp->get_rx_stream(stream_args); //setup streaming std::cout << std::endl; diff --git a/host/examples/rx_samples_to_file.cpp b/host/examples/rx_samples_to_file.cpp index 58bd158a5..605439748 100644 --- a/host/examples/rx_samples_to_file.cpp +++ b/host/examples/rx_samples_to_file.cpp @@ -39,8 +39,8 @@ template void recv_to_file( size_t samps_per_buff ){ //create a receive streamer - uhd::streamer_args stream_args(cpu_format); - uhd::rx_streamer::sptr rx_stream = usrp->get_rx_streamer(stream_args); + uhd::stream_args_t stream_args(cpu_format); + uhd::rx_streamer::sptr rx_stream = usrp->get_rx_stream(stream_args); uhd::rx_metadata_t md; std::vector buff(samps_per_buff); diff --git a/host/examples/rx_samples_to_udp.cpp b/host/examples/rx_samples_to_udp.cpp index 3db436ad5..cf7fd493a 100644 --- a/host/examples/rx_samples_to_udp.cpp +++ b/host/examples/rx_samples_to_udp.cpp @@ -131,8 +131,8 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){ } //create a receive streamer - uhd::streamer_args stream_args("fc32"); //complex floats - uhd::rx_streamer::sptr rx_stream = usrp->get_rx_streamer(stream_args); + uhd::stream_args_t stream_args("fc32"); //complex floats + uhd::rx_streamer::sptr rx_stream = usrp->get_rx_stream(stream_args); //setup streaming uhd::stream_cmd_t stream_cmd(uhd::stream_cmd_t::STREAM_MODE_NUM_SAMPS_AND_DONE); diff --git a/host/examples/rx_timed_samples.cpp b/host/examples/rx_timed_samples.cpp index 6389375d9..0851593cd 100644 --- a/host/examples/rx_timed_samples.cpp +++ b/host/examples/rx_timed_samples.cpp @@ -71,8 +71,8 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){ usrp->set_time_now(uhd::time_spec_t(0.0)); //create a receive streamer - uhd::streamer_args stream_args("fc32"); //complex floats - uhd::rx_streamer::sptr rx_stream = usrp->get_rx_streamer(stream_args); + uhd::stream_args_t stream_args("fc32"); //complex floats + uhd::rx_streamer::sptr rx_stream = usrp->get_rx_stream(stream_args); //setup streaming std::cout << std::endl; diff --git a/host/examples/test_messages.cpp b/host/examples/test_messages.cpp index 668f25ef3..f24a172d1 100644 --- a/host/examples/test_messages.cpp +++ b/host/examples/test_messages.cpp @@ -302,9 +302,9 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){ std::cout << boost::format("Using Device: %s") % usrp->get_pp_string() << std::endl; //create RX and TX streamers - uhd::streamer_args stream_args("fc32"); //complex floats - uhd::rx_streamer::sptr rx_stream = usrp->get_rx_streamer(stream_args); - uhd::tx_streamer::sptr tx_stream = usrp->get_tx_streamer(stream_args); + uhd::stream_args_t stream_args("fc32"); //complex floats + uhd::rx_streamer::sptr rx_stream = usrp->get_rx_stream(stream_args); + uhd::tx_streamer::sptr tx_stream = usrp->get_tx_stream(stream_args); //------------------------------------------------------------------ // begin messages test diff --git a/host/examples/tx_bursts.cpp b/host/examples/tx_bursts.cpp index 98853ce20..f5ae18a9f 100644 --- a/host/examples/tx_bursts.cpp +++ b/host/examples/tx_bursts.cpp @@ -94,8 +94,8 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){ usrp->set_time_now(uhd::time_spec_t(0.0)); //create a transmit streamer - uhd::streamer_args stream_args("fc32"); //complex floats - uhd::tx_streamer::sptr tx_stream = usrp->get_tx_streamer(stream_args); + uhd::stream_args_t stream_args("fc32"); //complex floats + uhd::tx_streamer::sptr tx_stream = usrp->get_tx_stream(stream_args); //allocate buffer with data to send const size_t spb = tx_stream->get_max_num_samps(); diff --git a/host/examples/tx_samples_from_file.cpp b/host/examples/tx_samples_from_file.cpp index 09939183b..964c6cea8 100644 --- a/host/examples/tx_samples_from_file.cpp +++ b/host/examples/tx_samples_from_file.cpp @@ -34,8 +34,8 @@ template void send_from_file( size_t samps_per_buff ){ //create a transmit streamer - uhd::streamer_args stream_args(cpu_format); - uhd::tx_streamer::sptr tx_stream = usrp->get_tx_streamer(stream_args); + uhd::stream_args_t stream_args(cpu_format); + uhd::tx_streamer::sptr tx_stream = usrp->get_tx_stream(stream_args); uhd::tx_metadata_t md; md.start_of_burst = false; diff --git a/host/examples/tx_timed_samples.cpp b/host/examples/tx_timed_samples.cpp index 3daf1974a..3b8cc75d4 100644 --- a/host/examples/tx_timed_samples.cpp +++ b/host/examples/tx_timed_samples.cpp @@ -74,8 +74,8 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){ usrp->set_time_now(uhd::time_spec_t(0.0)); //create a transmit streamer - uhd::streamer_args stream_args("fc32"); //complex floats - uhd::tx_streamer::sptr tx_stream = usrp->get_tx_streamer(stream_args); + uhd::stream_args_t stream_args("fc32"); //complex floats + uhd::tx_streamer::sptr tx_stream = usrp->get_tx_stream(stream_args); //allocate buffer with data to send std::vector > buff(tx_stream->get_max_num_samps(), std::complex(ampl, ampl)); diff --git a/host/examples/tx_waveforms.cpp b/host/examples/tx_waveforms.cpp index 9aa3ec71f..1eb6c2f1e 100644 --- a/host/examples/tx_waveforms.cpp +++ b/host/examples/tx_waveforms.cpp @@ -204,10 +204,10 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){ //create a transmit streamer //linearly map channels (index0 = channel0, index1 = channel1, ...) - uhd::streamer_args stream_args("fc32"); + uhd::stream_args_t stream_args("fc32"); for (size_t chan = 0; chan < usrp->get_tx_num_channels(); chan++) stream_args.channels.push_back(chan); //linear mapping - uhd::tx_streamer::sptr tx_stream = usrp->get_tx_streamer(stream_args); + uhd::tx_streamer::sptr tx_stream = usrp->get_tx_stream(stream_args); //allocate a buffer which we re-use for each channel std::vector > buff(spb); diff --git a/host/include/uhd/CMakeLists.txt b/host/include/uhd/CMakeLists.txt index 6b277654d..2b0c6ec14 100644 --- a/host/include/uhd/CMakeLists.txt +++ b/host/include/uhd/CMakeLists.txt @@ -30,7 +30,7 @@ INSTALL(FILES exception.hpp property_tree.ipp property_tree.hpp - streamer.hpp + stream.hpp version.hpp wax.hpp DESTINATION ${INCLUDE_DIR}/uhd diff --git a/host/include/uhd/device.hpp b/host/include/uhd/device.hpp index c96139858..89c6332da 100644 --- a/host/include/uhd/device.hpp +++ b/host/include/uhd/device.hpp @@ -19,7 +19,7 @@ #define INCLUDED_UHD_DEVICE_HPP #include -#include +#include #include #include #include @@ -77,10 +77,10 @@ public: static sptr make(const device_addr_t &hint, size_t which = 0); //! Make a new receive streamer from the streamer arguments - virtual rx_streamer::sptr get_rx_streamer(const streamer_args &args) = 0; + virtual rx_streamer::sptr get_rx_stream(const stream_args_t &args) = 0; //! Make a new transmit streamer from the streamer arguments - virtual tx_streamer::sptr get_tx_streamer(const streamer_args &args) = 0; + virtual tx_streamer::sptr get_tx_stream(const stream_args_t &args) = 0; /*! * Receive and asynchronous message from the device. diff --git a/host/include/uhd/device_deprecated.ipp b/host/include/uhd/device_deprecated.ipp index 7afaaca2d..8e61c389f 100644 --- a/host/include/uhd/device_deprecated.ipp +++ b/host/include/uhd/device_deprecated.ipp @@ -80,12 +80,12 @@ size_t send( if (_tx_streamer.get() == NULL or _tx_streamer->get_num_channels() != buffs.size() or _send_tid != io_type.tid){ _send_tid = io_type.tid; _tx_streamer.reset(); //cleanup possible old one - streamer_args args; + stream_args_t args; args.cpu_format = (_send_tid == io_type_t::COMPLEX_FLOAT32)? "fc32" : "sc16"; args.otw_format = "sc16"; for (size_t ch = 0; ch < buffs.size(); ch++) args.channels.push_back(ch); //linear mapping - _tx_streamer = get_tx_streamer(args); + _tx_streamer = get_tx_stream(args); } const size_t nsamps = (send_mode == SEND_MODE_ONE_PACKET)? std::min(nsamps_per_buff, get_max_send_samps_per_packet()) : @@ -135,12 +135,12 @@ size_t recv( if (_rx_streamer.get() == NULL or _rx_streamer->get_num_channels() != buffs.size() or _recv_tid != io_type.tid){ _recv_tid = io_type.tid; _rx_streamer.reset(); //cleanup possible old one - streamer_args args; + stream_args_t args; args.cpu_format = (_recv_tid == io_type_t::COMPLEX_FLOAT32)? "fc32" : "sc16"; args.otw_format = "sc16"; for (size_t ch = 0; ch < buffs.size(); ch++) args.channels.push_back(ch); //linear mapping - _rx_streamer = get_rx_streamer(args); + _rx_streamer = get_rx_stream(args); } const size_t nsamps = (recv_mode == RECV_MODE_ONE_PACKET)? std::min(nsamps_per_buff, get_max_recv_samps_per_packet()) : @@ -154,10 +154,10 @@ size_t recv( */ size_t get_max_send_samps_per_packet(void){ if (_tx_streamer.get() == NULL){ - streamer_args args; + stream_args_t args; args.cpu_format = "fc32"; args.otw_format = "sc16"; - _tx_streamer = get_tx_streamer(args); + _tx_streamer = get_tx_stream(args); _send_tid = io_type_t::COMPLEX_FLOAT32; } return _tx_streamer->get_max_num_samps(); @@ -169,10 +169,10 @@ size_t get_max_send_samps_per_packet(void){ */ size_t get_max_recv_samps_per_packet(void){ if (_rx_streamer.get() == NULL){ - streamer_args args; + stream_args_t args; args.cpu_format = "fc32"; args.otw_format = "sc16"; - _rx_streamer = get_rx_streamer(args); + _rx_streamer = get_rx_stream(args); _recv_tid = io_type_t::COMPLEX_FLOAT32; } return _rx_streamer->get_max_num_samps(); diff --git a/host/include/uhd/stream.hpp b/host/include/uhd/stream.hpp new file mode 100644 index 000000000..583dfd1e4 --- /dev/null +++ b/host/include/uhd/stream.hpp @@ -0,0 +1,189 @@ +// +// 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 . +// + +#ifndef INCLUDED_UHD_STREAM_HPP +#define INCLUDED_UHD_STREAM_HPP + +#include +#include +#include +#include +#include +#include +#include + +namespace uhd{ + +/*! + * A struct of parameters to construct a streamer. + * + * Note: + * Not all combinations of CPU and OTW format have conversion support. + * You may however write and register your own conversion routines. + */ +struct UHD_API stream_args_t{ + + //! Convenience constructor for streamer args + stream_args_t( + const std::string &cpu = "fc32", + const std::string &otw = "sc16" + ){ + cpu_format = cpu; + otw_format = otw; + } + + /*! + * The CPU format is a string that describes the format of host memory. + * Common CPU formats are: + * - fc32 - complex + * - fc64 - complex + * - sc16 - complex + * - sc8 - complex + * - f32 - float + * - f64 - double + * - s16 - int16_t + * - s8 - int8_t + */ + std::string cpu_format; + + /*! + * The OTW format is a string that describes the format over-the-wire. + * Common OTW format are: + * - sc16 - Q16 I16 + * - sc8 - Q8_1 I8_1 Q8_0 I8_0 + * - s16 - R16_1 R16_0 + * - s8 - R8_3 R8_2 R8_1 R8_0 + */ + std::string otw_format; + + /*! + * The args parameter is currently unused. Leave it blank. + * The intention is that a user with a custom DSP design + * may want to pass args and do something special with it. + */ + std::string args; + + /*! + * The channels is a list of channel numbers. + * Leave this blank to default to channel 0. + * Set channels for a multi-channel application. + * Channel mapping depends on the front-end selection. + */ + std::vector channels; +}; + +/*! + * The RX streamer is the host interface to receiving samples. + * It represents the layer between the samples on the host + * and samples inside the device's receive DSP processing. + */ +class UHD_API rx_streamer : boost::noncopyable{ +public: + typedef boost::shared_ptr sptr; + + //! Get the number of channels associated with this streamer + virtual size_t get_num_channels(void) const = 0; + + //! Get the max number of samples per buffer per packet + virtual size_t get_max_num_samps(void) const = 0; + + //! Typedef for a pointer to a single, or a collection of recv buffers + typedef ref_vector buffs_type; + + /*! + * Receive buffers containing samples described by the metadata. + * + * Receive handles fragmentation as follows: + * If the buffer has insufficient space to hold all samples + * that were received in a single packet over-the-wire, + * then the buffer will be completely filled and the implementation + * will hold a pointer into the remaining portion of the packet. + * Subsequent calls will load from the remainder of the packet, + * and will flag the metadata to show that this is a fragment. + * The next call to receive, after the remainder becomes exahausted, + * will perform an over-the-wire receive as usual. + * See the rx metadata fragment flags and offset fields for details. + * + * This is a blocking call and will not return until the number + * of samples returned have been written into each buffer. + * Under a timeout condition, the number of samples returned + * may be less than the number of samples specified. + * + * \param buffs a vector of writable memory to fill with samples + * \param nsamps_per_buff the size of each buffer in number of samples + * \param metadata data to fill describing the buffer + * \param timeout the timeout in seconds to wait for a packet + * \return the number of samples received or 0 on error + */ + virtual size_t recv( + const buffs_type &buffs, + const size_t nsamps_per_buff, + rx_metadata_t &metadata, + double timeout = 0.1 + ) = 0; +}; + +/*! + * The TX streamer is the host interface to transmitting samples. + * It represents the layer between the samples on the host + * and samples inside the device's transmit DSP processing. + */ +class UHD_API tx_streamer : boost::noncopyable{ +public: + typedef boost::shared_ptr sptr; + + //! Get the number of channels associated with this streamer + virtual size_t get_num_channels(void) const = 0; + + //! Get the max number of samples per buffer per packet + virtual size_t get_max_num_samps(void) const = 0; + + //! Typedef for a pointer to a single, or a collection of send buffers + typedef ref_vector buffs_type; + + /*! + * Send buffers containing samples described by the metadata. + * + * Send handles fragmentation as follows: + * If the buffer has more items than the maximum per packet, + * the send method will fragment the samples across several packets. + * Send will respect the burst flags when fragmenting to ensure + * that start of burst can only be set on the first fragment and + * that end of burst can only be set on the final fragment. + * + * This is a blocking call and will not return until the number + * of samples returned have been read out of each buffer. + * Under a timeout condition, the number of samples returned + * may be less than the number of samples specified. + * + * \param buffs a vector of read-only memory containing samples + * \param nsamps_per_buff the number of samples to send, per buffer + * \param metadata data describing the buffer's contents + * \param timeout the timeout in seconds to wait on a packet + * \return the number of samples sent + */ + virtual size_t send( + const buffs_type &buffs, + const size_t nsamps_per_buff, + const tx_metadata_t &metadata, + double timeout = 0.1 + ) = 0; +}; + +} //namespace uhd + +#endif /* INCLUDED_UHD_STREAM_HPP */ diff --git a/host/include/uhd/streamer.hpp b/host/include/uhd/streamer.hpp deleted file mode 100644 index c9c6fef89..000000000 --- a/host/include/uhd/streamer.hpp +++ /dev/null @@ -1,189 +0,0 @@ -// -// 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 . -// - -#ifndef INCLUDED_UHD_STREAMER_HPP -#define INCLUDED_UHD_STREAMER_HPP - -#include -#include -#include -#include -#include -#include -#include - -namespace uhd{ - -/*! - * A struct of parameters to construct a streamer. - * - * Note: - * Not all combinations of CPU and OTW format have conversion support. - * You may however write and register your own conversion routines. - */ -struct UHD_API streamer_args{ - - //! Convenience constructor for streamer args - streamer_args( - const std::string &cpu = "fc32", - const std::string &otw = "sc16" - ){ - cpu_format = cpu; - otw_format = otw; - } - - /*! - * The CPU format is a string that describes the format of host memory. - * Common CPU formats are: - * - fc32 - complex - * - fc64 - complex - * - sc16 - complex - * - sc8 - complex - * - f32 - float - * - f64 - double - * - s16 - int16_t - * - s8 - int8_t - */ - std::string cpu_format; - - /*! - * The OTW format is a string that describes the format over-the-wire. - * Common OTW format are: - * - sc16 - Q16 I16 - * - sc8 - Q8_1 I8_1 Q8_0 I8_0 - * - s16 - R16_1 R16_0 - * - s8 - R8_3 R8_2 R8_1 R8_0 - */ - std::string otw_format; - - /*! - * The args parameter is currently unused. Leave it blank. - * The intention is that a user with a custom DSP design - * may want to pass args and do something special with it. - */ - std::string args; - - /*! - * The channels is a list of channel numbers. - * Leave this blank to default to channel 0. - * Set channels for a multi-channel application. - * Channel mapping depends on the front-end selection. - */ - std::vector channels; -}; - -/*! - * The RX streamer is the host interface to receiving samples. - * It represents the layer between the samples on the host - * and samples inside the device's receive DSP processing. - */ -class UHD_API rx_streamer : boost::noncopyable{ -public: - typedef boost::shared_ptr sptr; - - //! Get the number of channels associated with this streamer - virtual size_t get_num_channels(void) const = 0; - - //! Get the max number of samples per buffer per packet - virtual size_t get_max_num_samps(void) const = 0; - - //! Typedef for a pointer to a single, or a collection of recv buffers - typedef ref_vector buffs_type; - - /*! - * Receive buffers containing samples described by the metadata. - * - * Receive handles fragmentation as follows: - * If the buffer has insufficient space to hold all samples - * that were received in a single packet over-the-wire, - * then the buffer will be completely filled and the implementation - * will hold a pointer into the remaining portion of the packet. - * Subsequent calls will load from the remainder of the packet, - * and will flag the metadata to show that this is a fragment. - * The next call to receive, after the remainder becomes exahausted, - * will perform an over-the-wire receive as usual. - * See the rx metadata fragment flags and offset fields for details. - * - * This is a blocking call and will not return until the number - * of samples returned have been written into each buffer. - * Under a timeout condition, the number of samples returned - * may be less than the number of samples specified. - * - * \param buffs a vector of writable memory to fill with samples - * \param nsamps_per_buff the size of each buffer in number of samples - * \param metadata data to fill describing the buffer - * \param timeout the timeout in seconds to wait for a packet - * \return the number of samples received or 0 on error - */ - virtual size_t recv( - const buffs_type &buffs, - const size_t nsamps_per_buff, - rx_metadata_t &metadata, - double timeout = 0.1 - ) = 0; -}; - -/*! - * The TX streamer is the host interface to transmitting samples. - * It represents the layer between the samples on the host - * and samples inside the device's transmit DSP processing. - */ -class UHD_API tx_streamer : boost::noncopyable{ -public: - typedef boost::shared_ptr sptr; - - //! Get the number of channels associated with this streamer - virtual size_t get_num_channels(void) const = 0; - - //! Get the max number of samples per buffer per packet - virtual size_t get_max_num_samps(void) const = 0; - - //! Typedef for a pointer to a single, or a collection of send buffers - typedef ref_vector buffs_type; - - /*! - * Send buffers containing samples described by the metadata. - * - * Send handles fragmentation as follows: - * If the buffer has more items than the maximum per packet, - * the send method will fragment the samples across several packets. - * Send will respect the burst flags when fragmenting to ensure - * that start of burst can only be set on the first fragment and - * that end of burst can only be set on the final fragment. - * - * This is a blocking call and will not return until the number - * of samples returned have been read out of each buffer. - * Under a timeout condition, the number of samples returned - * may be less than the number of samples specified. - * - * \param buffs a vector of read-only memory containing samples - * \param nsamps_per_buff the number of samples to send, per buffer - * \param metadata data describing the buffer's contents - * \param timeout the timeout in seconds to wait on a packet - * \return the number of samples sent - */ - virtual size_t send( - const buffs_type &buffs, - const size_t nsamps_per_buff, - const tx_metadata_t &metadata, - double timeout = 0.1 - ) = 0; -}; - -} //namespace uhd - -#endif /* INCLUDED_UHD_STREAMER_HPP */ diff --git a/host/include/uhd/usrp/multi_usrp.hpp b/host/include/uhd/usrp/multi_usrp.hpp index 303af7ef9..72386204f 100644 --- a/host/include/uhd/usrp/multi_usrp.hpp +++ b/host/include/uhd/usrp/multi_usrp.hpp @@ -109,13 +109,13 @@ public: virtual device::sptr get_device(void) = 0; //! Convenience method to get a RX streamer - rx_streamer::sptr get_rx_streamer(const streamer_args &args){ - return this->get_device()->get_rx_streamer(args); + rx_streamer::sptr get_rx_stream(const stream_args_t &args){ + return this->get_device()->get_rx_stream(args); } //! Convenience method to get a TX streamer - tx_streamer::sptr get_tx_streamer(const streamer_args &args){ - return this->get_device()->get_tx_streamer(args); + tx_streamer::sptr get_tx_stream(const stream_args_t &args){ + return this->get_device()->get_tx_stream(args); } /******************************************************************* diff --git a/host/lib/transport/super_recv_packet_handler.hpp b/host/lib/transport/super_recv_packet_handler.hpp index f4dbc5531..de7b4b34c 100644 --- a/host/lib/transport/super_recv_packet_handler.hpp +++ b/host/lib/transport/super_recv_packet_handler.hpp @@ -21,7 +21,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/host/lib/transport/super_send_packet_handler.hpp b/host/lib/transport/super_send_packet_handler.hpp index 079fea11e..42bac5e21 100644 --- a/host/lib/transport/super_send_packet_handler.hpp +++ b/host/lib/transport/super_send_packet_handler.hpp @@ -21,7 +21,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/host/lib/usrp/usrp1/io_impl.cpp b/host/lib/usrp/usrp1/io_impl.cpp index 7d4fe2ec7..22c2db6ae 100644 --- a/host/lib/usrp/usrp1/io_impl.cpp +++ b/host/lib/usrp/usrp1/io_impl.cpp @@ -527,7 +527,7 @@ bool usrp1_impl::recv_async_msg( /*********************************************************************** * Receive streamer **********************************************************************/ -rx_streamer::sptr usrp1_impl::get_rx_streamer(const uhd::streamer_args &args){ +rx_streamer::sptr usrp1_impl::get_rx_stream(const uhd::stream_args_t &args){ //map an empty channel set to chan0 const std::vector channels = args.channels.empty()? std::vector(1, 0) : args.channels; @@ -567,7 +567,7 @@ rx_streamer::sptr usrp1_impl::get_rx_streamer(const uhd::streamer_args &args){ /*********************************************************************** * Transmit streamer **********************************************************************/ -tx_streamer::sptr usrp1_impl::get_tx_streamer(const uhd::streamer_args &args){ +tx_streamer::sptr usrp1_impl::get_tx_stream(const uhd::stream_args_t &args){ //map an empty channel set to chan0 const std::vector channels = args.channels.empty()? std::vector(1, 0) : args.channels; diff --git a/host/lib/usrp/usrp1/usrp1_impl.hpp b/host/lib/usrp/usrp1/usrp1_impl.hpp index 7776ea8d6..c777307ee 100644 --- a/host/lib/usrp/usrp1/usrp1_impl.hpp +++ b/host/lib/usrp/usrp1/usrp1_impl.hpp @@ -55,8 +55,8 @@ public: ~usrp1_impl(void); //the io interface - uhd::rx_streamer::sptr get_rx_streamer(const uhd::streamer_args &args); - uhd::tx_streamer::sptr get_tx_streamer(const uhd::streamer_args &args); + uhd::rx_streamer::sptr get_rx_stream(const uhd::stream_args_t &args); + uhd::tx_streamer::sptr get_tx_stream(const uhd::stream_args_t &args); bool recv_async_msg(uhd::async_metadata_t &, double); private: diff --git a/host/lib/usrp/usrp2/io_impl.cpp b/host/lib/usrp/usrp2/io_impl.cpp index f271d480a..d37be403b 100644 --- a/host/lib/usrp/usrp2/io_impl.cpp +++ b/host/lib/usrp/usrp2/io_impl.cpp @@ -366,7 +366,7 @@ bool usrp2_impl::recv_async_msg( /*********************************************************************** * Receive streamer **********************************************************************/ -rx_streamer::sptr usrp2_impl::get_rx_streamer(const uhd::streamer_args &args){ +rx_streamer::sptr usrp2_impl::get_rx_stream(const uhd::stream_args_t &args){ //map an empty channel set to chan0 const std::vector channels = args.channels.empty()? std::vector(1, 0) : args.channels; @@ -426,7 +426,7 @@ rx_streamer::sptr usrp2_impl::get_rx_streamer(const uhd::streamer_args &args){ /*********************************************************************** * Transmit streamer **********************************************************************/ -tx_streamer::sptr usrp2_impl::get_tx_streamer(const uhd::streamer_args &args){ +tx_streamer::sptr usrp2_impl::get_tx_stream(const uhd::stream_args_t &args){ //map an empty channel set to chan0 const std::vector channels = args.channels.empty()? std::vector(1, 0) : args.channels; diff --git a/host/lib/usrp/usrp2/usrp2_impl.hpp b/host/lib/usrp/usrp2/usrp2_impl.hpp index a67c704c8..31a390af7 100644 --- a/host/lib/usrp/usrp2/usrp2_impl.hpp +++ b/host/lib/usrp/usrp2/usrp2_impl.hpp @@ -72,8 +72,8 @@ public: ~usrp2_impl(void); //the io interface - uhd::rx_streamer::sptr get_rx_streamer(const uhd::streamer_args &args); - uhd::tx_streamer::sptr get_tx_streamer(const uhd::streamer_args &args); + uhd::rx_streamer::sptr get_rx_stream(const uhd::stream_args_t &args); + uhd::tx_streamer::sptr get_tx_stream(const uhd::stream_args_t &args); bool recv_async_msg(uhd::async_metadata_t &, double); private: -- cgit v1.2.3 From de17ef4614c3c14212f239e3c735bfde3f47a68f Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Thu, 6 Oct 2011 13:38:29 -0700 Subject: usrp1: multi channel receive working --- host/lib/convert/convert_impl.cpp | 2 +- host/lib/transport/super_recv_packet_handler.hpp | 2 +- host/lib/transport/super_send_packet_handler.hpp | 2 +- host/lib/usrp/usrp1/io_impl.cpp | 8 ++++---- 4 files changed, 7 insertions(+), 7 deletions(-) (limited to 'host') diff --git a/host/lib/convert/convert_impl.cpp b/host/lib/convert/convert_impl.cpp index 5c9e77e93..280957c2a 100644 --- a/host/lib/convert/convert_impl.cpp +++ b/host/lib/convert/convert_impl.cpp @@ -124,7 +124,7 @@ size_t convert::get_bytes_per_item(const std::string &markup){ return get_bytes_per_item(markup.substr(0, pos)); } - throw uhd::key_error("Cannot find an item size " + markup); + throw uhd::key_error("Cannot find an item size:\n" + markup); } UHD_STATIC_BLOCK(convert_register_item_sizes){ diff --git a/host/lib/transport/super_recv_packet_handler.hpp b/host/lib/transport/super_recv_packet_handler.hpp index de7b4b34c..83c8988e8 100644 --- a/host/lib/transport/super_recv_packet_handler.hpp +++ b/host/lib/transport/super_recv_packet_handler.hpp @@ -123,7 +123,7 @@ public: //! Set the conversion routine for all channels void set_converter(const uhd::convert::id_type &id){ - _io_buffs.resize(id.num_inputs); + _io_buffs.resize(id.num_outputs); _converter = uhd::convert::get_converter(id); _bytes_per_otw_item = uhd::convert::get_bytes_per_item(id.input_markup); _bytes_per_cpu_item = uhd::convert::get_bytes_per_item(id.output_markup); diff --git a/host/lib/transport/super_send_packet_handler.hpp b/host/lib/transport/super_send_packet_handler.hpp index 42bac5e21..1ac178ad2 100644 --- a/host/lib/transport/super_send_packet_handler.hpp +++ b/host/lib/transport/super_send_packet_handler.hpp @@ -99,7 +99,7 @@ public: //! Set the conversion routine for all channels void set_converter(const uhd::convert::id_type &id){ - _io_buffs.resize(id.num_outputs); + _io_buffs.resize(id.num_inputs); _converter = uhd::convert::get_converter(id); _bytes_per_otw_item = uhd::convert::get_bytes_per_item(id.output_markup); _bytes_per_cpu_item = uhd::convert::get_bytes_per_item(id.input_markup); diff --git a/host/lib/usrp/usrp1/io_impl.cpp b/host/lib/usrp/usrp1/io_impl.cpp index 22c2db6ae..03263ed26 100644 --- a/host/lib/usrp/usrp1/io_impl.cpp +++ b/host/lib/usrp/usrp1/io_impl.cpp @@ -549,9 +549,9 @@ rx_streamer::sptr usrp1_impl::get_rx_stream(const uhd::stream_args_t &args){ //set the converter uhd::convert::id_type id; id.input_markup = args.otw_format + "_item32_le"; - id.num_inputs = channels.size(); + id.num_inputs = 1; id.output_markup = args.cpu_format; - id.num_outputs = 1; + id.num_outputs = channels.size(); id.args = args.args; my_streamer->set_converter(id); @@ -590,9 +590,9 @@ tx_streamer::sptr usrp1_impl::get_tx_stream(const uhd::stream_args_t &args){ //set the converter uhd::convert::id_type id; id.input_markup = args.cpu_format; - id.num_inputs = 1; + id.num_inputs = channels.size(); id.output_markup = args.otw_format + "_item32_le"; - id.num_outputs = channels.size(); + id.num_outputs = 1; id.args = args.args; my_streamer->set_converter(id); -- cgit v1.2.3 From 4c4f0810ef06be18e989b6933ff236ff97c13dd0 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Thu, 6 Oct 2011 18:41:59 -0700 Subject: usrp1: type conversions and 8-bit work --- host/lib/convert/convert_common.hpp | 12 ++-- host/lib/convert/gen_convert_general.py | 102 ++++++++++++++++++++++++++------ host/lib/usrp/usrp1/io_impl.cpp | 69 ++++++++++++++------- host/lib/usrp/usrp1/usrp1_calc_mux.hpp | 4 +- host/lib/usrp/usrp1/usrp1_impl.cpp | 4 +- host/lib/usrp/usrp1/usrp1_impl.hpp | 4 +- 6 files changed, 143 insertions(+), 52 deletions(-) (limited to 'host') diff --git a/host/lib/convert/convert_common.hpp b/host/lib/convert/convert_common.hpp index 8c8cc88b0..612fa312b 100644 --- a/host/lib/convert/convert_common.hpp +++ b/host/lib/convert/convert_common.hpp @@ -86,19 +86,19 @@ static UHD_INLINE sc16_t item32_to_sc16(item32_t item, double){ /*********************************************************************** * Convert complex float buffer to items32 (no swap) **********************************************************************/ -static UHD_INLINE item32_t fc32_to_item32(fc32_t num, float scale_factor){ - boost::uint16_t real = boost::int16_t(num.real()*scale_factor); - boost::uint16_t imag = boost::int16_t(num.imag()*scale_factor); +static UHD_INLINE item32_t fc32_to_item32(fc32_t num, double scale_factor){ + boost::uint16_t real = boost::int16_t(num.real()*float(scale_factor)); + boost::uint16_t imag = boost::int16_t(num.imag()*float(scale_factor)); return (item32_t(real) << 16) | (item32_t(imag) << 0); } /*********************************************************************** * Convert items32 buffer to complex float **********************************************************************/ -static UHD_INLINE fc32_t item32_to_fc32(item32_t item, float scale_factor){ +static UHD_INLINE fc32_t item32_to_fc32(item32_t item, double scale_factor){ return fc32_t( - float(boost::int16_t(item >> 16)*scale_factor), - float(boost::int16_t(item >> 0)*scale_factor) + float(boost::int16_t(item >> 16)*float(scale_factor)), + float(boost::int16_t(item >> 0)*float(scale_factor)) ); } diff --git a/host/lib/convert/gen_convert_general.py b/host/lib/convert/gen_convert_general.py index 0d68a4dd3..a5c4d4cb7 100644 --- a/host/lib/convert/gen_convert_general.py +++ b/host/lib/convert/gen_convert_general.py @@ -28,13 +28,13 @@ TMPL_HEADER = """ using namespace uhd::convert; """ -TMPL_CONV_TO_FROM_ITEM32_1 = """ +TMPL_CONV_GEN2_COMPLEX = """ DECLARE_CONVERTER($(cpu_type), 1, sc16_item32_$(end), 1, PRIORITY_GENERAL){ const $(cpu_type)_t *input = reinterpret_cast(inputs[0]); item32_t *output = reinterpret_cast(outputs[0]); for (size_t i = 0; i < nsamps; i++){ - output[i] = $(to_wire)($(cpu_type)_to_item32(input[i], float(scale_factor))); + output[i] = $(to_wire)($(cpu_type)_to_item32(input[i], scale_factor)); } } @@ -43,33 +43,83 @@ DECLARE_CONVERTER(sc16_item32_$(end), 1, $(cpu_type), 1, PRIORITY_GENERAL){ $(cpu_type)_t *output = reinterpret_cast<$(cpu_type)_t *>(outputs[0]); for (size_t i = 0; i < nsamps; i++){ - output[i] = item32_to_$(cpu_type)($(to_host)(input[i]), float(scale_factor)); + output[i] = item32_to_$(cpu_type)($(to_host)(input[i]), scale_factor); } } """ -TMPL_CONV_TO_FROM_ITEM32_X = """ -DECLARE_CONVERTER($(cpu_type), $(width), sc16_item32_$(end), 1, PRIORITY_GENERAL){ + +TMPL_CONV_USRP1_COMPLEX = """ +DECLARE_CONVERTER($(cpu_type), $(width), sc16_item16_usrp1, 1, PRIORITY_GENERAL){ #for $w in range($width) const $(cpu_type)_t *input$(w) = reinterpret_cast(inputs[$(w)]); #end for - item32_t *output = reinterpret_cast(outputs[0]); + boost::uint16_t *output = reinterpret_cast(outputs[0]); + + if (scale_factor == 0){} //avoids unused warning for (size_t i = 0, j = 0; i < nsamps; i++){ #for $w in range($width) - output[j++] = $(to_wire)($(cpu_type)_to_item32(input$(w)[i], float(scale_factor))); + output[j++] = $(to_wire)(boost::int16_t(input$(w)[i].real()$(do_scale))); + output[j++] = $(to_wire)(boost::int16_t(input$(w)[i].imag()$(do_scale))); #end for } } -DECLARE_CONVERTER(sc16_item32_$(end), 1, $(cpu_type), $(width), PRIORITY_GENERAL){ - const item32_t *input = reinterpret_cast(inputs[0]); +DECLARE_CONVERTER(sc16_item16_usrp1, 1, $(cpu_type), $(width), PRIORITY_GENERAL){ + const boost::uint16_t *input = reinterpret_cast(inputs[0]); #for $w in range($width) $(cpu_type)_t *output$(w) = reinterpret_cast<$(cpu_type)_t *>(outputs[$(w)]); #end for + if (scale_factor == 0){} //avoids unused warning + for (size_t i = 0, j = 0; i < nsamps; i++){ #for $w in range($width) - output$(w)[i] = item32_to_$(cpu_type)($(to_host)(input[j++]), float(scale_factor)); + output$(w)[i] = $(cpu_type)_t( + boost::int16_t($(to_host)(input[j+0]))$(do_scale), + boost::int16_t($(to_host)(input[j+1]))$(do_scale) + ); + j += 2; + #end for + } +} + +DECLARE_CONVERTER($(cpu_type), $(width), sc8_item16_usrp1, 1, PRIORITY_GENERAL){ + #for $w in range($width) + const $(cpu_type)_t *input$(w) = reinterpret_cast(inputs[$(w)]); + #end for + boost::uint16_t *output = reinterpret_cast(outputs[0]); + + if (scale_factor == 0){} //avoids unused warning + + for (size_t i = 0, j = 0; i < nsamps; i++){ + #for $w in range($width) + { + const boost::uint8_t real = boost::int8_t(input$(w)[i].real()$(do_scale)); + const boost::uint8_t imag = boost::int8_t(input$(w)[i].imag()$(do_scale)); + output[j++] = $(to_wire)((boost::uint16_t(imag) << 8) | real); + } + #end for + } +} + +DECLARE_CONVERTER(sc8_item16_usrp1, 1, $(cpu_type), $(width), PRIORITY_GENERAL){ + const boost::uint16_t *input = reinterpret_cast(inputs[0]); + #for $w in range($width) + $(cpu_type)_t *output$(w) = reinterpret_cast<$(cpu_type)_t *>(outputs[$(w)]); + #end for + + if (scale_factor == 0){} //avoids unused warning + + for (size_t i = 0, j = 0; i < nsamps; i++){ + #for $w in range($width) + { + const boost::uint16_t num = $(to_host)(input[j++]); + output$(w)[i] = $(cpu_type)_t( + boost::int8_t(num)$(do_scale), + boost::int8_t(num >> 8)$(do_scale) + ); + } #end for } } @@ -83,14 +133,28 @@ if __name__ == '__main__': import sys, os file = os.path.basename(__file__) output = parse_tmpl(TMPL_HEADER, file=file) - for width in 1, 2, 3, 4: - for end, to_host, to_wire in ( - ('be', 'uhd::ntohx', 'uhd::htonx'), - ('le', 'uhd::wtohx', 'uhd::htowx'), + + #generate complex converters for all gen2 platforms + for end, to_host, to_wire in ( + ('be', 'uhd::ntohx', 'uhd::htonx'), + ('le', 'uhd::wtohx', 'uhd::htowx'), + ): + for cpu_type in 'fc64', 'fc32', 'sc16': + output += parse_tmpl( + TMPL_CONV_GEN2_COMPLEX, + end=end, to_host=to_host, to_wire=to_wire, cpu_type=cpu_type + ) + + #generate complex converters for usrp1 format + for width in 1, 2, 4: + for cpu_type, do_scale in ( + ('fc64', '*scale_factor'), + ('fc32', '*float(scale_factor)'), + ('sc16', ''), ): - for cpu_type in 'fc64', 'fc32', 'sc16': - output += parse_tmpl( - TMPL_CONV_TO_FROM_ITEM32_1 if width == 1 else TMPL_CONV_TO_FROM_ITEM32_X, - width=width, end=end, to_host=to_host, to_wire=to_wire, cpu_type=cpu_type - ) + output += parse_tmpl( + TMPL_CONV_USRP1_COMPLEX, + width=width, to_host='uhd::wtohx', to_wire='uhd::htowx', + cpu_type=cpu_type, do_scale=do_scale + ) open(sys.argv[1], 'w').write(output) diff --git a/host/lib/usrp/usrp1/io_impl.cpp b/host/lib/usrp/usrp1/io_impl.cpp index 03263ed26..7f20a8608 100644 --- a/host/lib/usrp/usrp1/io_impl.cpp +++ b/host/lib/usrp/usrp1/io_impl.cpp @@ -438,41 +438,45 @@ void usrp1_impl::update_tx_subdev_spec(const uhd::usrp::subdev_spec_t &spec){ this->restore_tx(s); } -double usrp1_impl::update_rx_samp_rate(const double samp_rate){ +double usrp1_impl::update_rx_samp_rate(size_t dspno, const double samp_rate){ const size_t rate = uhd::clip( - boost::math::iround(_master_clock_rate / samp_rate), size_t(std::ceil(_master_clock_rate / 8e6)), 256 + boost::math::iround(_master_clock_rate / samp_rate), size_t(std::ceil(_master_clock_rate / 16e6)), 256 ); - bool s = this->disable_rx(); - _iface->poke32(FR_DECIM_RATE, rate/2 - 1); - this->restore_rx(s); + if (dspno == 0){ //only care if dsp0 is set since its homogeneous + bool s = this->disable_rx(); + _iface->poke32(FR_DECIM_RATE, rate/2 - 1); + this->restore_rx(s); - //update the streamer if created - boost::shared_ptr my_streamer = - boost::dynamic_pointer_cast(_rx_streamer.lock()); - if (my_streamer.get() != NULL){ - my_streamer->set_samp_rate(_master_clock_rate / rate); + //update the streamer if created + boost::shared_ptr my_streamer = + boost::dynamic_pointer_cast(_rx_streamer.lock()); + if (my_streamer.get() != NULL){ + my_streamer->set_samp_rate(_master_clock_rate / rate); + } } return _master_clock_rate / rate; } -double usrp1_impl::update_tx_samp_rate(const double samp_rate){ +double usrp1_impl::update_tx_samp_rate(size_t dspno, const double samp_rate){ const size_t rate = uhd::clip( boost::math::iround(_master_clock_rate / samp_rate), size_t(std::ceil(_master_clock_rate / 8e6)), 256 ); - bool s = this->disable_tx(); - _iface->poke32(FR_INTERP_RATE, rate/2 - 1); - this->restore_tx(s); + if (dspno == 0){ //only care if dsp0 is set since its homogeneous + bool s = this->disable_tx(); + _iface->poke32(FR_INTERP_RATE, rate/2 - 1); + this->restore_tx(s); - //update the streamer if created - boost::shared_ptr my_streamer = - boost::dynamic_pointer_cast(_tx_streamer.lock()); - if (my_streamer.get() != NULL){ - my_streamer->set_samp_rate(_master_clock_rate / rate); + //update the streamer if created + boost::shared_ptr my_streamer = + boost::dynamic_pointer_cast(_tx_streamer.lock()); + if (my_streamer.get() != NULL){ + my_streamer->set_samp_rate(_master_clock_rate / rate); + } } return _master_clock_rate / rate; @@ -528,6 +532,25 @@ bool usrp1_impl::recv_async_msg( * Receive streamer **********************************************************************/ rx_streamer::sptr usrp1_impl::get_rx_stream(const uhd::stream_args_t &args){ + if (args.otw_format == "sc16"){ + _iface->poke32(FR_RX_FORMAT, 0 + | (0 << bmFR_RX_FORMAT_SHIFT_SHIFT) + | (16 << bmFR_RX_FORMAT_WIDTH_SHIFT) + | bmFR_RX_FORMAT_WANT_Q + ); + } + else if (args.otw_format == "sc8"){ + _iface->poke32(FR_RX_FORMAT, 0 + | (8 << bmFR_RX_FORMAT_SHIFT_SHIFT) + | (8 << bmFR_RX_FORMAT_WIDTH_SHIFT) + | bmFR_RX_FORMAT_WANT_Q + | bmFR_RX_FORMAT_BYPASS_HB //needed for 16Msps + ); + } + else{ + throw uhd::value_error("USRP1 RX cannot handle requested wire format: " + args.otw_format); + } + //map an empty channel set to chan0 const std::vector channels = args.channels.empty()? std::vector(1, 0) : args.channels; @@ -548,7 +571,7 @@ rx_streamer::sptr usrp1_impl::get_rx_stream(const uhd::stream_args_t &args){ //set the converter uhd::convert::id_type id; - id.input_markup = args.otw_format + "_item32_le"; + id.input_markup = args.otw_format + "_item16_usrp1"; id.num_inputs = 1; id.output_markup = args.cpu_format; id.num_outputs = channels.size(); @@ -568,6 +591,10 @@ rx_streamer::sptr usrp1_impl::get_rx_stream(const uhd::stream_args_t &args){ * Transmit streamer **********************************************************************/ tx_streamer::sptr usrp1_impl::get_tx_stream(const uhd::stream_args_t &args){ + if (args.otw_format != "sc16"){ + throw uhd::value_error("USRP1 TX cannot handle requested wire format: " + args.otw_format); + } + //map an empty channel set to chan0 const std::vector channels = args.channels.empty()? std::vector(1, 0) : args.channels; @@ -591,7 +618,7 @@ tx_streamer::sptr usrp1_impl::get_tx_stream(const uhd::stream_args_t &args){ uhd::convert::id_type id; id.input_markup = args.cpu_format; id.num_inputs = channels.size(); - id.output_markup = args.otw_format + "_item32_le"; + id.output_markup = args.otw_format + "_item16_usrp1"; id.num_outputs = 1; id.args = args.args; my_streamer->set_converter(id); diff --git a/host/lib/usrp/usrp1/usrp1_calc_mux.hpp b/host/lib/usrp/usrp1/usrp1_calc_mux.hpp index 31c190db0..d86a7a809 100644 --- a/host/lib/usrp/usrp1/usrp1_calc_mux.hpp +++ b/host/lib/usrp/usrp1/usrp1_calc_mux.hpp @@ -37,7 +37,7 @@ typedef std::pair mapping_pair_t; * to account for the reversal in the type conversion routines. **********************************************************************/ static int calc_rx_mux_pair(int adc_for_i, int adc_for_q){ - return (adc_for_i << 2) | (adc_for_q << 0); //shift reversal here + return (adc_for_i << 0) | (adc_for_q << 2); } /*! @@ -98,7 +98,7 @@ static boost::uint32_t calc_rx_mux(const std::vector &mapping){ * to account for the reversal in the type conversion routines. **********************************************************************/ static int calc_tx_mux_pair(int chn_for_i, int chn_for_q){ - return (chn_for_i << 4) | (chn_for_q << 0); //shift reversal here + return (chn_for_i << 0) | (chn_for_q << 4); } /*! diff --git a/host/lib/usrp/usrp1/usrp1_impl.cpp b/host/lib/usrp/usrp1/usrp1_impl.cpp index d169c4823..93a301c02 100644 --- a/host/lib/usrp/usrp1/usrp1_impl.cpp +++ b/host/lib/usrp/usrp1/usrp1_impl.cpp @@ -282,7 +282,7 @@ usrp1_impl::usrp1_impl(const device_addr_t &device_addr){ fs_path rx_dsp_path = mb_path / str(boost::format("rx_dsps/%u") % dspno); _tree->create(rx_dsp_path / "rate/value") .set(1e6) - .coerce(boost::bind(&usrp1_impl::update_rx_samp_rate, this, _1)); + .coerce(boost::bind(&usrp1_impl::update_rx_samp_rate, this, dspno, _1)); _tree->create(rx_dsp_path / "freq/value") .coerce(boost::bind(&usrp1_impl::update_rx_dsp_freq, this, dspno, _1)); _tree->create(rx_dsp_path / "freq/range") @@ -303,7 +303,7 @@ usrp1_impl::usrp1_impl(const device_addr_t &device_addr){ fs_path tx_dsp_path = mb_path / str(boost::format("tx_dsps/%u") % dspno); _tree->create(tx_dsp_path / "rate/value") .set(1e6) - .coerce(boost::bind(&usrp1_impl::update_tx_samp_rate, this, _1)); + .coerce(boost::bind(&usrp1_impl::update_tx_samp_rate, this, dspno, _1)); _tree->create(tx_dsp_path / "freq/value") .coerce(boost::bind(&usrp1_impl::update_tx_dsp_freq, this, dspno, _1)); _tree->create(tx_dsp_path / "freq/range") //magic scalar comes from codec control: diff --git a/host/lib/usrp/usrp1/usrp1_impl.hpp b/host/lib/usrp/usrp1/usrp1_impl.hpp index c777307ee..cfdcbbcc1 100644 --- a/host/lib/usrp/usrp1/usrp1_impl.hpp +++ b/host/lib/usrp/usrp1/usrp1_impl.hpp @@ -90,8 +90,8 @@ private: double update_rx_codec_gain(const std::string &, const double); //sets A and B at once void update_rx_subdev_spec(const uhd::usrp::subdev_spec_t &); void update_tx_subdev_spec(const uhd::usrp::subdev_spec_t &); - double update_rx_samp_rate(const double); - double update_tx_samp_rate(const double); + double update_rx_samp_rate(size_t dspno, const double); + double update_tx_samp_rate(size_t dspno, const double); void update_rates(void); double update_rx_dsp_freq(const size_t, const double); double update_tx_dsp_freq(const size_t, const double); -- cgit v1.2.3 From 65fb4d225204b4ee2b7c73fc0ec393cfff9d6149 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Fri, 7 Oct 2011 10:47:56 -0700 Subject: usrp1: various tweaks related to streaming --- host/lib/convert/gen_convert_general.py | 19 ------------------- host/lib/usrp/usrp1/io_impl.cpp | 18 ++++++++++-------- host/lib/usrp/usrp1/soft_time_ctrl.cpp | 7 +++---- host/lib/usrp/usrp1/soft_time_ctrl.hpp | 2 +- host/lib/usrp/usrp1/usrp1_impl.cpp | 2 -- 5 files changed, 14 insertions(+), 34 deletions(-) (limited to 'host') diff --git a/host/lib/convert/gen_convert_general.py b/host/lib/convert/gen_convert_general.py index a5c4d4cb7..0cd4155fa 100644 --- a/host/lib/convert/gen_convert_general.py +++ b/host/lib/convert/gen_convert_general.py @@ -84,25 +84,6 @@ DECLARE_CONVERTER(sc16_item16_usrp1, 1, $(cpu_type), $(width), PRIORITY_GENERAL) } } -DECLARE_CONVERTER($(cpu_type), $(width), sc8_item16_usrp1, 1, PRIORITY_GENERAL){ - #for $w in range($width) - const $(cpu_type)_t *input$(w) = reinterpret_cast(inputs[$(w)]); - #end for - boost::uint16_t *output = reinterpret_cast(outputs[0]); - - if (scale_factor == 0){} //avoids unused warning - - for (size_t i = 0, j = 0; i < nsamps; i++){ - #for $w in range($width) - { - const boost::uint8_t real = boost::int8_t(input$(w)[i].real()$(do_scale)); - const boost::uint8_t imag = boost::int8_t(input$(w)[i].imag()$(do_scale)); - output[j++] = $(to_wire)((boost::uint16_t(imag) << 8) | real); - } - #end for - } -} - DECLARE_CONVERTER(sc8_item16_usrp1, 1, $(cpu_type), $(width), PRIORITY_GENERAL){ const boost::uint16_t *input = reinterpret_cast(inputs[0]); #for $w in range($width) diff --git a/host/lib/usrp/usrp1/io_impl.cpp b/host/lib/usrp/usrp1/io_impl.cpp index 7f20a8608..835c78ecc 100644 --- a/host/lib/usrp/usrp1/io_impl.cpp +++ b/host/lib/usrp/usrp1/io_impl.cpp @@ -22,6 +22,7 @@ #include "../../transport/super_send_packet_handler.hpp" #include "usrp1_calc_mux.hpp" #include "fpga_regs_standard.h" +#include "fpga_regs_common.h" #include "usrp_commands.h" #include "usrp1_impl.hpp" #include @@ -367,7 +368,7 @@ public: const uhd::tx_metadata_t &metadata, double timeout ){ - if (_stc->send_pre(metadata, timeout)) return 0; + _stc->send_pre(metadata, timeout); _tx_enb_fcn(true); //always enable (it will do the right thing) size_t num_samps_sent = sph::send_packet_handler::send( @@ -440,13 +441,14 @@ void usrp1_impl::update_tx_subdev_spec(const uhd::usrp::subdev_spec_t &spec){ double usrp1_impl::update_rx_samp_rate(size_t dspno, const double samp_rate){ + const size_t div = 2; const size_t rate = uhd::clip( - boost::math::iround(_master_clock_rate / samp_rate), size_t(std::ceil(_master_clock_rate / 16e6)), 256 - ); + boost::math::iround(_master_clock_rate / samp_rate), 4, 256) & ~(div-1); if (dspno == 0){ //only care if dsp0 is set since its homogeneous bool s = this->disable_rx(); - _iface->poke32(FR_DECIM_RATE, rate/2 - 1); + _iface->poke32(FR_RX_SAMPLE_RATE_DIV, div - 1); + _iface->poke32(FR_DECIM_RATE, rate/div - 1); this->restore_rx(s); //update the streamer if created @@ -462,13 +464,14 @@ double usrp1_impl::update_rx_samp_rate(size_t dspno, const double samp_rate){ double usrp1_impl::update_tx_samp_rate(size_t dspno, const double samp_rate){ + const size_t div = 2; const size_t rate = uhd::clip( - boost::math::iround(_master_clock_rate / samp_rate), size_t(std::ceil(_master_clock_rate / 8e6)), 256 - ); + boost::math::iround(_master_clock_rate / samp_rate), 8, 256) & ~(div-1); if (dspno == 0){ //only care if dsp0 is set since its homogeneous bool s = this->disable_tx(); - _iface->poke32(FR_INTERP_RATE, rate/2 - 1); + _iface->poke32(FR_TX_SAMPLE_RATE_DIV, div - 1); + _iface->poke32(FR_INTERP_RATE, rate/div - 1); this->restore_tx(s); //update the streamer if created @@ -544,7 +547,6 @@ rx_streamer::sptr usrp1_impl::get_rx_stream(const uhd::stream_args_t &args){ | (8 << bmFR_RX_FORMAT_SHIFT_SHIFT) | (8 << bmFR_RX_FORMAT_WIDTH_SHIFT) | bmFR_RX_FORMAT_WANT_Q - | bmFR_RX_FORMAT_BYPASS_HB //needed for 16Msps ); } else{ diff --git a/host/lib/usrp/usrp1/soft_time_ctrl.cpp b/host/lib/usrp/usrp1/soft_time_ctrl.cpp index 78481c3ff..b8af8af06 100644 --- a/host/lib/usrp/usrp1/soft_time_ctrl.cpp +++ b/host/lib/usrp/usrp1/soft_time_ctrl.cpp @@ -131,8 +131,8 @@ public: /******************************************************************* * Transmit control ******************************************************************/ - bool send_pre(const tx_metadata_t &md, double &timeout){ - if (not md.has_time_spec) return false; + void send_pre(const tx_metadata_t &md, double &timeout){ + if (not md.has_time_spec) return; boost::mutex::scoped_lock lock(_update_mutex); @@ -146,12 +146,11 @@ public: metadata.time_spec = this->time_now(); metadata.event_code = async_metadata_t::EVENT_CODE_TIME_ERROR; _async_msg_queue.push_with_pop_on_full(metadata); - return true; + return; } timeout -= (time_at - time_now()).get_real_secs(); sleep_until_time(lock, time_at); - return false; } /******************************************************************* diff --git a/host/lib/usrp/usrp1/soft_time_ctrl.hpp b/host/lib/usrp/usrp1/soft_time_ctrl.hpp index e91aaf6a2..b92b51252 100644 --- a/host/lib/usrp/usrp1/soft_time_ctrl.hpp +++ b/host/lib/usrp/usrp1/soft_time_ctrl.hpp @@ -57,7 +57,7 @@ public: virtual size_t recv_post(rx_metadata_t &md, const size_t nsamps) = 0; //! Call before the internal send function - virtual bool send_pre(const tx_metadata_t &md, double &timeout) = 0; + virtual void send_pre(const tx_metadata_t &md, double &timeout) = 0; //! Issue a stream command to receive virtual void issue_stream_cmd(const stream_cmd_t &cmd) = 0; diff --git a/host/lib/usrp/usrp1/usrp1_impl.cpp b/host/lib/usrp/usrp1/usrp1_impl.cpp index 93a301c02..108fdc9ac 100644 --- a/host/lib/usrp/usrp1/usrp1_impl.cpp +++ b/host/lib/usrp/usrp1/usrp1_impl.cpp @@ -187,8 +187,6 @@ usrp1_impl::usrp1_impl(const device_addr_t &device_addr){ // Normal mode with no loopback or Rx counting _iface->poke32(FR_MODE, 0x00000000); _iface->poke32(FR_DEBUG_EN, 0x00000000); - _iface->poke32(FR_RX_SAMPLE_RATE_DIV, 0x00000001); //divide by 2 - _iface->poke32(FR_TX_SAMPLE_RATE_DIV, 0x00000001); //divide by 2 _iface->poke32(FR_DC_OFFSET_CL_EN, 0x0000000f); // Reset offset correction registers -- cgit v1.2.3 From 861e66848f05001fcaca4fe91dbf67cd186649dc Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Fri, 7 Oct 2011 17:30:42 -0700 Subject: usrp2: work on alternative OTW formats --- host/lib/convert/convert_common.hpp | 66 +++++++++++++++++++++++------ host/lib/convert/convert_fc32_with_sse2.cpp | 16 +++---- host/lib/convert/convert_fc64_with_sse2.cpp | 8 ++-- host/lib/convert/gen_convert_general.py | 32 +++++++++++++- host/lib/usrp/cores/rx_dsp_core_200.cpp | 21 ++++++++- host/lib/usrp/cores/rx_dsp_core_200.hpp | 1 + host/lib/usrp/usrp1/io_impl.cpp | 4 ++ host/lib/usrp/usrp2/io_impl.cpp | 7 ++- 8 files changed, 126 insertions(+), 29 deletions(-) (limited to 'host') diff --git a/host/lib/convert/convert_common.hpp b/host/lib/convert/convert_common.hpp index 612fa312b..56b718292 100644 --- a/host/lib/convert/convert_common.hpp +++ b/host/lib/convert/convert_common.hpp @@ -65,18 +65,18 @@ typedef boost::int8_t s8_t; typedef boost::uint32_t item32_t; /*********************************************************************** - * Convert complex short buffer to items32 + * Convert complex short buffer to items32 sc16 **********************************************************************/ -static UHD_INLINE item32_t sc16_to_item32(sc16_t num, double){ +static UHD_INLINE item32_t sc16_to_item32_sc16(sc16_t num, double){ boost::uint16_t real = num.real(); boost::uint16_t imag = num.imag(); return (item32_t(real) << 16) | (item32_t(imag) << 0); } /*********************************************************************** - * Convert items32 buffer to complex short + * Convert items32 sc16 buffer to complex short **********************************************************************/ -static UHD_INLINE sc16_t item32_to_sc16(item32_t item, double){ +static UHD_INLINE sc16_t item32_sc16_to_sc16(item32_t item, double){ return sc16_t( boost::int16_t(item >> 16), boost::int16_t(item >> 0) @@ -84,18 +84,18 @@ static UHD_INLINE sc16_t item32_to_sc16(item32_t item, double){ } /*********************************************************************** - * Convert complex float buffer to items32 (no swap) + * Convert complex float buffer to items32 sc16 **********************************************************************/ -static UHD_INLINE item32_t fc32_to_item32(fc32_t num, double scale_factor){ +static UHD_INLINE item32_t fc32_to_item32_sc16(fc32_t num, double scale_factor){ boost::uint16_t real = boost::int16_t(num.real()*float(scale_factor)); boost::uint16_t imag = boost::int16_t(num.imag()*float(scale_factor)); return (item32_t(real) << 16) | (item32_t(imag) << 0); } /*********************************************************************** - * Convert items32 buffer to complex float + * Convert items32 sc16 buffer to complex float **********************************************************************/ -static UHD_INLINE fc32_t item32_to_fc32(item32_t item, double scale_factor){ +static UHD_INLINE fc32_t item32_sc16_to_fc32(item32_t item, double scale_factor){ return fc32_t( float(boost::int16_t(item >> 16)*float(scale_factor)), float(boost::int16_t(item >> 0)*float(scale_factor)) @@ -103,22 +103,64 @@ static UHD_INLINE fc32_t item32_to_fc32(item32_t item, double scale_factor){ } /*********************************************************************** - * Convert complex double buffer to items32 (no swap) + * Convert complex double buffer to items32 sc16 **********************************************************************/ -static UHD_INLINE item32_t fc64_to_item32(fc64_t num, double scale_factor){ +static UHD_INLINE item32_t fc64_to_item32_sc16(fc64_t num, double scale_factor){ boost::uint16_t real = boost::int16_t(num.real()*scale_factor); boost::uint16_t imag = boost::int16_t(num.imag()*scale_factor); return (item32_t(real) << 16) | (item32_t(imag) << 0); } /*********************************************************************** - * Convert items32 buffer to complex double + * Convert items32 sc16 buffer to complex double **********************************************************************/ -static UHD_INLINE fc64_t item32_to_fc64(item32_t item, double scale_factor){ +static UHD_INLINE fc64_t item32_sc16_to_fc64(item32_t item, double scale_factor){ return fc64_t( float(boost::int16_t(item >> 16)*scale_factor), float(boost::int16_t(item >> 0)*scale_factor) ); } +/*********************************************************************** + * Convert items32 sc8 buffer to complex short + **********************************************************************/ +static UHD_INLINE void item32_sc8_to_sc16(item32_t item, sc16_t &out0, sc16_t &out1, double){ + out0 = sc16_t( + boost::int8_t(item >> 8), + boost::int8_t(item >> 0) + ); + out1 = sc16_t( + boost::int8_t(item >> 24), + boost::int8_t(item >> 16) + ); +} + +/*********************************************************************** + * Convert items32 sc8 buffer to complex float + **********************************************************************/ +static UHD_INLINE void item32_sc8_to_fc32(item32_t item, fc32_t &out0, fc32_t &out1, double scale_factor){ + out0 = fc32_t( + float(boost::int8_t(item >> 8)*float(scale_factor)), + float(boost::int8_t(item >> 0)*float(scale_factor)) + ); + out1 = fc32_t( + float(boost::int8_t(item >> 24)*float(scale_factor)), + float(boost::int8_t(item >> 16)*float(scale_factor)) + ); +} + +/*********************************************************************** + * Convert items32 sc8 buffer to complex double + **********************************************************************/ +static UHD_INLINE void item32_sc8_to_fc64(item32_t item, fc64_t &out0, fc64_t &out1, double scale_factor){ + out0 = fc64_t( + float(boost::int8_t(item >> 8)*scale_factor), + float(boost::int8_t(item >> 0)*scale_factor) + ); + out1 = fc64_t( + float(boost::int8_t(item >> 24)*scale_factor), + float(boost::int8_t(item >> 16)*scale_factor) + ); +} + #endif /* INCLUDED_LIBUHD_CONVERT_COMMON_HPP */ diff --git a/host/lib/convert/convert_fc32_with_sse2.cpp b/host/lib/convert/convert_fc32_with_sse2.cpp index 34c85db80..b8d1aa8cc 100644 --- a/host/lib/convert/convert_fc32_with_sse2.cpp +++ b/host/lib/convert/convert_fc32_with_sse2.cpp @@ -51,7 +51,7 @@ DECLARE_CONVERTER(fc32, 1, sc16_item32_le, 1, PRIORITY_CUSTOM){ //dispatch according to alignment switch (size_t(input) & 0xf){ case 0x8: - output[i] = fc32_to_item32(input[i], float(scale_factor)); i++; + output[i] = fc32_to_item32_sc16(input[i], float(scale_factor)); i++; case 0x0: convert_fc32_1_to_item32_1_nswap_guts(_) break; @@ -60,7 +60,7 @@ DECLARE_CONVERTER(fc32, 1, sc16_item32_le, 1, PRIORITY_CUSTOM){ //convert remainder for (; i < nsamps; i++){ - output[i] = fc32_to_item32(input[i], float(scale_factor)); + output[i] = fc32_to_item32_sc16(input[i], float(scale_factor)); } } @@ -93,7 +93,7 @@ DECLARE_CONVERTER(fc32, 1, sc16_item32_be, 1, PRIORITY_CUSTOM){ //dispatch according to alignment switch (size_t(input) & 0xf){ case 0x8: - output[i] = uhd::byteswap(fc32_to_item32(input[i], float(scale_factor))); i++; + output[i] = uhd::byteswap(fc32_to_item32_sc16(input[i], float(scale_factor))); i++; case 0x0: convert_fc32_1_to_item32_1_bswap_guts(_) break; @@ -102,7 +102,7 @@ DECLARE_CONVERTER(fc32, 1, sc16_item32_be, 1, PRIORITY_CUSTOM){ //convert remainder for (; i < nsamps; i++){ - output[i] = uhd::byteswap(fc32_to_item32(input[i], float(scale_factor))); + output[i] = uhd::byteswap(fc32_to_item32_sc16(input[i], float(scale_factor))); } } @@ -138,7 +138,7 @@ DECLARE_CONVERTER(sc16_item32_le, 1, fc32, 1, PRIORITY_CUSTOM){ //dispatch according to alignment switch (size_t(output) & 0xf){ case 0x8: - output[i] = item32_to_fc32(input[i], float(scale_factor)); i++; + output[i] = item32_sc16_to_fc32(input[i], float(scale_factor)); i++; case 0x0: convert_item32_1_to_fc32_1_nswap_guts(_) break; @@ -147,7 +147,7 @@ DECLARE_CONVERTER(sc16_item32_le, 1, fc32, 1, PRIORITY_CUSTOM){ //convert remainder for (; i < nsamps; i++){ - output[i] = item32_to_fc32(input[i], float(scale_factor)); + output[i] = item32_sc16_to_fc32(input[i], float(scale_factor)); } } @@ -182,7 +182,7 @@ DECLARE_CONVERTER(sc16_item32_be, 1, fc32, 1, PRIORITY_CUSTOM){ //dispatch according to alignment switch (size_t(output) & 0xf){ case 0x8: - output[i] = item32_to_fc32(uhd::byteswap(input[i]), float(scale_factor)); i++; + output[i] = item32_sc16_to_fc32(uhd::byteswap(input[i]), float(scale_factor)); i++; case 0x0: convert_item32_1_to_fc32_1_bswap_guts(_) break; @@ -191,6 +191,6 @@ DECLARE_CONVERTER(sc16_item32_be, 1, fc32, 1, PRIORITY_CUSTOM){ //convert remainder for (; i < nsamps; i++){ - output[i] = item32_to_fc32(uhd::byteswap(input[i]), float(scale_factor)); + output[i] = item32_sc16_to_fc32(uhd::byteswap(input[i]), float(scale_factor)); } } diff --git a/host/lib/convert/convert_fc64_with_sse2.cpp b/host/lib/convert/convert_fc64_with_sse2.cpp index 2093cf476..a4f2df2e7 100644 --- a/host/lib/convert/convert_fc64_with_sse2.cpp +++ b/host/lib/convert/convert_fc64_with_sse2.cpp @@ -64,7 +64,7 @@ DECLARE_CONVERTER(fc64, 1, sc16_item32_le, 1, PRIORITY_CUSTOM){ //convert remainder for (; i < nsamps; i++){ - output[i] = fc64_to_item32(input[i], scale_factor); + output[i] = fc64_to_item32_sc16(input[i], scale_factor); } } @@ -110,7 +110,7 @@ DECLARE_CONVERTER(fc64, 1, sc16_item32_be, 1, PRIORITY_CUSTOM){ //convert remainder for (; i < nsamps; i++){ - output[i] = uhd::byteswap(fc64_to_item32(input[i], scale_factor)); + output[i] = uhd::byteswap(fc64_to_item32_sc16(input[i], scale_factor)); } } @@ -159,7 +159,7 @@ DECLARE_CONVERTER(sc16_item32_le, 1, fc64, 1, PRIORITY_CUSTOM){ //convert remainder for (; i < nsamps; i++){ - output[i] = item32_to_fc64(input[i], scale_factor); + output[i] = item32_sc16_to_fc64(input[i], scale_factor); } } @@ -207,6 +207,6 @@ DECLARE_CONVERTER(sc16_item32_be, 1, fc64, 1, PRIORITY_CUSTOM){ //convert remainder for (; i < nsamps; i++){ - output[i] = item32_to_fc64(uhd::byteswap(input[i]), scale_factor); + output[i] = item32_sc16_to_fc64(uhd::byteswap(input[i]), scale_factor); } } diff --git a/host/lib/convert/gen_convert_general.py b/host/lib/convert/gen_convert_general.py index 0cd4155fa..43e1f9967 100644 --- a/host/lib/convert/gen_convert_general.py +++ b/host/lib/convert/gen_convert_general.py @@ -34,7 +34,7 @@ DECLARE_CONVERTER($(cpu_type), 1, sc16_item32_$(end), 1, PRIORITY_GENERAL){ item32_t *output = reinterpret_cast(outputs[0]); for (size_t i = 0; i < nsamps; i++){ - output[i] = $(to_wire)($(cpu_type)_to_item32(input[i], scale_factor)); + output[i] = $(to_wire)($(cpu_type)_to_item32_sc16(input[i], scale_factor)); } } @@ -43,7 +43,35 @@ DECLARE_CONVERTER(sc16_item32_$(end), 1, $(cpu_type), 1, PRIORITY_GENERAL){ $(cpu_type)_t *output = reinterpret_cast<$(cpu_type)_t *>(outputs[0]); for (size_t i = 0; i < nsamps; i++){ - output[i] = item32_to_$(cpu_type)($(to_host)(input[i]), scale_factor); + output[i] = item32_sc16_to_$(cpu_type)($(to_host)(input[i]), scale_factor); + } +} + +DECLARE_CONVERTER(sc8_item32_$(end), 1, $(cpu_type), 1, PRIORITY_GENERAL){ + const item32_t *input = reinterpret_cast(size_t(inputs[0]) & ~0x3); + $(cpu_type)_t *output = reinterpret_cast<$(cpu_type)_t *>(outputs[0]); + $(cpu_type)_t dummy; + + const bool head_case = ((size_t(inputs[0]) & 0x3) != 0); + const bool tail_case = ((nsamps & 0x1) == 0)? head_case : not head_case; + const size_t num_pairs = (head_case? nsamps-1 : nsamps)/2; + size_t i = 0, j = 0; + + //special head case, probably from a partial recv + if (head_case){ + const item32_t item0 = $(to_host)(input[i++]); + item32_sc8_to_$(cpu_type)(item0, dummy, output[j++], scale_factor); + } + + for (; i < num_pairs; i++, j+=2){ + const item32_t item_i = $(to_host)(input[i]); + item32_sc8_to_$(cpu_type)(item_i, output[j], output[j+1], scale_factor); + } + + //special tail case, finished on an odd number + if (tail_case){ + const item32_t item_i = $(to_host)(input[i]); + item32_sc8_to_$(cpu_type)(item_i, output[j], dummy, scale_factor); } } """ diff --git a/host/lib/usrp/cores/rx_dsp_core_200.cpp b/host/lib/usrp/cores/rx_dsp_core_200.cpp index d562c64db..023216a09 100644 --- a/host/lib/usrp/cores/rx_dsp_core_200.cpp +++ b/host/lib/usrp/cores/rx_dsp_core_200.cpp @@ -42,6 +42,7 @@ #define REG_RX_CTRL_VRT_TLR _ctrl_base + 24 #define REG_RX_CTRL_NSAMPS_PP _ctrl_base + 28 #define REG_RX_CTRL_NCHANNELS _ctrl_base + 32 +#define REG_RX_CTRL_FORMAT _ctrl_base + 36 template T ceil_log2(T num){ return std::ceil(std::log(num)/std::log(T(2))); @@ -162,7 +163,7 @@ public: } double get_scaling_adjustment(void){ - return _scaling_adjustment; + return _scaling_adjustment/_fxpt_scale_adj; } double set_freq(const double freq_){ @@ -192,12 +193,28 @@ public: if (_continuous_streaming) issue_stream_command(stream_cmd_t::STREAM_MODE_START_CONTINUOUS); } + void set_format(const std::string &format, const unsigned scale){ + unsigned format_word = 0; + if (format == "sc16"){ + format_word = 0; + _fxpt_scale_adj = 32767.; + } + else if (format == "sc8"){ + format_word = (1 << 18); + _fxpt_scale_adj = 32767./scale; + } + else throw uhd::value_error("USRP RX cannot handle requested wire format: " + format); + + const unsigned scale_word = scale & 0x3ffff; //18 bits; + _iface->poke32(REG_RX_CTRL_FORMAT, format_word | scale_word); + } + private: wb_iface::sptr _iface; const size_t _dsp_base, _ctrl_base; double _tick_rate, _link_rate; bool _continuous_streaming; - double _scaling_adjustment; + double _scaling_adjustment, _fxpt_scale_adj; }; rx_dsp_core_200::sptr rx_dsp_core_200::make(wb_iface::sptr iface, const size_t dsp_base, const size_t ctrl_base, const boost::uint32_t sid, const bool lingering_packet){ diff --git a/host/lib/usrp/cores/rx_dsp_core_200.hpp b/host/lib/usrp/cores/rx_dsp_core_200.hpp index 391cc8441..ddd6f2abf 100644 --- a/host/lib/usrp/cores/rx_dsp_core_200.hpp +++ b/host/lib/usrp/cores/rx_dsp_core_200.hpp @@ -56,6 +56,7 @@ public: virtual void handle_overflow(void) = 0; + virtual void set_format(const std::string &format, const unsigned scale) = 0; }; #endif /* INCLUDED_LIBUHD_USRP_RX_DSP_CORE_200_HPP */ diff --git a/host/lib/usrp/usrp1/io_impl.cpp b/host/lib/usrp/usrp1/io_impl.cpp index 835c78ecc..eaa6d02b4 100644 --- a/host/lib/usrp/usrp1/io_impl.cpp +++ b/host/lib/usrp/usrp1/io_impl.cpp @@ -564,6 +564,10 @@ rx_streamer::sptr usrp1_impl::get_rx_stream(const uhd::stream_args_t &args){ boost::shared_ptr my_streamer = boost::make_shared(spp, _soft_time_ctrl); + //special scale factor change for sc8 + if (args.otw_format == "sc8") + my_streamer->set_scale_factor(1.0/127); + //init some streamer stuff my_streamer->set_tick_rate(_master_clock_rate); my_streamer->set_vrt_unpacker(&usrp1_bs_vrt_unpacker); diff --git a/host/lib/usrp/usrp2/io_impl.cpp b/host/lib/usrp/usrp2/io_impl.cpp index d37be403b..f917a35db 100644 --- a/host/lib/usrp/usrp2/io_impl.cpp +++ b/host/lib/usrp/usrp2/io_impl.cpp @@ -290,7 +290,7 @@ void usrp2_impl::update_rx_samp_rate(const std::string &mb, const size_t dsp, co my_streamer->set_samp_rate(rate); const double adj = _mbc[mb].rx_dsps[dsp]->get_scaling_adjustment(); - my_streamer->set_scale_factor(adj/32767.); + my_streamer->set_scale_factor(adj); } void usrp2_impl::update_tx_samp_rate(const std::string &mb, const size_t dsp, const double rate){ @@ -404,6 +404,7 @@ rx_streamer::sptr usrp2_impl::get_rx_stream(const uhd::stream_args_t &args){ if (chan < num_chan_so_far){ const size_t dsp = num_chan_so_far - chan - 1; _mbc[mb].rx_dsps[dsp]->set_nsamps_per_packet(spp); //seems to be a good place to set this + _mbc[mb].rx_dsps[dsp]->set_format(args.otw_format, 0x400); my_streamer->set_xport_chan_get_buff(chan_i, boost::bind( &zero_copy_if::get_recv_buff, _mbc[mb].rx_dsp_xports[dsp], _1 )); @@ -427,6 +428,10 @@ rx_streamer::sptr usrp2_impl::get_rx_stream(const uhd::stream_args_t &args){ * Transmit streamer **********************************************************************/ tx_streamer::sptr usrp2_impl::get_tx_stream(const uhd::stream_args_t &args){ + if (args.otw_format != "sc16"){ + throw uhd::value_error("USRP TX cannot handle requested wire format: " + args.otw_format); + } + //map an empty channel set to chan0 const std::vector channels = args.channels.empty()? std::vector(1, 0) : args.channels; -- cgit v1.2.3 From 0946176f513dd58407869e3b019207ff3eef24f5 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Mon, 10 Oct 2011 20:55:01 -0700 Subject: usrp1: got the 16Msps working (needed non hb-filter image) --- host/include/uhd/stream.hpp | 4 ++-- host/lib/usrp/usrp1/io_impl.cpp | 40 +++++++++++++++++++++++++------------- host/lib/usrp/usrp1/usrp1_impl.cpp | 6 ------ host/lib/usrp/usrp2/io_impl.cpp | 32 +++++++++++++++++------------- 4 files changed, 48 insertions(+), 34 deletions(-) (limited to 'host') diff --git a/host/include/uhd/stream.hpp b/host/include/uhd/stream.hpp index 583dfd1e4..7a3151276 100644 --- a/host/include/uhd/stream.hpp +++ b/host/include/uhd/stream.hpp @@ -39,8 +39,8 @@ struct UHD_API stream_args_t{ //! Convenience constructor for streamer args stream_args_t( - const std::string &cpu = "fc32", - const std::string &otw = "sc16" + const std::string &cpu = "", + const std::string &otw = "" ){ cpu_format = cpu; otw_format = otw; diff --git a/host/lib/usrp/usrp1/io_impl.cpp b/host/lib/usrp/usrp1/io_impl.cpp index eaa6d02b4..c199e4178 100644 --- a/host/lib/usrp/usrp1/io_impl.cpp +++ b/host/lib/usrp/usrp1/io_impl.cpp @@ -441,10 +441,16 @@ void usrp1_impl::update_tx_subdev_spec(const uhd::usrp::subdev_spec_t &spec){ double usrp1_impl::update_rx_samp_rate(size_t dspno, const double samp_rate){ - const size_t div = 2; + const size_t div = this->has_rx_halfband()? 2 : 1; const size_t rate = uhd::clip( boost::math::iround(_master_clock_rate / samp_rate), 4, 256) & ~(div-1); + if (rate < 8 and this->has_rx_halfband()) UHD_MSG(warning) << + "USRP1 cannot achieve decimations below 8 when the half-band filter is present.\n" + "The usrp1_fpga_4rx.rbf file is a special FPGA image without RX half-band filters.\n" + "To load this image, set the device address key/value pair: fpga=usrp1_fpga_4rx.rbf\n" + << std::endl; + if (dspno == 0){ //only care if dsp0 is set since its homogeneous bool s = this->disable_rx(); _iface->poke32(FR_RX_SAMPLE_RATE_DIV, div - 1); @@ -464,7 +470,7 @@ double usrp1_impl::update_rx_samp_rate(size_t dspno, const double samp_rate){ double usrp1_impl::update_tx_samp_rate(size_t dspno, const double samp_rate){ - const size_t div = 2; + const size_t div = this->has_tx_halfband()? 2 : 1; const size_t rate = uhd::clip( boost::math::iround(_master_clock_rate / samp_rate), 8, 256) & ~(div-1); @@ -534,7 +540,13 @@ bool usrp1_impl::recv_async_msg( /*********************************************************************** * Receive streamer **********************************************************************/ -rx_streamer::sptr usrp1_impl::get_rx_stream(const uhd::stream_args_t &args){ +rx_streamer::sptr usrp1_impl::get_rx_stream(const uhd::stream_args_t &args_){ + stream_args_t args = args_; + + //setup defaults for unspecified values + args.otw_format = args.otw_format.empty()? "sc16" : args.otw_format; + args.channels = args.channels.empty()? std::vector(1, 0) : args.channels; + if (args.otw_format == "sc16"){ _iface->poke32(FR_RX_FORMAT, 0 | (0 << bmFR_RX_FORMAT_SHIFT_SHIFT) @@ -553,11 +565,8 @@ rx_streamer::sptr usrp1_impl::get_rx_stream(const uhd::stream_args_t &args){ throw uhd::value_error("USRP1 RX cannot handle requested wire format: " + args.otw_format); } - //map an empty channel set to chan0 - const std::vector channels = args.channels.empty()? std::vector(1, 0) : args.channels; - //calculate packet size - const size_t bpp = _data_transport->get_recv_frame_size()/channels.size(); + const size_t bpp = _data_transport->get_recv_frame_size()/args.channels.size(); const size_t spp = bpp/convert::get_bytes_per_item(args.otw_format); //make the new streamer given the samples per packet @@ -580,7 +589,7 @@ rx_streamer::sptr usrp1_impl::get_rx_stream(const uhd::stream_args_t &args){ id.input_markup = args.otw_format + "_item16_usrp1"; id.num_inputs = 1; id.output_markup = args.cpu_format; - id.num_outputs = channels.size(); + id.num_outputs = args.channels.size(); id.args = args.args; my_streamer->set_converter(id); @@ -596,16 +605,21 @@ rx_streamer::sptr usrp1_impl::get_rx_stream(const uhd::stream_args_t &args){ /*********************************************************************** * Transmit streamer **********************************************************************/ -tx_streamer::sptr usrp1_impl::get_tx_stream(const uhd::stream_args_t &args){ +tx_streamer::sptr usrp1_impl::get_tx_stream(const uhd::stream_args_t &args_){ + stream_args_t args = args_; + + //setup defaults for unspecified values + args.otw_format = args.otw_format.empty()? "sc16" : args.otw_format; + args.channels = args.channels.empty()? std::vector(1, 0) : args.channels; + if (args.otw_format != "sc16"){ throw uhd::value_error("USRP1 TX cannot handle requested wire format: " + args.otw_format); } - //map an empty channel set to chan0 - const std::vector channels = args.channels.empty()? std::vector(1, 0) : args.channels; + _iface->poke32(FR_TX_FORMAT, bmFR_TX_FORMAT_16_IQ); //calculate packet size - const size_t bpp = _data_transport->get_send_frame_size()/channels.size(); + const size_t bpp = _data_transport->get_send_frame_size()/args.channels.size(); const size_t spp = bpp/convert::get_bytes_per_item(args.otw_format); //make the new streamer given the samples per packet @@ -623,7 +637,7 @@ tx_streamer::sptr usrp1_impl::get_tx_stream(const uhd::stream_args_t &args){ //set the converter uhd::convert::id_type id; id.input_markup = args.cpu_format; - id.num_inputs = channels.size(); + id.num_inputs = args.channels.size(); id.output_markup = args.otw_format + "_item16_usrp1"; id.num_outputs = 1; id.args = args.args; diff --git a/host/lib/usrp/usrp1/usrp1_impl.cpp b/host/lib/usrp/usrp1/usrp1_impl.cpp index 108fdc9ac..db652b033 100644 --- a/host/lib/usrp/usrp1/usrp1_impl.cpp +++ b/host/lib/usrp/usrp1/usrp1_impl.cpp @@ -195,12 +195,6 @@ usrp1_impl::usrp1_impl(const device_addr_t &device_addr){ _iface->poke32(FR_ADC_OFFSET_2, 0x00000000); _iface->poke32(FR_ADC_OFFSET_3, 0x00000000); - // Set default for RX format to 16-bit I&Q and no half-band filter bypass - _iface->poke32(FR_RX_FORMAT, 0x00000300); - - // Set default for TX format to 16-bit I&Q - _iface->poke32(FR_TX_FORMAT, 0x00000000); - UHD_LOG << "USRP1 Capabilities" << std::endl << " number of duc's: " << get_num_ddcs() << std::endl diff --git a/host/lib/usrp/usrp2/io_impl.cpp b/host/lib/usrp/usrp2/io_impl.cpp index f917a35db..f1d0aee2a 100644 --- a/host/lib/usrp/usrp2/io_impl.cpp +++ b/host/lib/usrp/usrp2/io_impl.cpp @@ -366,9 +366,12 @@ bool usrp2_impl::recv_async_msg( /*********************************************************************** * Receive streamer **********************************************************************/ -rx_streamer::sptr usrp2_impl::get_rx_stream(const uhd::stream_args_t &args){ - //map an empty channel set to chan0 - const std::vector channels = args.channels.empty()? std::vector(1, 0) : args.channels; +rx_streamer::sptr usrp2_impl::get_rx_stream(const uhd::stream_args_t &args_){ + stream_args_t args = args_; + + //setup defaults for unspecified values + args.otw_format = args.otw_format.empty()? "sc16" : args.otw_format; + args.channels = args.channels.empty()? std::vector(1, 0) : args.channels; //calculate packet size static const size_t hdr_size = 0 @@ -383,7 +386,7 @@ rx_streamer::sptr usrp2_impl::get_rx_stream(const uhd::stream_args_t &args){ boost::shared_ptr my_streamer = boost::make_shared(spp); //init some streamer stuff - my_streamer->resize(channels.size()); + my_streamer->resize(args.channels.size()); my_streamer->set_vrt_unpacker(&vrt::if_hdr_unpack_be); //set the converter @@ -396,8 +399,8 @@ rx_streamer::sptr usrp2_impl::get_rx_stream(const uhd::stream_args_t &args){ my_streamer->set_converter(id); //bind callbacks for the handler - for (size_t chan_i = 0; chan_i < channels.size(); chan_i++){ - const size_t chan = channels[chan_i]; + for (size_t chan_i = 0; chan_i < args.channels.size(); chan_i++){ + const size_t chan = args.channels[chan_i]; size_t num_chan_so_far = 0; BOOST_FOREACH(const std::string &mb, _mbc.keys()){ num_chan_so_far += _mbc[mb].rx_chan_occ; @@ -427,14 +430,17 @@ rx_streamer::sptr usrp2_impl::get_rx_stream(const uhd::stream_args_t &args){ /*********************************************************************** * Transmit streamer **********************************************************************/ -tx_streamer::sptr usrp2_impl::get_tx_stream(const uhd::stream_args_t &args){ +tx_streamer::sptr usrp2_impl::get_tx_stream(const uhd::stream_args_t &args_){ + stream_args_t args = args_; + + //setup defaults for unspecified values + args.otw_format = args.otw_format.empty()? "sc16" : args.otw_format; + args.channels = args.channels.empty()? std::vector(1, 0) : args.channels; + if (args.otw_format != "sc16"){ throw uhd::value_error("USRP TX cannot handle requested wire format: " + args.otw_format); } - //map an empty channel set to chan0 - const std::vector channels = args.channels.empty()? std::vector(1, 0) : args.channels; - //calculate packet size static const size_t hdr_size = 0 + vrt::max_if_hdr_words32*sizeof(boost::uint32_t) @@ -448,7 +454,7 @@ tx_streamer::sptr usrp2_impl::get_tx_stream(const uhd::stream_args_t &args){ boost::shared_ptr my_streamer = boost::make_shared(spp); //init some streamer stuff - my_streamer->resize(channels.size()); + my_streamer->resize(args.channels.size()); my_streamer->set_vrt_packer(&vrt::if_hdr_pack_be, vrt_send_header_offset_words32); //set the converter @@ -461,8 +467,8 @@ tx_streamer::sptr usrp2_impl::get_tx_stream(const uhd::stream_args_t &args){ my_streamer->set_converter(id); //bind callbacks for the handler - for (size_t chan_i = 0; chan_i < channels.size(); chan_i++){ - const size_t chan = channels[chan_i]; + for (size_t chan_i = 0; chan_i < args.channels.size(); chan_i++){ + const size_t chan = args.channels[chan_i]; size_t num_chan_so_far = 0; size_t abs = 0; BOOST_FOREACH(const std::string &mb, _mbc.keys()){ -- cgit v1.2.3 From fce49fd66f577b92482af6ad516944befa31b861 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Tue, 11 Oct 2011 10:29:33 -0700 Subject: uhd: added one packet mode to rx streamer --- host/include/uhd/stream.hpp | 10 +++++-- host/lib/transport/super_recv_packet_handler.hpp | 14 +++++----- host/lib/transport/super_send_packet_handler.hpp | 6 ++--- host/lib/usrp/usrp1/io_impl.cpp | 18 +++++++++---- host/tests/sph_recv_test.cpp | 33 ++++++++++++------------ 5 files changed, 47 insertions(+), 34 deletions(-) (limited to 'host') diff --git a/host/include/uhd/stream.hpp b/host/include/uhd/stream.hpp index 7a3151276..c86463184 100644 --- a/host/include/uhd/stream.hpp +++ b/host/include/uhd/stream.hpp @@ -123,17 +123,23 @@ public: * Under a timeout condition, the number of samples returned * may be less than the number of samples specified. * + * The one_packet option allows the user to guarantee that + * the call will return after a single packet has been processed. + * This may be useful to maintain packet boundaries in some cases. + * * \param buffs a vector of writable memory to fill with samples * \param nsamps_per_buff the size of each buffer in number of samples * \param metadata data to fill describing the buffer * \param timeout the timeout in seconds to wait for a packet + * \param one_packet return after the first packet is received * \return the number of samples received or 0 on error */ virtual size_t recv( const buffs_type &buffs, const size_t nsamps_per_buff, rx_metadata_t &metadata, - double timeout = 0.1 + const double timeout = 0.1, + const bool one_packet = false ) = 0; }; @@ -180,7 +186,7 @@ public: const buffs_type &buffs, const size_t nsamps_per_buff, const tx_metadata_t &metadata, - double timeout = 0.1 + const double timeout = 0.1 ) = 0; }; diff --git a/host/lib/transport/super_recv_packet_handler.hpp b/host/lib/transport/super_recv_packet_handler.hpp index 83c8988e8..6762a8a00 100644 --- a/host/lib/transport/super_recv_packet_handler.hpp +++ b/host/lib/transport/super_recv_packet_handler.hpp @@ -148,7 +148,8 @@ public: const uhd::rx_streamer::buffs_type &buffs, const size_t nsamps_per_buff, uhd::rx_metadata_t &metadata, - double timeout + const double timeout, + const bool one_packet ){ //handle metadata queued from a previous receive if (_queue_error_for_next_call){ @@ -163,9 +164,7 @@ public: buffs, nsamps_per_buff, metadata, timeout ); - #ifdef SRPH_TEST_MODE_ONE_PACKET - return accum_num_samps; - #endif + if (one_packet) return accum_num_samps; //first recv had an error code set, return immediately if (metadata.error_code != rx_metadata_t::ERROR_CODE_NONE) return accum_num_samps; @@ -493,7 +492,7 @@ private: const uhd::rx_streamer::buffs_type &buffs, const size_t nsamps_per_buff, uhd::rx_metadata_t &metadata, - double timeout, + const double timeout, const size_t buffer_offset_bytes = 0 ){ //get the next buffer if the current one has expired @@ -571,9 +570,10 @@ public: const rx_streamer::buffs_type &buffs, const size_t nsamps_per_buff, uhd::rx_metadata_t &metadata, - double timeout + const double timeout, + const bool one_packet ){ - return recv_packet_handler::recv(buffs, nsamps_per_buff, metadata, timeout); + return recv_packet_handler::recv(buffs, nsamps_per_buff, metadata, timeout, one_packet); } private: diff --git a/host/lib/transport/super_send_packet_handler.hpp b/host/lib/transport/super_send_packet_handler.hpp index 1ac178ad2..5b5ee2981 100644 --- a/host/lib/transport/super_send_packet_handler.hpp +++ b/host/lib/transport/super_send_packet_handler.hpp @@ -128,7 +128,7 @@ public: const uhd::tx_streamer::buffs_type &buffs, const size_t nsamps_per_buff, const uhd::tx_metadata_t &metadata, - double timeout + const double timeout ){ //translate the metadata to vrt if packet info vrt::if_packet_info_t if_packet_info; @@ -215,7 +215,7 @@ private: const uhd::tx_streamer::buffs_type &buffs, const size_t nsamps_per_buff, vrt::if_packet_info_t &if_packet_info, - double timeout, + const double timeout, const size_t buffer_offset_bytes = 0 ){ //load the rest of the if_packet_info in here @@ -269,7 +269,7 @@ public: const tx_streamer::buffs_type &buffs, const size_t nsamps_per_buff, const uhd::tx_metadata_t &metadata, - double timeout + const double timeout ){ return send_packet_handler::send(buffs, nsamps_per_buff, metadata, timeout); } diff --git a/host/lib/usrp/usrp1/io_impl.cpp b/host/lib/usrp/usrp1/io_impl.cpp index c199e4178..a0fdfc6bf 100644 --- a/host/lib/usrp/usrp1/io_impl.cpp +++ b/host/lib/usrp/usrp1/io_impl.cpp @@ -325,13 +325,14 @@ public: const rx_streamer::buffs_type &buffs, const size_t nsamps_per_buff, uhd::rx_metadata_t &metadata, - double timeout + const double timeout, + const bool one_packet ){ //interleave a "soft" inline message into the receive stream: if (_stc->get_inline_queue().pop_with_haste(metadata)) return 0; size_t num_samps_recvd = sph::recv_packet_handler::recv( - buffs, nsamps_per_buff, metadata, timeout + buffs, nsamps_per_buff, metadata, timeout, one_packet ); return _stc->recv_post(metadata, num_samps_recvd); @@ -366,8 +367,9 @@ public: const tx_streamer::buffs_type &buffs, const size_t nsamps_per_buff, const uhd::tx_metadata_t &metadata, - double timeout + const double timeout_ ){ + double timeout = timeout_; //rw copy _stc->send_pre(metadata, timeout); _tx_enb_fcn(true); //always enable (it will do the right thing) @@ -545,7 +547,10 @@ rx_streamer::sptr usrp1_impl::get_rx_stream(const uhd::stream_args_t &args_){ //setup defaults for unspecified values args.otw_format = args.otw_format.empty()? "sc16" : args.otw_format; - args.channels = args.channels.empty()? std::vector(1, 0) : args.channels; + args.channels.clear(); //NOTE: we have no choice about the channel mapping + for (size_t ch = 0; ch < _rx_subdev_spec.size(); ch++){ + args.channels.push_back(ch); + } if (args.otw_format == "sc16"){ _iface->poke32(FR_RX_FORMAT, 0 @@ -610,7 +615,10 @@ tx_streamer::sptr usrp1_impl::get_tx_stream(const uhd::stream_args_t &args_){ //setup defaults for unspecified values args.otw_format = args.otw_format.empty()? "sc16" : args.otw_format; - args.channels = args.channels.empty()? std::vector(1, 0) : args.channels; + args.channels.clear(); //NOTE: we have no choice about the channel mapping + for (size_t ch = 0; ch < _tx_subdev_spec.size(); ch++){ + args.channels.push_back(ch); + } if (args.otw_format != "sc16"){ throw uhd::value_error("USRP1 TX cannot handle requested wire format: " + args.otw_format); diff --git a/host/tests/sph_recv_test.cpp b/host/tests/sph_recv_test.cpp index 3ca123ef2..6fab2ad5f 100644 --- a/host/tests/sph_recv_test.cpp +++ b/host/tests/sph_recv_test.cpp @@ -16,7 +16,6 @@ // #include -#define SRPH_TEST_MODE_ONE_PACKET #include "../lib/transport/super_recv_packet_handler.hpp" #include #include @@ -155,7 +154,7 @@ BOOST_AUTO_TEST_CASE(test_sph_recv_one_channel_normal){ for (size_t i = 0; i < NUM_PKTS_TO_TEST; i++){ std::cout << "data check " << i << std::endl; size_t num_samps_ret = handler.recv( - &buff.front(), buff.size(), metadata, 1.0 + &buff.front(), buff.size(), metadata, 1.0, true ); BOOST_CHECK_EQUAL(metadata.error_code, uhd::rx_metadata_t::ERROR_CODE_NONE); BOOST_CHECK(not metadata.more_fragments); @@ -169,7 +168,7 @@ BOOST_AUTO_TEST_CASE(test_sph_recv_one_channel_normal){ for (size_t i = 0; i < 3; i++){ std::cout << "timeout check " << i << std::endl; handler.recv( - &buff.front(), buff.size(), metadata, 1.0 + &buff.front(), buff.size(), metadata, 1.0, true ); BOOST_CHECK_EQUAL(metadata.error_code, uhd::rx_metadata_t::ERROR_CODE_TIMEOUT); } @@ -228,7 +227,7 @@ BOOST_AUTO_TEST_CASE(test_sph_recv_one_channel_sequence_error){ for (size_t i = 0; i < NUM_PKTS_TO_TEST; i++){ std::cout << "data check " << i << std::endl; size_t num_samps_ret = handler.recv( - &buff.front(), buff.size(), metadata, 1.0 + &buff.front(), buff.size(), metadata, 1.0, true ); if (i == NUM_PKTS_TO_TEST/2){ //must get the soft overflow here @@ -250,7 +249,7 @@ BOOST_AUTO_TEST_CASE(test_sph_recv_one_channel_sequence_error){ for (size_t i = 0; i < 3; i++){ std::cout << "timeout check " << i << std::endl; handler.recv( - &buff.front(), buff.size(), metadata, 1.0 + &buff.front(), buff.size(), metadata, 1.0, true ); BOOST_CHECK_EQUAL(metadata.error_code, uhd::rx_metadata_t::ERROR_CODE_TIMEOUT); } @@ -319,7 +318,7 @@ BOOST_AUTO_TEST_CASE(test_sph_recv_one_channel_inline_message){ for (size_t i = 0; i < NUM_PKTS_TO_TEST; i++){ std::cout << "data check " << i << std::endl; size_t num_samps_ret = handler.recv( - &buff.front(), buff.size(), metadata, 1.0 + &buff.front(), buff.size(), metadata, 1.0, true ); BOOST_CHECK_EQUAL(metadata.error_code, uhd::rx_metadata_t::ERROR_CODE_NONE); BOOST_CHECK(not metadata.more_fragments); @@ -329,7 +328,7 @@ BOOST_AUTO_TEST_CASE(test_sph_recv_one_channel_inline_message){ num_accum_samps += num_samps_ret; if (i == NUM_PKTS_TO_TEST/2){ handler.recv( - &buff.front(), buff.size(), metadata, 1.0 + &buff.front(), buff.size(), metadata, 1.0, true ); std::cout << "metadata.error_code " << metadata.error_code << std::endl; BOOST_REQUIRE(metadata.error_code == uhd::rx_metadata_t::ERROR_CODE_OVERFLOW); @@ -342,7 +341,7 @@ BOOST_AUTO_TEST_CASE(test_sph_recv_one_channel_inline_message){ for (size_t i = 0; i < 3; i++){ std::cout << "timeout check " << i << std::endl; handler.recv( - &buff.front(), buff.size(), metadata, 1.0 + &buff.front(), buff.size(), metadata, 1.0, true ); BOOST_CHECK_EQUAL(metadata.error_code, uhd::rx_metadata_t::ERROR_CODE_TIMEOUT); } @@ -410,7 +409,7 @@ BOOST_AUTO_TEST_CASE(test_sph_recv_multi_channel_normal){ for (size_t i = 0; i < NUM_PKTS_TO_TEST; i++){ std::cout << "data check " << i << std::endl; size_t num_samps_ret = handler.recv( - buffs, NUM_SAMPS_PER_BUFF, metadata, 1.0 + buffs, NUM_SAMPS_PER_BUFF, metadata, 1.0, true ); BOOST_CHECK_EQUAL(metadata.error_code, uhd::rx_metadata_t::ERROR_CODE_NONE); BOOST_CHECK(not metadata.more_fragments); @@ -424,7 +423,7 @@ BOOST_AUTO_TEST_CASE(test_sph_recv_multi_channel_normal){ for (size_t i = 0; i < 3; i++){ std::cout << "timeout check " << i << std::endl; handler.recv( - buffs, NUM_SAMPS_PER_BUFF, metadata, 1.0 + buffs, NUM_SAMPS_PER_BUFF, metadata, 1.0, true ); BOOST_CHECK_EQUAL(metadata.error_code, uhd::rx_metadata_t::ERROR_CODE_TIMEOUT); } @@ -496,7 +495,7 @@ BOOST_AUTO_TEST_CASE(test_sph_recv_multi_channel_sequence_error){ for (size_t i = 0; i < NUM_PKTS_TO_TEST; i++){ std::cout << "data check " << i << std::endl; size_t num_samps_ret = handler.recv( - buffs, NUM_SAMPS_PER_BUFF, metadata, 1.0 + buffs, NUM_SAMPS_PER_BUFF, metadata, 1.0, true ); if (i == NUM_PKTS_TO_TEST/2){ //must get the soft overflow here @@ -518,7 +517,7 @@ BOOST_AUTO_TEST_CASE(test_sph_recv_multi_channel_sequence_error){ for (size_t i = 0; i < 3; i++){ std::cout << "timeout check " << i << std::endl; handler.recv( - buffs, NUM_SAMPS_PER_BUFF, metadata, 1.0 + buffs, NUM_SAMPS_PER_BUFF, metadata, 1.0, true ); BOOST_CHECK_EQUAL(metadata.error_code, uhd::rx_metadata_t::ERROR_CODE_TIMEOUT); } @@ -589,7 +588,7 @@ BOOST_AUTO_TEST_CASE(test_sph_recv_multi_channel_time_error){ for (size_t i = 0; i < NUM_PKTS_TO_TEST; i++){ std::cout << "data check " << i << std::endl; size_t num_samps_ret = handler.recv( - buffs, NUM_SAMPS_PER_BUFF, metadata, 1.0 + buffs, NUM_SAMPS_PER_BUFF, metadata, 1.0, true ); BOOST_CHECK_EQUAL(metadata.error_code, uhd::rx_metadata_t::ERROR_CODE_NONE); BOOST_CHECK(not metadata.more_fragments); @@ -606,7 +605,7 @@ BOOST_AUTO_TEST_CASE(test_sph_recv_multi_channel_time_error){ for (size_t i = 0; i < 3; i++){ std::cout << "timeout check " << i << std::endl; handler.recv( - buffs, NUM_SAMPS_PER_BUFF, metadata, 1.0 + buffs, NUM_SAMPS_PER_BUFF, metadata, 1.0, true ); BOOST_CHECK_EQUAL(metadata.error_code, uhd::rx_metadata_t::ERROR_CODE_TIMEOUT); } @@ -674,7 +673,7 @@ BOOST_AUTO_TEST_CASE(test_sph_recv_multi_channel_fragment){ for (size_t i = 0; i < NUM_PKTS_TO_TEST; i++){ std::cout << "data check " << i << std::endl; size_t num_samps_ret = handler.recv( - buffs, NUM_SAMPS_PER_BUFF, metadata, 1.0 + buffs, NUM_SAMPS_PER_BUFF, metadata, 1.0, true ); BOOST_CHECK_EQUAL(metadata.error_code, uhd::rx_metadata_t::ERROR_CODE_NONE); BOOST_CHECK(metadata.has_time_spec); @@ -685,7 +684,7 @@ BOOST_AUTO_TEST_CASE(test_sph_recv_multi_channel_fragment){ if (not metadata.more_fragments) continue; num_samps_ret = handler.recv( - buffs, NUM_SAMPS_PER_BUFF, metadata, 1.0 + buffs, NUM_SAMPS_PER_BUFF, metadata, 1.0, true ); BOOST_CHECK_EQUAL(metadata.error_code, uhd::rx_metadata_t::ERROR_CODE_NONE); BOOST_CHECK(not metadata.more_fragments); @@ -700,7 +699,7 @@ BOOST_AUTO_TEST_CASE(test_sph_recv_multi_channel_fragment){ for (size_t i = 0; i < 3; i++){ std::cout << "timeout check " << i << std::endl; handler.recv( - buffs, NUM_SAMPS_PER_BUFF, metadata, 1.0 + buffs, NUM_SAMPS_PER_BUFF, metadata, 1.0, true ); BOOST_CHECK_EQUAL(metadata.error_code, uhd::rx_metadata_t::ERROR_CODE_TIMEOUT); } -- cgit v1.2.3 From 5538048873f140f3ac2bbab12dc5b0729f68f1a5 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Tue, 11 Oct 2011 12:12:25 -0700 Subject: usrp1: support variable clock rate through API --- host/docs/usrp1.rst | 6 ++++++ host/lib/usrp/usrp1/dboard_iface.cpp | 26 +++++++++++++------------- host/lib/usrp/usrp1/io_impl.cpp | 9 +++++++++ host/lib/usrp/usrp1/usrp1_impl.cpp | 36 ++++++++++++++++++++++++++++-------- host/lib/usrp/usrp1/usrp1_impl.hpp | 5 ++++- 5 files changed, 60 insertions(+), 22 deletions(-) (limited to 'host') diff --git a/host/docs/usrp1.rst b/host/docs/usrp1.rst index 8b274a2b3..597b5b17f 100644 --- a/host/docs/usrp1.rst +++ b/host/docs/usrp1.rst @@ -84,3 +84,9 @@ Run the following commands to record the setting into the EEPROM: cd /share/uhd/utils ./usrp_burn_mb_eeprom --args= --key=mcr --val= + +The user may override the clock rate specified in the EEPROM by using a device address: +Example: +:: + + uhd_usrp_probe --args="mcr=52e6" diff --git a/host/lib/usrp/usrp1/dboard_iface.cpp b/host/lib/usrp/usrp1/dboard_iface.cpp index 449ec64fe..34bbe1893 100644 --- a/host/lib/usrp/usrp1/dboard_iface.cpp +++ b/host/lib/usrp/usrp1/dboard_iface.cpp @@ -39,7 +39,7 @@ public: usrp1_dboard_iface(usrp1_iface::sptr iface, usrp1_codec_ctrl::sptr codec, usrp1_impl::dboard_slot_t dboard_slot, - const double master_clock_rate, + const double &master_clock_rate, const dboard_id_t &rx_dboard_id ): _dboard_slot(dboard_slot), @@ -49,10 +49,8 @@ public: _iface = iface; _codec = codec; - //init the clock rate shadows - this->set_clock_rate(UNIT_RX, this->get_clock_rates(UNIT_RX).front()); - this->set_clock_rate(UNIT_TX, this->get_clock_rates(UNIT_TX).front()); - + _dbsrx_classic_div = 1; + //yes this is evil but it's necessary for TVRX to work on USRP1 if(_rx_dboard_id == tvrx_id) _codec->bypass_adc_buffers(false); //else _codec->bypass_adc_buffers(false); //don't think this is necessary @@ -103,9 +101,9 @@ public: private: usrp1_iface::sptr _iface; usrp1_codec_ctrl::sptr _codec; - uhd::dict _clock_rates; + unsigned _dbsrx_classic_div; const usrp1_impl::dboard_slot_t _dboard_slot; - const double _master_clock_rate; + const double &_master_clock_rate; const dboard_id_t _rx_dboard_id; }; @@ -115,7 +113,7 @@ private: dboard_iface::sptr usrp1_impl::make_dboard_iface(usrp1_iface::sptr iface, usrp1_codec_ctrl::sptr codec, usrp1_impl::dboard_slot_t dboard_slot, - const double master_clock_rate, + const double &master_clock_rate, const dboard_id_t &rx_dboard_id ){ return dboard_iface::sptr(new usrp1_dboard_iface( @@ -137,17 +135,16 @@ static const dboard_id_t dbsrx_classic_id(0x0002); void usrp1_dboard_iface::set_clock_rate(unit_t unit, double rate) { assert_has(this->get_clock_rates(unit), rate, "dboard clock rate"); - _clock_rates[unit] = rate; if (unit == UNIT_RX && _rx_dboard_id == dbsrx_classic_id){ - size_t divider = size_t(_master_clock_rate/rate); + _dbsrx_classic_div = size_t(_master_clock_rate/rate); switch(_dboard_slot){ case usrp1_impl::DBOARD_SLOT_A: - _iface->poke32(FR_RX_A_REFCLK, (divider & 0x7f) | 0x80); + _iface->poke32(FR_RX_A_REFCLK, (_dbsrx_classic_div & 0x7f) | 0x80); break; case usrp1_impl::DBOARD_SLOT_B: - _iface->poke32(FR_RX_B_REFCLK, (divider & 0x7f) | 0x80); + _iface->poke32(FR_RX_B_REFCLK, (_dbsrx_classic_div & 0x7f) | 0x80); break; } } @@ -168,7 +165,10 @@ std::vector usrp1_dboard_iface::get_clock_rates(unit_t unit) double usrp1_dboard_iface::get_clock_rate(unit_t unit) { - return _clock_rates[unit]; + if (unit == UNIT_RX && _rx_dboard_id == dbsrx_classic_id){ + return _master_clock_rate/_dbsrx_classic_div; + } + return _master_clock_rate; } void usrp1_dboard_iface::set_clock_enabled(unit_t, bool) diff --git a/host/lib/usrp/usrp1/io_impl.cpp b/host/lib/usrp/usrp1/io_impl.cpp index a0fdfc6bf..f46f4741b 100644 --- a/host/lib/usrp/usrp1/io_impl.cpp +++ b/host/lib/usrp/usrp1/io_impl.cpp @@ -441,6 +441,14 @@ void usrp1_impl::update_tx_subdev_spec(const uhd::usrp::subdev_spec_t &spec){ this->restore_tx(s); } + +void usrp1_impl::update_tick_rate(const double rate){ + //updating this variable should: + //update dboard iface -> it has a reference + //update dsp freq bounds -> publisher + _master_clock_rate = rate; +} + double usrp1_impl::update_rx_samp_rate(size_t dspno, const double samp_rate){ const size_t div = this->has_rx_halfband()? 2 : 1; @@ -495,6 +503,7 @@ double usrp1_impl::update_tx_samp_rate(size_t dspno, const double samp_rate){ void usrp1_impl::update_rates(void){ const fs_path mb_path = "/mboards/0"; + this->update_tick_rate(_master_clock_rate); BOOST_FOREACH(const std::string &name, _tree->list(mb_path / "rx_dsps")){ _tree->access(mb_path / "rx_dsps" / name / "rate" / "value").update(); } diff --git a/host/lib/usrp/usrp1/usrp1_impl.cpp b/host/lib/usrp/usrp1/usrp1_impl.cpp index db652b033..5788c536f 100644 --- a/host/lib/usrp/usrp1/usrp1_impl.cpp +++ b/host/lib/usrp/usrp1/usrp1_impl.cpp @@ -225,14 +225,25 @@ usrp1_impl::usrp1_impl(const device_addr_t &device_addr){ // create clock control objects //////////////////////////////////////////////////////////////////// _master_clock_rate = 64e6; - try{ - if (not mb_eeprom["mcr"].empty()) + if (device_addr.has_key("mcr")){ + try{ + _master_clock_rate = boost::lexical_cast(device_addr["mcr"]); + } + catch(const std::exception &e){ + UHD_MSG(error) << "Error parsing FPGA clock rate from device address: " << e.what() << std::endl; + } + } + else if (not mb_eeprom["mcr"].empty()){ + try{ _master_clock_rate = boost::lexical_cast(mb_eeprom["mcr"]); - }catch(const std::exception &e){ - UHD_MSG(error) << "Error parsing FPGA clock rate from EEPROM: " << e.what() << std::endl; + } + catch(const std::exception &e){ + UHD_MSG(error) << "Error parsing FPGA clock rate from EEPROM: " << e.what() << std::endl; + } } UHD_MSG(status) << boost::format("Using FPGA clock rate of %fMHz...") % (_master_clock_rate/1e6) << std::endl; - _tree->create(mb_path / "tick_rate").set(_master_clock_rate); + _tree->create(mb_path / "tick_rate") + .subscribe(boost::bind(&usrp1_impl::update_tick_rate, this, _1)); //////////////////////////////////////////////////////////////////// // create codec control objects @@ -278,7 +289,7 @@ usrp1_impl::usrp1_impl(const device_addr_t &device_addr){ _tree->create(rx_dsp_path / "freq/value") .coerce(boost::bind(&usrp1_impl::update_rx_dsp_freq, this, dspno, _1)); _tree->create(rx_dsp_path / "freq/range") - .set(meta_range_t(-_master_clock_rate/2, +_master_clock_rate/2)); + .publish(boost::bind(&usrp1_impl::get_rx_dsp_freq_range, this)); _tree->create(rx_dsp_path / "stream_cmd"); if (dspno == 0){ //only subscribe the callback for dspno 0 since it will stream all dsps @@ -298,8 +309,8 @@ usrp1_impl::usrp1_impl(const device_addr_t &device_addr){ .coerce(boost::bind(&usrp1_impl::update_tx_samp_rate, this, dspno, _1)); _tree->create(tx_dsp_path / "freq/value") .coerce(boost::bind(&usrp1_impl::update_tx_dsp_freq, this, dspno, _1)); - _tree->create(tx_dsp_path / "freq/range") //magic scalar comes from codec control: - .set(meta_range_t(-_master_clock_rate*0.6875, +_master_clock_rate*0.6875)); + _tree->create(tx_dsp_path / "freq/range") + .publish(boost::bind(&usrp1_impl::get_tx_dsp_freq_range, this)); } //////////////////////////////////////////////////////////////////// @@ -443,3 +454,12 @@ double usrp1_impl::update_rx_codec_gain(const std::string &db, const double gain _dbc[db].codec->set_rx_pga_gain(gain, 'B'); return _dbc[db].codec->get_rx_pga_gain('A'); } + +uhd::meta_range_t usrp1_impl::get_rx_dsp_freq_range(void){ + return meta_range_t(-_master_clock_rate/2, +_master_clock_rate/2); +} + +uhd::meta_range_t usrp1_impl::get_tx_dsp_freq_range(void){ + //magic scalar comes from codec control: + return meta_range_t(-_master_clock_rate*0.6875, +_master_clock_rate*0.6875); +} diff --git a/host/lib/usrp/usrp1/usrp1_impl.hpp b/host/lib/usrp/usrp1/usrp1_impl.hpp index cfdcbbcc1..6f427c31e 100644 --- a/host/lib/usrp/usrp1/usrp1_impl.hpp +++ b/host/lib/usrp/usrp1/usrp1_impl.hpp @@ -95,12 +95,15 @@ private: void update_rates(void); double update_rx_dsp_freq(const size_t, const double); double update_tx_dsp_freq(const size_t, const double); + void update_tick_rate(const double rate); + uhd::meta_range_t get_rx_dsp_freq_range(void); + uhd::meta_range_t get_tx_dsp_freq_range(void); static uhd::usrp::dboard_iface::sptr make_dboard_iface( usrp1_iface::sptr, usrp1_codec_ctrl::sptr, dboard_slot_t, - const double, + const double &, const uhd::usrp::dboard_id_t & ); -- cgit v1.2.3 From ba0323c616e032ebde12073521c754d93c65f821 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Tue, 11 Oct 2011 14:54:02 -0700 Subject: b100: performed streamer API update to b100 impl --- host/lib/usrp/b100/b100_impl.cpp | 18 ++-- host/lib/usrp/b100/b100_impl.hpp | 23 ++-- host/lib/usrp/b100/io_impl.cpp | 222 ++++++++++++++++++++++++--------------- 3 files changed, 151 insertions(+), 112 deletions(-) (limited to 'host') diff --git a/host/lib/usrp/b100/b100_impl.cpp b/host/lib/usrp/b100/b100_impl.cpp index 98c5cab8c..d1928735b 100644 --- a/host/lib/usrp/b100/b100_impl.cpp +++ b/host/lib/usrp/b100/b100_impl.cpp @@ -297,8 +297,9 @@ b100_impl::b100_impl(const device_addr_t &device_addr){ .subscribe(boost::bind(&rx_dsp_core_200::set_tick_rate, _rx_dsps[dspno], _1)); fs_path rx_dsp_path = mb_path / str(boost::format("rx_dsps/%u") % dspno); _tree->create(rx_dsp_path / "rate/value") + .set(1e6) //some default .coerce(boost::bind(&rx_dsp_core_200::set_host_rate, _rx_dsps[dspno], _1)) - .subscribe(boost::bind(&b100_impl::update_rx_samp_rate, this, _1)); + .subscribe(boost::bind(&b100_impl::update_rx_samp_rate, this, dspno, _1)); _tree->create(rx_dsp_path / "freq/value") .coerce(boost::bind(&rx_dsp_core_200::set_freq, _rx_dsps[dspno], _1)); _tree->create(rx_dsp_path / "freq/range") @@ -317,8 +318,9 @@ b100_impl::b100_impl(const device_addr_t &device_addr){ _tree->access(mb_path / "tick_rate") .subscribe(boost::bind(&tx_dsp_core_200::set_tick_rate, _tx_dsp, _1)); _tree->create(mb_path / "tx_dsps/0/rate/value") + .set(1e6) //some default .coerce(boost::bind(&tx_dsp_core_200::set_host_rate, _tx_dsp, _1)) - .subscribe(boost::bind(&b100_impl::update_tx_samp_rate, this, _1)); + .subscribe(boost::bind(&b100_impl::update_tx_samp_rate, this, 0, _1)); _tree->create(mb_path / "tx_dsps/0/freq/value") .coerce(boost::bind(&tx_dsp_core_200::set_freq, _tx_dsp, _1)); _tree->create(mb_path / "tx_dsps/0/freq/range") @@ -402,16 +404,10 @@ b100_impl::b100_impl(const device_addr_t &device_addr){ //////////////////////////////////////////////////////////////////// // do some post-init tasks //////////////////////////////////////////////////////////////////// - _tree->access(mb_path / "tick_rate").update() //update and then subscribe the clock callback - .subscribe(boost::bind(&b100_clock_ctrl::set_fpga_clock_rate, _clock_ctrl, _1)); + this->update_rates(); - //and now that the tick rate is set, init the host rates to something - BOOST_FOREACH(const std::string &name, _tree->list(mb_path / "rx_dsps")){ - _tree->access(mb_path / "rx_dsps" / name / "rate" / "value").set(1e6); - } - BOOST_FOREACH(const std::string &name, _tree->list(mb_path / "tx_dsps")){ - _tree->access(mb_path / "tx_dsps" / name / "rate" / "value").set(1e6); - } + _tree->access(mb_path / "tick_rate") //now subscribe the clock rate setter + .subscribe(boost::bind(&b100_clock_ctrl::set_fpga_clock_rate, _clock_ctrl, _1)); _tree->access(mb_path / "rx_subdev_spec").set(subdev_spec_t("A:"+_dboard_manager->get_rx_subdev_names()[0])); _tree->access(mb_path / "tx_subdev_spec").set(subdev_spec_t("A:"+_dboard_manager->get_tx_subdev_names()[0])); diff --git a/host/lib/usrp/b100/b100_impl.hpp b/host/lib/usrp/b100/b100_impl.hpp index 5ec3dde7b..fb440e8be 100644 --- a/host/lib/usrp/b100/b100_impl.hpp +++ b/host/lib/usrp/b100/b100_impl.hpp @@ -33,7 +33,6 @@ #include #include #include -#include #include #include #include @@ -69,17 +68,8 @@ public: ~b100_impl(void); //the io interface - size_t send(const send_buffs_type &, - size_t, - const uhd::tx_metadata_t &, - const uhd::io_type_t &, - send_mode_t, double); - size_t recv(const recv_buffs_type &, - size_t, uhd::rx_metadata_t &, - const uhd::io_type_t &, - recv_mode_t, double); - size_t get_max_send_samps_per_packet(void) const; - size_t get_max_recv_samps_per_packet(void) const; + uhd::rx_streamer::sptr get_rx_stream(const uhd::stream_args_t &args); + uhd::tx_streamer::sptr get_tx_stream(const uhd::stream_args_t &args); bool recv_async_msg(uhd::async_metadata_t &, double); private: @@ -106,7 +96,6 @@ private: uhd::usrp::dboard_iface::sptr _dboard_iface; //handle io stuff - uhd::otw_type_t _rx_otw_type, _tx_otw_type; UHD_PIMPL_DECL(io_impl) _io_impl; void io_init(void); @@ -115,14 +104,18 @@ private: return _tree; } + std::vector > _rx_streamers; + std::vector > _tx_streamers; + void check_fw_compat(void); void check_fpga_compat(void); double update_rx_codec_gain(const double); //sets A and B at once void set_mb_eeprom(const uhd::usrp::mboard_eeprom_t &); void set_db_eeprom(const std::string &, const uhd::usrp::dboard_eeprom_t &); void update_tick_rate(const double rate); - void update_rx_samp_rate(const double rate); - void update_tx_samp_rate(const double rate); + void update_rx_samp_rate(const size_t, const double rate); + void update_tx_samp_rate(const size_t, const double rate); + void update_rates(void); void update_rx_subdev_spec(const uhd::usrp::subdev_spec_t &); void update_tx_subdev_spec(const uhd::usrp::subdev_spec_t &); void update_clock_source(const std::string &); diff --git a/host/lib/usrp/b100/io_impl.cpp b/host/lib/usrp/b100/io_impl.cpp index d2eee4f7c..82298dca6 100644 --- a/host/lib/usrp/b100/io_impl.cpp +++ b/host/lib/usrp/b100/io_impl.cpp @@ -30,6 +30,7 @@ #include #include #include +#include using namespace uhd; using namespace uhd::usrp; @@ -46,8 +47,6 @@ struct b100_impl::io_impl{ zero_copy_if::sptr data_transport; bounded_buffer async_msg_fifo; recv_packet_demuxer::sptr demuxer; - sph::recv_packet_handler recv_handler; - sph::send_packet_handler send_handler; }; /*********************************************************************** @@ -55,16 +54,6 @@ struct b100_impl::io_impl{ **********************************************************************/ void b100_impl::io_init(void){ - //setup rx otw type - _rx_otw_type.width = 16; - _rx_otw_type.shift = 0; - _rx_otw_type.byteorder = uhd::otw_type_t::BO_LITTLE_ENDIAN; - - //setup tx otw type - _tx_otw_type.width = 16; - _tx_otw_type.shift = 0; - _tx_otw_type.byteorder = uhd::otw_type_t::BO_LITTLE_ENDIAN; - //clear state machines _fpga_ctrl->poke32(B100_REG_CLEAR_RX, 0); _fpga_ctrl->poke32(B100_REG_CLEAR_TX, 0); @@ -72,19 +61,16 @@ void b100_impl::io_init(void){ //set the expected packet size in USB frames _fpga_ctrl->poke32(B100_REG_MISC_RX_LEN, 4); + //allocate streamer weak ptrs containers + _rx_streamers.resize(_rx_dsps.size()); + _tx_streamers.resize(1/*known to be 1 dsp*/); + //create new io impl _io_impl = UHD_PIMPL_MAKE(io_impl, ()); _io_impl->demuxer = recv_packet_demuxer::make(_data_transport, _rx_dsps.size(), B100_RX_SID_BASE); //now its safe to register the async callback _fpga_ctrl->set_async_cb(boost::bind(&b100_impl::handle_async_message, this, _1)); - - //init some handler stuff - _io_impl->recv_handler.set_vrt_unpacker(&vrt::if_hdr_unpack_le); - _io_impl->recv_handler.set_converter(_rx_otw_type); - _io_impl->send_handler.set_vrt_packer(&vrt::if_hdr_pack_le); - _io_impl->send_handler.set_converter(_tx_otw_type); - _io_impl->send_handler.set_max_samples_per_packet(get_max_send_samps_per_packet()); } void b100_impl::handle_async_message(managed_recv_buffer::sptr rbuf){ @@ -120,27 +106,54 @@ void b100_impl::handle_async_message(managed_recv_buffer::sptr rbuf){ else UHD_MSG(error) << "Unknown async packet" << std::endl; } +void b100_impl::update_rates(void){ + const fs_path mb_path = "/mboards/0"; + _tree->access(mb_path / "tick_rate").update(); + + //and now that the tick rate is set, init the host rates to something + BOOST_FOREACH(const std::string &name, _tree->list(mb_path / "rx_dsps")){ + _tree->access(mb_path / "rx_dsps" / name / "rate" / "value").update(); + } + BOOST_FOREACH(const std::string &name, _tree->list(mb_path / "tx_dsps")){ + _tree->access(mb_path / "tx_dsps" / name / "rate" / "value").update(); + } +} + void b100_impl::update_tick_rate(const double rate){ - boost::mutex::scoped_lock recv_lock = _io_impl->recv_handler.get_scoped_lock(); - _io_impl->recv_handler.set_tick_rate(rate); - boost::mutex::scoped_lock send_lock = _io_impl->send_handler.get_scoped_lock(); - _io_impl->send_handler.set_tick_rate(rate); + //update the tick rate on all existing streamers -> thread safe + for (size_t i = 0; i < _rx_streamers.size(); i++){ + boost::shared_ptr my_streamer = + boost::dynamic_pointer_cast(_rx_streamers[i].lock()); + if (my_streamer.get() == NULL) continue; + my_streamer->set_tick_rate(rate); + } + for (size_t i = 0; i < _tx_streamers.size(); i++){ + boost::shared_ptr my_streamer = + boost::dynamic_pointer_cast(_tx_streamers[i].lock()); + if (my_streamer.get() == NULL) continue; + my_streamer->set_tick_rate(rate); + } } -void b100_impl::update_rx_samp_rate(const double rate){ - boost::mutex::scoped_lock recv_lock = _io_impl->recv_handler.get_scoped_lock(); - _io_impl->recv_handler.set_samp_rate(rate); - const double adj = _rx_dsps.front()->get_scaling_adjustment(); - _io_impl->recv_handler.set_scale_factor(adj/32767.); +void b100_impl::update_rx_samp_rate(const size_t dspno, const double rate){ + boost::shared_ptr my_streamer = + boost::dynamic_pointer_cast(_rx_streamers[dspno].lock()); + if (my_streamer.get() == NULL) return; + + my_streamer->set_samp_rate(rate); + const double adj = _rx_dsps[dspno]->get_scaling_adjustment(); + my_streamer->set_scale_factor(adj); } -void b100_impl::update_tx_samp_rate(const double rate){ - boost::mutex::scoped_lock send_lock = _io_impl->send_handler.get_scoped_lock(); - _io_impl->send_handler.set_samp_rate(rate); +void b100_impl::update_tx_samp_rate(const size_t dspno, const double rate){ + boost::shared_ptr my_streamer = + boost::dynamic_pointer_cast(_tx_streamers[dspno].lock()); + if (my_streamer.get() == NULL) return; + + my_streamer->set_samp_rate(rate); } void b100_impl::update_rx_subdev_spec(const uhd::usrp::subdev_spec_t &spec){ - boost::mutex::scoped_lock recv_lock = _io_impl->recv_handler.get_scoped_lock(); fs_path root = "/mboards/0/dboards"; //sanity checking @@ -154,22 +167,9 @@ void b100_impl::update_rx_subdev_spec(const uhd::usrp::subdev_spec_t &spec){ _rx_dsps[i]->set_mux(conn, fe_swapped); } _rx_fe->set_mux(fe_swapped); - - //resize for the new occupancy - _io_impl->recv_handler.resize(spec.size()); - - //bind new callbacks for the handler - for (size_t i = 0; i < _io_impl->recv_handler.size(); i++){ - _rx_dsps[i]->set_nsamps_per_packet(get_max_recv_samps_per_packet()); //seems to be a good place to set this - _io_impl->recv_handler.set_xport_chan_get_buff(i, boost::bind( - &recv_packet_demuxer::get_recv_buff, _io_impl->demuxer, i, _1 - )); - _io_impl->recv_handler.set_overflow_handler(i, boost::bind(&rx_dsp_core_200::handle_overflow, _rx_dsps[i])); - } } void b100_impl::update_tx_subdev_spec(const uhd::usrp::subdev_spec_t &spec){ - boost::mutex::scoped_lock send_lock = _io_impl->send_handler.get_scoped_lock(); fs_path root = "/mboards/0/dboards"; //sanity checking @@ -178,16 +178,6 @@ void b100_impl::update_tx_subdev_spec(const uhd::usrp::subdev_spec_t &spec){ //set the mux for this spec const std::string conn = _tree->access(root / spec[0].db_name / "tx_frontends" / spec[0].sd_name / "connection").get(); _tx_fe->set_mux(conn); - - //resize for the new occupancy - _io_impl->send_handler.resize(spec.size()); - - //bind new callbacks for the handler - for (size_t i = 0; i < _io_impl->send_handler.size(); i++){ - _io_impl->send_handler.set_xport_chan_get_buff(i, boost::bind( - &zero_copy_if::get_send_buff, _data_transport, _1 - )); - } } /*********************************************************************** @@ -201,50 +191,110 @@ bool b100_impl::recv_async_msg( } /*********************************************************************** - * Send Data + * Receive streamer **********************************************************************/ -size_t b100_impl::get_max_send_samps_per_packet(void) const { +rx_streamer::sptr b100_impl::get_rx_stream(const uhd::stream_args_t &args_){ + stream_args_t args = args_; + + //setup defaults for unspecified values + args.otw_format = args.otw_format.empty()? "sc16" : args.otw_format; + args.channels = args.channels.empty()? std::vector(1, 0) : args.channels; + + //calculate packet size static const size_t hdr_size = 0 + vrt::max_if_hdr_words32*sizeof(boost::uint32_t) + + sizeof(vrt::if_packet_info_t().tlr) //forced to have trailer - sizeof(vrt::if_packet_info_t().cid) //no class id ever used ; - static const size_t bpp = 2048 - hdr_size; - return bpp / _tx_otw_type.get_sample_size(); -} + const size_t bpp = 2048 - hdr_size; //limited by FPGA pkt buffer size + const size_t spp = bpp/convert::get_bytes_per_item(args.otw_format); + + //make the new streamer given the samples per packet + boost::shared_ptr my_streamer = boost::make_shared(spp); + + //init some streamer stuff + my_streamer->resize(args.channels.size()); + my_streamer->set_vrt_unpacker(&vrt::if_hdr_unpack_le); + + //set the converter + uhd::convert::id_type id; + id.input_markup = args.otw_format + "_item32_le"; + id.num_inputs = 1; + id.output_markup = args.cpu_format; + id.num_outputs = 1; + id.args = args.args; + my_streamer->set_converter(id); + + //bind callbacks for the handler + for (size_t chan_i = 0; chan_i < args.channels.size(); chan_i++){ + const size_t dsp = args.channels[chan_i]; + _rx_dsps[dsp]->set_nsamps_per_packet(spp); //seems to be a good place to set this + _rx_dsps[dsp]->set_format(args.otw_format, 0x400); + my_streamer->set_xport_chan_get_buff(chan_i, boost::bind( + &recv_packet_demuxer::get_recv_buff, _io_impl->demuxer, dsp, _1 + )); + my_streamer->set_overflow_handler(chan_i, boost::bind( + &rx_dsp_core_200::handle_overflow, _rx_dsps[dsp] + )); + _rx_streamers[dsp] = my_streamer; //store weak pointer + } -size_t b100_impl::send( - const send_buffs_type &buffs, size_t nsamps_per_buff, - const tx_metadata_t &metadata, const io_type_t &io_type, - send_mode_t send_mode, double timeout -){ - return _io_impl->send_handler.send( - buffs, nsamps_per_buff, - metadata, io_type, - send_mode, timeout - ); + //sets all tick and samp rates on this streamer + this->update_rates(); + + return my_streamer; } /*********************************************************************** - * Receive Data + * Transmit streamer **********************************************************************/ -size_t b100_impl::get_max_recv_samps_per_packet(void) const { +tx_streamer::sptr b100_impl::get_tx_stream(const uhd::stream_args_t &args_){ + stream_args_t args = args_; + + //setup defaults for unspecified values + args.otw_format = args.otw_format.empty()? "sc16" : args.otw_format; + args.channels = args.channels.empty()? std::vector(1, 0) : args.channels; + + if (args.otw_format != "sc16"){ + throw uhd::value_error("USRP TX cannot handle requested wire format: " + args.otw_format); + } + + //calculate packet size static const size_t hdr_size = 0 + vrt::max_if_hdr_words32*sizeof(boost::uint32_t) - + sizeof(vrt::if_packet_info_t().tlr) //forced to have trailer - sizeof(vrt::if_packet_info_t().cid) //no class id ever used ; - size_t bpp = 2048 - hdr_size; //limited by FPGA pkt buffer size - return bpp/_rx_otw_type.get_sample_size(); -} + static const size_t bpp = 2048 - hdr_size; + const size_t spp = bpp/convert::get_bytes_per_item(args.otw_format); + + //make the new streamer given the samples per packet + boost::shared_ptr my_streamer = boost::make_shared(spp); + + //init some streamer stuff + my_streamer->resize(args.channels.size()); + my_streamer->set_vrt_packer(&vrt::if_hdr_pack_le); + + //set the converter + uhd::convert::id_type id; + id.input_markup = args.cpu_format; + id.num_inputs = 1; + id.output_markup = args.otw_format + "_item32_le"; + id.num_outputs = 1; + id.args = args.args; + my_streamer->set_converter(id); + + //bind callbacks for the handler + for (size_t chan_i = 0; chan_i < args.channels.size(); chan_i++){ + const size_t dsp = args.channels[chan_i]; + UHD_ASSERT_THROW(dsp == 0); //always 0 + my_streamer->set_xport_chan_get_buff(chan_i, boost::bind( + &zero_copy_if::get_send_buff, _data_transport, _1 + )); + _tx_streamers[dsp] = my_streamer; //store weak pointer + } -size_t b100_impl::recv( - const recv_buffs_type &buffs, size_t nsamps_per_buff, - rx_metadata_t &metadata, const io_type_t &io_type, - recv_mode_t recv_mode, double timeout -){ - return _io_impl->recv_handler.recv( - buffs, nsamps_per_buff, - metadata, io_type, - recv_mode, timeout - ); + //sets all tick and samp rates on this streamer + this->update_rates(); + + return my_streamer; } -- cgit v1.2.3 From 9fc513c961775c9682123394fe5d42ef914bbbd6 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Tue, 11 Oct 2011 17:46:44 -0700 Subject: e100: performed streamer API update to e100 impl --- host/lib/usrp/b100/b100_impl.hpp | 1 + host/lib/usrp/e100/e100_impl.cpp | 18 ++- host/lib/usrp/e100/e100_impl.hpp | 18 +-- host/lib/usrp/e100/io_impl.cpp | 241 +++++++++++++++++++++++---------------- 4 files changed, 162 insertions(+), 116 deletions(-) (limited to 'host') diff --git a/host/lib/usrp/b100/b100_impl.hpp b/host/lib/usrp/b100/b100_impl.hpp index fb440e8be..25badc967 100644 --- a/host/lib/usrp/b100/b100_impl.hpp +++ b/host/lib/usrp/b100/b100_impl.hpp @@ -41,6 +41,7 @@ #include #include #include +#include static const double B100_LINK_RATE_BPS = 256e6/8; //pratical link rate (< 480 Mbps) static const std::string B100_FW_FILE_NAME = "usrp_b100_fw.ihx"; diff --git a/host/lib/usrp/e100/e100_impl.cpp b/host/lib/usrp/e100/e100_impl.cpp index 564a05a7e..deb52b2d7 100644 --- a/host/lib/usrp/e100/e100_impl.cpp +++ b/host/lib/usrp/e100/e100_impl.cpp @@ -271,8 +271,9 @@ e100_impl::e100_impl(const uhd::device_addr_t &device_addr){ .subscribe(boost::bind(&rx_dsp_core_200::set_tick_rate, _rx_dsps[dspno], _1)); fs_path rx_dsp_path = mb_path / str(boost::format("rx_dsps/%u") % dspno); _tree->create(rx_dsp_path / "rate/value") + .set(1e6) //some default .coerce(boost::bind(&rx_dsp_core_200::set_host_rate, _rx_dsps[dspno], _1)) - .subscribe(boost::bind(&e100_impl::update_rx_samp_rate, this, _1)); + .subscribe(boost::bind(&e100_impl::update_rx_samp_rate, this, dspno, _1)); _tree->create(rx_dsp_path / "freq/value") .coerce(boost::bind(&rx_dsp_core_200::set_freq, _rx_dsps[dspno], _1)); _tree->create(rx_dsp_path / "freq/range") @@ -291,8 +292,9 @@ e100_impl::e100_impl(const uhd::device_addr_t &device_addr){ _tree->access(mb_path / "tick_rate") .subscribe(boost::bind(&tx_dsp_core_200::set_tick_rate, _tx_dsp, _1)); _tree->create(mb_path / "tx_dsps/0/rate/value") + .set(1e6) //some default .coerce(boost::bind(&tx_dsp_core_200::set_host_rate, _tx_dsp, _1)) - .subscribe(boost::bind(&e100_impl::update_tx_samp_rate, this, _1)); + .subscribe(boost::bind(&e100_impl::update_tx_samp_rate, this, 0, _1)); _tree->create(mb_path / "tx_dsps/0/freq/value") .coerce(boost::bind(&tx_dsp_core_200::set_freq, _tx_dsp, _1)); _tree->create(mb_path / "tx_dsps/0/freq/range") @@ -376,16 +378,10 @@ e100_impl::e100_impl(const uhd::device_addr_t &device_addr){ //////////////////////////////////////////////////////////////////// // do some post-init tasks //////////////////////////////////////////////////////////////////// - _tree->access(mb_path / "tick_rate").update() //update and then subscribe the clock callback - .subscribe(boost::bind(&e100_clock_ctrl::set_fpga_clock_rate, _clock_ctrl, _1)); + this->update_rates(); - //and now that the tick rate is set, init the host rates to something - BOOST_FOREACH(const std::string &name, _tree->list(mb_path / "rx_dsps")){ - _tree->access(mb_path / "rx_dsps" / name / "rate" / "value").set(1e6); - } - BOOST_FOREACH(const std::string &name, _tree->list(mb_path / "tx_dsps")){ - _tree->access(mb_path / "tx_dsps" / name / "rate" / "value").set(1e6); - } + _tree->access(mb_path / "tick_rate") //now subscribe the clock rate setter + .subscribe(boost::bind(&e100_clock_ctrl::set_fpga_clock_rate, _clock_ctrl, _1)); _tree->access(mb_path / "rx_subdev_spec").set(subdev_spec_t("A:"+_dboard_manager->get_rx_subdev_names()[0])); _tree->access(mb_path / "tx_subdev_spec").set(subdev_spec_t("A:"+_dboard_manager->get_tx_subdev_names()[0])); diff --git a/host/lib/usrp/e100/e100_impl.hpp b/host/lib/usrp/e100/e100_impl.hpp index 4b2ec5ee0..954d6bd93 100644 --- a/host/lib/usrp/e100/e100_impl.hpp +++ b/host/lib/usrp/e100/e100_impl.hpp @@ -33,11 +33,10 @@ #include #include #include -#include -#include #include #include #include +#include #ifndef INCLUDED_E100_IMPL_HPP #define INCLUDED_E100_IMPL_HPP @@ -78,11 +77,9 @@ public: ~e100_impl(void); //the io interface - size_t send(const send_buffs_type &, size_t, const uhd::tx_metadata_t &, const uhd::io_type_t &, send_mode_t, double); - size_t recv(const recv_buffs_type &, size_t, uhd::rx_metadata_t &, const uhd::io_type_t &, recv_mode_t, double); + uhd::rx_streamer::sptr get_rx_stream(const uhd::stream_args_t &args); + uhd::tx_streamer::sptr get_tx_stream(const uhd::stream_args_t &args); bool recv_async_msg(uhd::async_metadata_t &, double); - size_t get_max_send_samps_per_packet(void) const; - size_t get_max_recv_samps_per_packet(void) const; private: uhd::property_tree::sptr _tree; @@ -110,7 +107,6 @@ private: uhd::usrp::dboard_iface::sptr _dboard_iface; //handle io stuff - uhd::otw_type_t _rx_otw_type, _tx_otw_type; UHD_PIMPL_DECL(io_impl) _io_impl; void io_init(void); @@ -119,12 +115,16 @@ private: return _tree; } + std::vector > _rx_streamers; + std::vector > _tx_streamers; + double update_rx_codec_gain(const double); //sets A and B at once void set_mb_eeprom(const uhd::usrp::mboard_eeprom_t &); void set_db_eeprom(const std::string &, const uhd::usrp::dboard_eeprom_t &); void update_tick_rate(const double rate); - void update_rx_samp_rate(const double rate); - void update_tx_samp_rate(const double rate); + void update_rx_samp_rate(const size_t, const double rate); + void update_tx_samp_rate(const size_t, const double rate); + void update_rates(void); void update_rx_subdev_spec(const uhd::usrp::subdev_spec_t &); void update_tx_subdev_spec(const uhd::usrp::subdev_spec_t &); void update_clock_source(const std::string &); diff --git a/host/lib/usrp/e100/io_impl.cpp b/host/lib/usrp/e100/io_impl.cpp index 0b81c1a86..5936ee2d7 100644 --- a/host/lib/usrp/e100/io_impl.cpp +++ b/host/lib/usrp/e100/io_impl.cpp @@ -35,6 +35,7 @@ #include //open, close #include #include +#include using namespace uhd; using namespace uhd::usrp; @@ -60,10 +61,6 @@ struct e100_impl::io_impl{ //which is after the states and booty which may hold managed buffers. recv_packet_demuxer::sptr demuxer; - //state management for the vrt packet handler code - sph::recv_packet_handler recv_handler; - sph::send_packet_handler send_handler; - //a pirate's life is the life for me! void recv_pirate_loop( spi_iface::sptr //keep a sptr to iface which shares gpio147 @@ -159,16 +156,6 @@ void e100_impl::io_impl::handle_irq(void){ **********************************************************************/ void e100_impl::io_init(void){ - //setup rx otw type - _rx_otw_type.width = 16; - _rx_otw_type.shift = 0; - _rx_otw_type.byteorder = uhd::otw_type_t::BO_LITTLE_ENDIAN; - - //setup tx otw type - _tx_otw_type.width = 16; - _tx_otw_type.shift = 0; - _tx_otw_type.byteorder = uhd::otw_type_t::BO_LITTLE_ENDIAN; - //create new io impl _io_impl = UHD_PIMPL_MAKE(io_impl, ()); _io_impl->demuxer = recv_packet_demuxer::make(_data_transport, _rx_dsps.size(), E100_RX_SID_BASE); @@ -178,6 +165,10 @@ void e100_impl::io_init(void){ _fpga_ctrl->poke32(E100_REG_CLEAR_RX, 0); _fpga_ctrl->poke32(E100_REG_CLEAR_TX, 0); + //allocate streamer weak ptrs containers + _rx_streamers.resize(_rx_dsps.size()); + _tx_streamers.resize(1/*known to be 1 dsp*/); + //prepare the async msg buffer for incoming messages _fpga_ctrl->poke32(E100_REG_SR_ERR_CTRL, 1 << 0); //clear while ((_fpga_ctrl->peek32(E100_REG_RB_ERR_STATUS) & (1 << 2)) == 0){} //wait for idle @@ -187,37 +178,58 @@ void e100_impl::io_init(void){ _io_impl->pirate_task = task::make(boost::bind( &e100_impl::io_impl::recv_pirate_loop, _io_impl.get(), _aux_spi_iface )); - - //init some handler stuff - _io_impl->recv_handler.set_vrt_unpacker(&vrt::if_hdr_unpack_le); - _io_impl->recv_handler.set_converter(_rx_otw_type); - _io_impl->send_handler.set_vrt_packer(&vrt::if_hdr_pack_le); - _io_impl->send_handler.set_converter(_tx_otw_type); - _io_impl->send_handler.set_max_samples_per_packet(get_max_send_samps_per_packet()); } void e100_impl::update_tick_rate(const double rate){ _io_impl->tick_rate = rate; - boost::mutex::scoped_lock recv_lock = _io_impl->recv_handler.get_scoped_lock(); - _io_impl->recv_handler.set_tick_rate(rate); - boost::mutex::scoped_lock send_lock = _io_impl->send_handler.get_scoped_lock(); - _io_impl->send_handler.set_tick_rate(rate); + + //update the tick rate on all existing streamers -> thread safe + for (size_t i = 0; i < _rx_streamers.size(); i++){ + boost::shared_ptr my_streamer = + boost::dynamic_pointer_cast(_rx_streamers[i].lock()); + if (my_streamer.get() == NULL) continue; + my_streamer->set_tick_rate(rate); + } + for (size_t i = 0; i < _tx_streamers.size(); i++){ + boost::shared_ptr my_streamer = + boost::dynamic_pointer_cast(_tx_streamers[i].lock()); + if (my_streamer.get() == NULL) continue; + my_streamer->set_tick_rate(rate); + } } -void e100_impl::update_rx_samp_rate(const double rate){ - boost::mutex::scoped_lock recv_lock = _io_impl->recv_handler.get_scoped_lock(); - _io_impl->recv_handler.set_samp_rate(rate); - const double adj = _rx_dsps.front()->get_scaling_adjustment(); - _io_impl->recv_handler.set_scale_factor(adj/32767.); +void e100_impl::update_rx_samp_rate(const size_t dspno, const double rate){ + boost::shared_ptr my_streamer = + boost::dynamic_pointer_cast(_rx_streamers[dspno].lock()); + if (my_streamer.get() == NULL) return; + + my_streamer->set_samp_rate(rate); + const double adj = _rx_dsps[dspno]->get_scaling_adjustment(); + my_streamer->set_scale_factor(adj); +} + +void e100_impl::update_tx_samp_rate(const size_t dspno, const double rate){ + boost::shared_ptr my_streamer = + boost::dynamic_pointer_cast(_tx_streamers[dspno].lock()); + if (my_streamer.get() == NULL) return; + + my_streamer->set_samp_rate(rate); } -void e100_impl::update_tx_samp_rate(const double rate){ - boost::mutex::scoped_lock send_lock = _io_impl->send_handler.get_scoped_lock(); - _io_impl->send_handler.set_samp_rate(rate); +void e100_impl::update_rates(void){ + const fs_path mb_path = "/mboards/0"; + _tree->access(mb_path / "tick_rate").update(); + + //and now that the tick rate is set, init the host rates to something + BOOST_FOREACH(const std::string &name, _tree->list(mb_path / "rx_dsps")){ + _tree->access(mb_path / "rx_dsps" / name / "rate" / "value").update(); + } + BOOST_FOREACH(const std::string &name, _tree->list(mb_path / "tx_dsps")){ + _tree->access(mb_path / "tx_dsps" / name / "rate" / "value").update(); + } } void e100_impl::update_rx_subdev_spec(const uhd::usrp::subdev_spec_t &spec){ - boost::mutex::scoped_lock recv_lock = _io_impl->recv_handler.get_scoped_lock(); fs_path root = "/mboards/0/dboards"; //sanity checking @@ -231,22 +243,9 @@ void e100_impl::update_rx_subdev_spec(const uhd::usrp::subdev_spec_t &spec){ _rx_dsps[i]->set_mux(conn, fe_swapped); } _rx_fe->set_mux(fe_swapped); - - //resize for the new occupancy - _io_impl->recv_handler.resize(spec.size()); - - //bind new callbacks for the handler - for (size_t i = 0; i < _io_impl->recv_handler.size(); i++){ - _rx_dsps[i]->set_nsamps_per_packet(get_max_recv_samps_per_packet()); //seems to be a good place to set this - _io_impl->recv_handler.set_xport_chan_get_buff(i, boost::bind( - &recv_packet_demuxer::get_recv_buff, _io_impl->demuxer, i, _1 - )); - _io_impl->recv_handler.set_overflow_handler(i, boost::bind(&rx_dsp_core_200::handle_overflow, _rx_dsps[i])); - } } void e100_impl::update_tx_subdev_spec(const uhd::usrp::subdev_spec_t &spec){ - boost::mutex::scoped_lock send_lock = _io_impl->send_handler.get_scoped_lock(); fs_path root = "/mboards/0/dboards"; //sanity checking @@ -255,73 +254,123 @@ void e100_impl::update_tx_subdev_spec(const uhd::usrp::subdev_spec_t &spec){ //set the mux for this spec const std::string conn = _tree->access(root / spec[0].db_name / "tx_frontends" / spec[0].sd_name / "connection").get(); _tx_fe->set_mux(conn); +} - //resize for the new occupancy - _io_impl->send_handler.resize(spec.size()); - - //bind new callbacks for the handler - for (size_t i = 0; i < _io_impl->send_handler.size(); i++){ - _io_impl->send_handler.set_xport_chan_get_buff(i, boost::bind( - &zero_copy_if::get_send_buff, _data_transport, _1 - )); - } +/*********************************************************************** + * Async Recv + **********************************************************************/ +bool e100_impl::recv_async_msg( + async_metadata_t &async_metadata, double timeout +){ + boost::this_thread::disable_interruption di; //disable because the wait can throw + return _io_impl->async_msg_fifo.pop_with_timed_wait(async_metadata, timeout); } /*********************************************************************** - * Data Send + * Receive streamer **********************************************************************/ -size_t e100_impl::get_max_send_samps_per_packet(void) const{ +rx_streamer::sptr e100_impl::get_rx_stream(const uhd::stream_args_t &args_){ + stream_args_t args = args_; + + //setup defaults for unspecified values + args.otw_format = args.otw_format.empty()? "sc16" : args.otw_format; + args.channels = args.channels.empty()? std::vector(1, 0) : args.channels; + + //calculate packet size static const size_t hdr_size = 0 + vrt::max_if_hdr_words32*sizeof(boost::uint32_t) + + sizeof(vrt::if_packet_info_t().tlr) //forced to have trailer - sizeof(vrt::if_packet_info_t().cid) //no class id ever used ; - size_t bpp = _data_transport->get_send_frame_size() - hdr_size; - return bpp/_tx_otw_type.get_sample_size(); -} + const size_t bpp = _data_transport->get_recv_frame_size() - hdr_size; + const size_t spp = bpp/convert::get_bytes_per_item(args.otw_format); + + //make the new streamer given the samples per packet + boost::shared_ptr my_streamer = boost::make_shared(spp); + + //init some streamer stuff + my_streamer->resize(args.channels.size()); + my_streamer->set_vrt_unpacker(&vrt::if_hdr_unpack_le); + + //set the converter + uhd::convert::id_type id; + id.input_markup = args.otw_format + "_item32_le"; + id.num_inputs = 1; + id.output_markup = args.cpu_format; + id.num_outputs = 1; + id.args = args.args; + my_streamer->set_converter(id); + + //bind callbacks for the handler + for (size_t chan_i = 0; chan_i < args.channels.size(); chan_i++){ + const size_t dsp = args.channels[chan_i]; + _rx_dsps[dsp]->set_nsamps_per_packet(spp); //seems to be a good place to set this + _rx_dsps[dsp]->set_format(args.otw_format, 0x400); + my_streamer->set_xport_chan_get_buff(chan_i, boost::bind( + &recv_packet_demuxer::get_recv_buff, _io_impl->demuxer, dsp, _1 + )); + my_streamer->set_overflow_handler(chan_i, boost::bind( + &rx_dsp_core_200::handle_overflow, _rx_dsps[dsp] + )); + _rx_streamers[dsp] = my_streamer; //store weak pointer + } -size_t e100_impl::send( - const send_buffs_type &buffs, size_t nsamps_per_buff, - const tx_metadata_t &metadata, const io_type_t &io_type, - send_mode_t send_mode, double timeout -){ - return _io_impl->send_handler.send( - buffs, nsamps_per_buff, - metadata, io_type, - send_mode, timeout - ); + //sets all tick and samp rates on this streamer + this->update_rates(); + + return my_streamer; } /*********************************************************************** - * Data Recv + * Transmit streamer **********************************************************************/ -size_t e100_impl::get_max_recv_samps_per_packet(void) const{ +tx_streamer::sptr e100_impl::get_tx_stream(const uhd::stream_args_t &args_){ + stream_args_t args = args_; + + //setup defaults for unspecified values + args.otw_format = args.otw_format.empty()? "sc16" : args.otw_format; + args.channels = args.channels.empty()? std::vector(1, 0) : args.channels; + + if (args.otw_format != "sc16"){ + throw uhd::value_error("USRP TX cannot handle requested wire format: " + args.otw_format); + } + + //calculate packet size static const size_t hdr_size = 0 + vrt::max_if_hdr_words32*sizeof(boost::uint32_t) - + sizeof(vrt::if_packet_info_t().tlr) //forced to have trailer - sizeof(vrt::if_packet_info_t().cid) //no class id ever used ; - size_t bpp = _data_transport->get_recv_frame_size() - hdr_size; - return bpp/_rx_otw_type.get_sample_size(); -} + static const size_t bpp = _data_transport->get_send_frame_size() - hdr_size; + const size_t spp = bpp/convert::get_bytes_per_item(args.otw_format); + + //make the new streamer given the samples per packet + boost::shared_ptr my_streamer = boost::make_shared(spp); + + //init some streamer stuff + my_streamer->resize(args.channels.size()); + my_streamer->set_vrt_packer(&vrt::if_hdr_pack_le); + + //set the converter + uhd::convert::id_type id; + id.input_markup = args.cpu_format; + id.num_inputs = 1; + id.output_markup = args.otw_format + "_item32_le"; + id.num_outputs = 1; + id.args = args.args; + my_streamer->set_converter(id); + + //bind callbacks for the handler + for (size_t chan_i = 0; chan_i < args.channels.size(); chan_i++){ + const size_t dsp = args.channels[chan_i]; + UHD_ASSERT_THROW(dsp == 0); //always 0 + my_streamer->set_xport_chan_get_buff(chan_i, boost::bind( + &zero_copy_if::get_send_buff, _data_transport, _1 + )); + _tx_streamers[dsp] = my_streamer; //store weak pointer + } -size_t e100_impl::recv( - const recv_buffs_type &buffs, size_t nsamps_per_buff, - rx_metadata_t &metadata, const io_type_t &io_type, - recv_mode_t recv_mode, double timeout -){ - return _io_impl->recv_handler.recv( - buffs, nsamps_per_buff, - metadata, io_type, - recv_mode, timeout - ); -} + //sets all tick and samp rates on this streamer + this->update_rates(); -/*********************************************************************** - * Async Recv - **********************************************************************/ -bool e100_impl::recv_async_msg( - async_metadata_t &async_metadata, double timeout -){ - boost::this_thread::disable_interruption di; //disable because the wait can throw - return _io_impl->async_msg_fifo.pop_with_timed_wait(async_metadata, timeout); + return my_streamer; } -- cgit v1.2.3 From c885da11389ee275f9c5206b9f8a2155a5393a8a Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Wed, 12 Oct 2011 00:39:04 -0700 Subject: uhd: renamed convert markup to format removed convert args added simd level got orc and neon updated --- host/include/uhd/convert.hpp | 16 ++++----- host/lib/convert/convert_common.hpp | 16 ++++----- host/lib/convert/convert_fc32_with_sse2.cpp | 8 ++--- host/lib/convert/convert_fc64_with_sse2.cpp | 8 ++--- host/lib/convert/convert_impl.cpp | 37 +++++++++----------- host/lib/convert/convert_with_neon.cpp | 8 ++--- host/lib/convert/convert_with_orc.cpp | 12 +++---- host/lib/transport/super_recv_packet_handler.hpp | 4 +-- host/lib/transport/super_send_packet_handler.hpp | 4 +-- host/lib/usrp/b100/io_impl.cpp | 10 +++--- host/lib/usrp/e100/io_impl.cpp | 10 +++--- host/lib/usrp/usrp1/io_impl.cpp | 10 +++--- host/lib/usrp/usrp2/io_impl.cpp | 10 +++--- host/tests/convert_test.cpp | 44 ++++++++++++------------ host/tests/sph_recv_test.cpp | 28 +++++++-------- host/tests/sph_send_test.cpp | 8 ++--- 16 files changed, 110 insertions(+), 123 deletions(-) (limited to 'host') diff --git a/host/include/uhd/convert.hpp b/host/include/uhd/convert.hpp index a0b502ab0..c42edfdec 100644 --- a/host/include/uhd/convert.hpp +++ b/host/include/uhd/convert.hpp @@ -42,17 +42,17 @@ namespace uhd{ namespace convert{ enum priority_type{ PRIORITY_GENERAL = 0, PRIORITY_LIBORC = 1, - PRIORITY_CUSTOM = 2, + PRIORITY_SIMD = 2, + PRIORITY_CUSTOM = 3, PRIORITY_EMPTY = -1, }; //! Identify a conversion routine in the registry struct id_type : boost::equality_comparable{ - std::string input_markup; + std::string input_format; size_t num_inputs; - std::string output_markup; + std::string output_format; size_t num_outputs; - std::string args; std::string to_pp_string(void) const; }; @@ -80,15 +80,15 @@ namespace uhd{ namespace convert{ /*! * Register the size of a particular item. - * \param markup the item markup + * \param format the item format * \param size the size in bytes */ UHD_API void register_bytes_per_item( - const std::string &markup, const size_t size + const std::string &format, const size_t size ); - //! Convert an item markup to a size in bytes - UHD_API size_t get_bytes_per_item(const std::string &markup); + //! Convert an item format to a size in bytes + UHD_API size_t get_bytes_per_item(const std::string &format); }} //namespace diff --git a/host/lib/convert/convert_common.hpp b/host/lib/convert/convert_common.hpp index 56b718292..34fb848c3 100644 --- a/host/lib/convert/convert_common.hpp +++ b/host/lib/convert/convert_common.hpp @@ -23,30 +23,28 @@ #include #include -#define _DECLARE_CONVERTER(fcn, in_mark, num_in, out_mark, num_out, prio) \ +#define _DECLARE_CONVERTER(fcn, in_form, num_in, out_form, num_out, prio) \ static void fcn( \ const uhd::convert::input_type &inputs, \ const uhd::convert::output_type &outputs, \ - const size_t nsamps, \ - const double scale_factor \ + const size_t nsamps, const double scale_factor \ ); \ UHD_STATIC_BLOCK(__register_##fcn##_##prio){ \ uhd::convert::id_type id; \ - id.input_markup = #in_mark; \ + id.input_format = #in_form; \ id.num_inputs = num_in; \ - id.output_markup = #out_mark; \ + id.output_format = #out_form; \ id.num_outputs = num_out; \ uhd::convert::register_converter(id, fcn, prio); \ } \ static void fcn( \ const uhd::convert::input_type &inputs, \ const uhd::convert::output_type &outputs, \ - const size_t nsamps, \ - const double scale_factor \ + const size_t nsamps, const double scale_factor \ ) -#define DECLARE_CONVERTER(in_mark, num_in, out_mark, num_out, prio) \ - _DECLARE_CONVERTER(__convert_##in_mark##_##num_in##_##out_mark##_##num_out, in_mark, num_in, out_mark, num_out, prio) +#define DECLARE_CONVERTER(in_form, num_in, out_form, num_out, prio) \ + _DECLARE_CONVERTER(__convert_##in_form##_##num_in##_##out_form##_##num_out, in_form, num_in, out_form, num_out, prio) /*********************************************************************** * Typedefs diff --git a/host/lib/convert/convert_fc32_with_sse2.cpp b/host/lib/convert/convert_fc32_with_sse2.cpp index b8d1aa8cc..24a939d6c 100644 --- a/host/lib/convert/convert_fc32_with_sse2.cpp +++ b/host/lib/convert/convert_fc32_with_sse2.cpp @@ -21,7 +21,7 @@ using namespace uhd::convert; -DECLARE_CONVERTER(fc32, 1, sc16_item32_le, 1, PRIORITY_CUSTOM){ +DECLARE_CONVERTER(fc32, 1, sc16_item32_le, 1, PRIORITY_SIMD){ const fc32_t *input = reinterpret_cast(inputs[0]); item32_t *output = reinterpret_cast(outputs[0]); @@ -64,7 +64,7 @@ DECLARE_CONVERTER(fc32, 1, sc16_item32_le, 1, PRIORITY_CUSTOM){ } } -DECLARE_CONVERTER(fc32, 1, sc16_item32_be, 1, PRIORITY_CUSTOM){ +DECLARE_CONVERTER(fc32, 1, sc16_item32_be, 1, PRIORITY_SIMD){ const fc32_t *input = reinterpret_cast(inputs[0]); item32_t *output = reinterpret_cast(outputs[0]); @@ -106,7 +106,7 @@ DECLARE_CONVERTER(fc32, 1, sc16_item32_be, 1, PRIORITY_CUSTOM){ } } -DECLARE_CONVERTER(sc16_item32_le, 1, fc32, 1, PRIORITY_CUSTOM){ +DECLARE_CONVERTER(sc16_item32_le, 1, fc32, 1, PRIORITY_SIMD){ const item32_t *input = reinterpret_cast(inputs[0]); fc32_t *output = reinterpret_cast(outputs[0]); @@ -151,7 +151,7 @@ DECLARE_CONVERTER(sc16_item32_le, 1, fc32, 1, PRIORITY_CUSTOM){ } } -DECLARE_CONVERTER(sc16_item32_be, 1, fc32, 1, PRIORITY_CUSTOM){ +DECLARE_CONVERTER(sc16_item32_be, 1, fc32, 1, PRIORITY_SIMD){ const item32_t *input = reinterpret_cast(inputs[0]); fc32_t *output = reinterpret_cast(outputs[0]); diff --git a/host/lib/convert/convert_fc64_with_sse2.cpp b/host/lib/convert/convert_fc64_with_sse2.cpp index a4f2df2e7..837bb584e 100644 --- a/host/lib/convert/convert_fc64_with_sse2.cpp +++ b/host/lib/convert/convert_fc64_with_sse2.cpp @@ -21,7 +21,7 @@ using namespace uhd::convert; -DECLARE_CONVERTER(fc64, 1, sc16_item32_le, 1, PRIORITY_CUSTOM){ +DECLARE_CONVERTER(fc64, 1, sc16_item32_le, 1, PRIORITY_SIMD){ const fc64_t *input = reinterpret_cast(inputs[0]); item32_t *output = reinterpret_cast(outputs[0]); @@ -68,7 +68,7 @@ DECLARE_CONVERTER(fc64, 1, sc16_item32_le, 1, PRIORITY_CUSTOM){ } } -DECLARE_CONVERTER(fc64, 1, sc16_item32_be, 1, PRIORITY_CUSTOM){ +DECLARE_CONVERTER(fc64, 1, sc16_item32_be, 1, PRIORITY_SIMD){ const fc64_t *input = reinterpret_cast(inputs[0]); item32_t *output = reinterpret_cast(outputs[0]); @@ -114,7 +114,7 @@ DECLARE_CONVERTER(fc64, 1, sc16_item32_be, 1, PRIORITY_CUSTOM){ } } -DECLARE_CONVERTER(sc16_item32_le, 1, fc64, 1, PRIORITY_CUSTOM){ +DECLARE_CONVERTER(sc16_item32_le, 1, fc64, 1, PRIORITY_SIMD){ const item32_t *input = reinterpret_cast(inputs[0]); fc64_t *output = reinterpret_cast(outputs[0]); @@ -163,7 +163,7 @@ DECLARE_CONVERTER(sc16_item32_le, 1, fc64, 1, PRIORITY_CUSTOM){ } } -DECLARE_CONVERTER(sc16_item32_be, 1, fc64, 1, PRIORITY_CUSTOM){ +DECLARE_CONVERTER(sc16_item32_be, 1, fc64, 1, PRIORITY_SIMD){ const item32_t *input = reinterpret_cast(inputs[0]); fc64_t *output = reinterpret_cast(outputs[0]); diff --git a/host/lib/convert/convert_impl.cpp b/host/lib/convert/convert_impl.cpp index 280957c2a..df03b44f9 100644 --- a/host/lib/convert/convert_impl.cpp +++ b/host/lib/convert/convert_impl.cpp @@ -27,29 +27,26 @@ using namespace uhd; bool convert::operator==(const convert::id_type &lhs, const convert::id_type &rhs){ - return - (lhs.input_markup == rhs.input_markup) and - (lhs.num_inputs == rhs.num_inputs) and - (lhs.output_markup == rhs.output_markup) and - (lhs.num_outputs == rhs.num_outputs) and - (lhs.args == rhs.args) + return true + and (lhs.input_format == rhs.input_format) + and (lhs.num_inputs == rhs.num_inputs) + and (lhs.output_format == rhs.output_format) + and (lhs.num_outputs == rhs.num_outputs) ; } std::string convert::id_type::to_pp_string(void) const{ return str(boost::format( "conversion ID\n" - " Input markup: %s\n" + " Input format: %s\n" " Num inputs: %d\n" - " Output markup: %s\n" + " Output format: %s\n" " Num outputs: %d\n" - " Optional args: %s\n" ) - % this->input_markup + % this->input_format % this->num_inputs - % this->output_markup + % this->output_format % this->num_outputs - % this->args ); } @@ -101,30 +98,30 @@ convert::function_type convert::get_converter(const id_type &id){ } /*********************************************************************** - * Mappings for item markup to byte size for all items we can + * Mappings for item format to byte size for all items we can **********************************************************************/ typedef uhd::dict item_size_type; UHD_SINGLETON_FCN(item_size_type, get_item_size_table); void register_bytes_per_item( - const std::string &markup, const size_t size + const std::string &format, const size_t size ){ - get_item_size_table()[markup] = size; + get_item_size_table()[format] = size; } -size_t convert::get_bytes_per_item(const std::string &markup){ - if (get_item_size_table().has_key(markup)) return get_item_size_table()[markup]; +size_t convert::get_bytes_per_item(const std::string &format){ + if (get_item_size_table().has_key(format)) return get_item_size_table()[format]; //OK. I am sorry about this. //We didnt find a match, so lets find a match for the first term. //This is partially a hack because of the way I append strings. //But as long as life is kind, we can keep this. - const size_t pos = markup.find("_"); + const size_t pos = format.find("_"); if (pos != std::string::npos){ - return get_bytes_per_item(markup.substr(0, pos)); + return get_bytes_per_item(format.substr(0, pos)); } - throw uhd::key_error("Cannot find an item size:\n" + markup); + throw uhd::key_error("Cannot find an item size:\n" + format); } UHD_STATIC_BLOCK(convert_register_item_sizes){ diff --git a/host/lib/convert/convert_with_neon.cpp b/host/lib/convert/convert_with_neon.cpp index e5f08cad9..c7ad62104 100644 --- a/host/lib/convert/convert_with_neon.cpp +++ b/host/lib/convert/convert_with_neon.cpp @@ -20,7 +20,7 @@ using namespace uhd::convert; -DECLARE_CONVERTER(convert_fc32_1_to_item32_1_nswap, PRIORITY_CUSTOM){ +DECLARE_CONVERTER(fc32, 1, sc16_item32_le, 1, PRIORITY_SIMD){ const fc32_t *input = reinterpret_cast(inputs[0]); item32_t *output = reinterpret_cast(outputs[0]); @@ -37,10 +37,10 @@ DECLARE_CONVERTER(convert_fc32_1_to_item32_1_nswap, PRIORITY_CUSTOM){ } for (; i < nsamps; i++) - output[i] = fc32_to_item32(input[i], float(scale_factor)); + output[i] = fc32_to_item32_sc16(input[i], scale_factor); } -DECLARE_CONVERTER(convert_item32_1_to_fc32_1_nswap, PRIORITY_CUSTOM){ +DECLARE_CONVERTER(sc16_item32_le, 1, fc32, 1, PRIORITY_SIMD){ const item32_t *input = reinterpret_cast(inputs[0]); fc32_t *output = reinterpret_cast(outputs[0]); @@ -57,5 +57,5 @@ DECLARE_CONVERTER(convert_item32_1_to_fc32_1_nswap, PRIORITY_CUSTOM){ } for (; i < nsamps; i++) - output[i] = item32_to_fc32(input[i], float(scale_factor)); + output[i] = item32_sc16_to_fc32(input[i], scale_factor); } diff --git a/host/lib/convert/convert_with_orc.cpp b/host/lib/convert/convert_with_orc.cpp index 844c2595c..0c46bcf1e 100644 --- a/host/lib/convert/convert_with_orc.cpp +++ b/host/lib/convert/convert_with_orc.cpp @@ -29,26 +29,26 @@ extern void _convert_sc16_1_to_item32_1_nswap_orc(void *, const void *, float, i extern void _convert_item32_1_to_sc16_1_nswap_orc(void *, const void *, float, int); } -DECLARE_CONVERTER(convert_fc32_1_to_item32_1_nswap, PRIORITY_LIBORC){ +DECLARE_CONVERTER(fc32, 1, sc16_item32_le, 1, PRIORITY_LIBORC){ _convert_fc32_1_to_item32_1_nswap_orc(outputs[0], inputs[0], scale_factor, nsamps); } -DECLARE_CONVERTER(convert_fc32_1_to_item32_1_bswap, PRIORITY_LIBORC){ +DECLARE_CONVERTER(fc32, 1, sc16_item32_be, 1, PRIORITY_LIBORC){ _convert_fc32_1_to_item32_1_bswap_orc(outputs[0], inputs[0], scale_factor, nsamps); } -DECLARE_CONVERTER(convert_item32_1_to_fc32_1_nswap, PRIORITY_LIBORC){ +DECLARE_CONVERTER(sc16_item32_le, 1, fc32, 1, PRIORITY_LIBORC){ _convert_item32_1_to_fc32_1_nswap_orc(outputs[0], inputs[0], scale_factor, nsamps); } -DECLARE_CONVERTER(convert_item32_1_to_fc32_1_bswap, PRIORITY_LIBORC){ +DECLARE_CONVERTER(sc16_item32_be, 1, fc32, 1, PRIORITY_LIBORC){ _convert_item32_1_to_fc32_1_bswap_orc(outputs[0], inputs[0], scale_factor, nsamps); } -DECLARE_CONVERTER(convert_sc16_1_to_item32_1_nswap, PRIORITY_LIBORC){ +DECLARE_CONVERTER(sc16, 1, sc16_item32_le, 1, PRIORITY_LIBORC){ _convert_sc16_1_to_item32_1_nswap_orc(outputs[0], inputs[0], scale_factor, nsamps); } -DECLARE_CONVERTER(convert_item32_1_to_sc16_1_nswap, PRIORITY_LIBORC){ +DECLARE_CONVERTER(sc16_item32_le, 1, sc16, 1, PRIORITY_LIBORC){ _convert_item32_1_to_sc16_1_nswap_orc(outputs[0], inputs[0], scale_factor, nsamps); } diff --git a/host/lib/transport/super_recv_packet_handler.hpp b/host/lib/transport/super_recv_packet_handler.hpp index 6762a8a00..2310d6aea 100644 --- a/host/lib/transport/super_recv_packet_handler.hpp +++ b/host/lib/transport/super_recv_packet_handler.hpp @@ -125,8 +125,8 @@ public: void set_converter(const uhd::convert::id_type &id){ _io_buffs.resize(id.num_outputs); _converter = uhd::convert::get_converter(id); - _bytes_per_otw_item = uhd::convert::get_bytes_per_item(id.input_markup); - _bytes_per_cpu_item = uhd::convert::get_bytes_per_item(id.output_markup); + _bytes_per_otw_item = uhd::convert::get_bytes_per_item(id.input_format); + _bytes_per_cpu_item = uhd::convert::get_bytes_per_item(id.output_format); } //! Set the transport channel's overflow handler diff --git a/host/lib/transport/super_send_packet_handler.hpp b/host/lib/transport/super_send_packet_handler.hpp index 5b5ee2981..779259d4f 100644 --- a/host/lib/transport/super_send_packet_handler.hpp +++ b/host/lib/transport/super_send_packet_handler.hpp @@ -101,8 +101,8 @@ public: void set_converter(const uhd::convert::id_type &id){ _io_buffs.resize(id.num_inputs); _converter = uhd::convert::get_converter(id); - _bytes_per_otw_item = uhd::convert::get_bytes_per_item(id.output_markup); - _bytes_per_cpu_item = uhd::convert::get_bytes_per_item(id.input_markup); + _bytes_per_otw_item = uhd::convert::get_bytes_per_item(id.output_format); + _bytes_per_cpu_item = uhd::convert::get_bytes_per_item(id.input_format); } /*! diff --git a/host/lib/usrp/b100/io_impl.cpp b/host/lib/usrp/b100/io_impl.cpp index 82298dca6..28b19f14e 100644 --- a/host/lib/usrp/b100/io_impl.cpp +++ b/host/lib/usrp/b100/io_impl.cpp @@ -218,11 +218,10 @@ rx_streamer::sptr b100_impl::get_rx_stream(const uhd::stream_args_t &args_){ //set the converter uhd::convert::id_type id; - id.input_markup = args.otw_format + "_item32_le"; + id.input_format = args.otw_format + "_item32_le"; id.num_inputs = 1; - id.output_markup = args.cpu_format; + id.output_format = args.cpu_format; id.num_outputs = 1; - id.args = args.args; my_streamer->set_converter(id); //bind callbacks for the handler @@ -276,11 +275,10 @@ tx_streamer::sptr b100_impl::get_tx_stream(const uhd::stream_args_t &args_){ //set the converter uhd::convert::id_type id; - id.input_markup = args.cpu_format; + id.input_format = args.cpu_format; id.num_inputs = 1; - id.output_markup = args.otw_format + "_item32_le"; + id.output_format = args.otw_format + "_item32_le"; id.num_outputs = 1; - id.args = args.args; my_streamer->set_converter(id); //bind callbacks for the handler diff --git a/host/lib/usrp/e100/io_impl.cpp b/host/lib/usrp/e100/io_impl.cpp index 5936ee2d7..c47eb8940 100644 --- a/host/lib/usrp/e100/io_impl.cpp +++ b/host/lib/usrp/e100/io_impl.cpp @@ -294,11 +294,10 @@ rx_streamer::sptr e100_impl::get_rx_stream(const uhd::stream_args_t &args_){ //set the converter uhd::convert::id_type id; - id.input_markup = args.otw_format + "_item32_le"; + id.input_format = args.otw_format + "_item32_le"; id.num_inputs = 1; - id.output_markup = args.cpu_format; + id.output_format = args.cpu_format; id.num_outputs = 1; - id.args = args.args; my_streamer->set_converter(id); //bind callbacks for the handler @@ -352,11 +351,10 @@ tx_streamer::sptr e100_impl::get_tx_stream(const uhd::stream_args_t &args_){ //set the converter uhd::convert::id_type id; - id.input_markup = args.cpu_format; + id.input_format = args.cpu_format; id.num_inputs = 1; - id.output_markup = args.otw_format + "_item32_le"; + id.output_format = args.otw_format + "_item32_le"; id.num_outputs = 1; - id.args = args.args; my_streamer->set_converter(id); //bind callbacks for the handler diff --git a/host/lib/usrp/usrp1/io_impl.cpp b/host/lib/usrp/usrp1/io_impl.cpp index f46f4741b..534d33959 100644 --- a/host/lib/usrp/usrp1/io_impl.cpp +++ b/host/lib/usrp/usrp1/io_impl.cpp @@ -600,11 +600,10 @@ rx_streamer::sptr usrp1_impl::get_rx_stream(const uhd::stream_args_t &args_){ //set the converter uhd::convert::id_type id; - id.input_markup = args.otw_format + "_item16_usrp1"; + id.input_format = args.otw_format + "_item16_usrp1"; id.num_inputs = 1; - id.output_markup = args.cpu_format; + id.output_format = args.cpu_format; id.num_outputs = args.channels.size(); - id.args = args.args; my_streamer->set_converter(id); //save as weak ptr for update access @@ -653,11 +652,10 @@ tx_streamer::sptr usrp1_impl::get_tx_stream(const uhd::stream_args_t &args_){ //set the converter uhd::convert::id_type id; - id.input_markup = args.cpu_format; + id.input_format = args.cpu_format; id.num_inputs = args.channels.size(); - id.output_markup = args.otw_format + "_item16_usrp1"; + id.output_format = args.otw_format + "_item16_usrp1"; id.num_outputs = 1; - id.args = args.args; my_streamer->set_converter(id); //save as weak ptr for update access diff --git a/host/lib/usrp/usrp2/io_impl.cpp b/host/lib/usrp/usrp2/io_impl.cpp index f1d0aee2a..660156285 100644 --- a/host/lib/usrp/usrp2/io_impl.cpp +++ b/host/lib/usrp/usrp2/io_impl.cpp @@ -391,11 +391,10 @@ rx_streamer::sptr usrp2_impl::get_rx_stream(const uhd::stream_args_t &args_){ //set the converter uhd::convert::id_type id; - id.input_markup = args.otw_format + "_item32_be"; + id.input_format = args.otw_format + "_item32_be"; id.num_inputs = 1; - id.output_markup = args.cpu_format; + id.output_format = args.cpu_format; id.num_outputs = 1; - id.args = args.args; my_streamer->set_converter(id); //bind callbacks for the handler @@ -459,11 +458,10 @@ tx_streamer::sptr usrp2_impl::get_tx_stream(const uhd::stream_args_t &args_){ //set the converter uhd::convert::id_type id; - id.input_markup = args.cpu_format; + id.input_format = args.cpu_format; id.num_inputs = 1; - id.output_markup = args.otw_format + "_item32_be"; + id.output_format = args.otw_format + "_item32_be"; id.num_outputs = 1; - id.args = args.args; my_streamer->set_converter(id); //bind callbacks for the handler diff --git a/host/tests/convert_test.cpp b/host/tests/convert_test.cpp index 9dabcf54e..b63ff6752 100644 --- a/host/tests/convert_test.cpp +++ b/host/tests/convert_test.cpp @@ -75,7 +75,7 @@ static void test_convert_types_sc16( //run the loopback and test convert::id_type in_id = id; convert::id_type out_id = id; - std::swap(out_id.input_markup, out_id.output_markup); + std::swap(out_id.input_format, out_id.output_format); std::swap(out_id.num_inputs, out_id.num_outputs); loopback(nsamps, in_id, out_id, input, output); BOOST_CHECK_EQUAL_COLLECTIONS(input.begin(), input.end(), output.begin(), output.end()); @@ -83,9 +83,9 @@ static void test_convert_types_sc16( BOOST_AUTO_TEST_CASE(test_convert_types_be_sc16){ convert::id_type id; - id.input_markup = "sc16"; + id.input_format = "sc16"; id.num_inputs = 1; - id.output_markup = "sc16_item32_be"; + id.output_format = "sc16_item32_be"; id.num_outputs = 1; //try various lengths to test edge cases @@ -96,9 +96,9 @@ BOOST_AUTO_TEST_CASE(test_convert_types_be_sc16){ BOOST_AUTO_TEST_CASE(test_convert_types_le_sc16){ convert::id_type id; - id.input_markup = "sc16"; + id.input_format = "sc16"; id.num_inputs = 1; - id.output_markup = "sc16_item32_le"; + id.output_format = "sc16_item32_le"; id.num_outputs = 1; //try various lengths to test edge cases @@ -126,7 +126,7 @@ static void test_convert_types_for_floats( //run the loopback and test convert::id_type in_id = id; convert::id_type out_id = id; - std::swap(out_id.input_markup, out_id.output_markup); + std::swap(out_id.input_format, out_id.output_format); std::swap(out_id.num_inputs, out_id.num_outputs); loopback(nsamps, in_id, out_id, input, output); for (size_t i = 0; i < nsamps; i++){ @@ -137,9 +137,9 @@ static void test_convert_types_for_floats( BOOST_AUTO_TEST_CASE(test_convert_types_be_fc32){ convert::id_type id; - id.input_markup = "fc32"; + id.input_format = "fc32"; id.num_inputs = 1; - id.output_markup = "sc16_item32_be"; + id.output_format = "sc16_item32_be"; id.num_outputs = 1; //try various lengths to test edge cases @@ -150,9 +150,9 @@ BOOST_AUTO_TEST_CASE(test_convert_types_be_fc32){ BOOST_AUTO_TEST_CASE(test_convert_types_le_fc32){ convert::id_type id; - id.input_markup = "fc32"; + id.input_format = "fc32"; id.num_inputs = 1; - id.output_markup = "sc16_item32_le"; + id.output_format = "sc16_item32_le"; id.num_outputs = 1; //try various lengths to test edge cases @@ -163,9 +163,9 @@ BOOST_AUTO_TEST_CASE(test_convert_types_le_fc32){ BOOST_AUTO_TEST_CASE(test_convert_types_be_fc64){ convert::id_type id; - id.input_markup = "fc64"; + id.input_format = "fc64"; id.num_inputs = 1; - id.output_markup = "sc16_item32_be"; + id.output_format = "sc16_item32_be"; id.num_outputs = 1; //try various lengths to test edge cases @@ -176,9 +176,9 @@ BOOST_AUTO_TEST_CASE(test_convert_types_be_fc64){ BOOST_AUTO_TEST_CASE(test_convert_types_le_fc64){ convert::id_type id; - id.input_markup = "fc64"; + id.input_format = "fc64"; id.num_inputs = 1; - id.output_markup = "sc16_item32_le"; + id.output_format = "sc16_item32_le"; id.num_outputs = 1; //try various lengths to test edge cases @@ -192,15 +192,15 @@ BOOST_AUTO_TEST_CASE(test_convert_types_le_fc64){ **********************************************************************/ BOOST_AUTO_TEST_CASE(test_convert_types_fc32_to_sc16){ convert::id_type in_id; - in_id.input_markup = "fc32"; + in_id.input_format = "fc32"; in_id.num_inputs = 1; - in_id.output_markup = "sc16_item32_le"; + in_id.output_format = "sc16_item32_le"; in_id.num_outputs = 1; convert::id_type out_id; - out_id.input_markup = "sc16_item32_le"; + out_id.input_format = "sc16_item32_le"; out_id.num_inputs = 1; - out_id.output_markup = "sc16"; + out_id.output_format = "sc16"; out_id.num_outputs = 1; const size_t nsamps = 13; @@ -233,15 +233,15 @@ BOOST_AUTO_TEST_CASE(test_convert_types_fc32_to_sc16){ **********************************************************************/ BOOST_AUTO_TEST_CASE(test_convert_types_sc16_to_fc32){ convert::id_type in_id; - in_id.input_markup = "sc16"; + in_id.input_format = "sc16"; in_id.num_inputs = 1; - in_id.output_markup = "sc16_item32_le"; + in_id.output_format = "sc16_item32_le"; in_id.num_outputs = 1; convert::id_type out_id; - out_id.input_markup = "sc16_item32_le"; + out_id.input_format = "sc16_item32_le"; out_id.num_inputs = 1; - out_id.output_markup = "fc32"; + out_id.output_format = "fc32"; out_id.num_outputs = 1; const size_t nsamps = 13; diff --git a/host/tests/sph_recv_test.cpp b/host/tests/sph_recv_test.cpp index 6fab2ad5f..85d06aa0d 100644 --- a/host/tests/sph_recv_test.cpp +++ b/host/tests/sph_recv_test.cpp @@ -107,9 +107,9 @@ private: BOOST_AUTO_TEST_CASE(test_sph_recv_one_channel_normal){ //////////////////////////////////////////////////////////////////////// uhd::convert::id_type id; - id.input_markup = "sc16_item32_be"; + id.input_format = "sc16_item32_be"; id.num_inputs = 1; - id.output_markup = "fc32"; + id.output_format = "fc32"; id.num_outputs = 1; dummy_recv_xport_class dummy_recv_xport("big"); @@ -178,9 +178,9 @@ BOOST_AUTO_TEST_CASE(test_sph_recv_one_channel_normal){ BOOST_AUTO_TEST_CASE(test_sph_recv_one_channel_sequence_error){ //////////////////////////////////////////////////////////////////////// uhd::convert::id_type id; - id.input_markup = "sc16_item32_be"; + id.input_format = "sc16_item32_be"; id.num_inputs = 1; - id.output_markup = "fc32"; + id.output_format = "fc32"; id.num_outputs = 1; dummy_recv_xport_class dummy_recv_xport("big"); @@ -259,9 +259,9 @@ BOOST_AUTO_TEST_CASE(test_sph_recv_one_channel_sequence_error){ BOOST_AUTO_TEST_CASE(test_sph_recv_one_channel_inline_message){ //////////////////////////////////////////////////////////////////////// uhd::convert::id_type id; - id.input_markup = "sc16_item32_be"; + id.input_format = "sc16_item32_be"; id.num_inputs = 1; - id.output_markup = "fc32"; + id.output_format = "fc32"; id.num_outputs = 1; dummy_recv_xport_class dummy_recv_xport("big"); @@ -351,9 +351,9 @@ BOOST_AUTO_TEST_CASE(test_sph_recv_one_channel_inline_message){ BOOST_AUTO_TEST_CASE(test_sph_recv_multi_channel_normal){ //////////////////////////////////////////////////////////////////////// uhd::convert::id_type id; - id.input_markup = "sc16_item32_be"; + id.input_format = "sc16_item32_be"; id.num_inputs = 1; - id.output_markup = "fc32"; + id.output_format = "fc32"; id.num_outputs = 1; uhd::transport::vrt::if_packet_info_t ifpi; @@ -434,9 +434,9 @@ BOOST_AUTO_TEST_CASE(test_sph_recv_multi_channel_normal){ BOOST_AUTO_TEST_CASE(test_sph_recv_multi_channel_sequence_error){ //////////////////////////////////////////////////////////////////////// uhd::convert::id_type id; - id.input_markup = "sc16_item32_be"; + id.input_format = "sc16_item32_be"; id.num_inputs = 1; - id.output_markup = "fc32"; + id.output_format = "fc32"; id.num_outputs = 1; uhd::transport::vrt::if_packet_info_t ifpi; @@ -527,9 +527,9 @@ BOOST_AUTO_TEST_CASE(test_sph_recv_multi_channel_sequence_error){ BOOST_AUTO_TEST_CASE(test_sph_recv_multi_channel_time_error){ //////////////////////////////////////////////////////////////////////// uhd::convert::id_type id; - id.input_markup = "sc16_item32_be"; + id.input_format = "sc16_item32_be"; id.num_inputs = 1; - id.output_markup = "fc32"; + id.output_format = "fc32"; id.num_outputs = 1; uhd::transport::vrt::if_packet_info_t ifpi; @@ -615,9 +615,9 @@ BOOST_AUTO_TEST_CASE(test_sph_recv_multi_channel_time_error){ BOOST_AUTO_TEST_CASE(test_sph_recv_multi_channel_fragment){ //////////////////////////////////////////////////////////////////////// uhd::convert::id_type id; - id.input_markup = "sc16_item32_be"; + id.input_format = "sc16_item32_be"; id.num_inputs = 1; - id.output_markup = "fc32"; + id.output_format = "fc32"; id.num_outputs = 1; uhd::transport::vrt::if_packet_info_t ifpi; diff --git a/host/tests/sph_send_test.cpp b/host/tests/sph_send_test.cpp index 9a91008af..25a3f97ee 100644 --- a/host/tests/sph_send_test.cpp +++ b/host/tests/sph_send_test.cpp @@ -92,9 +92,9 @@ private: BOOST_AUTO_TEST_CASE(test_sph_send_one_channel_one_packet_mode){ //////////////////////////////////////////////////////////////////////// uhd::convert::id_type id; - id.input_markup = "fc32"; + id.input_format = "fc32"; id.num_inputs = 1; - id.output_markup = "sc16_item32_be"; + id.output_format = "sc16_item32_be"; id.num_outputs = 1; dummy_send_xport_class dummy_send_xport("big"); @@ -150,9 +150,9 @@ BOOST_AUTO_TEST_CASE(test_sph_send_one_channel_one_packet_mode){ BOOST_AUTO_TEST_CASE(test_sph_send_one_channel_full_buffer_mode){ //////////////////////////////////////////////////////////////////////// uhd::convert::id_type id; - id.input_markup = "fc32"; + id.input_format = "fc32"; id.num_inputs = 1; - id.output_markup = "sc16_item32_be"; + id.output_format = "sc16_item32_be"; id.num_outputs = 1; dummy_send_xport_class dummy_send_xport("big"); -- cgit v1.2.3 From 9369259177e5517e2b0e775804224c5467e14eab Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Wed, 12 Oct 2011 09:59:41 -0700 Subject: usrp: deprecated clock config, added time/clock source calls --- host/include/uhd/deprecated.hpp | 1 + host/include/uhd/types/clock_config.hpp | 5 ++- host/include/uhd/usrp/multi_usrp.hpp | 53 +++++++++++++++++++++++- host/lib/deprecated.cpp | 28 +++++++++++++ host/lib/types/CMakeLists.txt | 1 - host/lib/types/clock_config.cpp | 44 -------------------- host/lib/usrp/multi_usrp.cpp | 72 +++++++++++++++++++++++---------- 7 files changed, 136 insertions(+), 68 deletions(-) delete mode 100644 host/lib/types/clock_config.cpp (limited to 'host') diff --git a/host/include/uhd/deprecated.hpp b/host/include/uhd/deprecated.hpp index e4112fa66..d918836f1 100644 --- a/host/include/uhd/deprecated.hpp +++ b/host/include/uhd/deprecated.hpp @@ -243,3 +243,4 @@ namespace uhd{ #endif /* INCLUDED_UHD_TYPES_OTW_TYPE_HPP */ #include //wish it was in here +#include //wish it was in here diff --git a/host/include/uhd/types/clock_config.hpp b/host/include/uhd/types/clock_config.hpp index 24bd96d14..27b312245 100644 --- a/host/include/uhd/types/clock_config.hpp +++ b/host/include/uhd/types/clock_config.hpp @@ -23,10 +23,13 @@ namespace uhd{ /*! - * Clock configuration settings: + * The DEPRECATED Clock configuration settings: * The source for the 10MHz reference clock. * The source and polarity for the PPS clock. * + * Deprecated in favor of set time/clock source calls. + * Its still in this file for the sake of gr-uhd swig. + * * Use the convenience functions external() and internal(), * unless you have a special purpose and cannot use them. */ diff --git a/host/include/uhd/usrp/multi_usrp.hpp b/host/include/uhd/usrp/multi_usrp.hpp index 72386204f..ee7bf8424 100644 --- a/host/include/uhd/usrp/multi_usrp.hpp +++ b/host/include/uhd/usrp/multi_usrp.hpp @@ -18,11 +18,13 @@ #ifndef INCLUDED_UHD_USRP_MULTI_USRP_HPP #define INCLUDED_UHD_USRP_MULTI_USRP_HPP +#define UHD_USRP_MULTI_USRP_REF_SOURCES_API + #include #include +#include #include #include -#include #include #include #include @@ -31,6 +33,7 @@ #include #include #include +#include #include namespace uhd{ namespace usrp{ @@ -235,6 +238,7 @@ public: /*! * Set the clock configuration for the usrp device. + * DEPRECATED in favor of set time and clock source calls. * This tells the usrp how to get a 10Mhz reference and PPS clock. * See the documentation for clock_config_t for more info. * \param clock_config the clock configuration to set @@ -242,6 +246,53 @@ public: */ virtual void set_clock_config(const clock_config_t &clock_config, size_t mboard = ALL_MBOARDS) = 0; + /*! + * Set the time source for the usrp device. + * This sets the method of time synchronization, + * typically a pulse per second or an encoded time. + * Typical options for source: external, MIMO. + * \param source a string representing the time source + * \param mboard which motherboard to set the config + */ + virtual void set_time_source(const std::string &source, const size_t mboard = ALL_MBOARDS) = 0; + + /*! + * Get the currently set time source. + * \param mboard which motherboard to get the config + * \return the string representing the time source + */ + virtual std::string get_time_source(const size_t mboard) = 0; + + /*! + * Get a list of possible time sources. + * \param mboard which motherboard to get the list + * \return a vector of strings for possible settings + */ + virtual std::vector get_time_sources(const size_t mboard) = 0; + + /*! + * Set the clock source for the usrp device. + * This sets the source for a 10 Mhz reference clock. + * Typical options for source: internal, external, MIMO. + * \param source a string representing the clock source + * \param mboard which motherboard to set the config + */ + virtual void set_clock_source(const std::string &source, const size_t mboard = ALL_MBOARDS) = 0; + + /*! + * Get the currently set clock source. + * \param mboard which motherboard to get the config + * \return the string representing the clock source + */ + virtual std::string get_clock_source(const size_t mboard) = 0; + + /*! + * Get a list of possible clock sources. + * \param mboard which motherboard to get the list + * \return a vector of strings for possible settings + */ + virtual std::vector get_clock_sources(const size_t mboard) = 0; + /*! * Get the number of USRP motherboards in this configuration. */ diff --git a/host/lib/deprecated.cpp b/host/lib/deprecated.cpp index dd4cc02ad..b659d1be5 100644 --- a/host/lib/deprecated.cpp +++ b/host/lib/deprecated.cpp @@ -203,3 +203,31 @@ io_type_t::io_type_t(size_t size): { /* NOP */ } + +#include + +using namespace uhd; + +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_SMA; + 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_SMA), + pps_polarity(PPS_POS) +{ + /* NOP */ +} diff --git a/host/lib/types/CMakeLists.txt b/host/lib/types/CMakeLists.txt index 957dfd345..2ca0faef7 100644 --- a/host/lib/types/CMakeLists.txt +++ b/host/lib/types/CMakeLists.txt @@ -80,7 +80,6 @@ SET_SOURCE_FILES_PROPERTIES( # This file included, use CMake directory variables ######################################################################## LIBUHD_APPEND_SOURCES( - ${CMAKE_CURRENT_SOURCE_DIR}/clock_config.cpp ${CMAKE_CURRENT_SOURCE_DIR}/device_addr.cpp ${CMAKE_CURRENT_SOURCE_DIR}/mac_addr.cpp ${CMAKE_CURRENT_SOURCE_DIR}/ranges.cpp diff --git a/host/lib/types/clock_config.cpp b/host/lib/types/clock_config.cpp deleted file mode 100644 index c150c5cc3..000000000 --- a/host/lib/types/clock_config.cpp +++ /dev/null @@ -1,44 +0,0 @@ -// -// 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 . -// - -#include - -using namespace uhd; - -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_SMA; - 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_SMA), - pps_polarity(PPS_POS) -{ - /* NOP */ -} diff --git a/host/lib/usrp/multi_usrp.cpp b/host/lib/usrp/multi_usrp.cpp index 73699dc81..ab841487f 100644 --- a/host/lib/usrp/multi_usrp.cpp +++ b/host/lib/usrp/multi_usrp.cpp @@ -359,34 +359,64 @@ public: } void set_clock_config(const clock_config_t &clock_config, size_t mboard){ + //set the reference source... + std::string clock_source; + switch(clock_config.ref_source){ + case clock_config_t::REF_INT: clock_source = "internal"; break; + case clock_config_t::PPS_SMA: clock_source = "external"; break; + case clock_config_t::PPS_MIMO: clock_source = "mimo"; break; + default: clock_source = "unknown"; + } + this->set_clock_source(clock_source, mboard); + + //set the time source + std::string time_source; + switch(clock_config.pps_source){ + case clock_config_t::PPS_INT: time_source = "internal"; break; + case clock_config_t::PPS_SMA: time_source = "external"; break; + case clock_config_t::PPS_MIMO: time_source = "mimo"; break; + default: time_source = "unknown"; + } + if (time_source == "external" and clock_config.pps_polarity == clock_config_t::PPS_NEG) time_source = "_external_"; + this->set_time_source(time_source, mboard); + } + + void set_time_source(const std::string &source, const size_t mboard){ if (mboard != ALL_MBOARDS){ - //set the reference source... - std::string clock_source; - switch(clock_config.ref_source){ - case clock_config_t::REF_INT: clock_source = "internal"; break; - case clock_config_t::PPS_SMA: clock_source = "external"; break; - case clock_config_t::PPS_MIMO: clock_source = "mimo"; break; - default: clock_source = "unknown"; - } - _tree->access(mb_root(mboard) / "clock_source" / "value").set(clock_source); - - //set the time source - std::string time_source; - switch(clock_config.pps_source){ - case clock_config_t::PPS_INT: time_source = "internal"; break; - case clock_config_t::PPS_SMA: time_source = "external"; break; - case clock_config_t::PPS_MIMO: time_source = "mimo"; break; - default: time_source = "unknown"; - } - if (clock_source == "external" and clock_config.pps_polarity == clock_config_t::PPS_NEG) time_source = "_external_"; - _tree->access(mb_root(mboard) / "time_source" / "value").set(time_source); + _tree->access(mb_root(mboard) / "time_source" / "value").set(source); return; } for (size_t m = 0; m < get_num_mboards(); m++){ - set_clock_config(clock_config, m); + return this->set_time_source(source, m); } } + std::string get_time_source(const size_t mboard){ + return _tree->access(mb_root(mboard) / "time_source" / "value").get(); + } + + std::vector get_time_sources(const size_t mboard){ + return _tree->access >(mb_root(mboard) / "time_source" / "options").get(); + } + + void set_clock_source(const std::string &source, const size_t mboard){ + if (mboard != ALL_MBOARDS){ + _tree->access(mb_root(mboard) / "clock_source" / "value").set(source); + return; + } + for (size_t m = 0; m < get_num_mboards(); m++){ + return this->set_clock_source(source, m); + } + } + + std::string get_clock_source(const size_t mboard){ + return _tree->access(mb_root(mboard) / "clock_source" / "value").get(); + } + + std::vector get_clock_sources(const size_t mboard){ + return _tree->access >(mb_root(mboard) / "clock_source" / "options").get(); + } + size_t get_num_mboards(void){ return _tree->list("/mboards").size(); } -- cgit v1.2.3 From 522bc87d9f61668f3d22e067c39a98e5f33fc6c5 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Wed, 12 Oct 2011 20:05:57 -0700 Subject: uhd: fixed 8sc item32 converter on head/tail cases --- host/examples/rx_timed_samples.cpp | 2 +- host/lib/convert/gen_convert_general.py | 24 ++++++++++-------------- 2 files changed, 11 insertions(+), 15 deletions(-) (limited to 'host') diff --git a/host/examples/rx_timed_samples.cpp b/host/examples/rx_timed_samples.cpp index 0851593cd..143bceb03 100644 --- a/host/examples/rx_timed_samples.cpp +++ b/host/examples/rx_timed_samples.cpp @@ -98,7 +98,7 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){ while(num_acc_samps < total_num_samps){ //receive a single packet size_t num_rx_samps = rx_stream->recv( - &buff.front(), buff.size(), md, timeout + &buff.front(), buff.size(), md, timeout, true ); //use a small timeout for subsequent packets diff --git a/host/lib/convert/gen_convert_general.py b/host/lib/convert/gen_convert_general.py index 43e1f9967..9a1135b0b 100644 --- a/host/lib/convert/gen_convert_general.py +++ b/host/lib/convert/gen_convert_general.py @@ -51,27 +51,23 @@ DECLARE_CONVERTER(sc8_item32_$(end), 1, $(cpu_type), 1, PRIORITY_GENERAL){ const item32_t *input = reinterpret_cast(size_t(inputs[0]) & ~0x3); $(cpu_type)_t *output = reinterpret_cast<$(cpu_type)_t *>(outputs[0]); $(cpu_type)_t dummy; + size_t num_samps = nsamps; - const bool head_case = ((size_t(inputs[0]) & 0x3) != 0); - const bool tail_case = ((nsamps & 0x1) == 0)? head_case : not head_case; - const size_t num_pairs = (head_case? nsamps-1 : nsamps)/2; - size_t i = 0, j = 0; - - //special head case, probably from a partial recv - if (head_case){ - const item32_t item0 = $(to_host)(input[i++]); - item32_sc8_to_$(cpu_type)(item0, dummy, output[j++], scale_factor); + if ((size_t(inputs[0]) & 0x3) != 0){ + const item32_t item0 = $(to_host)(*input++); + item32_sc8_to_$(cpu_type)(item0, dummy, *output++, scale_factor); + num_samps--; } - for (; i < num_pairs; i++, j+=2){ + const size_t num_pairs = num_samps/2; + for (size_t i = 0, j = 0; i < num_pairs; i++, j+=2){ const item32_t item_i = $(to_host)(input[i]); item32_sc8_to_$(cpu_type)(item_i, output[j], output[j+1], scale_factor); } - //special tail case, finished on an odd number - if (tail_case){ - const item32_t item_i = $(to_host)(input[i]); - item32_sc8_to_$(cpu_type)(item_i, output[j], dummy, scale_factor); + if (num_samps != num_pairs*2){ + const item32_t item_n = $(to_host)(input[num_pairs]); + item32_sc8_to_$(cpu_type)(item_n, output[num_samps-1], dummy, scale_factor); } } """ -- cgit v1.2.3 From 00b6d8359de6ea616f7bd6573d7f87d635d78a79 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Thu, 13 Oct 2011 13:08:12 -0700 Subject: uhd: added trailer parsing for occupancy --- host/include/uhd/transport/vrt_if_packet.hpp | 1 + host/lib/convert/gen_convert_general.py | 1 + host/lib/transport/gen_vrt_if_packet.py | 51 ++++++++++++++++-------- host/lib/transport/super_recv_packet_handler.hpp | 11 ++--- host/lib/transport/super_send_packet_handler.hpp | 3 +- host/lib/usrp/cores/rx_dsp_core_200.cpp | 3 +- host/lib/usrp/cores/tx_dsp_core_200.cpp | 3 +- host/lib/usrp/usrp1/io_impl.cpp | 1 + 8 files changed, 46 insertions(+), 28 deletions(-) (limited to 'host') diff --git a/host/include/uhd/transport/vrt_if_packet.hpp b/host/include/uhd/transport/vrt_if_packet.hpp index 51bd81bb1..1be480874 100644 --- a/host/include/uhd/transport/vrt_if_packet.hpp +++ b/host/include/uhd/transport/vrt_if_packet.hpp @@ -44,6 +44,7 @@ namespace vrt{ //size fields size_t num_payload_words32; //required in pack, derived in unpack + size_t num_payload_bytes; //required in pack, derived in unpack size_t num_header_words32; //derived in pack, derived in unpack size_t num_packet_words32; //derived in pack, required in unpack diff --git a/host/lib/convert/gen_convert_general.py b/host/lib/convert/gen_convert_general.py index 9a1135b0b..be5a65130 100644 --- a/host/lib/convert/gen_convert_general.py +++ b/host/lib/convert/gen_convert_general.py @@ -48,6 +48,7 @@ DECLARE_CONVERTER(sc16_item32_$(end), 1, $(cpu_type), 1, PRIORITY_GENERAL){ } DECLARE_CONVERTER(sc8_item32_$(end), 1, $(cpu_type), 1, PRIORITY_GENERAL){ + if (nsamps == 0) return; //otherwise segfault const item32_t *input = reinterpret_cast(size_t(inputs[0]) & ~0x3); $(cpu_type)_t *output = reinterpret_cast<$(cpu_type)_t *>(outputs[0]); $(cpu_type)_t dummy; diff --git a/host/lib/transport/gen_vrt_if_packet.py b/host/lib/transport/gen_vrt_if_packet.py index 5f048d8c7..245a7ddbd 100755 --- a/host/lib/transport/gen_vrt_if_packet.py +++ b/host/lib/transport/gen_vrt_if_packet.py @@ -70,6 +70,10 @@ static pred_table_type get_pred_unpack_table(void){ static const pred_table_type pred_unpack_table(get_pred_unpack_table()); +//maps trailer bits to num empty bytes +//maps num empty bytes to trailer bits +static const size_t occ_table[] = {0, 2, 1, 3}; + ######################################################################## #def gen_code($XE_MACRO, $suffix) ######################################################################## @@ -122,14 +126,6 @@ void vrt::if_hdr_pack_$(suffix)( #set $num_header_words += 1 #set $flags |= (0x1 << 20); #end if - ########## Trailer ########## - #if $pred & $tlr_p - //packet_buff[$num_header_words+if_packet_info.num_payload_words32] = $(XE_MACRO)(if_packet_info.tlr); - #set $flags |= (0x1 << 26); - #set $num_trailer_words = 1; - #else - #set $num_trailer_words = 0; - #end if ########## Burst Flags ########## #if $pred & $eob_p #set $flags |= (0x1 << 24); @@ -137,6 +133,18 @@ void vrt::if_hdr_pack_$(suffix)( #if $pred & $sob_p #set $flags |= (0x1 << 25); #end if + ########## Trailer ########## + #if $pred & $tlr_p + { + const size_t empty_bytes = if_packet_info.num_payload_words32*sizeof(boost::uint32_t) - if_packet_info.num_payload_bytes; + if_packet_info.tlr |= (0x3 << 22) | (occ_table[empty_bytes & 0x3] << 10); + } + packet_buff[$num_header_words+if_packet_info.num_payload_words32] = $(XE_MACRO)(if_packet_info.tlr); + #set $flags |= (0x1 << 26); + #set $num_trailer_words = 1; + #else + #set $num_trailer_words = 0; + #end if ########## Variables ########## if_packet_info.num_header_words32 = $num_header_words; if_packet_info.num_packet_words32 = $($num_header_words + $num_trailer_words) + if_packet_info.num_payload_words32; @@ -172,6 +180,8 @@ void vrt::if_hdr_unpack_$(suffix)( const pred_type pred = pred_unpack_table[pred_table_index(vrt_hdr_word)]; + size_t empty_bytes = 0; + switch(pred){ #for $pred in range(2**7) case $pred: @@ -211,15 +221,6 @@ void vrt::if_hdr_unpack_$(suffix)( #else if_packet_info.has_tsf = false; #end if - ########## Trailer ########## - #if $pred & $tlr_p - if_packet_info.has_tlr = true; - if_packet_info.tlr = $(XE_MACRO)(packet_buff[packet_words32-1]); - #set $num_trailer_words = 1; - #else - if_packet_info.has_tlr = false; - #set $num_trailer_words = 0; - #end if ########## Burst Flags ########## #if $pred & $eob_p if_packet_info.eob = true; @@ -231,12 +232,28 @@ void vrt::if_hdr_unpack_$(suffix)( #else if_packet_info.sob = false; #end if + ########## Trailer ########## + #if $pred & $tlr_p + if_packet_info.has_tlr = true; + if_packet_info.tlr = $(XE_MACRO)(packet_buff[packet_words32-1]); + #set $num_trailer_words = 1; + { + const int indicators = (if_packet_info.tlr >> 20) & (if_packet_info.tlr >> 8); + if ((indicators & (1 << 0)) != 0) if_packet_info.eob = true; + if ((indicators & (1 << 1)) != 0) if_packet_info.sob = true; + empty_bytes = occ_table[(indicators >> 2) & 0x3]; + } + #else + if_packet_info.has_tlr = false; + #set $num_trailer_words = 0; + #end if ########## Variables ########## //another failure case if (packet_words32 < $($num_header_words + $num_trailer_words)) throw uhd::value_error("bad vrt header or invalid packet length"); if_packet_info.num_header_words32 = $num_header_words; if_packet_info.num_payload_words32 = packet_words32 - $($num_header_words + $num_trailer_words); + if_packet_info.num_payload_bytes = if_packet_info.num_payload_words32*sizeof(boost::uint32_t) - empty_bytes; break; #end for } diff --git a/host/lib/transport/super_recv_packet_handler.hpp b/host/lib/transport/super_recv_packet_handler.hpp index 2310d6aea..48b0acdb9 100644 --- a/host/lib/transport/super_recv_packet_handler.hpp +++ b/host/lib/transport/super_recv_packet_handler.hpp @@ -327,7 +327,7 @@ private: info.alignment_time = info[index].time; info.indexes_todo.set(); info.indexes_todo.reset(index); - info.data_bytes_to_copy = info[index].ifpi.num_payload_words32*sizeof(boost::uint32_t); + info.data_bytes_to_copy = info[index].ifpi.num_payload_bytes; } //if the sequence id matches: @@ -471,13 +471,8 @@ private: curr_info.metadata.time_spec = curr_info[0].time; curr_info.metadata.more_fragments = false; curr_info.metadata.fragment_offset = 0; - /* TODO SOB on RX not supported in hardware - static const int tlr_sob_flags = (1 << 21) | (1 << 9); //enable and indicator bits - curr_info.metadata.start_of_burst = curr_info[0].ifpi.has_tlr and (int(curr_info[0].ifpi.tlr & tlr_sob_flags) != 0); - */ - curr_info.metadata.start_of_burst = false; - static const int tlr_eob_flags = (1 << 20) | (1 << 8); //enable and indicator bits - curr_info.metadata.end_of_burst = curr_info[0].ifpi.has_tlr and (int(curr_info[0].ifpi.tlr & tlr_eob_flags) != 0); + curr_info.metadata.start_of_burst = curr_info[0].ifpi.sob; + curr_info.metadata.end_of_burst = curr_info[0].ifpi.eob; curr_info.metadata.error_code = rx_metadata_t::ERROR_CODE_NONE; } diff --git a/host/lib/transport/super_send_packet_handler.hpp b/host/lib/transport/super_send_packet_handler.hpp index 779259d4f..5696b5d39 100644 --- a/host/lib/transport/super_send_packet_handler.hpp +++ b/host/lib/transport/super_send_packet_handler.hpp @@ -219,7 +219,8 @@ private: const size_t buffer_offset_bytes = 0 ){ //load the rest of the if_packet_info in here - if_packet_info.num_payload_words32 = (nsamps_per_buff*_io_buffs.size()*_bytes_per_otw_item)/sizeof(boost::uint32_t); + if_packet_info.num_payload_bytes = nsamps_per_buff*_io_buffs.size()*_bytes_per_otw_item; + if_packet_info.num_payload_words32 = (if_packet_info.num_payload_bytes + 3/*round up*/)/sizeof(boost::uint32_t); if_packet_info.packet_count = _next_packet_seq; size_t buff_index = 0; diff --git a/host/lib/usrp/cores/rx_dsp_core_200.cpp b/host/lib/usrp/cores/rx_dsp_core_200.cpp index 023216a09..b121bc849 100644 --- a/host/lib/usrp/cores/rx_dsp_core_200.cpp +++ b/host/lib/usrp/cores/rx_dsp_core_200.cpp @@ -130,7 +130,8 @@ public: } void set_link_rate(const double rate){ - _link_rate = rate/sizeof(boost::uint32_t); //in samps/s + //_link_rate = rate/sizeof(boost::uint32_t); //in samps/s + _link_rate = rate/sizeof(boost::uint16_t); //in samps/s (allows for 8sc) } double set_host_rate(const double rate){ diff --git a/host/lib/usrp/cores/tx_dsp_core_200.cpp b/host/lib/usrp/cores/tx_dsp_core_200.cpp index 04e9f5da4..f37b53527 100644 --- a/host/lib/usrp/cores/tx_dsp_core_200.cpp +++ b/host/lib/usrp/cores/tx_dsp_core_200.cpp @@ -70,7 +70,8 @@ public: } void set_link_rate(const double rate){ - _link_rate = rate/sizeof(boost::uint32_t); //in samps/s + //_link_rate = rate/sizeof(boost::uint32_t); //in samps/s + _link_rate = rate/sizeof(boost::uint16_t); //in samps/s (allows for 8sc) } double set_host_rate(const double rate){ diff --git a/host/lib/usrp/usrp1/io_impl.cpp b/host/lib/usrp/usrp1/io_impl.cpp index 534d33959..12950d385 100644 --- a/host/lib/usrp/usrp1/io_impl.cpp +++ b/host/lib/usrp/usrp1/io_impl.cpp @@ -111,6 +111,7 @@ static void usrp1_bs_vrt_unpacker( ){ if_packet_info.packet_type = vrt::if_packet_info_t::PACKET_TYPE_DATA; if_packet_info.num_payload_words32 = if_packet_info.num_packet_words32; + if_packet_info.num_payload_bytes = if_packet_info.num_packet_words32*sizeof(boost::uint32_t); if_packet_info.num_header_words32 = 0; if_packet_info.packet_count = 0; if_packet_info.sob = false; -- cgit v1.2.3 From 929571756901c96a984bbb4e415478ac3deb1784 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Thu, 13 Oct 2011 13:26:07 -0700 Subject: uhd: added converter for item32 as cpu type --- host/lib/convert/gen_convert_general.py | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) (limited to 'host') diff --git a/host/lib/convert/gen_convert_general.py b/host/lib/convert/gen_convert_general.py index be5a65130..eafb145e6 100644 --- a/host/lib/convert/gen_convert_general.py +++ b/host/lib/convert/gen_convert_general.py @@ -28,6 +28,30 @@ TMPL_HEADER = """ using namespace uhd::convert; """ +TMPL_CONV_GEN2_ITEM32 = """ +DECLARE_CONVERTER(item32, 1, sc16_item32_$(end), 1, PRIORITY_GENERAL){ + const item32_t *input = reinterpret_cast(inputs[0]); + item32_t *output = reinterpret_cast(outputs[0]); + + if (scale_factor == 0){} //avoids unused warning + + for (size_t i = 0; i < nsamps; i++){ + output[i] = $(to_wire)(input[i]); + } +} + +DECLARE_CONVERTER(sc16_item32_$(end), 1, item32, 1, PRIORITY_GENERAL){ + const item32_t *input = reinterpret_cast(inputs[0]); + item32_t *output = reinterpret_cast(outputs[0]); + + if (scale_factor == 0){} //avoids unused warning + + for (size_t i = 0; i < nsamps; i++){ + output[i] = $(to_host)(input[i]); + } +} +""" + TMPL_CONV_GEN2_COMPLEX = """ DECLARE_CONVERTER($(cpu_type), 1, sc16_item32_$(end), 1, PRIORITY_GENERAL){ const $(cpu_type)_t *input = reinterpret_cast(inputs[0]); @@ -150,6 +174,10 @@ if __name__ == '__main__': TMPL_CONV_GEN2_COMPLEX, end=end, to_host=to_host, to_wire=to_wire, cpu_type=cpu_type ) + output += parse_tmpl( + TMPL_CONV_GEN2_ITEM32, + end=end, to_host=to_host, to_wire=to_wire + ) #generate complex converters for usrp1 format for width in 1, 2, 4: -- cgit v1.2.3 From 55d074fdd1fdada732b9e1b477d2f43948243ee1 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Thu, 13 Oct 2011 13:32:54 -0700 Subject: uhd: changed stream args args to device_addr_t --- host/include/uhd/stream.hpp | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) (limited to 'host') diff --git a/host/include/uhd/stream.hpp b/host/include/uhd/stream.hpp index c86463184..1f0332088 100644 --- a/host/include/uhd/stream.hpp +++ b/host/include/uhd/stream.hpp @@ -20,6 +20,7 @@ #include #include +#include #include #include #include @@ -71,11 +72,13 @@ struct UHD_API stream_args_t{ std::string otw_format; /*! - * The args parameter is currently unused. Leave it blank. - * The intention is that a user with a custom DSP design - * may want to pass args and do something special with it. + * The args parameter is used to pass arbitrary key/value pairs. + * Possible keys used by args (depends on implementation): + * - scaler: 8sc converter scaling factor + * - function: magnitude or phase/magnitude + * - units: numeric units like counts or dBm */ - std::string args; + device_addr_t args; /*! * The channels is a list of channel numbers. -- cgit v1.2.3 From fe204a322ecbba4dd8b195987667651f0a1b7c80 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Fri, 14 Oct 2011 09:58:40 -0700 Subject: uhd: added some stream docs/app notes --- host/docs/CMakeLists.txt | 1 + host/docs/index.rst | 1 + host/docs/stream.rst | 59 ++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 61 insertions(+) create mode 100644 host/docs/stream.rst (limited to 'host') diff --git a/host/docs/CMakeLists.txt b/host/docs/CMakeLists.txt index be00a6655..fe3799a2f 100644 --- a/host/docs/CMakeLists.txt +++ b/host/docs/CMakeLists.txt @@ -27,6 +27,7 @@ SET(manual_sources gpsdo.rst general.rst images.rst + stream.rst sync.rst transport.rst usrp1.rst diff --git a/host/docs/index.rst b/host/docs/index.rst index 7b6d026b5..0b24927e9 100644 --- a/host/docs/index.rst +++ b/host/docs/index.rst @@ -36,4 +36,5 @@ API Documentation ^^^^^^^^^^^^^^^^^^^^^ * `Doxygen <./../../doxygen/html/index.html>`_ * `Using the API <./coding.html>`_ +* `Device streaming <./stream.html>`_ diff --git a/host/docs/stream.rst b/host/docs/stream.rst new file mode 100644 index 000000000..9ffec22e5 --- /dev/null +++ b/host/docs/stream.rst @@ -0,0 +1,59 @@ +======================================================================== +UHD - Device streaming +======================================================================== + +.. contents:: Table of Contents + +------------------------------------------------------------------------ +Introduction to streaming +------------------------------------------------------------------------ +The concept of streaming refers to the transportation of samples between host and device. +A stream is an object that facilitates streaming between host application and device. +A RX stream allows the user to receive samples from the device. +A TX stream allows the user to transmit samples to the device. + +------------------------------------------------------------------------ +Link layer encapsulation +------------------------------------------------------------------------ +The VITA49 standard provides encapsulation for sample data across a link layer. +On all generation2 hardware, samples are encapsulated into VRT IF data packets. +These packets also provide sample decoration such as stream time and burst flags. +Sample decoration is exposed to the user in the form of RX and TX metadata structs. + +The length of an IF data packet can be limited by several factors: + +* MTU of the link layer - network card, network switch +* Buffering on the host - frame size in a ring buffer +* Buffering on the device - size of BRAM FIFOs + +------------------------------------------------------------------------ +Data types +------------------------------------------------------------------------ +There are two important data types to consider when streaming: + +* The data type of the samples used on the host for processing +* The data type of the samples sent through the link-layer + +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +The host/CPU data type +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +The host data type refers to the format of samples used in the host for baseband processing. +Typically, the data type is complex baseband such as normalized complex-float32 or complex-int16. + +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +The link-layer data type +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +The link-layer or "over-the-wire" data type refers to the format of the samples sent through the link. +Typically, this data type is complex-int16. +However, To increase throughput over the link-layer, +at the expense of precision, complex-int8 may be used. + +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Conversion +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +The user may request arbitrary combinations of host and link data types; +however, not all combinations are supported. +The user may register custom data type formats and conversion routines. +See uhd/convert.hpp for futher documentation. + +TODO provide example of convert API -- cgit v1.2.3 From ae9e89d76b2eb86a29995f04aaab1aa59ee93f04 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Sun, 16 Oct 2011 10:43:48 -0700 Subject: usrp: added get_tx/rx_rates --- host/include/uhd/usrp/multi_usrp.hpp | 16 ++++++++++++++++ host/lib/usrp/b100/b100_impl.cpp | 4 ++++ host/lib/usrp/cores/rx_dsp_core_200.cpp | 21 ++++++++++++++++----- host/lib/usrp/cores/rx_dsp_core_200.hpp | 2 ++ host/lib/usrp/cores/tx_dsp_core_200.cpp | 21 ++++++++++++++++----- host/lib/usrp/cores/tx_dsp_core_200.hpp | 2 ++ host/lib/usrp/e100/e100_impl.cpp | 4 ++++ host/lib/usrp/multi_usrp.cpp | 8 ++++++++ host/lib/usrp/usrp1/io_impl.cpp | 27 ++++++++++++++++++++++----- host/lib/usrp/usrp1/usrp1_impl.cpp | 8 ++++++-- host/lib/usrp/usrp1/usrp1_impl.hpp | 2 ++ host/lib/usrp/usrp2/usrp2_impl.cpp | 4 ++++ 12 files changed, 102 insertions(+), 17 deletions(-) (limited to 'host') diff --git a/host/include/uhd/usrp/multi_usrp.hpp b/host/include/uhd/usrp/multi_usrp.hpp index ee7bf8424..baa47b39e 100644 --- a/host/include/uhd/usrp/multi_usrp.hpp +++ b/host/include/uhd/usrp/multi_usrp.hpp @@ -18,7 +18,9 @@ #ifndef INCLUDED_UHD_USRP_MULTI_USRP_HPP #define INCLUDED_UHD_USRP_MULTI_USRP_HPP +//define API capabilities for compile time detection of new features #define UHD_USRP_MULTI_USRP_REF_SOURCES_API +#define UHD_USRP_MULTI_USRP_GET_RATES_API #include #include @@ -367,6 +369,13 @@ public: */ virtual double get_rx_rate(size_t chan = 0) = 0; + /*! + * Get a range of possible RX rates. + * \param chan the channel index 0 to N-1 + * \return the meta range of rates + */ + virtual meta_range_t get_rx_rates(size_t chan = 0) = 0; + /*! * Set the RX center frequency. * \param tune_request tune request instructions @@ -567,6 +576,13 @@ public: */ virtual double get_tx_rate(size_t chan = 0) = 0; + /*! + * Get a range of possible TX rates. + * \param chan the channel index 0 to N-1 + * \return the meta range of rates + */ + virtual meta_range_t get_tx_rates(size_t chan = 0) = 0; + /*! * Set the TX center frequency. * \param tune_request tune request instructions diff --git a/host/lib/usrp/b100/b100_impl.cpp b/host/lib/usrp/b100/b100_impl.cpp index d1928735b..bb91d415d 100644 --- a/host/lib/usrp/b100/b100_impl.cpp +++ b/host/lib/usrp/b100/b100_impl.cpp @@ -296,6 +296,8 @@ b100_impl::b100_impl(const device_addr_t &device_addr){ _tree->access(mb_path / "tick_rate") .subscribe(boost::bind(&rx_dsp_core_200::set_tick_rate, _rx_dsps[dspno], _1)); fs_path rx_dsp_path = mb_path / str(boost::format("rx_dsps/%u") % dspno); + _tree->create(rx_dsp_path / "rate/range") + .publish(boost::bind(&rx_dsp_core_200::get_host_rates, _rx_dsps[dspno])); _tree->create(rx_dsp_path / "rate/value") .set(1e6) //some default .coerce(boost::bind(&rx_dsp_core_200::set_host_rate, _rx_dsps[dspno], _1)) @@ -317,6 +319,8 @@ b100_impl::b100_impl(const device_addr_t &device_addr){ _tx_dsp->set_link_rate(B100_LINK_RATE_BPS); _tree->access(mb_path / "tick_rate") .subscribe(boost::bind(&tx_dsp_core_200::set_tick_rate, _tx_dsp, _1)); + _tree->create(mb_path / "tx_dsps/0/rate/range") + .publish(boost::bind(&tx_dsp_core_200::get_host_rates, _tx_dsp)); _tree->create(mb_path / "tx_dsps/0/rate/value") .set(1e6) //some default .coerce(boost::bind(&tx_dsp_core_200::set_host_rate, _tx_dsp, _1)) diff --git a/host/lib/usrp/cores/rx_dsp_core_200.cpp b/host/lib/usrp/cores/rx_dsp_core_200.cpp index b121bc849..6d306d507 100644 --- a/host/lib/usrp/cores/rx_dsp_core_200.cpp +++ b/host/lib/usrp/cores/rx_dsp_core_200.cpp @@ -134,12 +134,23 @@ public: _link_rate = rate/sizeof(boost::uint16_t); //in samps/s (allows for 8sc) } + uhd::meta_range_t get_host_rates(void){ + meta_range_t range; + for (int rate = 512; rate > 256; rate -= 4){ + range.push_back(range_t(_tick_rate/rate)); + } + for (int rate = 256; rate > 128; rate -= 2){ + range.push_back(range_t(_tick_rate/rate)); + } + for (int rate = 128; rate >= int(std::ceil(_tick_rate/_link_rate)); rate -= 1){ + range.push_back(range_t(_tick_rate/rate)); + } + return range; + } + double set_host_rate(const double rate){ - size_t decim_rate = uhd::clip( - boost::math::iround(_tick_rate/rate), size_t(std::ceil(_tick_rate/_link_rate)), 512 - ); - if (decim_rate > 128) decim_rate &= ~0x1; //CIC up to 128, have to use 1 HB - if (decim_rate > 256) decim_rate &= ~0x3; //CIC up to 128, have to use 2 HB + const size_t decim_rate = this->get_host_rates().clip( + boost::math::iround(_tick_rate/rate), true); size_t decim = decim_rate; //determine which half-band filters are activated diff --git a/host/lib/usrp/cores/rx_dsp_core_200.hpp b/host/lib/usrp/cores/rx_dsp_core_200.hpp index ddd6f2abf..89b8c1f51 100644 --- a/host/lib/usrp/cores/rx_dsp_core_200.hpp +++ b/host/lib/usrp/cores/rx_dsp_core_200.hpp @@ -48,6 +48,8 @@ public: virtual double set_host_rate(const double rate) = 0; + virtual uhd::meta_range_t get_host_rates(void) = 0; + virtual double get_scaling_adjustment(void) = 0; virtual uhd::meta_range_t get_freq_range(void) = 0; diff --git a/host/lib/usrp/cores/tx_dsp_core_200.cpp b/host/lib/usrp/cores/tx_dsp_core_200.cpp index f37b53527..1d571ea7c 100644 --- a/host/lib/usrp/cores/tx_dsp_core_200.cpp +++ b/host/lib/usrp/cores/tx_dsp_core_200.cpp @@ -74,12 +74,23 @@ public: _link_rate = rate/sizeof(boost::uint16_t); //in samps/s (allows for 8sc) } + uhd::meta_range_t get_host_rates(void){ + meta_range_t range; + for (int rate = 512; rate > 256; rate -= 4){ + range.push_back(range_t(_tick_rate/rate)); + } + for (int rate = 256; rate > 128; rate -= 2){ + range.push_back(range_t(_tick_rate/rate)); + } + for (int rate = 128; rate >= int(std::ceil(_tick_rate/_link_rate)); rate -= 1){ + range.push_back(range_t(_tick_rate/rate)); + } + return range; + } + double set_host_rate(const double rate){ - size_t interp_rate = uhd::clip( - boost::math::iround(_tick_rate/rate), size_t(std::ceil(_tick_rate/_link_rate)), 512 - ); - if (interp_rate > 128) interp_rate &= ~0x1; //CIC up to 128, have to use 1 HB - if (interp_rate > 256) interp_rate &= ~0x3; //CIC up to 128, have to use 2 HB + const size_t interp_rate = this->get_host_rates().clip( + boost::math::iround(_tick_rate/rate), true); size_t interp = interp_rate; //determine which half-band filters are activated diff --git a/host/lib/usrp/cores/tx_dsp_core_200.hpp b/host/lib/usrp/cores/tx_dsp_core_200.hpp index 65f822558..e6be63557 100644 --- a/host/lib/usrp/cores/tx_dsp_core_200.hpp +++ b/host/lib/usrp/cores/tx_dsp_core_200.hpp @@ -40,6 +40,8 @@ public: virtual double set_host_rate(const double rate) = 0; + virtual uhd::meta_range_t get_host_rates(void) = 0; + virtual uhd::meta_range_t get_freq_range(void) = 0; virtual double set_freq(const double freq) = 0; diff --git a/host/lib/usrp/e100/e100_impl.cpp b/host/lib/usrp/e100/e100_impl.cpp index deb52b2d7..6cb404000 100644 --- a/host/lib/usrp/e100/e100_impl.cpp +++ b/host/lib/usrp/e100/e100_impl.cpp @@ -270,6 +270,8 @@ e100_impl::e100_impl(const uhd::device_addr_t &device_addr){ _tree->access(mb_path / "tick_rate") .subscribe(boost::bind(&rx_dsp_core_200::set_tick_rate, _rx_dsps[dspno], _1)); fs_path rx_dsp_path = mb_path / str(boost::format("rx_dsps/%u") % dspno); + _tree->create(rx_dsp_path / "rate/range") + .publish(boost::bind(&rx_dsp_core_200::get_host_rates, _rx_dsps[dspno])); _tree->create(rx_dsp_path / "rate/value") .set(1e6) //some default .coerce(boost::bind(&rx_dsp_core_200::set_host_rate, _rx_dsps[dspno], _1)) @@ -291,6 +293,8 @@ e100_impl::e100_impl(const uhd::device_addr_t &device_addr){ _tx_dsp->set_link_rate(E100_TX_LINK_RATE_BPS); _tree->access(mb_path / "tick_rate") .subscribe(boost::bind(&tx_dsp_core_200::set_tick_rate, _tx_dsp, _1)); + _tree->create(mb_path / "tx_dsps/0/rate/range") + .publish(boost::bind(&tx_dsp_core_200::get_host_rates, _tx_dsp)); _tree->create(mb_path / "tx_dsps/0/rate/value") .set(1e6) //some default .coerce(boost::bind(&tx_dsp_core_200::set_host_rate, _tx_dsp, _1)) diff --git a/host/lib/usrp/multi_usrp.cpp b/host/lib/usrp/multi_usrp.cpp index ab841487f..97c5ea630 100644 --- a/host/lib/usrp/multi_usrp.cpp +++ b/host/lib/usrp/multi_usrp.cpp @@ -477,6 +477,10 @@ public: return _tree->access(rx_dsp_root(chan) / "rate" / "value").get(); } + meta_range_t get_rx_rates(size_t chan){ + return _tree->access(rx_dsp_root(chan) / "rate" / "range").get(); + } + tune_result_t set_rx_freq(const tune_request_t &tune_request, size_t chan){ tune_result_t r = tune_xx_subdev_and_dsp(RX_SIGN, _tree->subtree(rx_dsp_root(chan)), _tree->subtree(rx_rf_fe_root(chan)), tune_request); do_tune_freq_warning_message(tune_request.target_freq, get_rx_freq(chan), "RX"); @@ -587,6 +591,10 @@ public: return _tree->access(tx_dsp_root(chan) / "rate" / "value").get(); } + meta_range_t get_tx_rates(size_t chan){ + return _tree->access(tx_dsp_root(chan) / "rate" / "range").get(); + } + tune_result_t set_tx_freq(const tune_request_t &tune_request, size_t chan){ tune_result_t r = tune_xx_subdev_and_dsp(TX_SIGN, _tree->subtree(tx_dsp_root(chan)), _tree->subtree(tx_rf_fe_root(chan)), tune_request); do_tune_freq_warning_message(tune_request.target_freq, get_tx_freq(chan), "TX"); diff --git a/host/lib/usrp/usrp1/io_impl.cpp b/host/lib/usrp/usrp1/io_impl.cpp index 12950d385..31c834109 100644 --- a/host/lib/usrp/usrp1/io_impl.cpp +++ b/host/lib/usrp/usrp1/io_impl.cpp @@ -442,7 +442,6 @@ void usrp1_impl::update_tx_subdev_spec(const uhd::usrp::subdev_spec_t &spec){ this->restore_tx(s); } - void usrp1_impl::update_tick_rate(const double rate){ //updating this variable should: //update dboard iface -> it has a reference @@ -450,11 +449,29 @@ void usrp1_impl::update_tick_rate(const double rate){ _master_clock_rate = rate; } +uhd::meta_range_t usrp1_impl::get_rx_dsp_host_rates(void){ + meta_range_t range; + const size_t div = this->has_rx_halfband()? 2 : 1; + for (int rate = 256; rate >= 4; rate -= div){ + range.push_back(range_t(_master_clock_rate/rate)); + } + return range; +} + +uhd::meta_range_t usrp1_impl::get_tx_dsp_host_rates(void){ + meta_range_t range; + const size_t div = this->has_tx_halfband()? 2 : 1; + for (int rate = 256; rate >= 8; rate -= div){ + range.push_back(range_t(_master_clock_rate/rate)); + } + return range; +} + double usrp1_impl::update_rx_samp_rate(size_t dspno, const double samp_rate){ const size_t div = this->has_rx_halfband()? 2 : 1; - const size_t rate = uhd::clip( - boost::math::iround(_master_clock_rate / samp_rate), 4, 256) & ~(div-1); + const size_t rate = this->get_rx_dsp_host_rates().clip( + boost::math::iround(_master_clock_rate / samp_rate), true); if (rate < 8 and this->has_rx_halfband()) UHD_MSG(warning) << "USRP1 cannot achieve decimations below 8 when the half-band filter is present.\n" @@ -482,8 +499,8 @@ double usrp1_impl::update_rx_samp_rate(size_t dspno, const double samp_rate){ double usrp1_impl::update_tx_samp_rate(size_t dspno, const double samp_rate){ const size_t div = this->has_tx_halfband()? 2 : 1; - const size_t rate = uhd::clip( - boost::math::iround(_master_clock_rate / samp_rate), 8, 256) & ~(div-1); + const size_t rate = this->get_tx_dsp_host_rates().clip( + boost::math::iround(_master_clock_rate / samp_rate), true); if (dspno == 0){ //only care if dsp0 is set since its homogeneous bool s = this->disable_tx(); diff --git a/host/lib/usrp/usrp1/usrp1_impl.cpp b/host/lib/usrp/usrp1/usrp1_impl.cpp index 5788c536f..1a61f8136 100644 --- a/host/lib/usrp/usrp1/usrp1_impl.cpp +++ b/host/lib/usrp/usrp1/usrp1_impl.cpp @@ -283,8 +283,10 @@ usrp1_impl::usrp1_impl(const device_addr_t &device_addr){ _tree->create(mb_path / "rx_dsps"); //dummy in case we have none for (size_t dspno = 0; dspno < get_num_ddcs(); dspno++){ fs_path rx_dsp_path = mb_path / str(boost::format("rx_dsps/%u") % dspno); + _tree->create(rx_dsp_path / "rate/range") + .publish(boost::bind(&usrp1_impl::get_rx_dsp_host_rates, this)); _tree->create(rx_dsp_path / "rate/value") - .set(1e6) + .set(1e6) //some default rate .coerce(boost::bind(&usrp1_impl::update_rx_samp_rate, this, dspno, _1)); _tree->create(rx_dsp_path / "freq/value") .coerce(boost::bind(&usrp1_impl::update_rx_dsp_freq, this, dspno, _1)); @@ -304,8 +306,10 @@ usrp1_impl::usrp1_impl(const device_addr_t &device_addr){ _tree->create(mb_path / "tx_dsps"); //dummy in case we have none for (size_t dspno = 0; dspno < get_num_ducs(); dspno++){ fs_path tx_dsp_path = mb_path / str(boost::format("tx_dsps/%u") % dspno); + _tree->create(tx_dsp_path / "rate/range") + .publish(boost::bind(&usrp1_impl::get_tx_dsp_host_rates, this)); _tree->create(tx_dsp_path / "rate/value") - .set(1e6) + .set(1e6) //some default rate .coerce(boost::bind(&usrp1_impl::update_tx_samp_rate, this, dspno, _1)); _tree->create(tx_dsp_path / "freq/value") .coerce(boost::bind(&usrp1_impl::update_tx_dsp_freq, this, dspno, _1)); diff --git a/host/lib/usrp/usrp1/usrp1_impl.hpp b/host/lib/usrp/usrp1/usrp1_impl.hpp index 6f427c31e..ec313daf6 100644 --- a/host/lib/usrp/usrp1/usrp1_impl.hpp +++ b/host/lib/usrp/usrp1/usrp1_impl.hpp @@ -98,6 +98,8 @@ private: void update_tick_rate(const double rate); uhd::meta_range_t get_rx_dsp_freq_range(void); uhd::meta_range_t get_tx_dsp_freq_range(void); + uhd::meta_range_t get_rx_dsp_host_rates(void); + uhd::meta_range_t get_tx_dsp_host_rates(void); static uhd::usrp::dboard_iface::sptr make_dboard_iface( usrp1_iface::sptr, diff --git a/host/lib/usrp/usrp2/usrp2_impl.cpp b/host/lib/usrp/usrp2/usrp2_impl.cpp index 2d89ddaf4..24178d10c 100644 --- a/host/lib/usrp/usrp2/usrp2_impl.cpp +++ b/host/lib/usrp/usrp2/usrp2_impl.cpp @@ -480,6 +480,8 @@ usrp2_impl::usrp2_impl(const device_addr_t &_device_addr){ _mbc[mb].rx_dsp_xports[dspno]->get_recv_buff(0.01).get(); //recv with timeout for lingering _mbc[mb].rx_dsp_xports[dspno]->get_recv_buff(0.01).get(); //recv with timeout for expected fs_path rx_dsp_path = mb_path / str(boost::format("rx_dsps/%u") % dspno); + _tree->create(rx_dsp_path / "rate/range") + .publish(boost::bind(&rx_dsp_core_200::get_host_rates, _mbc[mb].rx_dsps[dspno])); _tree->create(rx_dsp_path / "rate/value") .set(1e6) //some default .coerce(boost::bind(&rx_dsp_core_200::set_host_rate, _mbc[mb].rx_dsps[dspno], _1)) @@ -501,6 +503,8 @@ usrp2_impl::usrp2_impl(const device_addr_t &_device_addr){ _mbc[mb].tx_dsp->set_link_rate(USRP2_LINK_RATE_BPS); _tree->access(mb_path / "tick_rate") .subscribe(boost::bind(&tx_dsp_core_200::set_tick_rate, _mbc[mb].tx_dsp, _1)); + _tree->create(mb_path / "tx_dsps/0/rate/range") + .publish(boost::bind(&tx_dsp_core_200::get_host_rates, _mbc[mb].tx_dsp)); _tree->create(mb_path / "tx_dsps/0/rate/value") .set(1e6) //some default .coerce(boost::bind(&tx_dsp_core_200::set_host_rate, _mbc[mb].tx_dsp, _1)) -- cgit v1.2.3 From 07ba94643ed2cfeed91542e3c1fc59cbdb39a932 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Fri, 21 Oct 2011 16:38:27 -0700 Subject: usrp: add api control for tx/rx dc offset control --- host/include/uhd/usrp/multi_usrp.hpp | 35 +++++++++++++++++++++++++++++++++++ host/lib/usrp/multi_usrp.cpp | 30 ++++++++++++++++++++++++++++++ 2 files changed, 65 insertions(+) (limited to 'host') diff --git a/host/include/uhd/usrp/multi_usrp.hpp b/host/include/uhd/usrp/multi_usrp.hpp index baa47b39e..9fbc9cfe6 100644 --- a/host/include/uhd/usrp/multi_usrp.hpp +++ b/host/include/uhd/usrp/multi_usrp.hpp @@ -21,6 +21,7 @@ //define API capabilities for compile time detection of new features #define UHD_USRP_MULTI_USRP_REF_SOURCES_API #define UHD_USRP_MULTI_USRP_GET_RATES_API +#define UHD_USRP_MULTI_USRP_DC_OFFSET_API #include #include @@ -35,6 +36,7 @@ #include #include #include +#include #include #include @@ -528,6 +530,30 @@ public: */ virtual std::vector get_rx_sensor_names(size_t chan = 0) = 0; + + /*! + * Enable/disable the automatic RX DC offset correction. + * The automatic correction subtracts out the long-run average. + * + * When disabled, the averaging option operation is halted. + * Once halted, the average value will be held constant + * until the user re-enables the automatic correction + * or overrides the value by manually setting the offset. + * + * \param enb true to enable automatic DC offset correction + * \param chan the channel index 0 to N-1 + */ + virtual void set_rx_dc_offset(const bool enb, size_t chan = ALL_CHANS) = 0; + + /*! + * Set a constant RX DC offset value. + * The value is complex to control both I and Q. + * Only set this when automatic correction is disabled. + * \param offset the dc offset (1.0 is full-scale) + * \param chan the channel index 0 to N-1 + */ + virtual void set_rx_dc_offset(const std::complex &offset, size_t chan = ALL_CHANS) = 0; + /******************************************************************* * TX methods ******************************************************************/ @@ -724,6 +750,15 @@ public: * \return a vector of sensor names */ virtual std::vector get_tx_sensor_names(size_t chan = 0) = 0; + + /*! + * Set a constant TX DC offset value. + * The value is complex to control both I and Q. + * \param offset the dc offset (1.0 is full-scale) + * \param chan the channel index 0 to N-1 + */ + virtual void set_tx_dc_offset(const std::complex &offset, size_t chan = ALL_CHANS) = 0; + }; }} diff --git a/host/lib/usrp/multi_usrp.cpp b/host/lib/usrp/multi_usrp.cpp index 97c5ea630..5fff989ce 100644 --- a/host/lib/usrp/multi_usrp.cpp +++ b/host/lib/usrp/multi_usrp.cpp @@ -547,6 +547,26 @@ public: return _tree->list(rx_rf_fe_root(chan) / "sensors"); } + void set_rx_dc_offset(const bool enb, size_t chan){ + if (chan != ALL_CHANS){ + _tree->access(rx_rf_fe_root(chan).branch_path() / "dc_offset" / "enable").set(enb); + return; + } + for (size_t c = 0; c < get_rx_num_channels(); c++){ + this->set_rx_dc_offset(enb, c); + } + } + + void set_rx_dc_offset(const std::complex &offset, size_t chan){ + if (chan != ALL_CHANS){ + _tree->access >(rx_rf_fe_root(chan).branch_path() / "dc_offset" / "value").set(offset); + return; + } + for (size_t c = 0; c < get_rx_num_channels(); c++){ + this->set_rx_dc_offset(offset, c); + } + } + /******************************************************************* * TX methods ******************************************************************/ @@ -661,6 +681,16 @@ public: return _tree->list(tx_rf_fe_root(chan) / "sensors"); } + void set_tx_dc_offset(const std::complex &offset, size_t chan){ + if (chan != ALL_CHANS){ + _tree->access >(tx_rf_fe_root(chan).branch_path() / "dc_offset" / "value").set(offset); + return; + } + for (size_t c = 0; c < get_tx_num_channels(); c++){ + this->set_tx_dc_offset(offset, c); + } + } + private: device::sptr _dev; property_tree::sptr _tree; -- cgit v1.2.3 From f11d64579a7c1421cc2b0f04c85f0c0e82b6a74e Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Fri, 21 Oct 2011 16:38:45 -0700 Subject: usrp1: implement rx dc offset control hooks --- host/lib/usrp/usrp1/usrp1_impl.cpp | 41 +++++++++++++++++++++++++++++++------- host/lib/usrp/usrp1/usrp1_impl.hpp | 4 ++++ 2 files changed, 38 insertions(+), 7 deletions(-) (limited to 'host') diff --git a/host/lib/usrp/usrp1/usrp1_impl.cpp b/host/lib/usrp/usrp1/usrp1_impl.cpp index 1a61f8136..fcc4f36ae 100644 --- a/host/lib/usrp/usrp1/usrp1_impl.cpp +++ b/host/lib/usrp/usrp1/usrp1_impl.cpp @@ -33,6 +33,7 @@ #include #include #include +#include #include using namespace uhd; @@ -187,13 +188,6 @@ usrp1_impl::usrp1_impl(const device_addr_t &device_addr){ // Normal mode with no loopback or Rx counting _iface->poke32(FR_MODE, 0x00000000); _iface->poke32(FR_DEBUG_EN, 0x00000000); - _iface->poke32(FR_DC_OFFSET_CL_EN, 0x0000000f); - - // Reset offset correction registers - _iface->poke32(FR_ADC_OFFSET_0, 0x00000000); - _iface->poke32(FR_ADC_OFFSET_1, 0x00000000); - _iface->poke32(FR_ADC_OFFSET_2, 0x00000000); - _iface->poke32(FR_ADC_OFFSET_3, 0x00000000); UHD_LOG << "USRP1 Capabilities" << std::endl @@ -277,6 +271,15 @@ usrp1_impl::usrp1_impl(const device_addr_t &device_addr){ _tree->create(mb_path / "tx_subdev_spec") .subscribe(boost::bind(&usrp1_impl::update_tx_subdev_spec, this, _1)); + BOOST_FOREACH(const std::string &db, _dbc.keys()){ + _tree->create >(mb_path / "dboards" / db / "rx_frontends" / "dc_offset" / "value") + .coerce(boost::bind(&usrp1_impl::set_rx_dc_offset, this, db, _1)) + .set(std::complex(0.0, 0.0)); + _tree->create(mb_path / "dboards" / db / "rx_frontends" / "dc_offset" / "enable") + .subscribe(boost::bind(&usrp1_impl::set_enb_rx_dc_offset, this, db, _1)) + .set(true); + } + //////////////////////////////////////////////////////////////////// // create rx dsp control objects //////////////////////////////////////////////////////////////////// @@ -467,3 +470,27 @@ uhd::meta_range_t usrp1_impl::get_tx_dsp_freq_range(void){ //magic scalar comes from codec control: return meta_range_t(-_master_clock_rate*0.6875, +_master_clock_rate*0.6875); } + +void usrp1_impl::set_enb_rx_dc_offset(const std::string &db, const bool enb){ + const size_t shift = (db == "A")? 0 : 2; + _rx_dc_offset_shadow &= ~(0x3 << shift); //clear bits + _rx_dc_offset_shadow &= ((enb)? 0x3 : 0x0) << shift; + _iface->poke32(FR_DC_OFFSET_CL_EN, _rx_dc_offset_shadow & 0xf); +} + +std::complex usrp1_impl::set_rx_dc_offset(const std::string &db, const std::complex &offset){ + const boost::int32_t i_off = boost::math::iround(offset.real() * (1ul << 31)); + const boost::int32_t q_off = boost::math::iround(offset.imag() * (1ul << 31)); + + if (db == "A"){ + _iface->poke32(FR_ADC_OFFSET_0, i_off); + _iface->poke32(FR_ADC_OFFSET_1, q_off); + } + + if (db == "B"){ + _iface->poke32(FR_ADC_OFFSET_2, i_off); + _iface->poke32(FR_ADC_OFFSET_3, q_off); + } + + return std::complex(double(i_off) * (1ul << 31), double(q_off) * (1ul << 31)); +} diff --git a/host/lib/usrp/usrp1/usrp1_impl.hpp b/host/lib/usrp/usrp1/usrp1_impl.hpp index ec313daf6..99bb01c76 100644 --- a/host/lib/usrp/usrp1/usrp1_impl.hpp +++ b/host/lib/usrp/usrp1/usrp1_impl.hpp @@ -31,6 +31,7 @@ #include #include #include +#include #ifndef INCLUDED_USRP1_IMPL_HPP #define INCLUDED_USRP1_IMPL_HPP @@ -100,6 +101,9 @@ private: uhd::meta_range_t get_tx_dsp_freq_range(void); uhd::meta_range_t get_rx_dsp_host_rates(void); uhd::meta_range_t get_tx_dsp_host_rates(void); + size_t _rx_dc_offset_shadow; + void set_enb_rx_dc_offset(const std::string &db, const bool); + std::complex set_rx_dc_offset(const std::string &db, const std::complex &); static uhd::usrp::dboard_iface::sptr make_dboard_iface( usrp1_iface::sptr, -- cgit v1.2.3 From c63a38e1f9b383663e5bb52a1ae35b54bbc0104e Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Sun, 23 Oct 2011 18:02:43 -0700 Subject: usrp: add api call to adjust phase/mag imbalance --- host/include/uhd/usrp/multi_usrp.hpp | 20 +++++++++++++++++++- host/lib/usrp/multi_usrp.cpp | 20 ++++++++++++++++++++ 2 files changed, 39 insertions(+), 1 deletion(-) (limited to 'host') diff --git a/host/include/uhd/usrp/multi_usrp.hpp b/host/include/uhd/usrp/multi_usrp.hpp index 9fbc9cfe6..1cbe3a684 100644 --- a/host/include/uhd/usrp/multi_usrp.hpp +++ b/host/include/uhd/usrp/multi_usrp.hpp @@ -22,6 +22,7 @@ #define UHD_USRP_MULTI_USRP_REF_SOURCES_API #define UHD_USRP_MULTI_USRP_GET_RATES_API #define UHD_USRP_MULTI_USRP_DC_OFFSET_API +#define UHD_USRP_MULTI_USRP_CORRECTION_API #include #include @@ -530,7 +531,6 @@ public: */ virtual std::vector get_rx_sensor_names(size_t chan = 0) = 0; - /*! * Enable/disable the automatic RX DC offset correction. * The automatic correction subtracts out the long-run average. @@ -554,6 +554,15 @@ public: */ virtual void set_rx_dc_offset(const std::complex &offset, size_t chan = ALL_CHANS) = 0; + /*! + * Set the RX frontend IQ imbalance and gain correction. + * Use this to adjust the magnitude and phase of I and Q. + * + * \param correction the complex correction value + * \param chan the channel index 0 to N-1 + */ + virtual void set_rx_correction(const std::complex &correction, size_t chan = ALL_CHANS) = 0; + /******************************************************************* * TX methods ******************************************************************/ @@ -759,6 +768,15 @@ public: */ virtual void set_tx_dc_offset(const std::complex &offset, size_t chan = ALL_CHANS) = 0; + /*! + * Set the TX frontend IQ imbalance and gain correction. + * Use this to adjust the magnitude and phase of I and Q. + * + * \param correction the complex correction value + * \param chan the channel index 0 to N-1 + */ + virtual void set_tx_correction(const std::complex &correction, size_t chan = ALL_CHANS) = 0; + }; }} diff --git a/host/lib/usrp/multi_usrp.cpp b/host/lib/usrp/multi_usrp.cpp index 5fff989ce..5a6acc2c5 100644 --- a/host/lib/usrp/multi_usrp.cpp +++ b/host/lib/usrp/multi_usrp.cpp @@ -567,6 +567,16 @@ public: } } + void set_rx_correction(const std::complex &offset, size_t chan){ + if (chan != ALL_CHANS){ + _tree->access >(rx_rf_fe_root(chan).branch_path() / "correction" / "value").set(offset); + return; + } + for (size_t c = 0; c < get_rx_num_channels(); c++){ + this->set_rx_correction(offset, c); + } + } + /******************************************************************* * TX methods ******************************************************************/ @@ -691,6 +701,16 @@ public: } } + void set_tx_correction(const std::complex &offset, size_t chan){ + if (chan != ALL_CHANS){ + _tree->access >(tx_rf_fe_root(chan).branch_path() / "correction" / "value").set(offset); + return; + } + for (size_t c = 0; c < get_tx_num_channels(); c++){ + this->set_tx_correction(offset, c); + } + } + private: device::sptr _dev; property_tree::sptr _tree; -- cgit v1.2.3 From 3d3c77983b917fefc7a3e59669a43e440ba4f688 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Sun, 23 Oct 2011 18:03:56 -0700 Subject: usrp: update frontend cores for dc offset --- host/lib/usrp/cores/rx_frontend_core_200.cpp | 24 +++++++++++++++++++++--- host/lib/usrp/cores/rx_frontend_core_200.hpp | 4 +++- host/lib/usrp/cores/tx_frontend_core_200.cpp | 12 +++++++++--- host/lib/usrp/cores/tx_frontend_core_200.hpp | 2 +- 4 files changed, 34 insertions(+), 8 deletions(-) (limited to 'host') diff --git a/host/lib/usrp/cores/rx_frontend_core_200.cpp b/host/lib/usrp/cores/rx_frontend_core_200.cpp index 0e8220b49..bb87cb600 100644 --- a/host/lib/usrp/cores/rx_frontend_core_200.cpp +++ b/host/lib/usrp/cores/rx_frontend_core_200.cpp @@ -24,6 +24,9 @@ #define REG_RX_FE_OFFSET_I _base + 12 //18 bits #define REG_RX_FE_OFFSET_Q _base + 16 //18 bits +#define OFFSET_FIXED (1ul << 31) +#define OFFSET_SET (1ul << 30) + static boost::uint32_t fs_to_bits(const double num, const size_t bits){ return boost::int32_t(boost::math::round(num * (1 << (bits-1)))); } @@ -41,9 +44,23 @@ public: _iface->poke32(REG_RX_FE_SWAP_IQ, swap? 1 : 0); } - void set_offset(const std::complex &off){ - _iface->poke32(REG_RX_FE_OFFSET_I, fs_to_bits(off.real(), 24)); - _iface->poke32(REG_RX_FE_OFFSET_Q, fs_to_bits(off.imag(), 24)); + void set_dc_offset_auto(const bool enb){ + this->set_dc_offset(enb? 0 : OFFSET_FIXED); + } + + std::complex set_dc_offset(const std::complex &off){ + static const double scaler = double(1ul << 29); + _i_dc_off = boost::math::iround(off.real()*scaler); + _q_dc_off = boost::math::iround(off.imag()*scaler); + + this->set_dc_offset(OFFSET_SET | OFFSET_FIXED); + + return std::complex(_i_dc_off/scaler, _q_dc_off/scaler); + } + + void set_dc_offset(const boost::uint32_t flags){ + _iface->poke32(REG_RX_FE_OFFSET_I, flags | _i_dc_off); + _iface->poke32(REG_RX_FE_OFFSET_Q, flags | _q_dc_off); } void set_correction(const std::complex &cor){ @@ -52,6 +69,7 @@ public: } private: + boost::int32_t _i_dc_off, _q_dc_off; wb_iface::sptr _iface; const size_t _base; }; diff --git a/host/lib/usrp/cores/rx_frontend_core_200.hpp b/host/lib/usrp/cores/rx_frontend_core_200.hpp index a950e2bb7..73dfbdc72 100644 --- a/host/lib/usrp/cores/rx_frontend_core_200.hpp +++ b/host/lib/usrp/cores/rx_frontend_core_200.hpp @@ -33,7 +33,9 @@ public: virtual void set_mux(const bool swap) = 0; - virtual void set_offset(const std::complex &off) = 0; + virtual void set_dc_offset_auto(const bool enb) = 0; + + virtual std::complex set_dc_offset(const std::complex &off) = 0; virtual void set_correction(const std::complex &cor) = 0; diff --git a/host/lib/usrp/cores/tx_frontend_core_200.cpp b/host/lib/usrp/cores/tx_frontend_core_200.cpp index a7568a81e..71555e47f 100644 --- a/host/lib/usrp/cores/tx_frontend_core_200.cpp +++ b/host/lib/usrp/cores/tx_frontend_core_200.cpp @@ -50,9 +50,15 @@ public: _iface->poke32(REG_TX_FE_MUX, mode_to_mux[mode]); } - void set_dc_offset(const std::complex &off){ - _iface->poke32(REG_TX_FE_DC_OFFSET_I, fs_to_bits(off.real(), 24)); - _iface->poke32(REG_TX_FE_DC_OFFSET_Q, fs_to_bits(off.imag(), 24)); + std::complex set_dc_offset(const std::complex &off){ + static const double scaler = double(1ul << 23); + const boost::int32_t i_dc_off = boost::math::iround(off.real()*scaler); + const boost::int32_t q_dc_off = boost::math::iround(off.imag()*scaler); + + _iface->poke32(REG_TX_FE_DC_OFFSET_I, i_dc_off); + _iface->poke32(REG_TX_FE_DC_OFFSET_Q, q_dc_off); + + return std::complex(i_dc_off/scaler, q_dc_off/scaler); } void set_correction(const std::complex &cor){ diff --git a/host/lib/usrp/cores/tx_frontend_core_200.hpp b/host/lib/usrp/cores/tx_frontend_core_200.hpp index 9e4a7bc79..f905e447d 100644 --- a/host/lib/usrp/cores/tx_frontend_core_200.hpp +++ b/host/lib/usrp/cores/tx_frontend_core_200.hpp @@ -33,7 +33,7 @@ public: virtual void set_mux(const std::string &mode) = 0; - virtual void set_dc_offset(const std::complex &off) = 0; + virtual std::complex set_dc_offset(const std::complex &off) = 0; virtual void set_correction(const std::complex &cor) = 0; -- cgit v1.2.3 From bd08f403e3936d9c35b04f8990605dd49310fbfd Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Sun, 23 Oct 2011 18:04:18 -0700 Subject: usrp: register properties for correction and dc offset --- host/lib/usrp/b100/b100_impl.cpp | 18 +++++++++++++++++- host/lib/usrp/e100/e100_impl.cpp | 18 +++++++++++++++++- host/lib/usrp/usrp2/usrp2_impl.cpp | 18 +++++++++++++++++- 3 files changed, 51 insertions(+), 3 deletions(-) (limited to 'host') diff --git a/host/lib/usrp/b100/b100_impl.cpp b/host/lib/usrp/b100/b100_impl.cpp index bb91d415d..ec31ce04e 100644 --- a/host/lib/usrp/b100/b100_impl.cpp +++ b/host/lib/usrp/b100/b100_impl.cpp @@ -276,12 +276,28 @@ b100_impl::b100_impl(const device_addr_t &device_addr){ //////////////////////////////////////////////////////////////////// _rx_fe = rx_frontend_core_200::make(_fpga_ctrl, B100_REG_SR_ADDR(B100_SR_RX_FRONT)); _tx_fe = tx_frontend_core_200::make(_fpga_ctrl, B100_REG_SR_ADDR(B100_SR_TX_FRONT)); - //TODO lots of properties to expose here for frontends + _tree->create(mb_path / "rx_subdev_spec") .subscribe(boost::bind(&b100_impl::update_rx_subdev_spec, this, _1)); _tree->create(mb_path / "tx_subdev_spec") .subscribe(boost::bind(&b100_impl::update_tx_subdev_spec, this, _1)); + _tree->create >(mb_path / "dboards" / "A" / "rx_frontends" / "dc_offset" / "value") + .coerce(boost::bind(&rx_frontend_core_200::set_dc_offset, _rx_fe, _1)) + .set(std::complex(0.0, 0.0)); + _tree->create(mb_path / "dboards" / "A" / "rx_frontends" / "dc_offset" / "enable") + .subscribe(boost::bind(&rx_frontend_core_200::set_dc_offset_auto, _rx_fe, _1)) + .set(true); + _tree->create >(mb_path / "dboards" / "A" / "rx_frontends" / "correction" / "value") + .subscribe(boost::bind(&rx_frontend_core_200::set_correction, _rx_fe, _1)) + .set(std::complex(0.0, 0.0)); + _tree->create >(mb_path / "dboards" / "A" / "tx_frontends" / "dc_offset" / "value") + .coerce(boost::bind(&tx_frontend_core_200::set_dc_offset, _tx_fe, _1)) + .set(std::complex(0.0, 0.0)); + _tree->create >(mb_path / "dboards" / "A" / "tx_frontends" / "correction" / "value") + .subscribe(boost::bind(&tx_frontend_core_200::set_correction, _tx_fe, _1)) + .set(std::complex(0.0, 0.0)); + //////////////////////////////////////////////////////////////////// // create rx dsp control objects //////////////////////////////////////////////////////////////////// diff --git a/host/lib/usrp/e100/e100_impl.cpp b/host/lib/usrp/e100/e100_impl.cpp index 6cb404000..bdf5a9b85 100644 --- a/host/lib/usrp/e100/e100_impl.cpp +++ b/host/lib/usrp/e100/e100_impl.cpp @@ -250,12 +250,28 @@ e100_impl::e100_impl(const uhd::device_addr_t &device_addr){ //////////////////////////////////////////////////////////////////// _rx_fe = rx_frontend_core_200::make(_fpga_ctrl, E100_REG_SR_ADDR(UE_SR_RX_FRONT)); _tx_fe = tx_frontend_core_200::make(_fpga_ctrl, E100_REG_SR_ADDR(UE_SR_TX_FRONT)); - //TODO lots of properties to expose here for frontends + _tree->create(mb_path / "rx_subdev_spec") .subscribe(boost::bind(&e100_impl::update_rx_subdev_spec, this, _1)); _tree->create(mb_path / "tx_subdev_spec") .subscribe(boost::bind(&e100_impl::update_tx_subdev_spec, this, _1)); + _tree->create >(mb_path / "dboards" / "A" / "rx_frontends" / "dc_offset" / "value") + .coerce(boost::bind(&rx_frontend_core_200::set_dc_offset, _rx_fe, _1)) + .set(std::complex(0.0, 0.0)); + _tree->create(mb_path / "dboards" / "A" / "rx_frontends" / "dc_offset" / "enable") + .subscribe(boost::bind(&rx_frontend_core_200::set_dc_offset_auto, _rx_fe, _1)) + .set(true); + _tree->create >(mb_path / "dboards" / "A" / "rx_frontends" / "correction" / "value") + .subscribe(boost::bind(&rx_frontend_core_200::set_correction, _rx_fe, _1)) + .set(std::complex(0.0, 0.0)); + _tree->create >(mb_path / "dboards" / "A" / "tx_frontends" / "dc_offset" / "value") + .coerce(boost::bind(&tx_frontend_core_200::set_dc_offset, _tx_fe, _1)) + .set(std::complex(0.0, 0.0)); + _tree->create >(mb_path / "dboards" / "A" / "tx_frontends" / "correction" / "value") + .subscribe(boost::bind(&tx_frontend_core_200::set_correction, _tx_fe, _1)) + .set(std::complex(0.0, 0.0)); + //////////////////////////////////////////////////////////////////// // create rx dsp control objects //////////////////////////////////////////////////////////////////// diff --git a/host/lib/usrp/usrp2/usrp2_impl.cpp b/host/lib/usrp/usrp2/usrp2_impl.cpp index 24178d10c..6f215471e 100644 --- a/host/lib/usrp/usrp2/usrp2_impl.cpp +++ b/host/lib/usrp/usrp2/usrp2_impl.cpp @@ -456,12 +456,28 @@ usrp2_impl::usrp2_impl(const device_addr_t &_device_addr){ _mbc[mb].tx_fe = tx_frontend_core_200::make( _mbc[mb].iface, U2_REG_SR_ADDR(SR_TX_FRONT) ); - //TODO lots of properties to expose here for frontends + _tree->create(mb_path / "rx_subdev_spec") .subscribe(boost::bind(&usrp2_impl::update_rx_subdev_spec, this, mb, _1)); _tree->create(mb_path / "tx_subdev_spec") .subscribe(boost::bind(&usrp2_impl::update_tx_subdev_spec, this, mb, _1)); + _tree->create >(mb_path / "dboards" / "A" / "rx_frontends" / "dc_offset" / "value") + .coerce(boost::bind(&rx_frontend_core_200::set_dc_offset, _mbc[mb].rx_fe, _1)) + .set(std::complex(0.0, 0.0)); + _tree->create(mb_path / "dboards" / "A" / "rx_frontends" / "dc_offset" / "enable") + .subscribe(boost::bind(&rx_frontend_core_200::set_dc_offset_auto, _mbc[mb].rx_fe, _1)) + .set(true); + _tree->create >(mb_path / "dboards" / "A" / "rx_frontends" / "correction" / "value") + .subscribe(boost::bind(&rx_frontend_core_200::set_correction, _mbc[mb].rx_fe, _1)) + .set(std::complex(0.0, 0.0)); + _tree->create >(mb_path / "dboards" / "A" / "tx_frontends" / "dc_offset" / "value") + .coerce(boost::bind(&tx_frontend_core_200::set_dc_offset, _mbc[mb].tx_fe, _1)) + .set(std::complex(0.0, 0.0)); + _tree->create >(mb_path / "dboards" / "A" / "tx_frontends" / "correction" / "value") + .subscribe(boost::bind(&tx_frontend_core_200::set_correction, _mbc[mb].tx_fe, _1)) + .set(std::complex(0.0, 0.0)); + //////////////////////////////////////////////////////////////// // create rx dsp control objects //////////////////////////////////////////////////////////////// -- cgit v1.2.3 From a62645089202ac2ac39a55c48d3876474b54223e Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Mon, 24 Oct 2011 10:36:41 -0700 Subject: usrp: prefer name iq_balance for api call --- host/include/uhd/usrp/multi_usrp.hpp | 11 +++++------ host/lib/usrp/b100/b100_impl.cpp | 8 ++++---- host/lib/usrp/cores/rx_frontend_core_200.cpp | 2 +- host/lib/usrp/cores/rx_frontend_core_200.hpp | 2 +- host/lib/usrp/cores/tx_frontend_core_200.cpp | 2 +- host/lib/usrp/cores/tx_frontend_core_200.hpp | 2 +- host/lib/usrp/e100/e100_impl.cpp | 8 ++++---- host/lib/usrp/multi_usrp.cpp | 12 ++++++------ host/lib/usrp/usrp2/usrp2_impl.cpp | 8 ++++---- 9 files changed, 27 insertions(+), 28 deletions(-) (limited to 'host') diff --git a/host/include/uhd/usrp/multi_usrp.hpp b/host/include/uhd/usrp/multi_usrp.hpp index 1cbe3a684..0cf50aa0d 100644 --- a/host/include/uhd/usrp/multi_usrp.hpp +++ b/host/include/uhd/usrp/multi_usrp.hpp @@ -21,8 +21,7 @@ //define API capabilities for compile time detection of new features #define UHD_USRP_MULTI_USRP_REF_SOURCES_API #define UHD_USRP_MULTI_USRP_GET_RATES_API -#define UHD_USRP_MULTI_USRP_DC_OFFSET_API -#define UHD_USRP_MULTI_USRP_CORRECTION_API +#define UHD_USRP_MULTI_USRP_FRONTEND_CAL_API #include #include @@ -555,13 +554,13 @@ public: virtual void set_rx_dc_offset(const std::complex &offset, size_t chan = ALL_CHANS) = 0; /*! - * Set the RX frontend IQ imbalance and gain correction. + * Set the RX frontend IQ imbalance correction. * Use this to adjust the magnitude and phase of I and Q. * * \param correction the complex correction value * \param chan the channel index 0 to N-1 */ - virtual void set_rx_correction(const std::complex &correction, size_t chan = ALL_CHANS) = 0; + virtual void set_rx_iq_balance(const std::complex &correction, size_t chan = ALL_CHANS) = 0; /******************************************************************* * TX methods @@ -769,13 +768,13 @@ public: virtual void set_tx_dc_offset(const std::complex &offset, size_t chan = ALL_CHANS) = 0; /*! - * Set the TX frontend IQ imbalance and gain correction. + * Set the TX frontend IQ imbalance correction. * Use this to adjust the magnitude and phase of I and Q. * * \param correction the complex correction value * \param chan the channel index 0 to N-1 */ - virtual void set_tx_correction(const std::complex &correction, size_t chan = ALL_CHANS) = 0; + virtual void set_tx_iq_balance(const std::complex &correction, size_t chan = ALL_CHANS) = 0; }; diff --git a/host/lib/usrp/b100/b100_impl.cpp b/host/lib/usrp/b100/b100_impl.cpp index ec31ce04e..0edaac914 100644 --- a/host/lib/usrp/b100/b100_impl.cpp +++ b/host/lib/usrp/b100/b100_impl.cpp @@ -288,14 +288,14 @@ b100_impl::b100_impl(const device_addr_t &device_addr){ _tree->create(mb_path / "dboards" / "A" / "rx_frontends" / "dc_offset" / "enable") .subscribe(boost::bind(&rx_frontend_core_200::set_dc_offset_auto, _rx_fe, _1)) .set(true); - _tree->create >(mb_path / "dboards" / "A" / "rx_frontends" / "correction" / "value") - .subscribe(boost::bind(&rx_frontend_core_200::set_correction, _rx_fe, _1)) + _tree->create >(mb_path / "dboards" / "A" / "rx_frontends" / "iq_balance" / "value") + .subscribe(boost::bind(&rx_frontend_core_200::set_iq_balance, _rx_fe, _1)) .set(std::complex(0.0, 0.0)); _tree->create >(mb_path / "dboards" / "A" / "tx_frontends" / "dc_offset" / "value") .coerce(boost::bind(&tx_frontend_core_200::set_dc_offset, _tx_fe, _1)) .set(std::complex(0.0, 0.0)); - _tree->create >(mb_path / "dboards" / "A" / "tx_frontends" / "correction" / "value") - .subscribe(boost::bind(&tx_frontend_core_200::set_correction, _tx_fe, _1)) + _tree->create >(mb_path / "dboards" / "A" / "tx_frontends" / "iq_balance" / "value") + .subscribe(boost::bind(&tx_frontend_core_200::set_iq_balance, _tx_fe, _1)) .set(std::complex(0.0, 0.0)); //////////////////////////////////////////////////////////////////// diff --git a/host/lib/usrp/cores/rx_frontend_core_200.cpp b/host/lib/usrp/cores/rx_frontend_core_200.cpp index bb87cb600..d42022947 100644 --- a/host/lib/usrp/cores/rx_frontend_core_200.cpp +++ b/host/lib/usrp/cores/rx_frontend_core_200.cpp @@ -63,7 +63,7 @@ public: _iface->poke32(REG_RX_FE_OFFSET_Q, flags | _q_dc_off); } - void set_correction(const std::complex &cor){ + void set_iq_balance(const std::complex &cor){ _iface->poke32(REG_RX_FE_MAG_CORRECTION, fs_to_bits(std::abs(cor), 18)); _iface->poke32(REG_RX_FE_PHASE_CORRECTION, fs_to_bits(std::atan2(cor.real(), cor.imag()), 18)); } diff --git a/host/lib/usrp/cores/rx_frontend_core_200.hpp b/host/lib/usrp/cores/rx_frontend_core_200.hpp index 73dfbdc72..5755424c8 100644 --- a/host/lib/usrp/cores/rx_frontend_core_200.hpp +++ b/host/lib/usrp/cores/rx_frontend_core_200.hpp @@ -37,7 +37,7 @@ public: virtual std::complex set_dc_offset(const std::complex &off) = 0; - virtual void set_correction(const std::complex &cor) = 0; + virtual void set_iq_balance(const std::complex &cor) = 0; }; diff --git a/host/lib/usrp/cores/tx_frontend_core_200.cpp b/host/lib/usrp/cores/tx_frontend_core_200.cpp index 71555e47f..327e8d344 100644 --- a/host/lib/usrp/cores/tx_frontend_core_200.cpp +++ b/host/lib/usrp/cores/tx_frontend_core_200.cpp @@ -61,7 +61,7 @@ public: return std::complex(i_dc_off/scaler, q_dc_off/scaler); } - void set_correction(const std::complex &cor){ + void set_iq_balance(const std::complex &cor){ _iface->poke32(REG_TX_FE_MAG_CORRECTION, fs_to_bits(std::abs(cor), 18)); _iface->poke32(REG_TX_FE_PHASE_CORRECTION, fs_to_bits(std::atan2(cor.real(), cor.imag()), 18)); } diff --git a/host/lib/usrp/cores/tx_frontend_core_200.hpp b/host/lib/usrp/cores/tx_frontend_core_200.hpp index f905e447d..8ee0f3e6d 100644 --- a/host/lib/usrp/cores/tx_frontend_core_200.hpp +++ b/host/lib/usrp/cores/tx_frontend_core_200.hpp @@ -35,7 +35,7 @@ public: virtual std::complex set_dc_offset(const std::complex &off) = 0; - virtual void set_correction(const std::complex &cor) = 0; + virtual void set_iq_balance(const std::complex &cor) = 0; }; diff --git a/host/lib/usrp/e100/e100_impl.cpp b/host/lib/usrp/e100/e100_impl.cpp index bdf5a9b85..4c5f5f066 100644 --- a/host/lib/usrp/e100/e100_impl.cpp +++ b/host/lib/usrp/e100/e100_impl.cpp @@ -262,14 +262,14 @@ e100_impl::e100_impl(const uhd::device_addr_t &device_addr){ _tree->create(mb_path / "dboards" / "A" / "rx_frontends" / "dc_offset" / "enable") .subscribe(boost::bind(&rx_frontend_core_200::set_dc_offset_auto, _rx_fe, _1)) .set(true); - _tree->create >(mb_path / "dboards" / "A" / "rx_frontends" / "correction" / "value") - .subscribe(boost::bind(&rx_frontend_core_200::set_correction, _rx_fe, _1)) + _tree->create >(mb_path / "dboards" / "A" / "rx_frontends" / "iq_balance" / "value") + .subscribe(boost::bind(&rx_frontend_core_200::set_iq_balance, _rx_fe, _1)) .set(std::complex(0.0, 0.0)); _tree->create >(mb_path / "dboards" / "A" / "tx_frontends" / "dc_offset" / "value") .coerce(boost::bind(&tx_frontend_core_200::set_dc_offset, _tx_fe, _1)) .set(std::complex(0.0, 0.0)); - _tree->create >(mb_path / "dboards" / "A" / "tx_frontends" / "correction" / "value") - .subscribe(boost::bind(&tx_frontend_core_200::set_correction, _tx_fe, _1)) + _tree->create >(mb_path / "dboards" / "A" / "tx_frontends" / "iq_balance" / "value") + .subscribe(boost::bind(&tx_frontend_core_200::set_iq_balance, _tx_fe, _1)) .set(std::complex(0.0, 0.0)); //////////////////////////////////////////////////////////////////// diff --git a/host/lib/usrp/multi_usrp.cpp b/host/lib/usrp/multi_usrp.cpp index 5a6acc2c5..7b3890c9b 100644 --- a/host/lib/usrp/multi_usrp.cpp +++ b/host/lib/usrp/multi_usrp.cpp @@ -567,13 +567,13 @@ public: } } - void set_rx_correction(const std::complex &offset, size_t chan){ + void set_rx_iq_balance(const std::complex &offset, size_t chan){ if (chan != ALL_CHANS){ - _tree->access >(rx_rf_fe_root(chan).branch_path() / "correction" / "value").set(offset); + _tree->access >(rx_rf_fe_root(chan).branch_path() / "iq_balance" / "value").set(offset); return; } for (size_t c = 0; c < get_rx_num_channels(); c++){ - this->set_rx_correction(offset, c); + this->set_rx_iq_balance(offset, c); } } @@ -701,13 +701,13 @@ public: } } - void set_tx_correction(const std::complex &offset, size_t chan){ + void set_tx_iq_balance(const std::complex &offset, size_t chan){ if (chan != ALL_CHANS){ - _tree->access >(tx_rf_fe_root(chan).branch_path() / "correction" / "value").set(offset); + _tree->access >(tx_rf_fe_root(chan).branch_path() / "iq_balance" / "value").set(offset); return; } for (size_t c = 0; c < get_tx_num_channels(); c++){ - this->set_tx_correction(offset, c); + this->set_tx_iq_balance(offset, c); } } diff --git a/host/lib/usrp/usrp2/usrp2_impl.cpp b/host/lib/usrp/usrp2/usrp2_impl.cpp index 6f215471e..50916fb37 100644 --- a/host/lib/usrp/usrp2/usrp2_impl.cpp +++ b/host/lib/usrp/usrp2/usrp2_impl.cpp @@ -468,14 +468,14 @@ usrp2_impl::usrp2_impl(const device_addr_t &_device_addr){ _tree->create(mb_path / "dboards" / "A" / "rx_frontends" / "dc_offset" / "enable") .subscribe(boost::bind(&rx_frontend_core_200::set_dc_offset_auto, _mbc[mb].rx_fe, _1)) .set(true); - _tree->create >(mb_path / "dboards" / "A" / "rx_frontends" / "correction" / "value") - .subscribe(boost::bind(&rx_frontend_core_200::set_correction, _mbc[mb].rx_fe, _1)) + _tree->create >(mb_path / "dboards" / "A" / "rx_frontends" / "iq_balance" / "value") + .subscribe(boost::bind(&rx_frontend_core_200::set_iq_balance, _mbc[mb].rx_fe, _1)) .set(std::complex(0.0, 0.0)); _tree->create >(mb_path / "dboards" / "A" / "tx_frontends" / "dc_offset" / "value") .coerce(boost::bind(&tx_frontend_core_200::set_dc_offset, _mbc[mb].tx_fe, _1)) .set(std::complex(0.0, 0.0)); - _tree->create >(mb_path / "dboards" / "A" / "tx_frontends" / "correction" / "value") - .subscribe(boost::bind(&tx_frontend_core_200::set_correction, _mbc[mb].tx_fe, _1)) + _tree->create >(mb_path / "dboards" / "A" / "tx_frontends" / "iq_balance" / "value") + .subscribe(boost::bind(&tx_frontend_core_200::set_iq_balance, _mbc[mb].tx_fe, _1)) .set(std::complex(0.0, 0.0)); //////////////////////////////////////////////////////////////// -- cgit v1.2.3 From 8e439ac16137c649b2a296967efe86d346f3968a Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Mon, 24 Oct 2011 11:27:21 -0700 Subject: usrp: docs tweaks and renames to multi-usrp --- host/include/uhd/usrp/multi_usrp.hpp | 85 +++++++++++++++++------------------- host/lib/usrp/multi_usrp.cpp | 5 --- 2 files changed, 39 insertions(+), 51 deletions(-) (limited to 'host') diff --git a/host/include/uhd/usrp/multi_usrp.hpp b/host/include/uhd/usrp/multi_usrp.hpp index 0cf50aa0d..9bb5b4381 100644 --- a/host/include/uhd/usrp/multi_usrp.hpp +++ b/host/include/uhd/usrp/multi_usrp.hpp @@ -33,7 +33,6 @@ #include #include #include -#include #include #include #include @@ -54,7 +53,7 @@ namespace uhd{ namespace usrp{ * In the single device, single channel case, these parameters can be unspecified. * * When using a single device with multiple channels: - * - Channel mapping is determined by the subdevice specifications + * - Channel mapping is determined by the frontend specifications * - All channels share a common RX sample rate * - All channels share a common TX sample rate * @@ -62,8 +61,8 @@ namespace uhd{ namespace usrp{ * - Channel mapping is determined by the device address arguments * - All boards share a common RX sample rate * - All boards share a common TX sample rate - * - All boards share a common RX subdevice specification size - * - All boards share a common TX subdevice specification size + * - All boards share a common RX frontend specification size + * - All boards share a common TX frontend specification size * - All boards must have synchronized times (see the set_time_*() calls) * * Example to setup channel mapping for multiple devices: @@ -75,13 +74,13 @@ namespace uhd{ namespace usrp{ * dev_addr["addr1"] = "192.168.10.3"; * multi_usrp::sptr dev = multi_usrp::make(dev_addr); * - * //set the board on 10.2 to use the A RX subdevice (RX channel 0) + * //set the board on 10.2 to use the A RX frontend (RX channel 0) * dev->set_rx_subdev_spec("A:A", 0); * - * //set the board on 10.3 to use the B RX subdevice (RX channel 1) + * //set the board on 10.3 to use the B RX frontend (RX channel 1) * dev->set_rx_subdev_spec("A:B", 1); * - * //set both boards to use the AB TX subdevice (TX channels 0 and 1) + * //set both boards to use the AB TX frontend (TX channels 0 and 1) * dev->set_tx_subdev_spec("A:AB", multi_usrp::ALL_MBOARDS); * * //now that all the channels are mapped, continue with configuration... @@ -316,30 +315,24 @@ public: * \return a vector of sensor names */ virtual std::vector get_mboard_sensor_names(size_t mboard = 0) = 0; - - /*! - * Get a handle to the mboard_iface object which controls peripheral access. - * \return a mboard_iface::sptr object - */ - virtual mboard_iface::sptr get_mboard_iface(size_t mboard) = 0; /******************************************************************* * RX methods ******************************************************************/ /*! - * Set the RX subdevice specification: + * Set the RX frontend specification: * The subdev spec maps a physical part of a daughter-board to a channel number. * Set the subdev spec before calling into any methods with a channel number. * The subdev spec must be the same size across all motherboards. - * \param spec the new subdevice specification + * \param spec the new frontend specification * \param mboard the motherboard index 0 to M-1 */ virtual void set_rx_subdev_spec(const uhd::usrp::subdev_spec_t &spec, size_t mboard = ALL_MBOARDS) = 0; /*! - * Get the RX subdevice specification. + * Get the RX frontend specification. * \param mboard the motherboard index 0 to M-1 - * \return the subdevice specification in use + * \return the frontend specification in use */ virtual uhd::usrp::subdev_spec_t get_rx_subdev_spec(size_t mboard = 0) = 0; @@ -351,9 +344,9 @@ public: virtual size_t get_rx_num_channels(void) = 0; /*! - * Get the name of the RX subdevice. + * Get the name of the RX frontend. * \param chan the channel index 0 to N-1 - * \return the subdevice name + * \return the frontend name */ virtual std::string get_rx_subdev_name(size_t chan = 0) = 0; @@ -453,28 +446,28 @@ public: virtual std::vector get_rx_gain_names(size_t chan = 0) = 0; /*! - * Select the RX antenna on the subdevice. + * Select the RX antenna on the frontend. * \param ant the antenna name * \param chan the channel index 0 to N-1 */ virtual void set_rx_antenna(const std::string &ant, size_t chan = 0) = 0; /*! - * Get the selected RX antenna on the subdevice. + * Get the selected RX antenna on the frontend. * \param chan the channel index 0 to N-1 * \return the antenna name */ virtual std::string get_rx_antenna(size_t chan = 0) = 0; /*! - * Get a list of possible RX antennas on the subdevice. + * Get a list of possible RX antennas on the frontend. * \param chan the channel index 0 to N-1 * \return a vector of antenna names */ virtual std::vector get_rx_antennas(size_t chan = 0) = 0; /*! - * Get the locked status of the LO on the subdevice. + * Get the locked status of the LO on the frontend. * \param chan the channel index 0 to N-1 * \return true for locked */ @@ -483,21 +476,21 @@ public: } /*! - * Set the RX bandwidth on the subdevice. + * Set the RX bandwidth on the frontend. * \param bandwidth the bandwidth in Hz * \param chan the channel index 0 to N-1 */ virtual void set_rx_bandwidth(double bandwidth, size_t chan = 0) = 0; /*! - * Get the RX bandwidth on the subdevice. + * Get the RX bandwidth on the frontend. * \param chan the channel index 0 to N-1 * \return the bandwidth in Hz */ virtual double get_rx_bandwidth(size_t chan = 0) = 0; /*! - * Read the RSSI value on the RX subdevice. + * Read the RSSI value on the RX frontend. * \param chan the channel index 0 to N-1 * \return the rssi in dB * \throw exception if RSSI readback not supported @@ -507,7 +500,7 @@ public: } /*! - * Get the dboard interface object for the RX subdevice. + * Get the dboard interface object for the RX frontend. * The dboard interface gives access to GPIOs, SPI, I2C, low-speed ADC and DAC. * Use at your own risk! * \param chan the channel index 0 to N-1 @@ -516,7 +509,7 @@ public: virtual dboard_iface::sptr get_rx_dboard_iface(size_t chan = 0) = 0; /*! - * Get an RX subdevice sensor value. + * Get an RX frontend sensor value. * \param name the name of the sensor * \param chan the channel index 0 to N-1 * \return a sensor value object @@ -524,7 +517,7 @@ public: virtual sensor_value_t get_rx_sensor(const std::string &name, size_t chan = 0) = 0; /*! - * Get a list of possible RX subdevice sensor names. + * Get a list of possible RX frontend sensor names. * \param chan the channel index 0 to N-1 * \return a vector of sensor names */ @@ -557,7 +550,7 @@ public: * Set the RX frontend IQ imbalance correction. * Use this to adjust the magnitude and phase of I and Q. * - * \param correction the complex correction value + * \param correction the complex correction (1.0 is full-scale) * \param chan the channel index 0 to N-1 */ virtual void set_rx_iq_balance(const std::complex &correction, size_t chan = ALL_CHANS) = 0; @@ -566,19 +559,19 @@ public: * TX methods ******************************************************************/ /*! - * Set the TX subdevice specification: + * Set the TX frontend specification: * The subdev spec maps a physical part of a daughter-board to a channel number. * Set the subdev spec before calling into any methods with a channel number. * The subdev spec must be the same size across all motherboards. - * \param spec the new subdevice specification + * \param spec the new frontend specification * \param mboard the motherboard index 0 to M-1 */ virtual void set_tx_subdev_spec(const uhd::usrp::subdev_spec_t &spec, size_t mboard = ALL_MBOARDS) = 0; /*! - * Get the TX subdevice specification. + * Get the TX frontend specification. * \param mboard the motherboard index 0 to M-1 - * \return the subdevice specification in use + * \return the frontend specification in use */ virtual uhd::usrp::subdev_spec_t get_tx_subdev_spec(size_t mboard = 0) = 0; @@ -590,9 +583,9 @@ public: virtual size_t get_tx_num_channels(void) = 0; /*! - * Get the name of the TX subdevice. + * Get the name of the TX frontend. * \param chan the channel index 0 to N-1 - * \return the subdevice name + * \return the frontend name */ virtual std::string get_tx_subdev_name(size_t chan = 0) = 0; @@ -692,28 +685,28 @@ public: virtual std::vector get_tx_gain_names(size_t chan = 0) = 0; /*! - * Select the TX antenna on the subdevice. + * Select the TX antenna on the frontend. * \param ant the antenna name * \param chan the channel index 0 to N-1 */ virtual void set_tx_antenna(const std::string &ant, size_t chan = 0) = 0; /*! - * Get the selected TX antenna on the subdevice. + * Get the selected TX antenna on the frontend. * \param chan the channel index 0 to N-1 * \return the antenna name */ virtual std::string get_tx_antenna(size_t chan = 0) = 0; /*! - * Get a list of possible TX antennas on the subdevice. + * Get a list of possible TX antennas on the frontend. * \param chan the channel index 0 to N-1 * \return a vector of antenna names */ virtual std::vector get_tx_antennas(size_t chan = 0) = 0; /*! - * Get the locked status of the LO on the subdevice. + * Get the locked status of the LO on the frontend. * \param chan the channel index 0 to N-1 * \return true for locked */ @@ -722,21 +715,21 @@ public: } /*! - * Set the TX bandwidth on the subdevice. + * Set the TX bandwidth on the frontend. * \param bandwidth the bandwidth in Hz * \param chan the channel index 0 to N-1 */ virtual void set_tx_bandwidth(double bandwidth, size_t chan = 0) = 0; /*! - * Get the TX bandwidth on the subdevice. + * Get the TX bandwidth on the frontend. * \param chan the channel index 0 to N-1 * \return the bandwidth in Hz */ virtual double get_tx_bandwidth(size_t chan = 0) = 0; /*! - * Get the dboard interface object for the TX subdevice. + * Get the dboard interface object for the TX frontend. * The dboard interface gives access to GPIOs, SPI, I2C, low-speed ADC and DAC. * Use at your own risk! * \param chan the channel index 0 to N-1 @@ -745,7 +738,7 @@ public: virtual dboard_iface::sptr get_tx_dboard_iface(size_t chan = 0) = 0; /*! - * Get an TX subdevice sensor value. + * Get an TX frontend sensor value. * \param name the name of the sensor * \param chan the channel index 0 to N-1 * \return a sensor value object @@ -753,7 +746,7 @@ public: virtual sensor_value_t get_tx_sensor(const std::string &name, size_t chan = 0) = 0; /*! - * Get a list of possible TX subdevice sensor names. + * Get a list of possible TX frontend sensor names. * \param chan the channel index 0 to N-1 * \return a vector of sensor names */ @@ -771,7 +764,7 @@ public: * Set the TX frontend IQ imbalance correction. * Use this to adjust the magnitude and phase of I and Q. * - * \param correction the complex correction value + * \param correction the complex correction (1.0 is full-scale) * \param chan the channel index 0 to N-1 */ virtual void set_tx_iq_balance(const std::complex &correction, size_t chan = ALL_CHANS) = 0; diff --git a/host/lib/usrp/multi_usrp.cpp b/host/lib/usrp/multi_usrp.cpp index 7b3890c9b..7383fa3c0 100644 --- a/host/lib/usrp/multi_usrp.cpp +++ b/host/lib/usrp/multi_usrp.cpp @@ -17,7 +17,6 @@ #include #include -#include #include #include #include @@ -429,10 +428,6 @@ public: return _tree->list(mb_root(mboard) / "sensors"); } - mboard_iface::sptr get_mboard_iface(size_t){ - return mboard_iface::sptr(); //not implemented - } - /******************************************************************* * RX methods ******************************************************************/ -- cgit v1.2.3 From 7f815e124f217f37eb5e612a34ec84c33043aa87 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Tue, 25 Oct 2011 18:04:32 -0700 Subject: usrp: placeholder for potential set_next_command_time call --- host/include/uhd/usrp/multi_usrp.hpp | 15 +++++++++++++++ host/lib/usrp/multi_usrp.cpp | 4 ++++ 2 files changed, 19 insertions(+) (limited to 'host') diff --git a/host/include/uhd/usrp/multi_usrp.hpp b/host/include/uhd/usrp/multi_usrp.hpp index 9bb5b4381..319301784 100644 --- a/host/include/uhd/usrp/multi_usrp.hpp +++ b/host/include/uhd/usrp/multi_usrp.hpp @@ -22,6 +22,7 @@ #define UHD_USRP_MULTI_USRP_REF_SOURCES_API #define UHD_USRP_MULTI_USRP_GET_RATES_API #define UHD_USRP_MULTI_USRP_FRONTEND_CAL_API +#define UHD_USRP_MULTI_USRP_COMMAND_TIME_API #include #include @@ -225,6 +226,20 @@ public: */ virtual bool get_time_synchronized(void) = 0; + /*! + * Set the time at which the next control command will take effect. + * + * The time spec setting only takes effect on the first command. + * Subsequent commands will be sent ASAP unless user set time again. + * A timed command will throttle/back-pressure all subsequent commands, + * assuming that the subsequent commands occur within the time-window. + * If the time spec is late, the command will be activated upon arrival. + * + * \param time_spec the time at which the next command will activate + * \param mboard which motherboard to set the config + */ + virtual void set_next_command_time(const time_spec_t &time_spec, size_t mboard = ALL_MBOARDS) = 0; + /*! * Issue a stream command to the usrp device. * This tells the usrp to send samples into the host. diff --git a/host/lib/usrp/multi_usrp.cpp b/host/lib/usrp/multi_usrp.cpp index 7383fa3c0..2e7c76a06 100644 --- a/host/lib/usrp/multi_usrp.cpp +++ b/host/lib/usrp/multi_usrp.cpp @@ -347,6 +347,10 @@ public: return true; } + void set_next_command_time(const time_spec_t &, size_t){ + throw uhd::not_implemented_error("Not implemented yet, but we have a very good idea of how to do it."); + } + void issue_stream_cmd(const stream_cmd_t &stream_cmd, size_t chan){ if (chan != ALL_CHANS){ _tree->access(rx_dsp_root(chan) / "stream_cmd").set(stream_cmd); -- cgit v1.2.3 From dedfa65256470f31a20c99a210457937d3f36056 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Tue, 25 Oct 2011 19:26:11 -0700 Subject: usrp: reorganize frontend paths in tree for correction stuff --- host/lib/usrp/b100/b100_impl.cpp | 13 ++++++++----- host/lib/usrp/e100/e100_impl.cpp | 13 ++++++++----- host/lib/usrp/multi_usrp.cpp | 22 +++++++++++++++++----- host/lib/usrp/usrp1/usrp1_impl.cpp | 5 +++-- host/lib/usrp/usrp2/usrp2_impl.cpp | 13 ++++++++----- 5 files changed, 44 insertions(+), 22 deletions(-) (limited to 'host') diff --git a/host/lib/usrp/b100/b100_impl.cpp b/host/lib/usrp/b100/b100_impl.cpp index 0edaac914..944b669b2 100644 --- a/host/lib/usrp/b100/b100_impl.cpp +++ b/host/lib/usrp/b100/b100_impl.cpp @@ -282,19 +282,22 @@ b100_impl::b100_impl(const device_addr_t &device_addr){ _tree->create(mb_path / "tx_subdev_spec") .subscribe(boost::bind(&b100_impl::update_tx_subdev_spec, this, _1)); - _tree->create >(mb_path / "dboards" / "A" / "rx_frontends" / "dc_offset" / "value") + const fs_path rx_fe_path = mb_path / "rx_frontends" / "A"; + const fs_path tx_fe_path = mb_path / "rx_frontends" / "A"; + + _tree->create >(rx_fe_path / "dc_offset" / "value") .coerce(boost::bind(&rx_frontend_core_200::set_dc_offset, _rx_fe, _1)) .set(std::complex(0.0, 0.0)); - _tree->create(mb_path / "dboards" / "A" / "rx_frontends" / "dc_offset" / "enable") + _tree->create(rx_fe_path / "dc_offset" / "enable") .subscribe(boost::bind(&rx_frontend_core_200::set_dc_offset_auto, _rx_fe, _1)) .set(true); - _tree->create >(mb_path / "dboards" / "A" / "rx_frontends" / "iq_balance" / "value") + _tree->create >(rx_fe_path / "iq_balance" / "value") .subscribe(boost::bind(&rx_frontend_core_200::set_iq_balance, _rx_fe, _1)) .set(std::complex(0.0, 0.0)); - _tree->create >(mb_path / "dboards" / "A" / "tx_frontends" / "dc_offset" / "value") + _tree->create >(tx_fe_path / "dc_offset" / "value") .coerce(boost::bind(&tx_frontend_core_200::set_dc_offset, _tx_fe, _1)) .set(std::complex(0.0, 0.0)); - _tree->create >(mb_path / "dboards" / "A" / "tx_frontends" / "iq_balance" / "value") + _tree->create >(tx_fe_path / "iq_balance" / "value") .subscribe(boost::bind(&tx_frontend_core_200::set_iq_balance, _tx_fe, _1)) .set(std::complex(0.0, 0.0)); diff --git a/host/lib/usrp/e100/e100_impl.cpp b/host/lib/usrp/e100/e100_impl.cpp index 4c5f5f066..064686dd2 100644 --- a/host/lib/usrp/e100/e100_impl.cpp +++ b/host/lib/usrp/e100/e100_impl.cpp @@ -256,19 +256,22 @@ e100_impl::e100_impl(const uhd::device_addr_t &device_addr){ _tree->create(mb_path / "tx_subdev_spec") .subscribe(boost::bind(&e100_impl::update_tx_subdev_spec, this, _1)); - _tree->create >(mb_path / "dboards" / "A" / "rx_frontends" / "dc_offset" / "value") + const fs_path rx_fe_path = mb_path / "rx_frontends" / "A"; + const fs_path tx_fe_path = mb_path / "rx_frontends" / "A"; + + _tree->create >(rx_fe_path / "dc_offset" / "value") .coerce(boost::bind(&rx_frontend_core_200::set_dc_offset, _rx_fe, _1)) .set(std::complex(0.0, 0.0)); - _tree->create(mb_path / "dboards" / "A" / "rx_frontends" / "dc_offset" / "enable") + _tree->create(rx_fe_path / "dc_offset" / "enable") .subscribe(boost::bind(&rx_frontend_core_200::set_dc_offset_auto, _rx_fe, _1)) .set(true); - _tree->create >(mb_path / "dboards" / "A" / "rx_frontends" / "iq_balance" / "value") + _tree->create >(rx_fe_path / "iq_balance" / "value") .subscribe(boost::bind(&rx_frontend_core_200::set_iq_balance, _rx_fe, _1)) .set(std::complex(0.0, 0.0)); - _tree->create >(mb_path / "dboards" / "A" / "tx_frontends" / "dc_offset" / "value") + _tree->create >(tx_fe_path / "dc_offset" / "value") .coerce(boost::bind(&tx_frontend_core_200::set_dc_offset, _tx_fe, _1)) .set(std::complex(0.0, 0.0)); - _tree->create >(mb_path / "dboards" / "A" / "tx_frontends" / "iq_balance" / "value") + _tree->create >(tx_fe_path / "iq_balance" / "value") .subscribe(boost::bind(&tx_frontend_core_200::set_iq_balance, _tx_fe, _1)) .set(std::complex(0.0, 0.0)); diff --git a/host/lib/usrp/multi_usrp.cpp b/host/lib/usrp/multi_usrp.cpp index 2e7c76a06..43534ff37 100644 --- a/host/lib/usrp/multi_usrp.cpp +++ b/host/lib/usrp/multi_usrp.cpp @@ -548,7 +548,7 @@ public: void set_rx_dc_offset(const bool enb, size_t chan){ if (chan != ALL_CHANS){ - _tree->access(rx_rf_fe_root(chan).branch_path() / "dc_offset" / "enable").set(enb); + _tree->access(rx_fe_root(chan) / "dc_offset" / "enable").set(enb); return; } for (size_t c = 0; c < get_rx_num_channels(); c++){ @@ -558,7 +558,7 @@ public: void set_rx_dc_offset(const std::complex &offset, size_t chan){ if (chan != ALL_CHANS){ - _tree->access >(rx_rf_fe_root(chan).branch_path() / "dc_offset" / "value").set(offset); + _tree->access >(rx_fe_root(chan) / "dc_offset" / "value").set(offset); return; } for (size_t c = 0; c < get_rx_num_channels(); c++){ @@ -568,7 +568,7 @@ public: void set_rx_iq_balance(const std::complex &offset, size_t chan){ if (chan != ALL_CHANS){ - _tree->access >(rx_rf_fe_root(chan).branch_path() / "iq_balance" / "value").set(offset); + _tree->access >(rx_fe_root(chan) / "iq_balance" / "value").set(offset); return; } for (size_t c = 0; c < get_rx_num_channels(); c++){ @@ -692,7 +692,7 @@ public: void set_tx_dc_offset(const std::complex &offset, size_t chan){ if (chan != ALL_CHANS){ - _tree->access >(tx_rf_fe_root(chan).branch_path() / "dc_offset" / "value").set(offset); + _tree->access >(tx_fe_root(chan) / "dc_offset" / "value").set(offset); return; } for (size_t c = 0; c < get_tx_num_channels(); c++){ @@ -702,7 +702,7 @@ public: void set_tx_iq_balance(const std::complex &offset, size_t chan){ if (chan != ALL_CHANS){ - _tree->access >(tx_rf_fe_root(chan).branch_path() / "iq_balance" / "value").set(offset); + _tree->access >(tx_fe_root(chan) / "iq_balance" / "value").set(offset); return; } for (size_t c = 0; c < get_tx_num_channels(); c++){ @@ -758,6 +758,18 @@ private: return mb_root(mcp.mboard) / "tx_dsps" / name; } + fs_path rx_fe_root(const size_t chan){ + mboard_chan_pair mcp = rx_chan_to_mcp(chan); + const subdev_spec_pair_t spec = get_rx_subdev_spec(mcp.mboard).at(mcp.chan); + return mb_root(mcp.mboard) / "rx_frontends" / spec.db_name; + } + + fs_path tx_fe_root(const size_t chan){ + mboard_chan_pair mcp = tx_chan_to_mcp(chan); + const subdev_spec_pair_t spec = get_tx_subdev_spec(mcp.mboard).at(mcp.chan); + return mb_root(mcp.mboard) / "tx_frontends" / spec.db_name; + } + fs_path rx_rf_fe_root(const size_t chan){ mboard_chan_pair mcp = rx_chan_to_mcp(chan); const subdev_spec_pair_t spec = get_rx_subdev_spec(mcp.mboard).at(mcp.chan); diff --git a/host/lib/usrp/usrp1/usrp1_impl.cpp b/host/lib/usrp/usrp1/usrp1_impl.cpp index fcc4f36ae..6634b43da 100644 --- a/host/lib/usrp/usrp1/usrp1_impl.cpp +++ b/host/lib/usrp/usrp1/usrp1_impl.cpp @@ -272,10 +272,11 @@ usrp1_impl::usrp1_impl(const device_addr_t &device_addr){ .subscribe(boost::bind(&usrp1_impl::update_tx_subdev_spec, this, _1)); BOOST_FOREACH(const std::string &db, _dbc.keys()){ - _tree->create >(mb_path / "dboards" / db / "rx_frontends" / "dc_offset" / "value") + const fs_path rx_fe_path = mb_path / "rx_frontends" / db; + _tree->create >(rx_fe_path / "dc_offset" / "value") .coerce(boost::bind(&usrp1_impl::set_rx_dc_offset, this, db, _1)) .set(std::complex(0.0, 0.0)); - _tree->create(mb_path / "dboards" / db / "rx_frontends" / "dc_offset" / "enable") + _tree->create(rx_fe_path / "dc_offset" / "enable") .subscribe(boost::bind(&usrp1_impl::set_enb_rx_dc_offset, this, db, _1)) .set(true); } diff --git a/host/lib/usrp/usrp2/usrp2_impl.cpp b/host/lib/usrp/usrp2/usrp2_impl.cpp index 50916fb37..db707b6af 100644 --- a/host/lib/usrp/usrp2/usrp2_impl.cpp +++ b/host/lib/usrp/usrp2/usrp2_impl.cpp @@ -462,19 +462,22 @@ usrp2_impl::usrp2_impl(const device_addr_t &_device_addr){ _tree->create(mb_path / "tx_subdev_spec") .subscribe(boost::bind(&usrp2_impl::update_tx_subdev_spec, this, mb, _1)); - _tree->create >(mb_path / "dboards" / "A" / "rx_frontends" / "dc_offset" / "value") + const fs_path rx_fe_path = mb_path / "rx_frontends" / "A"; + const fs_path tx_fe_path = mb_path / "rx_frontends" / "A"; + + _tree->create >(rx_fe_path / "dc_offset" / "value") .coerce(boost::bind(&rx_frontend_core_200::set_dc_offset, _mbc[mb].rx_fe, _1)) .set(std::complex(0.0, 0.0)); - _tree->create(mb_path / "dboards" / "A" / "rx_frontends" / "dc_offset" / "enable") + _tree->create(rx_fe_path / "dc_offset" / "enable") .subscribe(boost::bind(&rx_frontend_core_200::set_dc_offset_auto, _mbc[mb].rx_fe, _1)) .set(true); - _tree->create >(mb_path / "dboards" / "A" / "rx_frontends" / "iq_balance" / "value") + _tree->create >(rx_fe_path / "iq_balance" / "value") .subscribe(boost::bind(&rx_frontend_core_200::set_iq_balance, _mbc[mb].rx_fe, _1)) .set(std::complex(0.0, 0.0)); - _tree->create >(mb_path / "dboards" / "A" / "tx_frontends" / "dc_offset" / "value") + _tree->create >(tx_fe_path / "dc_offset" / "value") .coerce(boost::bind(&tx_frontend_core_200::set_dc_offset, _mbc[mb].tx_fe, _1)) .set(std::complex(0.0, 0.0)); - _tree->create >(mb_path / "dboards" / "A" / "tx_frontends" / "iq_balance" / "value") + _tree->create >(tx_fe_path / "iq_balance" / "value") .subscribe(boost::bind(&tx_frontend_core_200::set_iq_balance, _mbc[mb].tx_fe, _1)) .set(std::complex(0.0, 0.0)); -- cgit v1.2.3 From 3a9edd27d6976456ea9cf4565590d4dd5bee809c Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Wed, 26 Oct 2011 10:21:11 -0700 Subject: usrp: added called to query bw range as well --- host/include/uhd/usrp/multi_usrp.hpp | 15 +++++++++++++++ host/lib/usrp/multi_usrp.cpp | 8 ++++++++ 2 files changed, 23 insertions(+) (limited to 'host') diff --git a/host/include/uhd/usrp/multi_usrp.hpp b/host/include/uhd/usrp/multi_usrp.hpp index 319301784..0509c2f1d 100644 --- a/host/include/uhd/usrp/multi_usrp.hpp +++ b/host/include/uhd/usrp/multi_usrp.hpp @@ -23,6 +23,7 @@ #define UHD_USRP_MULTI_USRP_GET_RATES_API #define UHD_USRP_MULTI_USRP_FRONTEND_CAL_API #define UHD_USRP_MULTI_USRP_COMMAND_TIME_API +#define UHD_USRP_MULTI_USRP_BW_RANGE_API #include #include @@ -504,6 +505,13 @@ public: */ virtual double get_rx_bandwidth(size_t chan = 0) = 0; + /*! + * Get the range of the possible RX bandwidth settings. + * \param chan the channel index 0 to N-1 + * \return a range of bandwidths in Hz + */ + virtual meta_range_t get_rx_bandwidth_range(size_t chan = 0) = 0; + /*! * Read the RSSI value on the RX frontend. * \param chan the channel index 0 to N-1 @@ -743,6 +751,13 @@ public: */ virtual double get_tx_bandwidth(size_t chan = 0) = 0; + /*! + * Get the range of the possible TX bandwidth settings. + * \param chan the channel index 0 to N-1 + * \return a range of bandwidths in Hz + */ + virtual meta_range_t get_tx_bandwidth_range(size_t chan = 0) = 0; + /*! * Get the dboard interface object for the TX frontend. * The dboard interface gives access to GPIOs, SPI, I2C, low-speed ADC and DAC. diff --git a/host/lib/usrp/multi_usrp.cpp b/host/lib/usrp/multi_usrp.cpp index 43534ff37..d53004259 100644 --- a/host/lib/usrp/multi_usrp.cpp +++ b/host/lib/usrp/multi_usrp.cpp @@ -534,6 +534,10 @@ public: return _tree->access(rx_rf_fe_root(chan) / "bandwidth" / "value").get(); } + meta_range_t get_rx_bandwidth_range(size_t chan){ + return _tree->access(rx_rf_fe_root(chan) / "bandwidth" / "range").get(); + } + dboard_iface::sptr get_rx_dboard_iface(size_t chan){ return _tree->access(rx_rf_fe_root(chan).branch_path().branch_path() / "iface").get(); } @@ -678,6 +682,10 @@ public: return _tree->access(tx_rf_fe_root(chan) / "bandwidth" / "value").get(); } + meta_range_t get_tx_bandwidth_range(size_t chan){ + return _tree->access(tx_rf_fe_root(chan) / "bandwidth" / "range").get(); + } + dboard_iface::sptr get_tx_dboard_iface(size_t chan){ return _tree->access(tx_rf_fe_root(chan).branch_path().branch_path() / "iface").get(); } -- cgit v1.2.3 From fbc5b54f49eec3f27e5a351d27260783898b0bea Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Wed, 26 Oct 2011 19:23:24 -0700 Subject: somebody made a typo --- host/lib/usrp/b100/b100_impl.cpp | 2 +- host/lib/usrp/e100/e100_impl.cpp | 2 +- host/lib/usrp/usrp2/usrp2_impl.cpp | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) (limited to 'host') diff --git a/host/lib/usrp/b100/b100_impl.cpp b/host/lib/usrp/b100/b100_impl.cpp index 944b669b2..a047a9a53 100644 --- a/host/lib/usrp/b100/b100_impl.cpp +++ b/host/lib/usrp/b100/b100_impl.cpp @@ -283,7 +283,7 @@ b100_impl::b100_impl(const device_addr_t &device_addr){ .subscribe(boost::bind(&b100_impl::update_tx_subdev_spec, this, _1)); const fs_path rx_fe_path = mb_path / "rx_frontends" / "A"; - const fs_path tx_fe_path = mb_path / "rx_frontends" / "A"; + const fs_path tx_fe_path = mb_path / "tx_frontends" / "A"; _tree->create >(rx_fe_path / "dc_offset" / "value") .coerce(boost::bind(&rx_frontend_core_200::set_dc_offset, _rx_fe, _1)) diff --git a/host/lib/usrp/e100/e100_impl.cpp b/host/lib/usrp/e100/e100_impl.cpp index 064686dd2..00916ec2b 100644 --- a/host/lib/usrp/e100/e100_impl.cpp +++ b/host/lib/usrp/e100/e100_impl.cpp @@ -257,7 +257,7 @@ e100_impl::e100_impl(const uhd::device_addr_t &device_addr){ .subscribe(boost::bind(&e100_impl::update_tx_subdev_spec, this, _1)); const fs_path rx_fe_path = mb_path / "rx_frontends" / "A"; - const fs_path tx_fe_path = mb_path / "rx_frontends" / "A"; + const fs_path tx_fe_path = mb_path / "tx_frontends" / "A"; _tree->create >(rx_fe_path / "dc_offset" / "value") .coerce(boost::bind(&rx_frontend_core_200::set_dc_offset, _rx_fe, _1)) diff --git a/host/lib/usrp/usrp2/usrp2_impl.cpp b/host/lib/usrp/usrp2/usrp2_impl.cpp index db707b6af..ac3ee2e69 100644 --- a/host/lib/usrp/usrp2/usrp2_impl.cpp +++ b/host/lib/usrp/usrp2/usrp2_impl.cpp @@ -463,7 +463,7 @@ usrp2_impl::usrp2_impl(const device_addr_t &_device_addr){ .subscribe(boost::bind(&usrp2_impl::update_tx_subdev_spec, this, mb, _1)); const fs_path rx_fe_path = mb_path / "rx_frontends" / "A"; - const fs_path tx_fe_path = mb_path / "rx_frontends" / "A"; + const fs_path tx_fe_path = mb_path / "tx_frontends" / "A"; _tree->create >(rx_fe_path / "dc_offset" / "value") .coerce(boost::bind(&rx_frontend_core_200::set_dc_offset, _mbc[mb].rx_fe, _1)) -- cgit v1.2.3 From 5cdbf5b36969e12b93e720f67102dd4ab246b074 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Thu, 3 Nov 2011 20:29:18 -0700 Subject: usrp: multi usrp API tweak --- host/include/uhd/usrp/multi_usrp.hpp | 15 ++++++++++----- host/lib/usrp/multi_usrp.cpp | 6 +++++- 2 files changed, 15 insertions(+), 6 deletions(-) (limited to 'host') diff --git a/host/include/uhd/usrp/multi_usrp.hpp b/host/include/uhd/usrp/multi_usrp.hpp index 0509c2f1d..5ea00565a 100644 --- a/host/include/uhd/usrp/multi_usrp.hpp +++ b/host/include/uhd/usrp/multi_usrp.hpp @@ -228,18 +228,23 @@ public: virtual bool get_time_synchronized(void) = 0; /*! - * Set the time at which the next control command will take effect. + * Set the time at which the control commands will take effect. * - * The time spec setting only takes effect on the first command. - * Subsequent commands will be sent ASAP unless user set time again. - * A timed command will throttle/back-pressure all subsequent commands, + * A timed command will back-pressure all subsequent timed commands, * assuming that the subsequent commands occur within the time-window. * If the time spec is late, the command will be activated upon arrival. * * \param time_spec the time at which the next command will activate * \param mboard which motherboard to set the config */ - virtual void set_next_command_time(const time_spec_t &time_spec, size_t mboard = ALL_MBOARDS) = 0; + virtual void set_command_time(const uhd::time_spec_t &time_spec, size_t mboard = ALL_MBOARDS) = 0; + + /*! + * Clear the command time so future commands are sent ASAP. + * + * \param mboard which motherboard to set the config + */ + virtual void clear_command_time(size_t mboard = ALL_MBOARDS) = 0; /*! * Issue a stream command to the usrp device. diff --git a/host/lib/usrp/multi_usrp.cpp b/host/lib/usrp/multi_usrp.cpp index d53004259..1110f5ebd 100644 --- a/host/lib/usrp/multi_usrp.cpp +++ b/host/lib/usrp/multi_usrp.cpp @@ -347,7 +347,11 @@ public: return true; } - void set_next_command_time(const time_spec_t &, size_t){ + void set_command_time(const time_spec_t &, size_t){ + throw uhd::not_implemented_error("Not implemented yet, but we have a very good idea of how to do it."); + } + + void clear_command_time(size_t){ throw uhd::not_implemented_error("Not implemented yet, but we have a very good idea of how to do it."); } -- cgit v1.2.3 From 07fb8d2b82c59ddaf7722b12db8c1387011fb34b Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Thu, 3 Nov 2011 20:34:06 -0700 Subject: usrp: fix rate calculation logic --- host/lib/usrp/cores/rx_dsp_core_200.cpp | 3 +-- host/lib/usrp/cores/tx_dsp_core_200.cpp | 3 +-- host/lib/usrp/usrp1/io_impl.cpp | 6 ++---- host/tests/ranges_test.cpp | 13 +++++++++++++ 4 files changed, 17 insertions(+), 8 deletions(-) (limited to 'host') diff --git a/host/lib/usrp/cores/rx_dsp_core_200.cpp b/host/lib/usrp/cores/rx_dsp_core_200.cpp index 6d306d507..b97f9c58e 100644 --- a/host/lib/usrp/cores/rx_dsp_core_200.cpp +++ b/host/lib/usrp/cores/rx_dsp_core_200.cpp @@ -149,8 +149,7 @@ public: } double set_host_rate(const double rate){ - const size_t decim_rate = this->get_host_rates().clip( - boost::math::iround(_tick_rate/rate), true); + const size_t decim_rate = boost::math::iround(_tick_rate/this->get_host_rates().clip(rate, true)); size_t decim = decim_rate; //determine which half-band filters are activated diff --git a/host/lib/usrp/cores/tx_dsp_core_200.cpp b/host/lib/usrp/cores/tx_dsp_core_200.cpp index 1d571ea7c..9d90d30cc 100644 --- a/host/lib/usrp/cores/tx_dsp_core_200.cpp +++ b/host/lib/usrp/cores/tx_dsp_core_200.cpp @@ -89,8 +89,7 @@ public: } double set_host_rate(const double rate){ - const size_t interp_rate = this->get_host_rates().clip( - boost::math::iround(_tick_rate/rate), true); + const size_t interp_rate = boost::math::iround(_tick_rate/this->get_host_rates().clip(rate, true)); size_t interp = interp_rate; //determine which half-band filters are activated diff --git a/host/lib/usrp/usrp1/io_impl.cpp b/host/lib/usrp/usrp1/io_impl.cpp index 31c834109..937706fdd 100644 --- a/host/lib/usrp/usrp1/io_impl.cpp +++ b/host/lib/usrp/usrp1/io_impl.cpp @@ -470,8 +470,7 @@ uhd::meta_range_t usrp1_impl::get_tx_dsp_host_rates(void){ double usrp1_impl::update_rx_samp_rate(size_t dspno, const double samp_rate){ const size_t div = this->has_rx_halfband()? 2 : 1; - const size_t rate = this->get_rx_dsp_host_rates().clip( - boost::math::iround(_master_clock_rate / samp_rate), true); + const size_t rate = boost::math::iround(_master_clock_rate/this->get_rx_dsp_host_rates().clip(samp_rate, true)); if (rate < 8 and this->has_rx_halfband()) UHD_MSG(warning) << "USRP1 cannot achieve decimations below 8 when the half-band filter is present.\n" @@ -499,8 +498,7 @@ double usrp1_impl::update_rx_samp_rate(size_t dspno, const double samp_rate){ double usrp1_impl::update_tx_samp_rate(size_t dspno, const double samp_rate){ const size_t div = this->has_tx_halfband()? 2 : 1; - const size_t rate = this->get_tx_dsp_host_rates().clip( - boost::math::iround(_master_clock_rate / samp_rate), true); + const size_t rate = boost::math::iround(_master_clock_rate/this->get_tx_dsp_host_rates().clip(samp_rate, true)); if (dspno == 0){ //only care if dsp0 is set since its homogeneous bool s = this->disable_tx(); diff --git a/host/tests/ranges_test.cpp b/host/tests/ranges_test.cpp index 5f6de4645..85bb4c3c4 100644 --- a/host/tests/ranges_test.cpp +++ b/host/tests/ranges_test.cpp @@ -55,3 +55,16 @@ BOOST_AUTO_TEST_CASE(test_ranges_clip){ BOOST_CHECK_CLOSE(mr.clip(50.9, false), 50.9, tolerance); BOOST_CHECK_CLOSE(mr.clip(50.9, true), 51.0, tolerance); } + +BOOST_AUTO_TEST_CASE(test_ranges_clip2){ + meta_range_t mr; + mr.push_back(range_t(1.)); + mr.push_back(range_t(2.)); + mr.push_back(range_t(3.)); + + BOOST_CHECK_CLOSE(mr.clip(2., true), 2., tolerance); + BOOST_CHECK_CLOSE(mr.clip(0., true), 1., tolerance); + BOOST_CHECK_CLOSE(mr.clip(1.2, true), 1., tolerance); + BOOST_CHECK_CLOSE(mr.clip(3.1, true), 3., tolerance); + BOOST_CHECK_CLOSE(mr.clip(4., true), 3., tolerance); +} -- cgit v1.2.3 From 69adaee902c5f409ebd7844667a0c253d7a06c6a Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Wed, 26 Oct 2011 19:31:35 -0700 Subject: usrp2: reg map change for GPIO core --- host/lib/usrp/cores/gpio_core_200.cpp | 12 ++++++------ host/lib/usrp/cores/gpio_core_200.hpp | 2 +- host/lib/usrp/usrp2/dboard_iface.cpp | 2 +- host/lib/usrp/usrp2/fw_common.h | 2 +- host/lib/usrp/usrp2/usrp2_regs.hpp | 2 ++ 5 files changed, 11 insertions(+), 9 deletions(-) (limited to 'host') diff --git a/host/lib/usrp/cores/gpio_core_200.cpp b/host/lib/usrp/cores/gpio_core_200.cpp index 8639b1851..d756097ff 100644 --- a/host/lib/usrp/cores/gpio_core_200.cpp +++ b/host/lib/usrp/cores/gpio_core_200.cpp @@ -23,15 +23,14 @@ #define REG_GPIO_TX_ONLY _base + 8 #define REG_GPIO_BOTH _base + 12 #define REG_GPIO_DDR _base + 16 -#define REG_GPIO_READ _base + 0 //any address will readback using namespace uhd; using namespace usrp; class gpio_core_200_impl : public gpio_core_200{ public: - gpio_core_200_impl(wb_iface::sptr iface, const size_t base): - _iface(iface), _base(base) { /* NOP */ } + gpio_core_200_impl(wb_iface::sptr iface, const size_t base, const size_t rb_addr): + _iface(iface), _base(base), _rb_addr(rb_addr) { /* NOP */ } void set_pin_ctrl(const unit_t unit, const boost::uint16_t value){ _pin_ctrl[unit] = value; //shadow @@ -57,12 +56,13 @@ public: } boost::uint16_t read_gpio(const unit_t unit){ - return boost::uint16_t(_iface->peek32(REG_GPIO_READ) >> unit2shit(unit)); + return boost::uint16_t(_iface->peek32(_rb_addr) >> unit2shit(unit)); } private: wb_iface::sptr _iface; const size_t _base; + const size_t _rb_addr; uhd::dict _pin_ctrl, _gpio_out, _gpio_ddr; uhd::dict > _atr_regs; @@ -95,6 +95,6 @@ private: }; -gpio_core_200::sptr gpio_core_200::make(wb_iface::sptr iface, const size_t base){ - return sptr(new gpio_core_200_impl(iface, base)); +gpio_core_200::sptr gpio_core_200::make(wb_iface::sptr iface, const size_t base, const size_t rb_addr){ + return sptr(new gpio_core_200_impl(iface, base, rb_addr)); } diff --git a/host/lib/usrp/cores/gpio_core_200.hpp b/host/lib/usrp/cores/gpio_core_200.hpp index 7ff2af649..278575874 100644 --- a/host/lib/usrp/cores/gpio_core_200.hpp +++ b/host/lib/usrp/cores/gpio_core_200.hpp @@ -33,7 +33,7 @@ public: typedef uhd::usrp::dboard_iface::atr_reg_t atr_reg_t; //! makes a new GPIO core from iface and slave base - static sptr make(wb_iface::sptr iface, const size_t base); + static sptr make(wb_iface::sptr iface, const size_t base, const size_t rb_addr); //! 1 = ATR virtual void set_pin_ctrl(const unit_t unit, const boost::uint16_t value) = 0; diff --git a/host/lib/usrp/usrp2/dboard_iface.cpp b/host/lib/usrp/usrp2/dboard_iface.cpp index c31fc52b7..bc510c8a1 100644 --- a/host/lib/usrp/usrp2/dboard_iface.cpp +++ b/host/lib/usrp/usrp2/dboard_iface.cpp @@ -107,7 +107,7 @@ usrp2_dboard_iface::usrp2_dboard_iface( ){ _iface = iface; _clock_ctrl = clock_ctrl; - _gpio = gpio_core_200::make(_iface, GPIO_BASE); + _gpio = gpio_core_200::make(_iface, U2_REG_SR_ADDR(SR_GPIO), U2_REG_GPIO_RB); //reset the aux dacs _dac_regs[UNIT_RX] = ad5623_regs_t(); diff --git a/host/lib/usrp/usrp2/fw_common.h b/host/lib/usrp/usrp2/fw_common.h index 7ad06f33f..62ba2d792 100644 --- a/host/lib/usrp/usrp2/fw_common.h +++ b/host/lib/usrp/usrp2/fw_common.h @@ -30,7 +30,7 @@ extern "C" { #endif //fpga and firmware compatibility numbers -#define USRP2_FPGA_COMPAT_NUM 7 +#define USRP2_FPGA_COMPAT_NUM 8 #define USRP2_FW_COMPAT_NUM 11 #define USRP2_FW_VER_MINOR 0 diff --git a/host/lib/usrp/usrp2/usrp2_regs.hpp b/host/lib/usrp/usrp2/usrp2_regs.hpp index 8839997f1..179a930c6 100644 --- a/host/lib/usrp/usrp2/usrp2_regs.hpp +++ b/host/lib/usrp/usrp2/usrp2_regs.hpp @@ -50,6 +50,7 @@ #define SR_TX_CTRL 144 // 6 #define SR_TX_DSP 160 // 5 +#define SR_GPIO 184 #define SR_UDP_SM 192 // 64 #define U2_REG_SR_ADDR(sr) (SETTING_REGS_BASE + (4 * (sr))) @@ -95,6 +96,7 @@ // Readback regs //////////////////////////////////////////////// #define U2_REG_STATUS READBACK_BASE + 4*8 +#define U2_REG_GPIO_RB READBACK_BASE + 4*9 #define U2_REG_TIME64_SECS_RB_IMM READBACK_BASE + 4*10 #define U2_REG_TIME64_TICKS_RB_IMM READBACK_BASE + 4*11 #define U2_REG_COMPAT_NUM_RB READBACK_BASE + 4*12 -- cgit v1.2.3 From 0e7c8c388a5dcbd70631526b42e08178300b93c4 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Thu, 27 Oct 2011 12:32:06 -0700 Subject: e100/b100: moved gpio regs and compat readback --- host/lib/usrp/b100/b100_impl.cpp | 14 ++++-- host/lib/usrp/b100/b100_impl.hpp | 2 +- host/lib/usrp/b100/b100_regs.hpp | 42 ++---------------- host/lib/usrp/b100/dboard_iface.cpp | 71 +++++------------------------- host/lib/usrp/e100/dboard_iface.cpp | 71 +++++------------------------- host/lib/usrp/e100/e100_impl.cpp | 26 +++++++---- host/lib/usrp/e100/e100_impl.hpp | 3 +- host/lib/usrp/e100/e100_regs.hpp | 42 ++---------------- host/usrp_e_utils/CMakeLists.txt | 2 - host/usrp_e_utils/usrp-e-debug-pins.c | 78 -------------------------------- host/usrp_e_utils/usrp-e-gpio.c | 83 ----------------------------------- 11 files changed, 58 insertions(+), 376 deletions(-) delete mode 100644 host/usrp_e_utils/usrp-e-debug-pins.c delete mode 100644 host/usrp_e_utils/usrp-e-gpio.c (limited to 'host') diff --git a/host/lib/usrp/b100/b100_impl.cpp b/host/lib/usrp/b100/b100_impl.cpp index a047a9a53..6bebc75ab 100644 --- a/host/lib/usrp/b100/b100_impl.cpp +++ b/host/lib/usrp/b100/b100_impl.cpp @@ -457,13 +457,19 @@ void b100_impl::check_fw_compat(void){ } void b100_impl::check_fpga_compat(void){ - const boost::uint16_t fpga_compat_num = _fpga_ctrl->peek16(B100_REG_MISC_COMPAT); - if (fpga_compat_num != B100_FPGA_COMPAT_NUM){ + const boost::uint32_t fpga_compat_num = _fpga_ctrl->peek32(B100_REG_RB_COMPAT); + boost::uint16_t fpga_major = fpga_compat_num >> 16, fpga_minor = fpga_compat_num & 0xffff; + if (fpga_major == 0){ //old version scheme + fpga_major = fpga_minor; + fpga_minor = 0; + } + if (fpga_major != B100_FPGA_COMPAT_NUM){ throw uhd::runtime_error(str(boost::format( - "Expected FPGA compatibility number 0x%x, but got 0x%x:\n" + "Expected FPGA compatibility number %d, but got %d:\n" "The FPGA build is not compatible with the host code build." - ) % B100_FPGA_COMPAT_NUM % fpga_compat_num)); + ) % int(B100_FPGA_COMPAT_NUM) % fpga_major)); } + _tree->create("/mboards/0/fpga_version").set(str(boost::format("%u.%u") % fpga_major % fpga_minor)); } double b100_impl::update_rx_codec_gain(const double gain){ diff --git a/host/lib/usrp/b100/b100_impl.hpp b/host/lib/usrp/b100/b100_impl.hpp index 25badc967..0984260be 100644 --- a/host/lib/usrp/b100/b100_impl.hpp +++ b/host/lib/usrp/b100/b100_impl.hpp @@ -47,7 +47,7 @@ static const double B100_LINK_RATE_BPS = 256e6/8; //pratical link rate static const std::string B100_FW_FILE_NAME = "usrp_b100_fw.ihx"; static const std::string B100_FPGA_FILE_NAME = "usrp_b100_fpga.bin"; static const boost::uint16_t B100_FW_COMPAT_NUM = 0x02; -static const boost::uint16_t B100_FPGA_COMPAT_NUM = 0x05; +static const boost::uint16_t B100_FPGA_COMPAT_NUM = 0x08; static const boost::uint32_t B100_RX_SID_BASE = 2; static const boost::uint32_t B100_TX_ASYNC_SID = 1; static const double B100_DEFAULT_TICK_RATE = 64e6; diff --git a/host/lib/usrp/b100/b100_regs.hpp b/host/lib/usrp/b100/b100_regs.hpp index 5e24f9937..491e16eef 100644 --- a/host/lib/usrp/b100/b100_regs.hpp +++ b/host/lib/usrp/b100/b100_regs.hpp @@ -31,7 +31,6 @@ #define B100_REG_MISC_RX_LEN B100_REG_MISC_BASE + 10 #define B100_REG_MISC_TX_LEN B100_REG_MISC_BASE + 12 #define B100_REG_MISC_XFER_RATE B100_REG_MISC_BASE + 14 -#define B100_REG_MISC_COMPAT B100_REG_MISC_BASE + 16 ///////////////////////////////////////////////////// // Slave 1 -- UART @@ -61,43 +60,6 @@ #define B100_REG_I2C_BASE B100_REG_SLAVE(3) -//////////////////////////////////////////////// -// Slave 4 -- GPIO - -#define B100_REG_GPIO_BASE B100_REG_SLAVE(4) - -#define B100_REG_GPIO_RX_IO B100_REG_GPIO_BASE + 0 -#define B100_REG_GPIO_TX_IO B100_REG_GPIO_BASE + 2 -#define B100_REG_GPIO_RX_DDR B100_REG_GPIO_BASE + 4 -#define B100_REG_GPIO_TX_DDR B100_REG_GPIO_BASE + 6 -#define B100_REG_GPIO_RX_SEL B100_REG_GPIO_BASE + 8 -#define B100_REG_GPIO_TX_SEL B100_REG_GPIO_BASE + 10 -#define B100_REG_GPIO_RX_DBG B100_REG_GPIO_BASE + 12 -#define B100_REG_GPIO_TX_DBG B100_REG_GPIO_BASE + 14 - -//possible bit values for sel when dbg is 0: -#define GPIO_SEL_SW 0 // if pin is an output, set by software in the io reg -#define GPIO_SEL_ATR 1 // if pin is an output, set by ATR logic - -//possible bit values for sel when dbg is 1: -#define GPIO_SEL_DEBUG_0 0 // if pin is an output, debug lines from FPGA fabric -#define GPIO_SEL_DEBUG_1 1 // if pin is an output, debug lines from FPGA fabric - -/////////////////////////////////////////////////// -// Slave 6 -- ATR Controller -// 16 regs - -#define B100_REG_ATR_BASE B100_REG_SLAVE(6) - -#define B100_REG_ATR_IDLE_RXSIDE B100_REG_ATR_BASE + 0 -#define B100_REG_ATR_IDLE_TXSIDE B100_REG_ATR_BASE + 2 -#define B100_REG_ATR_INTX_RXSIDE B100_REG_ATR_BASE + 4 -#define B100_REG_ATR_INTX_TXSIDE B100_REG_ATR_BASE + 6 -#define B100_REG_ATR_INRX_RXSIDE B100_REG_ATR_BASE + 8 -#define B100_REG_ATR_INRX_TXSIDE B100_REG_ATR_BASE + 10 -#define B100_REG_ATR_FULL_RXSIDE B100_REG_ATR_BASE + 12 -#define B100_REG_ATR_FULL_TXSIDE B100_REG_ATR_BASE + 14 - /////////////////////////////////////////////////// // Slave 7 -- Readback Mux 32 @@ -108,6 +70,8 @@ #define B100_REG_RB_TIME_PPS_SECS B100_REG_RB_MUX_32_BASE + 8 #define B100_REG_RB_TIME_PPS_TICKS B100_REG_RB_MUX_32_BASE + 12 #define B100_REG_RB_MISC_TEST32 B100_REG_RB_MUX_32_BASE + 16 +#define B100_REG_RB_COMPAT B100_REG_RB_MUX_32_BASE + 24 +#define B100_REG_RB_GPIO B100_REG_RB_MUX_32_BASE + 28 //////////////////////////////////////////////////// // Slaves 8 & 9 -- Settings Bus @@ -132,6 +96,8 @@ #define B100_SR_CLEAR_TX_FIFO 62 // 1 reg #define B100_SR_GLOBAL_RESET 63 // 1 reg +#define B100_SR_GPIO 128 + #define B100_REG_SR_ADDR(n) (B100_REG_SLAVE(8) + (4*(n))) #define B100_REG_SR_MISC_TEST32 B100_REG_SR_ADDR(B100_SR_REG_TEST32) diff --git a/host/lib/usrp/b100/dboard_iface.cpp b/host/lib/usrp/b100/dboard_iface.cpp index 229215a4e..39ad5c5ac 100644 --- a/host/lib/usrp/b100/dboard_iface.cpp +++ b/host/lib/usrp/b100/dboard_iface.cpp @@ -15,7 +15,7 @@ // along with this program. If not, see . // -#include "wb_iface.hpp" +#include "gpio_core_200.hpp" #include #include "b100_regs.hpp" #include "clock_ctrl.hpp" @@ -45,13 +45,11 @@ public: _spi_iface = spi_iface; _clock = clock; _codec = codec; + _gpio = gpio_core_200::make(_wb_iface, B100_REG_SR_ADDR(B100_SR_GPIO), B100_REG_RB_GPIO); //init the clock rate shadows this->set_clock_rate(UNIT_RX, _clock->get_fpga_clock_rate()); this->set_clock_rate(UNIT_TX, _clock->get_fpga_clock_rate()); - - _wb_iface->poke16(B100_REG_GPIO_RX_DBG, 0); - _wb_iface->poke16(B100_REG_GPIO_TX_DBG, 0); } ~b100_dboard_iface(void){ @@ -104,6 +102,7 @@ private: spi_iface::sptr _spi_iface; b100_clock_ctrl::sptr _clock; b100_codec_ctrl::sptr _codec; + gpio_core_200::sptr _gpio; }; /*********************************************************************** @@ -160,77 +159,27 @@ double b100_dboard_iface::get_codec_rate(unit_t){ * GPIO **********************************************************************/ void b100_dboard_iface::_set_pin_ctrl(unit_t unit, boost::uint16_t value){ - UHD_ASSERT_THROW(GPIO_SEL_ATR == 1); //make this assumption - switch(unit){ - case UNIT_RX: _wb_iface->poke16(B100_REG_GPIO_RX_SEL, value); return; - case UNIT_TX: _wb_iface->poke16(B100_REG_GPIO_TX_SEL, value); return; - } + return _gpio->set_pin_ctrl(unit, value); } void b100_dboard_iface::_set_gpio_ddr(unit_t unit, boost::uint16_t value){ - switch(unit){ - case UNIT_RX: _wb_iface->poke16(B100_REG_GPIO_RX_DDR, value); return; - case UNIT_TX: _wb_iface->poke16(B100_REG_GPIO_TX_DDR, value); return; - } + return _gpio->set_gpio_ddr(unit, value); } void b100_dboard_iface::_set_gpio_out(unit_t unit, boost::uint16_t value){ - switch(unit){ - case UNIT_RX: _wb_iface->poke16(B100_REG_GPIO_RX_IO, value); return; - case UNIT_TX: _wb_iface->poke16(B100_REG_GPIO_TX_IO, value); return; - } + return _gpio->set_gpio_out(unit, value); } boost::uint16_t b100_dboard_iface::read_gpio(unit_t unit){ - switch(unit){ - case UNIT_RX: return _wb_iface->peek16(B100_REG_GPIO_RX_IO); - case UNIT_TX: return _wb_iface->peek16(B100_REG_GPIO_TX_IO); - default: UHD_THROW_INVALID_CODE_PATH(); - } + return _gpio->read_gpio(unit); } void b100_dboard_iface::_set_atr_reg(unit_t unit, atr_reg_t atr, boost::uint16_t value){ - //define mapping of unit to atr regs to register address - static const uhd::dict< - unit_t, uhd::dict - > unit_to_atr_to_addr = map_list_of - (UNIT_RX, map_list_of - (ATR_REG_IDLE, B100_REG_ATR_IDLE_RXSIDE) - (ATR_REG_TX_ONLY, B100_REG_ATR_INTX_RXSIDE) - (ATR_REG_RX_ONLY, B100_REG_ATR_INRX_RXSIDE) - (ATR_REG_FULL_DUPLEX, B100_REG_ATR_FULL_RXSIDE) - ) - (UNIT_TX, map_list_of - (ATR_REG_IDLE, B100_REG_ATR_IDLE_TXSIDE) - (ATR_REG_TX_ONLY, B100_REG_ATR_INTX_TXSIDE) - (ATR_REG_RX_ONLY, B100_REG_ATR_INRX_TXSIDE) - (ATR_REG_FULL_DUPLEX, B100_REG_ATR_FULL_TXSIDE) - ) - ; - _wb_iface->poke16(unit_to_atr_to_addr[unit][atr], value); + return _gpio->set_atr_reg(unit, atr, value); } -void b100_dboard_iface::set_gpio_debug(unit_t unit, int which){ - //set this unit to all outputs - this->set_gpio_ddr(unit, 0xffff); - - //calculate the debug selections - boost::uint32_t dbg_sels = 0x0; - int sel = (which == 0)? GPIO_SEL_DEBUG_0 : GPIO_SEL_DEBUG_1; - for(size_t i = 0; i < 16; i++) dbg_sels |= sel << i; - - //set the debug on and which debug selection - switch(unit){ - case UNIT_RX: - _wb_iface->poke16(B100_REG_GPIO_RX_DBG, 0xffff); - _wb_iface->poke16(B100_REG_GPIO_RX_SEL, dbg_sels); - return; - - case UNIT_TX: - _wb_iface->poke16(B100_REG_GPIO_TX_DBG, 0xffff); - _wb_iface->poke16(B100_REG_GPIO_TX_SEL, dbg_sels); - return; - } +void b100_dboard_iface::set_gpio_debug(unit_t, int){ + throw uhd::not_implemented_error("no set_gpio_debug implemented"); } /*********************************************************************** diff --git a/host/lib/usrp/e100/dboard_iface.cpp b/host/lib/usrp/e100/dboard_iface.cpp index d45577bd9..6afc7bc48 100644 --- a/host/lib/usrp/e100/dboard_iface.cpp +++ b/host/lib/usrp/e100/dboard_iface.cpp @@ -15,7 +15,7 @@ // along with this program. If not, see . // -#include "wb_iface.hpp" +#include "gpio_core_200.hpp" #include #include "e100_regs.hpp" #include "clock_ctrl.hpp" @@ -45,13 +45,11 @@ public: _spi_iface = spi_iface; _clock = clock; _codec = codec; + _gpio = gpio_core_200::make(_wb_iface, E100_REG_SR_ADDR(UE_SR_GPIO), E100_REG_RB_GPIO); //init the clock rate shadows this->set_clock_rate(UNIT_RX, _clock->get_fpga_clock_rate()); this->set_clock_rate(UNIT_TX, _clock->get_fpga_clock_rate()); - - _wb_iface->poke16(E100_REG_GPIO_RX_DBG, 0); - _wb_iface->poke16(E100_REG_GPIO_TX_DBG, 0); } ~e100_dboard_iface(void){ @@ -104,6 +102,7 @@ private: spi_iface::sptr _spi_iface; e100_clock_ctrl::sptr _clock; e100_codec_ctrl::sptr _codec; + gpio_core_200::sptr _gpio; }; /*********************************************************************** @@ -160,77 +159,27 @@ double e100_dboard_iface::get_codec_rate(unit_t){ * GPIO **********************************************************************/ void e100_dboard_iface::_set_pin_ctrl(unit_t unit, boost::uint16_t value){ - UHD_ASSERT_THROW(GPIO_SEL_ATR == 1); //make this assumption - switch(unit){ - case UNIT_RX: _wb_iface->poke16(E100_REG_GPIO_RX_SEL, value); return; - case UNIT_TX: _wb_iface->poke16(E100_REG_GPIO_TX_SEL, value); return; - } + return _gpio->set_pin_ctrl(unit, value); } void e100_dboard_iface::_set_gpio_ddr(unit_t unit, boost::uint16_t value){ - switch(unit){ - case UNIT_RX: _wb_iface->poke16(E100_REG_GPIO_RX_DDR, value); return; - case UNIT_TX: _wb_iface->poke16(E100_REG_GPIO_TX_DDR, value); return; - } + return _gpio->set_gpio_ddr(unit, value); } void e100_dboard_iface::_set_gpio_out(unit_t unit, boost::uint16_t value){ - switch(unit){ - case UNIT_RX: _wb_iface->poke16(E100_REG_GPIO_RX_IO, value); return; - case UNIT_TX: _wb_iface->poke16(E100_REG_GPIO_TX_IO, value); return; - } + return _gpio->set_gpio_out(unit, value); } boost::uint16_t e100_dboard_iface::read_gpio(unit_t unit){ - switch(unit){ - case UNIT_RX: return _wb_iface->peek16(E100_REG_GPIO_RX_IO); - case UNIT_TX: return _wb_iface->peek16(E100_REG_GPIO_TX_IO); - default: UHD_THROW_INVALID_CODE_PATH(); - } + return _gpio->read_gpio(unit); } void e100_dboard_iface::_set_atr_reg(unit_t unit, atr_reg_t atr, boost::uint16_t value){ - //define mapping of unit to atr regs to register address - static const uhd::dict< - unit_t, uhd::dict - > unit_to_atr_to_addr = map_list_of - (UNIT_RX, map_list_of - (ATR_REG_IDLE, E100_REG_ATR_IDLE_RXSIDE) - (ATR_REG_TX_ONLY, E100_REG_ATR_INTX_RXSIDE) - (ATR_REG_RX_ONLY, E100_REG_ATR_INRX_RXSIDE) - (ATR_REG_FULL_DUPLEX, E100_REG_ATR_FULL_RXSIDE) - ) - (UNIT_TX, map_list_of - (ATR_REG_IDLE, E100_REG_ATR_IDLE_TXSIDE) - (ATR_REG_TX_ONLY, E100_REG_ATR_INTX_TXSIDE) - (ATR_REG_RX_ONLY, E100_REG_ATR_INRX_TXSIDE) - (ATR_REG_FULL_DUPLEX, E100_REG_ATR_FULL_TXSIDE) - ) - ; - _wb_iface->poke16(unit_to_atr_to_addr[unit][atr], value); + return _gpio->set_atr_reg(unit, atr, value); } -void e100_dboard_iface::set_gpio_debug(unit_t unit, int which){ - //set this unit to all outputs - this->set_gpio_ddr(unit, 0xffff); - - //calculate the debug selections - boost::uint32_t dbg_sels = 0x0; - int sel = (which == 0)? GPIO_SEL_DEBUG_0 : GPIO_SEL_DEBUG_1; - for(size_t i = 0; i < 16; i++) dbg_sels |= sel << i; - - //set the debug on and which debug selection - switch(unit){ - case UNIT_RX: - _wb_iface->poke16(E100_REG_GPIO_RX_DBG, 0xffff); - _wb_iface->poke16(E100_REG_GPIO_RX_SEL, dbg_sels); - return; - - case UNIT_TX: - _wb_iface->poke16(E100_REG_GPIO_TX_DBG, 0xffff); - _wb_iface->poke16(E100_REG_GPIO_TX_SEL, dbg_sels); - return; - } +void e100_dboard_iface::set_gpio_debug(unit_t, int){ + throw uhd::not_implemented_error("no set_gpio_debug implemented"); } /*********************************************************************** diff --git a/host/lib/usrp/e100/e100_impl.cpp b/host/lib/usrp/e100/e100_impl.cpp index 00916ec2b..8fe9081b1 100644 --- a/host/lib/usrp/e100/e100_impl.cpp +++ b/host/lib/usrp/e100/e100_impl.cpp @@ -167,15 +167,7 @@ e100_impl::e100_impl(const uhd::device_addr_t &device_addr){ ); //check that the compatibility is correct - const boost::uint16_t fpga_compat_num = _fpga_ctrl->peek16(E100_REG_MISC_COMPAT); - if (fpga_compat_num != E100_FPGA_COMPAT_NUM){ - throw uhd::runtime_error(str(boost::format( - "\nPlease update the FPGA image for your device.\n" - "See the application notes for USRP E-Series for instructions.\n" - "Expected FPGA compatibility number 0x%x, but got 0x%x:\n" - "The FPGA build is not compatible with the host code build." - ) % E100_FPGA_COMPAT_NUM % fpga_compat_num)); - } + this->check_fpga_compat(); //////////////////////////////////////////////////////////////////// // Create controller objects @@ -455,3 +447,19 @@ sensor_value_t e100_impl::get_ref_locked(void){ const bool lock = _clock_ctrl->get_locked(); return sensor_value_t("Ref", lock, "locked", "unlocked"); } + +void e100_impl::check_fpga_compat(void){ + const boost::uint32_t fpga_compat_num = _fpga_ctrl->peek32(E100_REG_RB_COMPAT); + boost::uint16_t fpga_major = fpga_compat_num >> 16, fpga_minor = fpga_compat_num & 0xffff; + if (fpga_major == 0){ //old version scheme + fpga_major = fpga_minor; + fpga_minor = 0; + } + if (fpga_major != E100_FPGA_COMPAT_NUM){ + throw uhd::runtime_error(str(boost::format( + "Expected FPGA compatibility number %d, but got %d:\n" + "The FPGA build is not compatible with the host code build." + ) % int(E100_FPGA_COMPAT_NUM) % fpga_major)); + } + _tree->create("/mboards/0/fpga_version").set(str(boost::format("%u.%u") % fpga_major % fpga_minor)); +} diff --git a/host/lib/usrp/e100/e100_impl.hpp b/host/lib/usrp/e100/e100_impl.hpp index 954d6bd93..f3e481b93 100644 --- a/host/lib/usrp/e100/e100_impl.hpp +++ b/host/lib/usrp/e100/e100_impl.hpp @@ -48,7 +48,7 @@ static const double E100_RX_LINK_RATE_BPS = 166e6/3/2*2; static const double E100_TX_LINK_RATE_BPS = 166e6/3/1*2; static const std::string E100_I2C_DEV_NODE = "/dev/i2c-3"; static const std::string E100_UART_DEV_NODE = "/dev/ttyO0"; -static const boost::uint16_t E100_FPGA_COMPAT_NUM = 0x06; +static const boost::uint16_t E100_FPGA_COMPAT_NUM = 0x08; static const boost::uint32_t E100_RX_SID_BASE = 2; static const boost::uint32_t E100_TX_ASYNC_SID = 1; static const double E100_DEFAULT_CLOCK_RATE = 64e6; @@ -129,6 +129,7 @@ private: void update_tx_subdev_spec(const uhd::usrp::subdev_spec_t &); void update_clock_source(const std::string &); uhd::sensor_value_t get_ref_locked(void); + void check_fpga_compat(void); }; diff --git a/host/lib/usrp/e100/e100_regs.hpp b/host/lib/usrp/e100/e100_regs.hpp index 28ef707dc..f24f5895b 100644 --- a/host/lib/usrp/e100/e100_regs.hpp +++ b/host/lib/usrp/e100/e100_regs.hpp @@ -31,7 +31,6 @@ #define E100_REG_MISC_RX_LEN E100_REG_MISC_BASE + 10 #define E100_REG_MISC_TX_LEN E100_REG_MISC_BASE + 12 #define E100_REG_MISC_XFER_RATE E100_REG_MISC_BASE + 14 -#define E100_REG_MISC_COMPAT E100_REG_MISC_BASE + 16 ///////////////////////////////////////////////////// // Slave 1 -- UART @@ -67,43 +66,6 @@ #define E100_REG_ERR_BUFF E100_REG_SLAVE(5) -//////////////////////////////////////////////// -// Slave 4 -- GPIO - -#define E100_REG_GPIO_BASE E100_REG_SLAVE(4) - -#define E100_REG_GPIO_RX_IO E100_REG_GPIO_BASE + 0 -#define E100_REG_GPIO_TX_IO E100_REG_GPIO_BASE + 2 -#define E100_REG_GPIO_RX_DDR E100_REG_GPIO_BASE + 4 -#define E100_REG_GPIO_TX_DDR E100_REG_GPIO_BASE + 6 -#define E100_REG_GPIO_RX_SEL E100_REG_GPIO_BASE + 8 -#define E100_REG_GPIO_TX_SEL E100_REG_GPIO_BASE + 10 -#define E100_REG_GPIO_RX_DBG E100_REG_GPIO_BASE + 12 -#define E100_REG_GPIO_TX_DBG E100_REG_GPIO_BASE + 14 - -//possible bit values for sel when dbg is 0: -#define GPIO_SEL_SW 0 // if pin is an output, set by software in the io reg -#define GPIO_SEL_ATR 1 // if pin is an output, set by ATR logic - -//possible bit values for sel when dbg is 1: -#define GPIO_SEL_DEBUG_0 0 // if pin is an output, debug lines from FPGA fabric -#define GPIO_SEL_DEBUG_1 1 // if pin is an output, debug lines from FPGA fabric - -/////////////////////////////////////////////////// -// Slave 6 -- ATR Controller -// 16 regs - -#define E100_REG_ATR_BASE E100_REG_SLAVE(6) - -#define E100_REG_ATR_IDLE_RXSIDE E100_REG_ATR_BASE + 0 -#define E100_REG_ATR_IDLE_TXSIDE E100_REG_ATR_BASE + 2 -#define E100_REG_ATR_INTX_RXSIDE E100_REG_ATR_BASE + 4 -#define E100_REG_ATR_INTX_TXSIDE E100_REG_ATR_BASE + 6 -#define E100_REG_ATR_INRX_RXSIDE E100_REG_ATR_BASE + 8 -#define E100_REG_ATR_INRX_TXSIDE E100_REG_ATR_BASE + 10 -#define E100_REG_ATR_FULL_RXSIDE E100_REG_ATR_BASE + 12 -#define E100_REG_ATR_FULL_TXSIDE E100_REG_ATR_BASE + 14 - /////////////////////////////////////////////////// // Slave 7 -- Readback Mux 32 @@ -115,6 +77,8 @@ #define E100_REG_RB_TIME_PPS_TICKS E100_REG_RB_MUX_32_BASE + 12 #define E100_REG_RB_MISC_TEST32 E100_REG_RB_MUX_32_BASE + 16 #define E100_REG_RB_ERR_STATUS E100_REG_RB_MUX_32_BASE + 20 +#define E100_REG_RB_COMPAT E100_REG_RB_MUX_32_BASE + 24 +#define E100_REG_RB_GPIO E100_REG_RB_MUX_32_BASE + 28 //////////////////////////////////////////////////// // Slave 8 -- Settings Bus @@ -141,6 +105,8 @@ #define UE_SR_CLEAR_TX_FIFO 62 // 1 reg #define UE_SR_GLOBAL_RESET 63 // 1 reg +#define UE_SR_GPIO 128 + #define E100_REG_SR_ADDR(n) (E100_REG_SLAVE(8) + (4*(n))) #define E100_REG_SR_MISC_TEST32 E100_REG_SR_ADDR(UE_SR_REG_TEST32) diff --git a/host/usrp_e_utils/CMakeLists.txt b/host/usrp_e_utils/CMakeLists.txt index 721a40093..2b099cc5d 100644 --- a/host/usrp_e_utils/CMakeLists.txt +++ b/host/usrp_e_utils/CMakeLists.txt @@ -29,8 +29,6 @@ IF(ENABLE_USRP_E_UTILS) SET(usrp_e_utils_sources usrp-e-loopback.cpp usrp-e-wb-test.cpp - usrp-e-debug-pins.c - usrp-e-gpio.c ) #for each source: build an executable and install diff --git a/host/usrp_e_utils/usrp-e-debug-pins.c b/host/usrp_e_utils/usrp-e-debug-pins.c deleted file mode 100644 index 570ae63d8..000000000 --- a/host/usrp_e_utils/usrp-e-debug-pins.c +++ /dev/null @@ -1,78 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include - -#include -#include "e100_regs.hpp" - -// Usage: usrp_e_gpio - -static int fp; - -static int read_reg(__u16 reg) -{ - int ret; - struct usrp_e_ctl16 d; - - d.offset = reg; - d.count = 1; - ret = ioctl(fp, USRP_E_READ_CTL16, &d); - return d.buf[0]; -} - -static void write_reg(__u16 reg, __u16 val) -{ - int ret; - struct usrp_e_ctl16 d; - - d.offset = reg; - d.count = 1; - d.buf[0] = val; - ret = ioctl(fp, USRP_E_WRITE_CTL16, &d); -} - -int main(int argc, char *argv[]) -{ - int test; - - test = 0; - if (argc < 2) { - printf("%s 0|1|off\n", argv[0]); - return -1; - } - - fp = open("/dev/usrp_e0", O_RDWR); - printf("fp = %d\n", fp); - if (fp < 0) { - perror("Open failed"); - return -1; - } - - if (strcmp(argv[1], "0") == 0) { - printf("Selected 0 based on %s\n", argv[1]); - write_reg(E100_REG_GPIO_TX_DDR, 0xFFFF); - write_reg(E100_REG_GPIO_RX_DDR, 0xFFFF); - write_reg(E100_REG_GPIO_TX_SEL, 0x0); - write_reg(E100_REG_GPIO_RX_SEL, 0x0); - write_reg(E100_REG_GPIO_TX_DBG, 0xFFFF); - write_reg(E100_REG_GPIO_RX_DBG, 0xFFFF); - } else if (strcmp(argv[1], "1") == 0) { - printf("Selected 1 based on %s\n", argv[1]); - write_reg(E100_REG_GPIO_TX_DDR, 0xFFFF); - write_reg(E100_REG_GPIO_RX_DDR, 0xFFFF); - write_reg(E100_REG_GPIO_TX_SEL, 0xFFFF); - write_reg(E100_REG_GPIO_RX_SEL, 0xFFFF); - write_reg(E100_REG_GPIO_TX_DBG, 0xFFFF); - write_reg(E100_REG_GPIO_RX_DBG, 0xFFFF); - } else { - printf("Selected off based on %s\n", argv[1]); - write_reg(E100_REG_GPIO_TX_DDR, 0x0); - write_reg(E100_REG_GPIO_RX_DDR, 0x0); - } - - return 0; -} diff --git a/host/usrp_e_utils/usrp-e-gpio.c b/host/usrp_e_utils/usrp-e-gpio.c deleted file mode 100644 index 4b788e945..000000000 --- a/host/usrp_e_utils/usrp-e-gpio.c +++ /dev/null @@ -1,83 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include - -#include "linux/usrp_e.h" -#include "e100_regs.hpp" - -// Usage: usrp_e_gpio - -static int fp; - -static int read_reg(__u16 reg) -{ - int ret; - struct usrp_e_ctl16 d; - - d.offset = reg; - d.count = 1; - ret = ioctl(fp, USRP_E_READ_CTL16, &d); - return d.buf[0]; -} - -static void write_reg(__u16 reg, __u16 val) -{ - int ret; - struct usrp_e_ctl16 d; - - d.offset = reg; - d.count = 1; - d.buf[0] = val; - ret = ioctl(fp, USRP_E_WRITE_CTL16, &d); -} - -int main(int argc, char *argv[]) -{ - int i, test, data_in; - - test = 0; - if (argc > 1) - test = 1; - - fp = open("/dev/usrp_e0", O_RDWR); - printf("fp = %d\n", fp); - - write_reg(E100_REG_GPIO_TX_DDR, 0x0); - write_reg(E100_REG_GPIO_RX_DDR, 0xFFFF); - - for (i=0; i < 16; i++) { - write_reg(E100_REG_GPIO_RX_IO, 1 << i); - sleep(1); - if (test) { - data_in = read_reg(E100_REG_GPIO_TX_IO); - if (data_in != (1 << i)) - printf("Read failed, wrote: %X read: %X\n", \ - 1 << i, data_in); - } - } - - write_reg(E100_REG_GPIO_RX_DDR, 0x0); - write_reg(E100_REG_GPIO_TX_DDR, 0xFFFF); - - sleep(1); - - for (i=0; i < 16; i++) { - write_reg(E100_REG_GPIO_TX_IO, 1 << i); - sleep(1); - if (test) { - data_in = read_reg(E100_REG_GPIO_RX_IO); - if (data_in != (1 << i)) - printf("Read failed, wrote: %X read: %X\n", \ - 1 << i, data_in); - } - } - - write_reg(E100_REG_GPIO_RX_DDR, 0x0); - write_reg(E100_REG_GPIO_TX_DDR, 0x0); - - return 0; -} -- cgit v1.2.3 From 9c598203327943b6ec042b031849ec6d7d907479 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Fri, 4 Nov 2011 23:23:47 +0000 Subject: e100/b100: init tree before filling it git log --- host/lib/usrp/b100/b100_impl.cpp | 2 +- host/lib/usrp/e100/e100_impl.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'host') diff --git a/host/lib/usrp/b100/b100_impl.cpp b/host/lib/usrp/b100/b100_impl.cpp index 6bebc75ab..c15816cc2 100644 --- a/host/lib/usrp/b100/b100_impl.cpp +++ b/host/lib/usrp/b100/b100_impl.cpp @@ -139,6 +139,7 @@ UHD_STATIC_BLOCK(register_b100_device){ * Structors **********************************************************************/ b100_impl::b100_impl(const device_addr_t &device_addr){ + _tree = property_tree::make(); //extract the FPGA path for the B100 std::string b100_fpga_image = find_image_path( @@ -226,7 +227,6 @@ b100_impl::b100_impl(const device_addr_t &device_addr){ //////////////////////////////////////////////////////////////////// // Initialize the properties tree //////////////////////////////////////////////////////////////////// - _tree = property_tree::make(); _tree->create("/name").set("B-Series Device"); const fs_path mb_path = "/mboards/0"; _tree->create(mb_path / "name").set("B100 (B-Hundo)"); diff --git a/host/lib/usrp/e100/e100_impl.cpp b/host/lib/usrp/e100/e100_impl.cpp index 8fe9081b1..2e3a635a6 100644 --- a/host/lib/usrp/e100/e100_impl.cpp +++ b/host/lib/usrp/e100/e100_impl.cpp @@ -106,6 +106,7 @@ UHD_STATIC_BLOCK(register_e100_device){ * Structors **********************************************************************/ e100_impl::e100_impl(const uhd::device_addr_t &device_addr){ + _tree = property_tree::make(); //setup the main interface into fpga const std::string node = device_addr["node"]; @@ -179,7 +180,6 @@ e100_impl::e100_impl(const uhd::device_addr_t &device_addr){ //////////////////////////////////////////////////////////////////// // Initialize the properties tree //////////////////////////////////////////////////////////////////// - _tree = property_tree::make(); _tree->create("/name").set("E-Series Device"); const fs_path mb_path = "/mboards/0"; _tree->create(mb_path / "name").set(str(boost::format("%s (euewanee)") % model)); -- cgit v1.2.3 From 8bb81824ea3544352cf528cbd67efd04bde681c9 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Sat, 5 Nov 2011 12:14:14 -0700 Subject: usrp: parse rx stream args scalar --- host/lib/usrp/b100/io_impl.cpp | 3 ++- host/lib/usrp/e100/io_impl.cpp | 3 ++- host/lib/usrp/usrp2/io_impl.cpp | 3 ++- 3 files changed, 6 insertions(+), 3 deletions(-) (limited to 'host') diff --git a/host/lib/usrp/b100/io_impl.cpp b/host/lib/usrp/b100/io_impl.cpp index 28b19f14e..abbd9864f 100644 --- a/host/lib/usrp/b100/io_impl.cpp +++ b/host/lib/usrp/b100/io_impl.cpp @@ -199,6 +199,7 @@ rx_streamer::sptr b100_impl::get_rx_stream(const uhd::stream_args_t &args_){ //setup defaults for unspecified values args.otw_format = args.otw_format.empty()? "sc16" : args.otw_format; args.channels = args.channels.empty()? std::vector(1, 0) : args.channels; + const unsigned sc8_scalar = unsigned(args.args.cast("scalar", 0x400)); //calculate packet size static const size_t hdr_size = 0 @@ -228,7 +229,7 @@ rx_streamer::sptr b100_impl::get_rx_stream(const uhd::stream_args_t &args_){ for (size_t chan_i = 0; chan_i < args.channels.size(); chan_i++){ const size_t dsp = args.channels[chan_i]; _rx_dsps[dsp]->set_nsamps_per_packet(spp); //seems to be a good place to set this - _rx_dsps[dsp]->set_format(args.otw_format, 0x400); + _rx_dsps[dsp]->set_format(args.otw_format, sc8_scalar); my_streamer->set_xport_chan_get_buff(chan_i, boost::bind( &recv_packet_demuxer::get_recv_buff, _io_impl->demuxer, dsp, _1 )); diff --git a/host/lib/usrp/e100/io_impl.cpp b/host/lib/usrp/e100/io_impl.cpp index c47eb8940..3b0828b45 100644 --- a/host/lib/usrp/e100/io_impl.cpp +++ b/host/lib/usrp/e100/io_impl.cpp @@ -275,6 +275,7 @@ rx_streamer::sptr e100_impl::get_rx_stream(const uhd::stream_args_t &args_){ //setup defaults for unspecified values args.otw_format = args.otw_format.empty()? "sc16" : args.otw_format; args.channels = args.channels.empty()? std::vector(1, 0) : args.channels; + const unsigned sc8_scalar = unsigned(args.args.cast("scalar", 0x400)); //calculate packet size static const size_t hdr_size = 0 @@ -304,7 +305,7 @@ rx_streamer::sptr e100_impl::get_rx_stream(const uhd::stream_args_t &args_){ for (size_t chan_i = 0; chan_i < args.channels.size(); chan_i++){ const size_t dsp = args.channels[chan_i]; _rx_dsps[dsp]->set_nsamps_per_packet(spp); //seems to be a good place to set this - _rx_dsps[dsp]->set_format(args.otw_format, 0x400); + _rx_dsps[dsp]->set_format(args.otw_format, sc8_scalar); my_streamer->set_xport_chan_get_buff(chan_i, boost::bind( &recv_packet_demuxer::get_recv_buff, _io_impl->demuxer, dsp, _1 )); diff --git a/host/lib/usrp/usrp2/io_impl.cpp b/host/lib/usrp/usrp2/io_impl.cpp index 660156285..d144c08bf 100644 --- a/host/lib/usrp/usrp2/io_impl.cpp +++ b/host/lib/usrp/usrp2/io_impl.cpp @@ -372,6 +372,7 @@ rx_streamer::sptr usrp2_impl::get_rx_stream(const uhd::stream_args_t &args_){ //setup defaults for unspecified values args.otw_format = args.otw_format.empty()? "sc16" : args.otw_format; args.channels = args.channels.empty()? std::vector(1, 0) : args.channels; + const unsigned sc8_scalar = unsigned(args.args.cast("scalar", 0x400)); //calculate packet size static const size_t hdr_size = 0 @@ -406,7 +407,7 @@ rx_streamer::sptr usrp2_impl::get_rx_stream(const uhd::stream_args_t &args_){ if (chan < num_chan_so_far){ const size_t dsp = num_chan_so_far - chan - 1; _mbc[mb].rx_dsps[dsp]->set_nsamps_per_packet(spp); //seems to be a good place to set this - _mbc[mb].rx_dsps[dsp]->set_format(args.otw_format, 0x400); + _mbc[mb].rx_dsps[dsp]->set_format(args.otw_format, sc8_scalar); my_streamer->set_xport_chan_get_buff(chan_i, boost::bind( &zero_copy_if::get_recv_buff, _mbc[mb].rx_dsp_xports[dsp], _1 )); -- cgit v1.2.3 From f3afd2eb94a65b4e6494c269ff67cd283dcad1de Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Sat, 5 Nov 2011 11:44:37 -0700 Subject: uhd: performance speed up for tx waveforms, no iterative libmath per sample --- host/examples/tx_waveforms.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'host') diff --git a/host/examples/tx_waveforms.cpp b/host/examples/tx_waveforms.cpp index 1eb6c2f1e..4abca5dae 100644 --- a/host/examples/tx_waveforms.cpp +++ b/host/examples/tx_waveforms.cpp @@ -76,7 +76,7 @@ public: } inline std::complex operator()(const double theta) const{ - return _wave_table[unsigned(boost::math::iround(theta*wave_table_len))%wave_table_len]; + return _wave_table[unsigned(theta*wave_table_len)%wave_table_len]; } private: @@ -100,7 +100,7 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){ desc.add_options() ("help", "help message") ("args", po::value(&args)->default_value(""), "single uhd device address args") - ("spb", po::value(&spb)->default_value(10000), "samples per buffer") + ("spb", po::value(&spb)->default_value(0), "samples per buffer, 0 for default") ("rate", po::value(&rate), "rate of outgoing samples") ("freq", po::value(&freq), "RF center frequency in Hz") ("ampl", po::value(&l)->default_value(float(0.3)), "amplitude of the waveform [0 to 0.7]") @@ -210,6 +210,7 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){ uhd::tx_streamer::sptr tx_stream = usrp->get_tx_stream(stream_args); //allocate a buffer which we re-use for each channel + if (spb == 0) spb = tx_stream->get_max_num_samps()*10; std::vector > buff(spb); std::vector *> buffs(usrp->get_tx_num_channels(), &buff.front()); -- cgit v1.2.3 From d9035414a27f484b89816e6e99c7f14d1769dee0 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Sat, 30 Jul 2011 10:11:49 -0700 Subject: usrp: work on dboard code to use subtrees to populate frontend props --- host/include/uhd/usrp/dboard_base.hpp | 62 +------ host/include/uhd/usrp/dboard_manager.hpp | 24 +-- host/lib/usrp/b100/b100_impl.cpp | 21 +-- host/lib/usrp/dboard/CMakeLists.txt | 22 +-- host/lib/usrp/dboard_base.cpp | 41 +---- host/lib/usrp/dboard_ctor_args.hpp | 2 + host/lib/usrp/dboard_manager.cpp | 273 ++++--------------------------- host/lib/usrp/e100/e100_impl.cpp | 21 +-- host/lib/usrp/usrp1/usrp1_impl.cpp | 21 +-- host/lib/usrp/usrp2/usrp2_impl.cpp | 21 +-- 10 files changed, 85 insertions(+), 423 deletions(-) (limited to 'host') diff --git a/host/include/uhd/usrp/dboard_base.hpp b/host/include/uhd/usrp/dboard_base.hpp index 7e9557a95..31b3643c7 100644 --- a/host/include/uhd/usrp/dboard_base.hpp +++ b/host/include/uhd/usrp/dboard_base.hpp @@ -19,7 +19,7 @@ #define INCLUDED_UHD_USRP_DBOARD_BASE_HPP #include -#include +#include #include #include #include @@ -28,43 +28,6 @@ namespace uhd{ namespace usrp{ - /*! - * Possible subdev connection types: - * - * A complex subdevice is physically connected to both channels, - * which may be connected in one of two ways: IQ or QI (swapped). - * - * A real subdevice is only physically connected one channel, - * either only the I channel or only the Q channel. - */ - enum subdev_conn_t{ - SUBDEV_CONN_COMPLEX_IQ = 'C', - SUBDEV_CONN_COMPLEX_QI = 'c', - SUBDEV_CONN_REAL_I = 'R', - SUBDEV_CONN_REAL_Q = 'r' - }; - - /*! - * Possible device subdev properties - */ - enum subdev_prop_t{ - SUBDEV_PROP_NAME, //ro, std::string - SUBDEV_PROP_OTHERS, //ro, prop_names_t - SUBDEV_PROP_SENSOR, //ro, sensor_value_t - SUBDEV_PROP_SENSOR_NAMES, //ro, prop_names_t - SUBDEV_PROP_GAIN, //rw, double - SUBDEV_PROP_GAIN_RANGE, //ro, gain_range_t - SUBDEV_PROP_GAIN_NAMES, //ro, prop_names_t - SUBDEV_PROP_FREQ, //rw, double - SUBDEV_PROP_FREQ_RANGE, //ro, freq_range_t - SUBDEV_PROP_ANTENNA, //rw, std::string - SUBDEV_PROP_ANTENNA_NAMES, //ro, prop_names_t - SUBDEV_PROP_CONNECTION, //ro, subdev_conn_t - SUBDEV_PROP_ENABLED, //rw, bool - SUBDEV_PROP_USE_LO_OFFSET, //ro, bool - SUBDEV_PROP_BANDWIDTH //rw, double - }; - /*! * A daughter board dboard_base class for all dboards. * Only other dboard dboard_base classes should inherit this. @@ -81,19 +44,14 @@ public: //structors dboard_base(ctor_args_t); - virtual ~dboard_base(void); - - //interface - virtual void rx_get(const wax::obj &key, wax::obj &val) = 0; - virtual void rx_set(const wax::obj &key, const wax::obj &val) = 0; - virtual void tx_get(const wax::obj &key, wax::obj &val) = 0; - virtual void tx_set(const wax::obj &key, const wax::obj &val) = 0; protected: std::string get_subdev_name(void); dboard_iface::sptr get_iface(void); dboard_id_t get_rx_id(void); dboard_id_t get_tx_id(void); + property_tree::sptr get_rx_subtree(void); + property_tree::sptr get_tx_subtree(void); private: UHD_PIMPL_DECL(impl) _impl; @@ -109,8 +67,6 @@ public: * Create a new xcvr dboard object, override in subclasses. */ xcvr_dboard_base(ctor_args_t); - - virtual ~xcvr_dboard_base(void); }; /*! @@ -123,12 +79,6 @@ public: * Create a new rx dboard object, override in subclasses. */ rx_dboard_base(ctor_args_t); - - virtual ~rx_dboard_base(void); - - //override here so the derived classes cannot - void tx_get(const wax::obj &key, wax::obj &val); - void tx_set(const wax::obj &key, const wax::obj &val); }; /*! @@ -141,12 +91,6 @@ public: * Create a new rx dboard object, override in subclasses. */ tx_dboard_base(ctor_args_t); - - virtual ~tx_dboard_base(void); - - //override here so the derived classes cannot - void rx_get(const wax::obj &key, wax::obj &val); - void rx_set(const wax::obj &key, const wax::obj &val); }; }} //namespace diff --git a/host/include/uhd/usrp/dboard_manager.hpp b/host/include/uhd/usrp/dboard_manager.hpp index 091769a5c..d3a3ffb5c 100644 --- a/host/include/uhd/usrp/dboard_manager.hpp +++ b/host/include/uhd/usrp/dboard_manager.hpp @@ -20,11 +20,12 @@ #include #include -#include #include #include #include #include +#include +#include namespace uhd{ namespace usrp{ @@ -37,11 +38,6 @@ class UHD_API dboard_manager : boost::noncopyable{ public: typedef boost::shared_ptr sptr; - //! It does what it says... - static void populate_prop_tree_from_subdev( - property_tree::sptr subtree, wax::obj subdev - ); - //dboard constructor (each dboard should have a ::make with this signature) typedef dboard_base::sptr(*dboard_ctor_t)(dboard_base::ctor_args_t); @@ -57,7 +53,7 @@ public: const dboard_id_t &dboard_id, dboard_ctor_t dboard_ctor, const std::string &name, - const prop_names_t &subdev_names = prop_names_t(1, "0") + const std::vector &subdev_names = std::vector(1, "0") ); /*! @@ -74,27 +70,25 @@ public: const dboard_id_t &tx_dboard_id, dboard_ctor_t dboard_ctor, const std::string &name, - const prop_names_t &subdev_names = prop_names_t(1, "0") + const std::vector &subdev_names = std::vector(1, "0") ); /*! * Make a new dboard manager. * \param rx_dboard_id the id of the rx dboard * \param tx_dboard_id the id of the tx dboard + * \param gdboard_id the id of the grand-dboard * \param iface the custom dboard interface + * \param subtree the subtree to load with props * \return an sptr to the new dboard manager */ static sptr make( dboard_id_t rx_dboard_id, dboard_id_t tx_dboard_id, - dboard_iface::sptr iface + dboard_id_t gdboard_id, + dboard_iface::sptr iface, + property_tree::sptr subtree ); - - //dboard manager interface - virtual prop_names_t get_rx_subdev_names(void) = 0; - virtual prop_names_t get_tx_subdev_names(void) = 0; - virtual wax::obj get_rx_subdev(const std::string &subdev_name) = 0; - virtual wax::obj get_tx_subdev(const std::string &subdev_name) = 0; }; }} //namespace diff --git a/host/lib/usrp/b100/b100_impl.cpp b/host/lib/usrp/b100/b100_impl.cpp index c15816cc2..c506559be 100644 --- a/host/lib/usrp/b100/b100_impl.cpp +++ b/host/lib/usrp/b100/b100_impl.cpp @@ -404,22 +404,9 @@ b100_impl::b100_impl(const device_addr_t &device_addr){ _dboard_iface = make_b100_dboard_iface(_fpga_ctrl, _fpga_i2c_ctrl, _fpga_spi_ctrl, _clock_ctrl, _codec_ctrl); _tree->create(mb_path / "dboards/A/iface").set(_dboard_iface); _dboard_manager = dboard_manager::make( - rx_db_eeprom.id, - ((gdb_eeprom.id == dboard_id_t::none())? tx_db_eeprom : gdb_eeprom).id, - _dboard_iface + rx_db_eeprom.id, tx_db_eeprom.id, gdb_eeprom.id, + _dboard_iface, _tree->subtree(mb_path / "dboards/A") ); - BOOST_FOREACH(const std::string &name, _dboard_manager->get_rx_subdev_names()){ - dboard_manager::populate_prop_tree_from_subdev( - _tree->subtree(mb_path / "dboards/A/rx_frontends" / name), - _dboard_manager->get_rx_subdev(name) - ); - } - BOOST_FOREACH(const std::string &name, _dboard_manager->get_tx_subdev_names()){ - dboard_manager::populate_prop_tree_from_subdev( - _tree->subtree(mb_path / "dboards/A/tx_frontends" / name), - _dboard_manager->get_tx_subdev(name) - ); - } //initialize io handling this->io_init(); @@ -432,8 +419,8 @@ b100_impl::b100_impl(const device_addr_t &device_addr){ _tree->access(mb_path / "tick_rate") //now subscribe the clock rate setter .subscribe(boost::bind(&b100_clock_ctrl::set_fpga_clock_rate, _clock_ctrl, _1)); - _tree->access(mb_path / "rx_subdev_spec").set(subdev_spec_t("A:"+_dboard_manager->get_rx_subdev_names()[0])); - _tree->access(mb_path / "tx_subdev_spec").set(subdev_spec_t("A:"+_dboard_manager->get_tx_subdev_names()[0])); + _tree->access(mb_path / "rx_subdev_spec").set(subdev_spec_t("A:" + _tree->list(mb_path / "dboards/A/rx_frontends").at(0))); + _tree->access(mb_path / "tx_subdev_spec").set(subdev_spec_t("A:" + _tree->list(mb_path / "dboards/A/tx_frontends").at(0))); _tree->access(mb_path / "clock_source/value").set("internal"); _tree->access(mb_path / "time_source/value").set("none"); } diff --git a/host/lib/usrp/dboard/CMakeLists.txt b/host/lib/usrp/dboard/CMakeLists.txt index c7b46e7c4..b5474ed16 100644 --- a/host/lib/usrp/dboard/CMakeLists.txt +++ b/host/lib/usrp/dboard/CMakeLists.txt @@ -20,16 +20,16 @@ ######################################################################## LIBUHD_APPEND_SOURCES( - ${CMAKE_CURRENT_SOURCE_DIR}/db_basic_and_lf.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/db_rfx.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/db_xcvr2450.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/db_sbx.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/db_wbx_common.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/db_wbx_simple.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/db_dbsrx.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/db_unknown.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/db_tvrx.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/db_dbsrx2.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/db_tvrx2.cpp + #${CMAKE_CURRENT_SOURCE_DIR}/db_basic_and_lf.cpp + #${CMAKE_CURRENT_SOURCE_DIR}/db_rfx.cpp + #${CMAKE_CURRENT_SOURCE_DIR}/db_xcvr2450.cpp + #${CMAKE_CURRENT_SOURCE_DIR}/db_sbx.cpp + #${CMAKE_CURRENT_SOURCE_DIR}/db_wbx_common.cpp + #${CMAKE_CURRENT_SOURCE_DIR}/db_wbx_simple.cpp + #${CMAKE_CURRENT_SOURCE_DIR}/db_dbsrx.cpp + #${CMAKE_CURRENT_SOURCE_DIR}/db_unknown.cpp + #${CMAKE_CURRENT_SOURCE_DIR}/db_tvrx.cpp + #${CMAKE_CURRENT_SOURCE_DIR}/db_dbsrx2.cpp + #${CMAKE_CURRENT_SOURCE_DIR}/db_tvrx2.cpp ) diff --git a/host/lib/usrp/dboard_base.cpp b/host/lib/usrp/dboard_base.cpp index e14c9d144..fe14c02b9 100644 --- a/host/lib/usrp/dboard_base.cpp +++ b/host/lib/usrp/dboard_base.cpp @@ -20,6 +20,7 @@ #include #include +using namespace uhd; using namespace uhd::usrp; /*********************************************************************** @@ -34,10 +35,6 @@ dboard_base::dboard_base(ctor_args_t args){ _impl->args = *static_cast(args); } -dboard_base::~dboard_base(void){ - /* NOP */ -} - std::string dboard_base::get_subdev_name(void){ return _impl->args.sd_name; } @@ -54,6 +51,14 @@ dboard_id_t dboard_base::get_tx_id(void){ return _impl->args.tx_id; } +property_tree::sptr dboard_base::get_rx_subtree(void){ + return _impl->args.rx_subtree; +} + +property_tree::sptr dboard_base::get_tx_subtree(void){ + return _impl->args.tx_subtree; +} + /*********************************************************************** * xcvr dboard dboard_base class **********************************************************************/ @@ -70,10 +75,6 @@ xcvr_dboard_base::xcvr_dboard_base(ctor_args_t args) : dboard_base(args){ } } -xcvr_dboard_base::~xcvr_dboard_base(void){ - /* NOP */ -} - /*********************************************************************** * rx dboard dboard_base class **********************************************************************/ @@ -86,18 +87,6 @@ rx_dboard_base::rx_dboard_base(ctor_args_t args) : dboard_base(args){ } } -rx_dboard_base::~rx_dboard_base(void){ - /* NOP */ -} - -void rx_dboard_base::tx_get(const wax::obj &, wax::obj &){ - throw uhd::runtime_error("cannot call tx_get on a rx dboard"); -} - -void rx_dboard_base::tx_set(const wax::obj &, const wax::obj &){ - throw uhd::runtime_error("cannot call tx_set on a rx dboard"); -} - /*********************************************************************** * tx dboard dboard_base class **********************************************************************/ @@ -109,15 +98,3 @@ tx_dboard_base::tx_dboard_base(ctor_args_t args) : dboard_base(args){ ) % get_rx_id().to_pp_string() % dboard_id_t::none().to_pp_string())); } } - -tx_dboard_base::~tx_dboard_base(void){ - /* NOP */ -} - -void tx_dboard_base::rx_get(const wax::obj &, wax::obj &){ - throw uhd::runtime_error("cannot call rx_get on a tx dboard"); -} - -void tx_dboard_base::rx_set(const wax::obj &, const wax::obj &){ - throw uhd::runtime_error("cannot call rx_set on a tx dboard"); -} diff --git a/host/lib/usrp/dboard_ctor_args.hpp b/host/lib/usrp/dboard_ctor_args.hpp index 708f2ea08..99c071ff8 100644 --- a/host/lib/usrp/dboard_ctor_args.hpp +++ b/host/lib/usrp/dboard_ctor_args.hpp @@ -18,6 +18,7 @@ #ifndef INCLUDED_LIBUHD_USRP_DBOARD_CTOR_ARGS_HPP #define INCLUDED_LIBUHD_USRP_DBOARD_CTOR_ARGS_HPP +#include #include #include #include @@ -29,6 +30,7 @@ namespace uhd{ namespace usrp{ std::string sd_name; dboard_iface::sptr db_iface; dboard_id_t rx_id, tx_id; + property_tree::sptr rx_subtree, tx_subtree; }; }} //namespace diff --git a/host/lib/usrp/dboard_manager.cpp b/host/lib/usrp/dboard_manager.cpp index 0326c28ce..816fba0c4 100644 --- a/host/lib/usrp/dboard_manager.cpp +++ b/host/lib/usrp/dboard_manager.cpp @@ -79,7 +79,7 @@ bool operator==(const dboard_key_t &lhs, const dboard_key_t &rhs){ * storage and registering for dboards **********************************************************************/ //dboard registry tuple: dboard constructor, canonical name, subdev names -typedef boost::tuple args_t; +typedef boost::tuple > args_t; //map a dboard id to a dboard constructor typedef uhd::dict id_to_args_map_t; @@ -89,7 +89,7 @@ static void register_dboard_key( const dboard_key_t &dboard_key, dboard_manager::dboard_ctor_t dboard_ctor, const std::string &name, - const prop_names_t &subdev_names + const std::vector &subdev_names ){ UHD_LOGV(always) << "registering: " << name << std::endl; if (get_id_to_args_map().has_key(dboard_key)){ @@ -110,7 +110,7 @@ void dboard_manager::register_dboard( const dboard_id_t &dboard_id, dboard_ctor_t dboard_ctor, const std::string &name, - const prop_names_t &subdev_names + const std::vector &subdev_names ){ register_dboard_key(dboard_key_t(dboard_id), dboard_ctor, name, subdev_names); } @@ -120,7 +120,7 @@ void dboard_manager::register_dboard( const dboard_id_t &tx_dboard_id, dboard_ctor_t dboard_ctor, const std::string &name, - const prop_names_t &subdev_names + const std::vector &subdev_names ){ register_dboard_key(dboard_key_t(rx_dboard_id, tx_dboard_id), dboard_ctor, name, subdev_names); } @@ -143,46 +143,6 @@ std::string dboard_id_t::to_pp_string(void) const{ return str(boost::format("%s (%s)") % this->to_cname() % this->to_string()); } -/*********************************************************************** - * internal helper classes - **********************************************************************/ -/*! - * A special wax proxy object that forwards calls to a subdev. - * A sptr to an instance will be used in the properties structure. - */ -class subdev_proxy : boost::noncopyable, public wax::obj{ -public: - typedef boost::shared_ptr sptr; - enum type_t{RX_TYPE, TX_TYPE}; - - //structors - subdev_proxy(dboard_base::sptr subdev, type_t type): - _subdev(subdev), _type(type) - { - /* NOP */ - } - -private: - dboard_base::sptr _subdev; - type_t _type; - - //forward the get calls to the rx or tx - void get(const wax::obj &key, wax::obj &val){ - switch(_type){ - case RX_TYPE: return _subdev->rx_get(key, val); - case TX_TYPE: return _subdev->tx_get(key, val); - } - } - - //forward the set calls to the rx or tx - void set(const wax::obj &key, const wax::obj &val){ - switch(_type){ - case RX_TYPE: return _subdev->rx_set(key, val); - case TX_TYPE: return _subdev->tx_set(key, val); - } - } -}; - /*********************************************************************** * dboard manager implementation class **********************************************************************/ @@ -192,23 +152,18 @@ public: dboard_manager_impl( dboard_id_t rx_dboard_id, dboard_id_t tx_dboard_id, - dboard_iface::sptr iface + dboard_iface::sptr iface, + property_tree::sptr subtree ); ~dboard_manager_impl(void); - //dboard_iface - prop_names_t get_rx_subdev_names(void); - prop_names_t get_tx_subdev_names(void); - wax::obj get_rx_subdev(const std::string &subdev_name); - wax::obj get_tx_subdev(const std::string &subdev_name); - private: - void init(dboard_id_t, dboard_id_t); + void init(dboard_id_t, dboard_id_t, property_tree::sptr); //list of rx and tx dboards in this dboard_manager //each dboard here is actually a subdevice proxy //the subdevice proxy is internal to the cpp file - uhd::dict _rx_dboards; - uhd::dict _tx_dboards; + uhd::dict _rx_dboards; + uhd::dict _tx_dboards; dboard_iface::sptr _iface; void set_nice_dboard_if(void); }; @@ -219,10 +174,16 @@ private: dboard_manager::sptr dboard_manager::make( dboard_id_t rx_dboard_id, dboard_id_t tx_dboard_id, - dboard_iface::sptr iface + dboard_id_t gdboard_id, + dboard_iface::sptr iface, + property_tree::sptr subtree ){ return dboard_manager::sptr( - new dboard_manager_impl(rx_dboard_id, tx_dboard_id, iface) + new dboard_manager_impl( + rx_dboard_id, + (gdboard_id == dboard_id_t::none())? tx_dboard_id : gdboard_id, + iface, subtree + ) ); } @@ -232,21 +193,22 @@ dboard_manager::sptr dboard_manager::make( dboard_manager_impl::dboard_manager_impl( dboard_id_t rx_dboard_id, dboard_id_t tx_dboard_id, - dboard_iface::sptr iface + dboard_iface::sptr iface, + property_tree::sptr subtree ): _iface(iface) { try{ - this->init(rx_dboard_id, tx_dboard_id); + this->init(rx_dboard_id, tx_dboard_id, subtree); } catch(const std::exception &e){ UHD_MSG(error) << "The daughterboard manager encountered a recoverable error in init" << std::endl << e.what(); - this->init(dboard_id_t::none(), dboard_id_t::none()); + this->init(dboard_id_t::none(), dboard_id_t::none(), subtree); } } void dboard_manager_impl::init( - dboard_id_t rx_dboard_id, dboard_id_t tx_dboard_id + dboard_id_t rx_dboard_id, dboard_id_t tx_dboard_id, property_tree::sptr subtree ){ //find the dboard key matches for the dboard ids dboard_key_t rx_dboard_key, tx_dboard_key, xcvr_dboard_key; @@ -283,7 +245,7 @@ void dboard_manager_impl::init( if (xcvr_dboard_key.is_xcvr()){ //extract data for the xcvr dboard key - dboard_ctor_t dboard_ctor; std::string name; prop_names_t subdevs; + dboard_ctor_t dboard_ctor; std::string name; std::vector subdevs; boost::tie(dboard_ctor, name, subdevs) = get_id_to_args_map()[xcvr_dboard_key]; //create the xcvr object for each subdevice @@ -291,15 +253,11 @@ void dboard_manager_impl::init( db_ctor_args.sd_name = subdev; db_ctor_args.rx_id = rx_dboard_id; db_ctor_args.tx_id = tx_dboard_id; + db_ctor_args.rx_subtree = subtree->subtree("rx_frontends/" + subdev); + db_ctor_args.tx_subtree = subtree->subtree("tx_frontends/" + subdev); dboard_base::sptr xcvr_dboard = dboard_ctor(&db_ctor_args); - //create a rx proxy for this xcvr board - _rx_dboards[subdev] = subdev_proxy::sptr( - new subdev_proxy(xcvr_dboard, subdev_proxy::RX_TYPE) - ); - //create a tx proxy for this xcvr board - _tx_dboards[subdev] = subdev_proxy::sptr( - new subdev_proxy(xcvr_dboard, subdev_proxy::TX_TYPE) - ); + _rx_dboards[subdev] = xcvr_dboard; + _tx_dboards[subdev] = xcvr_dboard; } } @@ -312,7 +270,7 @@ void dboard_manager_impl::init( } //extract data for the rx dboard key - dboard_ctor_t rx_dboard_ctor; std::string rx_name; prop_names_t rx_subdevs; + dboard_ctor_t rx_dboard_ctor; std::string rx_name; std::vector rx_subdevs; boost::tie(rx_dboard_ctor, rx_name, rx_subdevs) = get_id_to_args_map()[rx_dboard_key]; //make the rx subdevs @@ -320,11 +278,9 @@ void dboard_manager_impl::init( db_ctor_args.sd_name = subdev; db_ctor_args.rx_id = rx_dboard_id; db_ctor_args.tx_id = dboard_id_t::none(); - dboard_base::sptr rx_dboard = rx_dboard_ctor(&db_ctor_args); - //create a rx proxy for this rx board - _rx_dboards[subdev] = subdev_proxy::sptr( - new subdev_proxy(rx_dboard, subdev_proxy::RX_TYPE) - ); + db_ctor_args.rx_subtree = subtree->subtree("rx_frontends/" + subdev); + db_ctor_args.tx_subtree = property_tree::sptr(); //null + _rx_dboards[subdev] = rx_dboard_ctor(&db_ctor_args); } //force the tx key to the unknown board for bad combinations @@ -333,7 +289,7 @@ void dboard_manager_impl::init( } //extract data for the tx dboard key - dboard_ctor_t tx_dboard_ctor; std::string tx_name; prop_names_t tx_subdevs; + dboard_ctor_t tx_dboard_ctor; std::string tx_name; std::vector tx_subdevs; boost::tie(tx_dboard_ctor, tx_name, tx_subdevs) = get_id_to_args_map()[tx_dboard_key]; //make the tx subdevs @@ -341,11 +297,9 @@ void dboard_manager_impl::init( db_ctor_args.sd_name = subdev; db_ctor_args.rx_id = dboard_id_t::none(); db_ctor_args.tx_id = tx_dboard_id; - dboard_base::sptr tx_dboard = tx_dboard_ctor(&db_ctor_args); - //create a tx proxy for this tx board - _tx_dboards[subdev] = subdev_proxy::sptr( - new subdev_proxy(tx_dboard, subdev_proxy::TX_TYPE) - ); + db_ctor_args.rx_subtree = property_tree::sptr(); //null + db_ctor_args.tx_subtree = subtree->subtree("tx_frontends/" + subdev); + _tx_dboards[subdev] = tx_dboard_ctor(&db_ctor_args); } } } @@ -354,30 +308,6 @@ dboard_manager_impl::~dboard_manager_impl(void){UHD_SAFE_CALL( set_nice_dboard_if(); )} -prop_names_t dboard_manager_impl::get_rx_subdev_names(void){ - return _rx_dboards.keys(); -} - -prop_names_t dboard_manager_impl::get_tx_subdev_names(void){ - return _tx_dboards.keys(); -} - -wax::obj dboard_manager_impl::get_rx_subdev(const std::string &subdev_name){ - if (not _rx_dboards.has_key(subdev_name)) throw uhd::key_error( - str(boost::format("Unknown rx subdev name %s") % subdev_name) - ); - //get a link to the rx subdev proxy - return _rx_dboards[subdev_name]->get_link(); -} - -wax::obj dboard_manager_impl::get_tx_subdev(const std::string &subdev_name){ - if (not _tx_dboards.has_key(subdev_name)) throw uhd::key_error( - str(boost::format("Unknown tx subdev name %s") % subdev_name) - ); - //get a link to the tx subdev proxy - return _tx_dboards[subdev_name]->get_link(); -} - void dboard_manager_impl::set_nice_dboard_if(void){ //make a list of possible unit types std::vector units = boost::assign::list_of @@ -392,137 +322,4 @@ void dboard_manager_impl::set_nice_dboard_if(void){ _iface->set_pin_ctrl(unit, 0x0000); //all gpio _iface->set_clock_enabled(unit, false); //clock off } - - //disable all rx subdevices - BOOST_FOREACH(const std::string &sd_name, this->get_rx_subdev_names()){ - this->get_rx_subdev(sd_name)[SUBDEV_PROP_ENABLED] = false; - } - - //disable all tx subdevices - BOOST_FOREACH(const std::string &sd_name, this->get_tx_subdev_names()){ - this->get_tx_subdev(sd_name)[SUBDEV_PROP_ENABLED] = false; - } -} - -/*********************************************************************** - * Populate a properties tree from a subdev waxy object - **********************************************************************/ -#include -#include - -static sensor_value_t get_sensor(wax::obj subdev, const std::string &name){ - return subdev[named_prop_t(SUBDEV_PROP_SENSOR, name)].as(); -} - -static void set_gain(wax::obj subdev, const std::string &name, const double gain){ - subdev[named_prop_t(SUBDEV_PROP_GAIN, name)] = gain; -} - -static double get_gain(wax::obj subdev, const std::string &name){ - return subdev[named_prop_t(SUBDEV_PROP_GAIN, name)].as(); -} - -static meta_range_t get_gain_range(wax::obj subdev, const std::string &name){ - return subdev[named_prop_t(SUBDEV_PROP_GAIN_RANGE, name)].as(); -} - -static void set_freq(wax::obj subdev, const double freq){ - subdev[SUBDEV_PROP_FREQ] = freq; -} - -static double get_freq(wax::obj subdev){ - return subdev[SUBDEV_PROP_FREQ].as(); -} - -static meta_range_t get_freq_range(wax::obj subdev){ - return subdev[SUBDEV_PROP_FREQ_RANGE].as(); -} - -static void set_ant(wax::obj subdev, const std::string &ant){ - subdev[SUBDEV_PROP_ANTENNA] = ant; -} - -static std::string get_ant(wax::obj subdev){ - return subdev[SUBDEV_PROP_ANTENNA].as(); -} - -static std::vector get_ants(wax::obj subdev){ - return subdev[SUBDEV_PROP_ANTENNA_NAMES].as >(); -} - -static std::string get_conn(wax::obj subdev){ - switch(subdev[SUBDEV_PROP_CONNECTION].as()){ - case SUBDEV_CONN_COMPLEX_IQ: return "IQ"; - case SUBDEV_CONN_COMPLEX_QI: return "QI"; - case SUBDEV_CONN_REAL_I: return "I"; - case SUBDEV_CONN_REAL_Q: return "Q"; - } - UHD_THROW_INVALID_CODE_PATH(); -} - -static bool get_use_lo_off(wax::obj subdev){ - return subdev[SUBDEV_PROP_USE_LO_OFFSET].as(); -} - -static bool get_set_enb(wax::obj subdev, const bool enb){ - subdev[SUBDEV_PROP_ENABLED] = enb; - return subdev[SUBDEV_PROP_ENABLED].as(); -} - -static void set_bw(wax::obj subdev, const double freq){ - subdev[SUBDEV_PROP_BANDWIDTH] = freq; -} - -static double get_bw(wax::obj subdev){ - return subdev[SUBDEV_PROP_BANDWIDTH].as(); -} - -void dboard_manager::populate_prop_tree_from_subdev( - property_tree::sptr subtree, wax::obj subdev -){ - subtree->create("name").set(subdev[SUBDEV_PROP_NAME].as()); - - const prop_names_t sensor_names = subdev[SUBDEV_PROP_SENSOR_NAMES].as(); - subtree->create("sensors"); //phony property so this dir exists - BOOST_FOREACH(const std::string &name, sensor_names){ - subtree->create("sensors/" + name) - .publish(boost::bind(&get_sensor, subdev, name)); - } - - const prop_names_t gain_names = subdev[SUBDEV_PROP_GAIN_NAMES].as(); - subtree->create("gains"); //phony property so this dir exists - BOOST_FOREACH(const std::string &name, gain_names){ - subtree->create("gains/" + name + "/value") - .publish(boost::bind(&get_gain, subdev, name)) - .subscribe(boost::bind(&set_gain, subdev, name, _1)); - subtree->create("gains/" + name + "/range") - .publish(boost::bind(&get_gain_range, subdev, name)); - } - - subtree->create("freq/value") - .publish(boost::bind(&get_freq, subdev)) - .subscribe(boost::bind(&set_freq, subdev, _1)); - - subtree->create("freq/range") - .publish(boost::bind(&get_freq_range, subdev)); - - subtree->create("antenna/value") - .publish(boost::bind(&get_ant, subdev)) - .subscribe(boost::bind(&set_ant, subdev, _1)); - - subtree->create >("antenna/options") - .publish(boost::bind(&get_ants, subdev)); - - subtree->create("connection") - .publish(boost::bind(&get_conn, subdev)); - - subtree->create("enabled") - .coerce(boost::bind(&get_set_enb, subdev, _1)); - - subtree->create("use_lo_offset") - .publish(boost::bind(&get_use_lo_off, subdev)); - - subtree->create("bandwidth/value") - .publish(boost::bind(&get_bw, subdev)) - .subscribe(boost::bind(&set_bw, subdev, _1)); } diff --git a/host/lib/usrp/e100/e100_impl.cpp b/host/lib/usrp/e100/e100_impl.cpp index 2e3a635a6..c0a8f46f3 100644 --- a/host/lib/usrp/e100/e100_impl.cpp +++ b/host/lib/usrp/e100/e100_impl.cpp @@ -370,22 +370,9 @@ e100_impl::e100_impl(const uhd::device_addr_t &device_addr){ _dboard_iface = make_e100_dboard_iface(_fpga_ctrl, _fpga_i2c_ctrl, _fpga_spi_ctrl, _clock_ctrl, _codec_ctrl); _tree->create(mb_path / "dboards/A/iface").set(_dboard_iface); _dboard_manager = dboard_manager::make( - rx_db_eeprom.id, - ((gdb_eeprom.id == dboard_id_t::none())? tx_db_eeprom : gdb_eeprom).id, - _dboard_iface + rx_db_eeprom.id, tx_db_eeprom.id, gdb_eeprom.id, + _dboard_iface, _tree->subtree(mb_path / "dboards/A") ); - BOOST_FOREACH(const std::string &name, _dboard_manager->get_rx_subdev_names()){ - dboard_manager::populate_prop_tree_from_subdev( - _tree->subtree(mb_path / "dboards/A/rx_frontends" / name), - _dboard_manager->get_rx_subdev(name) - ); - } - BOOST_FOREACH(const std::string &name, _dboard_manager->get_tx_subdev_names()){ - dboard_manager::populate_prop_tree_from_subdev( - _tree->subtree(mb_path / "dboards/A/tx_frontends" / name), - _dboard_manager->get_tx_subdev(name) - ); - } //initialize io handling this->io_init(); @@ -398,8 +385,8 @@ e100_impl::e100_impl(const uhd::device_addr_t &device_addr){ _tree->access(mb_path / "tick_rate") //now subscribe the clock rate setter .subscribe(boost::bind(&e100_clock_ctrl::set_fpga_clock_rate, _clock_ctrl, _1)); - _tree->access(mb_path / "rx_subdev_spec").set(subdev_spec_t("A:"+_dboard_manager->get_rx_subdev_names()[0])); - _tree->access(mb_path / "tx_subdev_spec").set(subdev_spec_t("A:"+_dboard_manager->get_tx_subdev_names()[0])); + _tree->access(mb_path / "rx_subdev_spec").set(subdev_spec_t("A:" + _tree->list(mb_path / "dboards/A/rx_frontends").at(0))); + _tree->access(mb_path / "tx_subdev_spec").set(subdev_spec_t("A:" + _tree->list(mb_path / "dboards/A/tx_frontends").at(0))); _tree->access(mb_path / "clock_source/value").set("internal"); _tree->access(mb_path / "time_source/value").set("none"); diff --git a/host/lib/usrp/usrp1/usrp1_impl.cpp b/host/lib/usrp/usrp1/usrp1_impl.cpp index 6634b43da..4be5a3a2b 100644 --- a/host/lib/usrp/usrp1/usrp1_impl.cpp +++ b/host/lib/usrp/usrp1/usrp1_impl.cpp @@ -363,29 +363,16 @@ usrp1_impl::usrp1_impl(const device_addr_t &device_addr){ ); _tree->create(mb_path / "dboards" / db/ "iface").set(_dbc[db].dboard_iface); _dbc[db].dboard_manager = dboard_manager::make( - rx_db_eeprom.id, - ((gdb_eeprom.id == dboard_id_t::none())? tx_db_eeprom : gdb_eeprom).id, - _dbc[db].dboard_iface + rx_db_eeprom.id, tx_db_eeprom.id, gdb_eeprom.id, + _dbc[db].dboard_iface, _tree->subtree(mb_path / "dboards" / db) ); - BOOST_FOREACH(const std::string &name, _dbc[db].dboard_manager->get_rx_subdev_names()){ - dboard_manager::populate_prop_tree_from_subdev( - _tree->subtree(mb_path / "dboards" / db/ "rx_frontends" / name), - _dbc[db].dboard_manager->get_rx_subdev(name) - ); - } - BOOST_FOREACH(const std::string &name, _dbc[db].dboard_manager->get_tx_subdev_names()){ - dboard_manager::populate_prop_tree_from_subdev( - _tree->subtree(mb_path / "dboards" / db/ "tx_frontends" / name), - _dbc[db].dboard_manager->get_tx_subdev(name) - ); - } //init the subdev specs if we have a dboard (wont leave this loop empty) if (rx_db_eeprom.id != dboard_id_t::none() or _rx_subdev_spec.empty()){ - _rx_subdev_spec = subdev_spec_t(db + ":" + _dbc[db].dboard_manager->get_rx_subdev_names()[0]); + _rx_subdev_spec = subdev_spec_t(db + ":" + _tree->list(mb_path / "dboards" / db / "rx_frontends").at(0)); } if (tx_db_eeprom.id != dboard_id_t::none() or _tx_subdev_spec.empty()){ - _tx_subdev_spec = subdev_spec_t(db + ":" + _dbc[db].dboard_manager->get_tx_subdev_names()[0]); + _tx_subdev_spec = subdev_spec_t(db + ":" + _tree->list(mb_path / "dboards" / db / "tx_frontends").at(0)); } } diff --git a/host/lib/usrp/usrp2/usrp2_impl.cpp b/host/lib/usrp/usrp2/usrp2_impl.cpp index ac3ee2e69..bb3bfc7e4 100644 --- a/host/lib/usrp/usrp2/usrp2_impl.cpp +++ b/host/lib/usrp/usrp2/usrp2_impl.cpp @@ -597,22 +597,9 @@ usrp2_impl::usrp2_impl(const device_addr_t &_device_addr){ _mbc[mb].dboard_iface = make_usrp2_dboard_iface(_mbc[mb].iface, _mbc[mb].clock); _tree->create(mb_path / "dboards/A/iface").set(_mbc[mb].dboard_iface); _mbc[mb].dboard_manager = dboard_manager::make( - rx_db_eeprom.id, - ((gdb_eeprom.id == dboard_id_t::none())? tx_db_eeprom : gdb_eeprom).id, - _mbc[mb].dboard_iface + rx_db_eeprom.id, tx_db_eeprom.id, gdb_eeprom.id, + _mbc[mb].dboard_iface, _tree->subtree(mb_path / "dboards/A") ); - BOOST_FOREACH(const std::string &name, _mbc[mb].dboard_manager->get_rx_subdev_names()){ - dboard_manager::populate_prop_tree_from_subdev( - _tree->subtree(mb_path / "dboards/A/rx_frontends" / name), - _mbc[mb].dboard_manager->get_rx_subdev(name) - ); - } - BOOST_FOREACH(const std::string &name, _mbc[mb].dboard_manager->get_tx_subdev_names()){ - dboard_manager::populate_prop_tree_from_subdev( - _tree->subtree(mb_path / "dboards/A/tx_frontends" / name), - _mbc[mb].dboard_manager->get_tx_subdev(name) - ); - } } //initialize io handling @@ -623,8 +610,8 @@ usrp2_impl::usrp2_impl(const device_addr_t &_device_addr){ BOOST_FOREACH(const std::string &mb, _mbc.keys()){ fs_path root = "/mboards/" + mb; - _tree->access(root / "rx_subdev_spec").set(subdev_spec_t("A:"+_mbc[mb].dboard_manager->get_rx_subdev_names()[0])); - _tree->access(root / "tx_subdev_spec").set(subdev_spec_t("A:"+_mbc[mb].dboard_manager->get_tx_subdev_names()[0])); + _tree->access(root / "rx_subdev_spec").set(subdev_spec_t("A:" + _tree->list(root / "dboards/A/rx_frontends").at(0))); + _tree->access(root / "tx_subdev_spec").set(subdev_spec_t("A:" + _tree->list(root / "dboards/A/tx_frontends").at(0))); _tree->access(root / "clock_source/value").set("internal"); _tree->access(root / "time_source/value").set("none"); -- cgit v1.2.3 From ef256d2f6c14006ba27eaf2ba1a7fba3a828420a Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Sat, 30 Jul 2011 11:34:47 -0700 Subject: rfx: setup frontend property tree for rfx dboard --- host/lib/usrp/dboard/CMakeLists.txt | 2 +- host/lib/usrp/dboard/db_rfx.cpp | 320 ++++++++---------------------------- 2 files changed, 65 insertions(+), 257 deletions(-) (limited to 'host') diff --git a/host/lib/usrp/dboard/CMakeLists.txt b/host/lib/usrp/dboard/CMakeLists.txt index b5474ed16..adaaab683 100644 --- a/host/lib/usrp/dboard/CMakeLists.txt +++ b/host/lib/usrp/dboard/CMakeLists.txt @@ -21,7 +21,7 @@ LIBUHD_APPEND_SOURCES( #${CMAKE_CURRENT_SOURCE_DIR}/db_basic_and_lf.cpp - #${CMAKE_CURRENT_SOURCE_DIR}/db_rfx.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/db_rfx.cpp #${CMAKE_CURRENT_SOURCE_DIR}/db_xcvr2450.cpp #${CMAKE_CURRENT_SOURCE_DIR}/db_sbx.cpp #${CMAKE_CURRENT_SOURCE_DIR}/db_wbx_common.cpp diff --git a/host/lib/usrp/dboard/db_rfx.cpp b/host/lib/usrp/dboard/db_rfx.cpp index 14129ef72..3e6d89758 100644 --- a/host/lib/usrp/dboard/db_rfx.cpp +++ b/host/lib/usrp/dboard/db_rfx.cpp @@ -45,6 +45,7 @@ #include #include #include +#include #include #include @@ -55,11 +56,9 @@ using namespace boost::assign; /*********************************************************************** * The RFX Series constants **********************************************************************/ -static const prop_names_t rfx_tx_antennas = list_of("TX/RX"); +static const std::vector rfx_tx_antennas = list_of("TX/RX"); -static const prop_names_t rfx_rx_antennas = list_of("TX/RX")("RX2"); - -static const uhd::dict rfx_tx_gain_ranges; //empty +static const std::vector rfx_rx_antennas = list_of("TX/RX")("RX2"); static const uhd::dict rfx_rx_gain_ranges = map_list_of ("PGA0", gain_range_t(0, 70, 0.022)) @@ -81,27 +80,17 @@ public: ); ~rfx_xcvr(void); - void rx_get(const wax::obj &key, wax::obj &val); - void rx_set(const wax::obj &key, const wax::obj &val); - - void tx_get(const wax::obj &key, wax::obj &val); - void tx_set(const wax::obj &key, const wax::obj &val); - private: const freq_range_t _freq_range; const uhd::dict _rx_gain_ranges; const uhd::dict _div2; - double _rx_lo_freq, _tx_lo_freq; std::string _rx_ant; uhd::dict _rx_gains; boost::uint16_t _power_up; - void set_rx_lo_freq(double freq); - void set_tx_lo_freq(double freq); void set_rx_ant(const std::string &ant); void set_tx_ant(const std::string &ant); - void set_rx_gain(double gain, const std::string &name); - void set_tx_gain(double gain, const std::string &name); + double set_rx_gain(double gain, const std::string &name); /*! * Set the LO frequency for the particular dboard unit. @@ -114,17 +103,18 @@ private: /*! * Get the lock detect status of the LO. * \param unit which unit rx or tx - * \return true for locked + * \return sensor for locked */ - bool get_locked(dboard_iface::unit_t unit){ - return (this->get_iface()->read_gpio(unit) & LOCKDET_MASK) != 0; + sensor_value_t get_locked(dboard_iface::unit_t unit){ + const bool locked = (this->get_iface()->read_gpio(unit) & LOCKDET_MASK) != 0; + return sensor_value_t("LO", locked, "locked", "unlocked"); } /*! * Read the RSSI from the aux adc - * \return the rssi in dB + * \return the rssi sensor in dBm */ - double get_rssi(void){ + sensor_value_t get_rssi(void){ //RSSI from VAGC vs RF Power, Fig 34, pg 13 double max_power = -3.0; @@ -133,7 +123,8 @@ private: static const double rssi_dyn_range = 60; //calculate the rssi from the voltage double voltage = this->get_iface()->read_aux_adc(dboard_iface::UNIT_RX, dboard_iface::AUX_ADC_B); - return max_power - rssi_dyn_range*(voltage - min_v)/(max_v - min_v); + const double rssi = max_power - rssi_dyn_range*(voltage - min_v)/(max_v - min_v); + return sensor_value_t("RSSI", rssi, "dBm"); } }; @@ -192,6 +183,55 @@ rfx_xcvr::rfx_xcvr( ), _power_up((get_rx_id() == 0x0024 && get_tx_id() == 0x0028) ? POWER_IO : 0) { + //////////////////////////////////////////////////////////////////// + // Register RX properties + //////////////////////////////////////////////////////////////////// + this->get_rx_subtree()->create("name").set("RFX RX"); + this->get_rx_subtree()->create("sensors/lo_locked") + .publish(boost::bind(&rfx_xcvr::get_locked, this, dboard_iface::UNIT_RX)); + this->get_rx_subtree()->create("sensors/rssi") + .publish(boost::bind(&rfx_xcvr::get_rssi, this)); + BOOST_FOREACH(const std::string &name, _rx_gain_ranges.keys()){ + this->get_rx_subtree()->create("gains/"+name+"/value") + .coerce(boost::bind(&rfx_xcvr::set_rx_gain, this, _1, name)) + .set(_rx_gain_ranges[name].start()); + this->get_rx_subtree()->create("gains/"+name+"/range") + .set(_rx_gain_ranges[name]); + } + this->get_rx_subtree()->create("freq/value") + .coerce(boost::bind(&rfx_xcvr::set_lo_freq, this, dboard_iface::UNIT_RX, _1)) + .set((_freq_range.start() + _freq_range.stop())/2.0); + this->get_rx_subtree()->create("freq/range").set(_freq_range); + this->get_rx_subtree()->create("antenna/value") + .subscribe(boost::bind(&rfx_xcvr::set_rx_ant, this, _1)) + .set("RX2"); + this->get_rx_subtree()->create >("antenna/options") + .set(rfx_rx_antennas); + this->get_rx_subtree()->create("connection").set("QI"); + this->get_rx_subtree()->create("enabled").set(true); //always enabled + this->get_rx_subtree()->create("use_lo_offset").set(false); + this->get_rx_subtree()->create("bandwidth/value").set(2*20.0e6); //20MHz low-pass, we want complex double-sided + + //////////////////////////////////////////////////////////////////// + // Register TX properties + //////////////////////////////////////////////////////////////////// + this->get_tx_subtree()->create("name").set("RFX TX"); + this->get_tx_subtree()->create("sensors/lo_locked") + .publish(boost::bind(&rfx_xcvr::get_locked, this, dboard_iface::UNIT_TX)); + this->get_tx_subtree()->create("gains"); //phony property so this dir exists + this->get_tx_subtree()->create("freq/value") + .coerce(boost::bind(&rfx_xcvr::set_lo_freq, this, dboard_iface::UNIT_TX, _1)) + .set((_freq_range.start() + _freq_range.stop())/2.0); + this->get_tx_subtree()->create("freq/range").set(_freq_range); + this->get_tx_subtree()->create("antenna/value") + .subscribe(boost::bind(&rfx_xcvr::set_tx_ant, this, _1)).set(rfx_tx_antennas.at(0)); + this->get_tx_subtree()->create >("antenna/options") + .set(rfx_tx_antennas); + this->get_tx_subtree()->create("connection").set("IQ"); + this->get_tx_subtree()->create("enabled").set(true); //always enabled + this->get_tx_subtree()->create("use_lo_offset").set(true); + this->get_tx_subtree()->create("bandwidth/value").set(2*20.0e6); //20MHz low-pass, we want complex double-sided + //enable the clocks that we need this->get_iface()->set_clock_enabled(dboard_iface::UNIT_TX, true); this->get_iface()->set_clock_enabled(dboard_iface::UNIT_RX, true); @@ -213,15 +253,6 @@ rfx_xcvr::rfx_xcvr( this->get_iface()->set_atr_reg(dboard_iface::UNIT_RX, dboard_iface::ATR_REG_IDLE, _power_up | ANT_XX | MIXER_DIS); this->get_iface()->set_atr_reg(dboard_iface::UNIT_RX, dboard_iface::ATR_REG_TX_ONLY, _power_up | ANT_XX | MIXER_DIS); this->get_iface()->set_atr_reg(dboard_iface::UNIT_RX, dboard_iface::ATR_REG_FULL_DUPLEX, _power_up | ANT_RX2| MIXER_ENB); - - //set some default values - set_rx_lo_freq((_freq_range.start() + _freq_range.stop())/2.0); - set_tx_lo_freq((_freq_range.start() + _freq_range.stop())/2.0); - set_rx_ant("RX2"); - - BOOST_FOREACH(const std::string &name, _rx_gain_ranges.keys()){ - set_rx_gain(_rx_gain_ranges[name].start(), name); - } } rfx_xcvr::~rfx_xcvr(void){ @@ -267,20 +298,16 @@ static double rx_pga0_gain_to_dac_volts(double &gain, double range){ return dac_volts; } -void rfx_xcvr::set_tx_gain(double, const std::string &name){ - assert_has(rfx_tx_gain_ranges.keys(), name, "rfx tx gain name"); - UHD_THROW_INVALID_CODE_PATH(); //no gains to set -} - -void rfx_xcvr::set_rx_gain(double gain, const std::string &name){ +double rfx_xcvr::set_rx_gain(double gain, const std::string &name){ assert_has(_rx_gain_ranges.keys(), name, "rfx rx gain name"); if(name == "PGA0"){ double dac_volts = rx_pga0_gain_to_dac_volts(gain, (_rx_gain_ranges["PGA0"].stop() - _rx_gain_ranges["PGA0"].start())); - _rx_gains[name] = gain; //write the new voltage to the aux dac this->get_iface()->write_aux_dac(dboard_iface::UNIT_RX, dboard_iface::AUX_DAC_A, dac_volts); + + return gain; } else UHD_THROW_INVALID_CODE_PATH(); } @@ -288,14 +315,6 @@ void rfx_xcvr::set_rx_gain(double gain, const std::string &name){ /*********************************************************************** * Tuning **********************************************************************/ -void rfx_xcvr::set_rx_lo_freq(double freq){ - _rx_lo_freq = set_lo_freq(dboard_iface::UNIT_RX, freq); -} - -void rfx_xcvr::set_tx_lo_freq(double freq){ - _tx_lo_freq = set_lo_freq(dboard_iface::UNIT_TX, freq); -} - double rfx_xcvr::set_lo_freq( dboard_iface::unit_t unit, double target_freq @@ -408,214 +427,3 @@ double rfx_xcvr::set_lo_freq( ) % (actual_freq/1e6) << std::endl; return actual_freq; } - -/*********************************************************************** - * RX Get and Set - **********************************************************************/ -void rfx_xcvr::rx_get(const wax::obj &key_, wax::obj &val){ - named_prop_t key = named_prop_t::extract(key_); - - //handle the get request conditioned on the key - switch(key.as()){ - case SUBDEV_PROP_NAME: - val = get_rx_id().to_pp_string(); - return; - - case SUBDEV_PROP_OTHERS: - val = prop_names_t(); //empty - return; - - case SUBDEV_PROP_GAIN: - assert_has(_rx_gains.keys(), key.name, "rfx rx gain name"); - val = _rx_gains[key.name]; - return; - - case SUBDEV_PROP_GAIN_RANGE: - assert_has(_rx_gain_ranges.keys(), key.name, "rfx rx gain name"); - val = _rx_gain_ranges[key.name]; - return; - - case SUBDEV_PROP_GAIN_NAMES: - val = prop_names_t(_rx_gain_ranges.keys()); - return; - - case SUBDEV_PROP_FREQ: - val = _rx_lo_freq; - return; - - case SUBDEV_PROP_FREQ_RANGE: - val = _freq_range; - return; - - case SUBDEV_PROP_ANTENNA: - val = _rx_ant; - return; - - case SUBDEV_PROP_ANTENNA_NAMES: - val = rfx_rx_antennas; - return; - - case SUBDEV_PROP_CONNECTION: - val = SUBDEV_CONN_COMPLEX_QI; - return; - - case SUBDEV_PROP_ENABLED: - val = true; //always enabled - return; - - case SUBDEV_PROP_USE_LO_OFFSET: - val = false; - return; - - case SUBDEV_PROP_SENSOR: - if (key.name == "lo_locked") - val = sensor_value_t("LO", this->get_locked(dboard_iface::UNIT_RX), "locked", "unlocked"); - else if ((key.name == "rssi") and (get_rx_id() != 0x0024)) - val = sensor_value_t("RSSI", this->get_rssi(), "dBm"); - else - UHD_THROW_INVALID_CODE_PATH(); - return; - - case SUBDEV_PROP_SENSOR_NAMES:{ - prop_names_t names = list_of("lo_locked"); - if (get_rx_id() != 0x0024) names.push_back("rssi"); - val = names; - } - return; - - case SUBDEV_PROP_BANDWIDTH: - val = 2*20.0e6; //20MHz low-pass, we want complex double-sided - return; - - default: UHD_THROW_PROP_GET_ERROR(); - } -} - -void rfx_xcvr::rx_set(const wax::obj &key_, const wax::obj &val){ - named_prop_t key = named_prop_t::extract(key_); - - //handle the get request conditioned on the key - switch(key.as()){ - - case SUBDEV_PROP_FREQ: - this->set_rx_lo_freq(val.as()); - return; - - case SUBDEV_PROP_GAIN: - this->set_rx_gain(val.as(), key.name); - return; - - case SUBDEV_PROP_ANTENNA: - this->set_rx_ant(val.as()); - return; - - case SUBDEV_PROP_ENABLED: - return; //always enabled - - case SUBDEV_PROP_BANDWIDTH: - UHD_MSG(warning) << "RFX: No tunable bandwidth, fixed filtered to 40MHz"; - return; - - default: UHD_THROW_PROP_SET_ERROR(); - } -} - -/*********************************************************************** - * TX Get and Set - **********************************************************************/ -void rfx_xcvr::tx_get(const wax::obj &key_, wax::obj &val){ - named_prop_t key = named_prop_t::extract(key_); - - //handle the get request conditioned on the key - switch(key.as()){ - case SUBDEV_PROP_NAME: - val = get_tx_id().to_pp_string(); - return; - - case SUBDEV_PROP_OTHERS: - val = prop_names_t(); //empty - return; - - case SUBDEV_PROP_GAIN: - case SUBDEV_PROP_GAIN_RANGE: - assert_has(rfx_tx_gain_ranges.keys(), key.name, "rfx tx gain name"); - //no controllable tx gains, will not get here - return; - - case SUBDEV_PROP_GAIN_NAMES: - val = prop_names_t(rfx_tx_gain_ranges.keys()); - return; - - case SUBDEV_PROP_FREQ: - val = _tx_lo_freq; - return; - - case SUBDEV_PROP_FREQ_RANGE: - val = _freq_range; - return; - - case SUBDEV_PROP_ANTENNA: - val = std::string("TX/RX"); - return; - - case SUBDEV_PROP_ANTENNA_NAMES: - val = rfx_tx_antennas; - return; - - case SUBDEV_PROP_CONNECTION: - val = SUBDEV_CONN_COMPLEX_IQ; - return; - - case SUBDEV_PROP_ENABLED: - val = true; //always enabled - return; - - case SUBDEV_PROP_USE_LO_OFFSET: - val = true; - return; - - case SUBDEV_PROP_SENSOR: - UHD_ASSERT_THROW(key.name == "lo_locked"); - val = sensor_value_t("LO", this->get_locked(dboard_iface::UNIT_TX), "locked", "unlocked"); - return; - - case SUBDEV_PROP_SENSOR_NAMES: - val = prop_names_t(1, "lo_locked"); - return; - - case SUBDEV_PROP_BANDWIDTH: - val = 2*20.0e6; //20MHz low-pass, we want complex double-sided - return; - - default: UHD_THROW_PROP_GET_ERROR(); - } -} - -void rfx_xcvr::tx_set(const wax::obj &key_, const wax::obj &val){ - named_prop_t key = named_prop_t::extract(key_); - - //handle the get request conditioned on the key - switch(key.as()){ - - case SUBDEV_PROP_FREQ: - this->set_tx_lo_freq(val.as()); - return; - - case SUBDEV_PROP_GAIN: - this->set_tx_gain(val.as(), key.name); - return; - - case SUBDEV_PROP_ANTENNA: - this->set_tx_ant(val.as()); - return; - - case SUBDEV_PROP_ENABLED: - return; //always enabled - - case SUBDEV_PROP_BANDWIDTH: - UHD_MSG(warning) << "RFX: No tunable bandwidth, fixed filtered to 40MHz"; - return; - - default: UHD_THROW_PROP_SET_ERROR(); - } -} -- cgit v1.2.3 From a445f30003c415843a779fd40e67eeb670ab5d29 Mon Sep 17 00:00:00 2001 From: Jason Abele Date: Thu, 22 Sep 2011 13:44:26 -0700 Subject: Port of daughterboards from wax to new property trees Ported: Basic/LF Unknown XCVR DBSRX DBSRX2 TVRX TVRX2 --- host/lib/usrp/dboard/CMakeLists.txt | 14 +- host/lib/usrp/dboard/db_basic_and_lf.cpp | 282 ++++++---------------- host/lib/usrp/dboard/db_dbsrx.cpp | 200 +++++----------- host/lib/usrp/dboard/db_dbsrx2.cpp | 194 +++++---------- host/lib/usrp/dboard/db_rfx.cpp | 4 + host/lib/usrp/dboard/db_tvrx.cpp | 175 ++++---------- host/lib/usrp/dboard/db_tvrx2.cpp | 309 ++++++++++-------------- host/lib/usrp/dboard/db_unknown.cpp | 246 +++++-------------- host/lib/usrp/dboard/db_xcvr2450.cpp | 397 +++++++++++-------------------- 9 files changed, 572 insertions(+), 1249 deletions(-) (limited to 'host') diff --git a/host/lib/usrp/dboard/CMakeLists.txt b/host/lib/usrp/dboard/CMakeLists.txt index adaaab683..cb71e695b 100644 --- a/host/lib/usrp/dboard/CMakeLists.txt +++ b/host/lib/usrp/dboard/CMakeLists.txt @@ -20,16 +20,16 @@ ######################################################################## LIBUHD_APPEND_SOURCES( - #${CMAKE_CURRENT_SOURCE_DIR}/db_basic_and_lf.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/db_basic_and_lf.cpp ${CMAKE_CURRENT_SOURCE_DIR}/db_rfx.cpp - #${CMAKE_CURRENT_SOURCE_DIR}/db_xcvr2450.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/db_xcvr2450.cpp #${CMAKE_CURRENT_SOURCE_DIR}/db_sbx.cpp #${CMAKE_CURRENT_SOURCE_DIR}/db_wbx_common.cpp #${CMAKE_CURRENT_SOURCE_DIR}/db_wbx_simple.cpp - #${CMAKE_CURRENT_SOURCE_DIR}/db_dbsrx.cpp - #${CMAKE_CURRENT_SOURCE_DIR}/db_unknown.cpp - #${CMAKE_CURRENT_SOURCE_DIR}/db_tvrx.cpp - #${CMAKE_CURRENT_SOURCE_DIR}/db_dbsrx2.cpp - #${CMAKE_CURRENT_SOURCE_DIR}/db_tvrx2.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/db_dbsrx.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/db_unknown.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/db_tvrx.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/db_dbsrx2.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/db_tvrx2.cpp ) diff --git a/host/lib/usrp/dboard/db_basic_and_lf.cpp b/host/lib/usrp/dboard/db_basic_and_lf.cpp index 86d86dda0..971ecaeda 100644 --- a/host/lib/usrp/dboard/db_basic_and_lf.cpp +++ b/host/lib/usrp/dboard/db_basic_and_lf.cpp @@ -23,6 +23,7 @@ #include #include #include +#include #include using namespace uhd; @@ -48,9 +49,6 @@ public: basic_rx(ctor_args_t args, double max_freq); ~basic_rx(void); - void rx_get(const wax::obj &key, wax::obj &val); - void rx_set(const wax::obj &key, const wax::obj &val); - private: double _max_freq; }; @@ -60,18 +58,15 @@ public: basic_tx(ctor_args_t args, double max_freq); ~basic_tx(void); - void tx_get(const wax::obj &key, wax::obj &val); - void tx_set(const wax::obj &key, const wax::obj &val); - private: double _max_freq; }; -static const uhd::dict sd_name_to_conn = map_list_of - ("AB", SUBDEV_CONN_COMPLEX_IQ) - ("BA", SUBDEV_CONN_COMPLEX_QI) - ("A", SUBDEV_CONN_REAL_I) - ("B", SUBDEV_CONN_REAL_Q) +static const uhd::dict sd_name_to_conn = map_list_of + ("AB", "IQ") + ("BA", "QI") + ("A", "I") + ("B", "Q") ; /*********************************************************************** @@ -105,222 +100,95 @@ UHD_STATIC_BLOCK(reg_basic_and_lf_dboards){ **********************************************************************/ basic_rx::basic_rx(ctor_args_t args, double max_freq) : rx_dboard_base(args){ _max_freq = max_freq; + //this->get_iface()->set_clock_enabled(dboard_iface::UNIT_RX, true); + //////////////////////////////////////////////////////////////////// + // Register properties + //////////////////////////////////////////////////////////////////// + this->get_rx_subtree()->create("name").set( + std::string(str(boost::format("%s - %s") + % get_rx_id().to_pp_string() + % get_subdev_name() + ))); + this->get_rx_subtree()->create("gains"); //phony property so this dir exists + this->get_rx_subtree()->create("freq/value") + .set(double(0.0)); + this->get_rx_subtree()->create("freq/range") + .set(freq_range_t(-_max_freq, +_max_freq)); + this->get_rx_subtree()->create("antenna/value") + .set(""); + this->get_rx_subtree()->create >("antenna/options") + .set(list_of("")); + this->get_rx_subtree()->create("sensors"); //phony property so this dir exists + this->get_rx_subtree()->create("connection") + .set(sd_name_to_conn[get_subdev_name()]); + this->get_rx_subtree()->create("enabled") + .set(true); //always enabled + this->get_rx_subtree()->create("use_lo_offset") + .set(false); + this->get_rx_subtree()->create("bandwidth/value") + .set(subdev_bandwidth_scalar[get_subdev_name()]*_max_freq); + this->get_rx_subtree()->create("bandwidth/range") + .set(freq_range_t(subdev_bandwidth_scalar[get_subdev_name()]*_max_freq, subdev_bandwidth_scalar[get_subdev_name()]*_max_freq)); + + //enable RX dboard clock + this->get_iface()->set_clock_enabled(dboard_iface::UNIT_RX, true); + //set GPIOs to output 0x0000 to decrease noise pickup this->get_iface()->set_pin_ctrl(dboard_iface::UNIT_RX, 0x0000); this->get_iface()->set_gpio_ddr(dboard_iface::UNIT_RX, 0xFFFF); this->get_iface()->set_gpio_out(dboard_iface::UNIT_RX, 0x0000); - //this->get_iface()->set_clock_enabled(dboard_iface::UNIT_RX, true); } basic_rx::~basic_rx(void){ /* NOP */ } -void basic_rx::rx_get(const wax::obj &key_, wax::obj &val){ - named_prop_t key = named_prop_t::extract(key_); - - //handle the get request conditioned on the key - switch(key.as()){ - case SUBDEV_PROP_NAME: - val = std::string(str(boost::format("%s - %s") - % get_rx_id().to_pp_string() - % get_subdev_name() - )); - return; - - case SUBDEV_PROP_OTHERS: - val = prop_names_t(); //empty - return; - - case SUBDEV_PROP_GAIN: - val = double(0); - return; - - case SUBDEV_PROP_GAIN_RANGE: - val = gain_range_t(0, 0, 0); - return; - - case SUBDEV_PROP_GAIN_NAMES: - val = prop_names_t(); //empty - return; - - case SUBDEV_PROP_FREQ: - val = double(0); - return; - - case SUBDEV_PROP_FREQ_RANGE: - val = freq_range_t(-_max_freq, +_max_freq); - return; - - case SUBDEV_PROP_ANTENNA: - val = std::string(""); - return; - - case SUBDEV_PROP_ANTENNA_NAMES: - val = prop_names_t(1, ""); //vector of 1 empty string - return; - - case SUBDEV_PROP_SENSOR_NAMES: - val = std::vector(); //empty - return; - - case SUBDEV_PROP_CONNECTION: - val = sd_name_to_conn[get_subdev_name()]; - return; - - case SUBDEV_PROP_ENABLED: - val = true; //always enabled - return; - - case SUBDEV_PROP_USE_LO_OFFSET: - val = false; - return; - - case SUBDEV_PROP_BANDWIDTH: - val = subdev_bandwidth_scalar[get_subdev_name()]*_max_freq; - return; - - default: UHD_THROW_PROP_GET_ERROR(); - } -} - -void basic_rx::rx_set(const wax::obj &key_, const wax::obj &val){ - named_prop_t key = named_prop_t::extract(key_); - - //handle the get request conditioned on the key - switch(key.as()){ - - case SUBDEV_PROP_GAIN: - UHD_ASSERT_THROW(val.as() == double(0)); - return; - - case SUBDEV_PROP_ANTENNA: - if (val.as().empty()) return; - throw uhd::value_error("no selectable antennas on this board"); - - case SUBDEV_PROP_FREQ: - return; // it wont do you much good, but you can set it - - case SUBDEV_PROP_ENABLED: - return; //always enabled - - case SUBDEV_PROP_BANDWIDTH: - UHD_MSG(warning) << boost::format( - "%s: No tunable bandwidth, fixed filtered to %0.2fMHz" - ) % get_rx_id().to_pp_string() % _max_freq; - return; - - default: UHD_THROW_PROP_SET_ERROR(); - } -} - /*********************************************************************** * Basic and LF TX dboard **********************************************************************/ basic_tx::basic_tx(ctor_args_t args, double max_freq) : tx_dboard_base(args){ _max_freq = max_freq; //this->get_iface()->set_clock_enabled(dboard_iface::UNIT_TX, true); -} -basic_tx::~basic_tx(void){ - /* NOP */ -} - -void basic_tx::tx_get(const wax::obj &key_, wax::obj &val){ - named_prop_t key = named_prop_t::extract(key_); - - //handle the get request conditioned on the key - switch(key.as()){ - case SUBDEV_PROP_NAME: - val = std::string(str(boost::format("%s - %s") - % get_tx_id().to_pp_string() + //////////////////////////////////////////////////////////////////// + // Register properties + //////////////////////////////////////////////////////////////////// + this->get_tx_subtree()->create("name").set( + std::string(str(boost::format("%s - %s") + % get_rx_id().to_pp_string() % get_subdev_name() - )); - return; - - case SUBDEV_PROP_OTHERS: - val = prop_names_t(); //empty - return; - - case SUBDEV_PROP_GAIN: - val = double(0); - return; - - case SUBDEV_PROP_GAIN_RANGE: - val = gain_range_t(0, 0, 0); - return; - - case SUBDEV_PROP_GAIN_NAMES: - val = prop_names_t(); //empty - return; - - case SUBDEV_PROP_FREQ: - val = double(0); - return; - - case SUBDEV_PROP_FREQ_RANGE: - val = freq_range_t(-_max_freq, +_max_freq); - return; - - case SUBDEV_PROP_ANTENNA: - val = std::string(""); - return; - - case SUBDEV_PROP_ANTENNA_NAMES: - val = prop_names_t(1, ""); //vector of 1 empty string - return; - - case SUBDEV_PROP_SENSOR_NAMES: - val = std::vector(); //empty - return; - - case SUBDEV_PROP_CONNECTION: - val = sd_name_to_conn[get_subdev_name()]; - return; - - case SUBDEV_PROP_ENABLED: - val = true; //always enabled - return; - - case SUBDEV_PROP_USE_LO_OFFSET: - val = false; - return; - - case SUBDEV_PROP_BANDWIDTH: - val = subdev_bandwidth_scalar[get_subdev_name()]*_max_freq; - return; + ))); + this->get_tx_subtree()->create("gains"); //phony property so this dir exists + this->get_tx_subtree()->create("freq/value") + .set(double(0.0)); + this->get_tx_subtree()->create("freq/range") + .set(freq_range_t(-_max_freq, +_max_freq)); + this->get_tx_subtree()->create("antenna/value") + .set(""); + this->get_tx_subtree()->create >("antenna/options") + .set(list_of("")); + this->get_tx_subtree()->create("sensors"); //phony property so this dir exists + this->get_tx_subtree()->create("connection") + .set(sd_name_to_conn[get_subdev_name()]); + this->get_tx_subtree()->create("enabled") + .set(true); //always enabled + this->get_tx_subtree()->create("use_lo_offset") + .set(false); + this->get_tx_subtree()->create("bandwidth/value") + .set(subdev_bandwidth_scalar[get_subdev_name()]*_max_freq); + this->get_tx_subtree()->create("bandwidth/range") + .set(freq_range_t(subdev_bandwidth_scalar[get_subdev_name()]*_max_freq, subdev_bandwidth_scalar[get_subdev_name()]*_max_freq)); + + //enable TX dboard clock + this->get_iface()->set_clock_enabled(dboard_iface::UNIT_TX, true); - default: UHD_THROW_PROP_GET_ERROR(); - } + //set GPIOs to output 0x0000 to decrease noise pickup + this->get_iface()->set_pin_ctrl(dboard_iface::UNIT_TX, 0x0000); + this->get_iface()->set_gpio_ddr(dboard_iface::UNIT_TX, 0xFFFF); + this->get_iface()->set_gpio_out(dboard_iface::UNIT_TX, 0x0000); } -void basic_tx::tx_set(const wax::obj &key_, const wax::obj &val){ - named_prop_t key = named_prop_t::extract(key_); - - //handle the get request conditioned on the key - switch(key.as()){ - - case SUBDEV_PROP_GAIN: - UHD_ASSERT_THROW(val.as() == double(0)); - return; - - case SUBDEV_PROP_ANTENNA: - if (val.as().empty()) return; - throw uhd::value_error("no selectable antennas on this board"); - - case SUBDEV_PROP_FREQ: - return; // it wont do you much good, but you can set it - - case SUBDEV_PROP_ENABLED: - return; //always enabled - - case SUBDEV_PROP_BANDWIDTH: - UHD_MSG(warning) << boost::format( - "%s: No tunable bandwidth, fixed filtered to %0.2fMHz" - ) % get_tx_id().to_pp_string() % _max_freq; - return; - - default: UHD_THROW_PROP_SET_ERROR(); - } +basic_tx::~basic_tx(void){ + /* NOP */ } diff --git a/host/lib/usrp/dboard/db_dbsrx.cpp b/host/lib/usrp/dboard/db_dbsrx.cpp index c65c52590..7a90467ef 100644 --- a/host/lib/usrp/dboard/db_dbsrx.cpp +++ b/host/lib/usrp/dboard/db_dbsrx.cpp @@ -46,9 +46,12 @@ using namespace boost::assign; **********************************************************************/ static const freq_range_t dbsrx_freq_range(0.8e9, 2.4e9); +//Multiplied by 2.0 for conversion to complex bandpass from lowpass +static const freq_range_t dbsrx_bandwidth_range(2.0*4.0e6, 2.0*33.0e6); + static const freq_range_t dbsrx_pfd_freq_range(0.15e6, 2.01e6); -static const prop_names_t dbsrx_antennas = list_of("J3"); +static const std::vector dbsrx_antennas = list_of("J3"); static const uhd::dict dbsrx_gain_ranges = map_list_of ("GC1", gain_range_t(0, 56, 0.5)) @@ -63,9 +66,6 @@ public: dbsrx(ctor_args_t args); ~dbsrx(void); - void rx_get(const wax::obj &key, wax::obj &val); - void rx_set(const wax::obj &key, const wax::obj &val); - private: double _lo_freq; double _bandwidth; @@ -76,9 +76,9 @@ private: return (this->get_iface()->get_special_props().mangle_i2c_addrs)? 0x65 : 0x67; }; - void set_lo_freq(double target_freq); - void set_gain(double gain, const std::string &name); - void set_bandwidth(double bandwidth); + double set_lo_freq(double target_freq); + double set_gain(double gain, const std::string &name); + double set_bandwidth(double bandwidth); void send_reg(boost::uint8_t start_reg, boost::uint8_t stop_reg){ start_reg = boost::uint8_t(uhd::clip(int(start_reg), 0x0, 0x5)); @@ -136,10 +136,10 @@ private: } /*! - * Is the LO locked? - * \return true for locked + * Get the lock detect status of the LO. + * \return sensor for locked */ - bool get_locked(void){ + sensor_value_t get_locked(void){ read_reg(0x0, 0x0); //mask and return lock detect @@ -149,9 +149,8 @@ private: "DBSRX: locked %d" ) % locked << std::endl; - return locked; + return sensor_value_t("LO", locked, "locked", "unlocked"); } - }; /*********************************************************************** @@ -190,30 +189,58 @@ dbsrx::dbsrx(ctor_args_t args) : rx_dboard_base(args){ "Please see the daughterboard app notes" ) % this->get_rx_id().to_pp_string(); + //send initial register settings + this->send_reg(0x0, 0x5); + + //set defaults for LO, gains, and filter bandwidth + _bandwidth = 33e6; + + //////////////////////////////////////////////////////////////////// + // Register properties + //////////////////////////////////////////////////////////////////// + this->get_rx_subtree()->create("name") + .set(get_rx_id().to_pp_string()); + this->get_rx_subtree()->create("sensors/lo_locked") + .publish(boost::bind(&dbsrx::get_locked, this)); + BOOST_FOREACH(const std::string &name, dbsrx_gain_ranges.keys()){ + this->get_rx_subtree()->create("gains/"+name+"/value") + .coerce(boost::bind(&dbsrx::set_gain, this, _1, name)) + .set(dbsrx_gain_ranges[name].start()); + this->get_rx_subtree()->create("gains/"+name+"/range") + .set(dbsrx_gain_ranges[name]); + } + this->get_rx_subtree()->create("freq/value") + .coerce(boost::bind(&dbsrx::set_lo_freq, this, _1)) + .set(dbsrx_freq_range.start()); + this->get_rx_subtree()->create("freq/range") + .set(dbsrx_freq_range); + this->get_rx_subtree()->create("antenna/value") + .set(dbsrx_antennas.at(0)); + this->get_rx_subtree()->create >("antenna/options") + .set(dbsrx_antennas); + this->get_rx_subtree()->create("connection") + .set("IQ"); + this->get_rx_subtree()->create("enabled") + .set(true); //always enabled + this->get_rx_subtree()->create("use_lo_offset") + .set(false); + this->get_rx_subtree()->create("bandwidth/value") + .coerce(boost::bind(&dbsrx::set_bandwidth, this, _1)) + .set(2.0*_bandwidth); //_bandwidth in lowpass, convert to complex bandpass + this->get_rx_subtree()->create("bandwidth/range") + .set(dbsrx_bandwidth_range); + //enable only the clocks we need this->get_iface()->set_clock_enabled(dboard_iface::UNIT_RX, true); //set the gpio directions and atr controls (identically) this->get_iface()->set_pin_ctrl(dboard_iface::UNIT_RX, 0x0); // All unused in atr if (this->get_iface()->get_special_props().soft_clock_divider){ - this->get_iface()->set_gpio_ddr(dboard_iface::UNIT_RX, 0x1); // GPIO0 is clock + this->get_iface()->set_gpio_ddr(dboard_iface::UNIT_RX, 0x1); // GPIO0 is clock when on USRP1 } else{ this->get_iface()->set_gpio_ddr(dboard_iface::UNIT_RX, 0x0); // All Inputs } - - //send initial register settings - this->send_reg(0x0, 0x5); - - //set defaults for LO, gains, and filter bandwidth - _bandwidth = 33e6; - set_lo_freq(dbsrx_freq_range.start()); - - BOOST_FOREACH(const std::string &name, dbsrx_gain_ranges.keys()){ - set_gain(dbsrx_gain_ranges[name].start(), name); - } - - set_bandwidth(33e6); // default bandwidth from datasheet } dbsrx::~dbsrx(void){ @@ -223,7 +250,7 @@ dbsrx::~dbsrx(void){ /*********************************************************************** * Tuning **********************************************************************/ -void dbsrx::set_lo_freq(double target_freq){ +double dbsrx::set_lo_freq(double target_freq){ target_freq = dbsrx_freq_range.clip(target_freq); double actual_freq=0.0, pfd_freq=0.0, ref_clock=0.0; @@ -398,6 +425,8 @@ void dbsrx::set_lo_freq(double target_freq){ if (update_filter_settings) set_bandwidth(_bandwidth); get_locked(); + + return _lo_freq; } /*********************************************************************** @@ -456,7 +485,7 @@ static double gain_to_gc1_rfvga_dac(double &gain){ return dac_volts; } -void dbsrx::set_gain(double gain, const std::string &name){ +double dbsrx::set_gain(double gain, const std::string &name){ assert_has(dbsrx_gain_ranges.keys(), name, "dbsrx gain name"); if (name == "GC2"){ _max2118_write_regs.gc2 = gain_to_gc2_vga_reg(gain); @@ -468,14 +497,19 @@ void dbsrx::set_gain(double gain, const std::string &name){ } else UHD_THROW_INVALID_CODE_PATH(); _gains[name] = gain; + + return gain; } /*********************************************************************** * Bandwidth Handling **********************************************************************/ -void dbsrx::set_bandwidth(double bandwidth){ +double dbsrx::set_bandwidth(double bandwidth){ + //convert complex bandpass to lowpass bandwidth + bandwidth = bandwidth/2.0; + //clip the input - bandwidth = uhd::clip(bandwidth, 4e6, 33e6); + bandwidth = dbsrx_bandwidth_range.clip(bandwidth); double ref_clock = this->get_iface()->get_clock_rate(dboard_iface::UNIT_RX); @@ -492,109 +526,7 @@ void dbsrx::set_bandwidth(double bandwidth){ ) % (_bandwidth/1e6) % int(_max2118_write_regs.m_divider) % int(_max2118_write_regs.f_dac) << std::endl; this->send_reg(0x3, 0x4); -} - -/*********************************************************************** - * RX Get and Set - **********************************************************************/ -void dbsrx::rx_get(const wax::obj &key_, wax::obj &val){ - named_prop_t key = named_prop_t::extract(key_); - - //handle the get request conditioned on the key - switch(key.as()){ - case SUBDEV_PROP_NAME: - val = get_rx_id().to_pp_string(); - return; - - case SUBDEV_PROP_OTHERS: - val = prop_names_t(); //empty - return; - - case SUBDEV_PROP_GAIN: - assert_has(_gains.keys(), key.name, "dbsrx gain name"); - val = _gains[key.name]; - return; - - case SUBDEV_PROP_GAIN_RANGE: - assert_has(dbsrx_gain_ranges.keys(), key.name, "dbsrx gain name"); - val = dbsrx_gain_ranges[key.name]; - return; - - case SUBDEV_PROP_GAIN_NAMES: - val = prop_names_t(dbsrx_gain_ranges.keys()); - return; - - case SUBDEV_PROP_FREQ: - val = _lo_freq; - return; - - case SUBDEV_PROP_FREQ_RANGE: - val = dbsrx_freq_range; - return; - - case SUBDEV_PROP_ANTENNA: - val = dbsrx_antennas.at(0); - return; - - case SUBDEV_PROP_ANTENNA_NAMES: - val = dbsrx_antennas; - return; - - case SUBDEV_PROP_CONNECTION: - val = SUBDEV_CONN_COMPLEX_IQ; - return; - - case SUBDEV_PROP_ENABLED: - val = true; //always enabled - return; - - case SUBDEV_PROP_USE_LO_OFFSET: - val = false; - return; - - case SUBDEV_PROP_SENSOR: - UHD_ASSERT_THROW(key.name == "lo_locked"); - val = sensor_value_t("LO", this->get_locked(), "locked", "unlocked"); - return; - - case SUBDEV_PROP_SENSOR_NAMES: - val = prop_names_t(1, "lo_locked"); - return; - - case SUBDEV_PROP_BANDWIDTH: - val = 2*_bandwidth; //_bandwidth is low-pass, we want complex double-sided - return; - - default: UHD_THROW_PROP_GET_ERROR(); - } -} - -void dbsrx::rx_set(const wax::obj &key_, const wax::obj &val){ - named_prop_t key = named_prop_t::extract(key_); - - //handle the get request conditioned on the key - switch(key.as()){ - - case SUBDEV_PROP_FREQ: - this->set_lo_freq(val.as()); - return; - - case SUBDEV_PROP_ANTENNA: - assert_has(dbsrx_antennas, val.as(), "DBSRX antenna name"); - return; - case SUBDEV_PROP_GAIN: - this->set_gain(val.as(), key.name); - return; - - case SUBDEV_PROP_ENABLED: - return; //always enabled - - case SUBDEV_PROP_BANDWIDTH: - this->set_bandwidth(val.as()/2.0); //complex double-sided, we want low-pass - return; - - default: UHD_THROW_PROP_SET_ERROR(); - } + //convert lowpass back to complex bandpass bandwidth + return 2.0*_bandwidth; } - diff --git a/host/lib/usrp/dboard/db_dbsrx2.cpp b/host/lib/usrp/dboard/db_dbsrx2.cpp index f19236907..954d7083d 100644 --- a/host/lib/usrp/dboard/db_dbsrx2.cpp +++ b/host/lib/usrp/dboard/db_dbsrx2.cpp @@ -42,9 +42,12 @@ using namespace boost::assign; **********************************************************************/ static const freq_range_t dbsrx2_freq_range(0.8e9, 2.4e9); +//Multiplied by 2.0 for conversion to complex bandpass from lowpass +static const freq_range_t dbsrx2_bandwidth_range(2.0*4.0e6, 2.0*40.0e6); + static const int dbsrx2_ref_divider = 4; // Hitachi HMC426 divider (U7) -static const prop_names_t dbsrx2_antennas = list_of("J3"); +static const std::vector dbsrx2_antennas = list_of("J3"); static const uhd::dict dbsrx2_gain_ranges = map_list_of ("GC1", gain_range_t(0, 73, 0.05)) @@ -59,9 +62,6 @@ public: dbsrx2(ctor_args_t args); ~dbsrx2(void); - void rx_get(const wax::obj &key, wax::obj &val); - void rx_set(const wax::obj &key, const wax::obj &val); - private: double _lo_freq; double _bandwidth; @@ -72,9 +72,9 @@ private: return (this->get_iface()->get_special_props().mangle_i2c_addrs)? 0x60 : 0x61; } - void set_lo_freq(double target_freq); - void set_gain(double gain, const std::string &name); - void set_bandwidth(double bandwidth); + double set_lo_freq(double target_freq); + double set_gain(double gain, const std::string &name); + double set_bandwidth(double bandwidth); void send_reg(boost::uint8_t start_reg, boost::uint8_t stop_reg){ start_reg = boost::uint8_t(uhd::clip(int(start_reg), 0x0, 0xB)); @@ -146,10 +146,10 @@ private: } /*! - * Is the LO locked? - * \return true for locked + * Get the lock detect status of the LO. + * \return sensor for locked */ - bool get_locked(void){ + sensor_value_t get_locked(void){ read_reg(0xC, 0xD); //mask and return lock detect @@ -159,9 +159,8 @@ private: "DBSRX2 locked: %d" ) % locked << std::endl; - return locked; + return sensor_value_t("LO", locked, "locked", "unlocked"); } - }; /*********************************************************************** @@ -182,28 +181,53 @@ UHD_STATIC_BLOCK(reg_dbsrx2_dboard){ * Structors **********************************************************************/ dbsrx2::dbsrx2(ctor_args_t args) : rx_dboard_base(args){ - //enable only the clocks we need - this->get_iface()->set_clock_enabled(dboard_iface::UNIT_RX, true); - - //set the gpio directions and atr controls (identically) - this->get_iface()->set_pin_ctrl(dboard_iface::UNIT_RX, 0x0); // All unused in atr - this->get_iface()->set_gpio_ddr(dboard_iface::UNIT_RX, 0x0); // All Inputs - //send initial register settings send_reg(0x0, 0xB); //for (boost::uint8_t addr=0; addr<=12; addr++) this->send_reg(addr, addr); - //set defaults for LO, gains - set_lo_freq(dbsrx2_freq_range.start()); + //////////////////////////////////////////////////////////////////// + // Register properties + //////////////////////////////////////////////////////////////////// + this->get_rx_subtree()->create("name") + .set(get_rx_id().to_pp_string()); + this->get_rx_subtree()->create("sensors/lo_locked") + .publish(boost::bind(&dbsrx2::get_locked, this)); BOOST_FOREACH(const std::string &name, dbsrx2_gain_ranges.keys()){ - set_gain(dbsrx2_gain_ranges[name].start(), name); + this->get_rx_subtree()->create("gains/"+name+"/value") + .coerce(boost::bind(&dbsrx2::set_gain, this, _1, name)) + .set(dbsrx2_gain_ranges[name].start()); + this->get_rx_subtree()->create("gains/"+name+"/range") + .set(dbsrx2_gain_ranges[name]); } + this->get_rx_subtree()->create("freq/value") + .coerce(boost::bind(&dbsrx2::set_lo_freq, this, _1)) + .set(dbsrx2_freq_range.start()); + this->get_rx_subtree()->create("freq/range") + .set(dbsrx2_freq_range); + this->get_rx_subtree()->create("antenna/value") + .set(dbsrx2_antennas.at(0)); + this->get_rx_subtree()->create >("antenna/options") + .set(dbsrx2_antennas); + this->get_rx_subtree()->create("connection") + .set("QI"); + this->get_rx_subtree()->create("enabled") + .set(true); //always enabled + this->get_rx_subtree()->create("use_lo_offset") + .set(false); + this->get_rx_subtree()->create("bandwidth/value") + .coerce(boost::bind(&dbsrx2::set_bandwidth, this, _1)) + .set(2.0*40.0e6); //bandwidth in lowpass, convert to complex bandpass + this->get_rx_subtree()->create("bandwidth/range") + .set(dbsrx2_bandwidth_range); - set_bandwidth(40e6); // default bandwidth from datasheet - get_locked(); + //enable only the clocks we need + this->get_iface()->set_clock_enabled(dboard_iface::UNIT_RX, true); + + //set the gpio directions and atr controls (identically) + this->get_iface()->set_pin_ctrl(dboard_iface::UNIT_RX, 0x0); // All unused in atr + this->get_iface()->set_gpio_ddr(dboard_iface::UNIT_RX, 0x0); // All Inputs - _max2112_write_regs.bbg = boost::math::iround(dbsrx2_gain_ranges["BBG"].start()); - send_reg(0x9, 0x9); + get_locked(); } dbsrx2::~dbsrx2(void){ @@ -213,8 +237,8 @@ dbsrx2::~dbsrx2(void){ /*********************************************************************** * Tuning **********************************************************************/ -void dbsrx2::set_lo_freq(double target_freq){ - //target_freq = uhd::clip(target_freq, dbsrx2_freq_range.min, dbsrx2_freq_range.max); +double dbsrx2::set_lo_freq(double target_freq){ + //target_freq = dbsrx2_freq_range.clip(target_freq); //variables used in the calculation below int scaler = target_freq > 1125e6 ? 2 : 4; @@ -257,6 +281,7 @@ void dbsrx2::set_lo_freq(double target_freq){ //FIXME: probably unnecessary to call get_locked here //get_locked(); + return _lo_freq; } /*********************************************************************** @@ -309,7 +334,7 @@ static double gain_to_gc1_rfvga_dac(double &gain){ return dac_volts; } -void dbsrx2::set_gain(double gain, const std::string &name){ +double dbsrx2::set_gain(double gain, const std::string &name){ assert_has(dbsrx2_gain_ranges.keys(), name, "dbsrx2 gain name"); if (name == "BBG"){ _max2112_write_regs.bbg = gain_to_bbg_vga_reg(gain); @@ -321,14 +346,19 @@ void dbsrx2::set_gain(double gain, const std::string &name){ } else UHD_THROW_INVALID_CODE_PATH(); _gains[name] = gain; + + return gain; } /*********************************************************************** * Bandwidth Handling **********************************************************************/ -void dbsrx2::set_bandwidth(double bandwidth){ +double dbsrx2::set_bandwidth(double bandwidth){ + //convert complex bandpass to lowpass bandwidth + bandwidth = bandwidth/2.0; + //clip the input - bandwidth = uhd::clip(bandwidth, 4e6, 40e6); + bandwidth = dbsrx2_bandwidth_range.clip(bandwidth); _max2112_write_regs.lp = int((bandwidth/1e6 - 4)/0.29 + 12); _bandwidth = double(4 + (_max2112_write_regs.lp - 12) * 0.29)*1e6; @@ -339,105 +369,7 @@ void dbsrx2::set_bandwidth(double bandwidth){ << std::endl; this->send_reg(0x8, 0x8); -} -/*********************************************************************** - * RX Get and Set - **********************************************************************/ -void dbsrx2::rx_get(const wax::obj &key_, wax::obj &val){ - named_prop_t key = named_prop_t::extract(key_); - - //handle the get request conditioned on the key - switch(key.as()){ - case SUBDEV_PROP_NAME: - val = get_rx_id().to_pp_string(); - return; - - case SUBDEV_PROP_OTHERS: - val = prop_names_t(); //empty - return; - - case SUBDEV_PROP_GAIN: - assert_has(_gains.keys(), key.name, "dbsrx2 gain name"); - val = _gains[key.name]; - return; - - case SUBDEV_PROP_GAIN_RANGE: - assert_has(dbsrx2_gain_ranges.keys(), key.name, "dbsrx2 gain name"); - val = dbsrx2_gain_ranges[key.name]; - return; - - case SUBDEV_PROP_GAIN_NAMES: - val = prop_names_t(dbsrx2_gain_ranges.keys()); - return; - - case SUBDEV_PROP_FREQ: - val = _lo_freq; - return; - - case SUBDEV_PROP_FREQ_RANGE: - val = dbsrx2_freq_range; - return; - - case SUBDEV_PROP_ANTENNA: - val = std::string("J3"); - return; - - case SUBDEV_PROP_ANTENNA_NAMES: - val = dbsrx2_antennas; - return; - - case SUBDEV_PROP_CONNECTION: - val = SUBDEV_CONN_COMPLEX_QI; - return; - - case SUBDEV_PROP_ENABLED: - val = true; //always enabled - return; - - case SUBDEV_PROP_USE_LO_OFFSET: - val = false; - return; - - case SUBDEV_PROP_SENSOR: - UHD_ASSERT_THROW(key.name == "lo_locked"); - val = sensor_value_t("LO", this->get_locked(), "locked", "unlocked"); - return; - - case SUBDEV_PROP_SENSOR_NAMES: - val = prop_names_t(1, "lo_locked"); - return; - - case SUBDEV_PROP_BANDWIDTH: - val = _bandwidth; - return; - - default: UHD_THROW_PROP_GET_ERROR(); - } + //convert lowpass back to complex bandpass bandwidth + return 2.0*_bandwidth; } - -void dbsrx2::rx_set(const wax::obj &key_, const wax::obj &val){ - named_prop_t key = named_prop_t::extract(key_); - - //handle the get request conditioned on the key - switch(key.as()){ - - case SUBDEV_PROP_FREQ: - this->set_lo_freq(val.as()); - return; - - case SUBDEV_PROP_GAIN: - this->set_gain(val.as(), key.name); - return; - - case SUBDEV_PROP_ENABLED: - return; //always enabled - - case SUBDEV_PROP_BANDWIDTH: - this->set_bandwidth(val.as()); - return; - - default: UHD_THROW_PROP_SET_ERROR(); - } -} - diff --git a/host/lib/usrp/dboard/db_rfx.cpp b/host/lib/usrp/dboard/db_rfx.cpp index 3e6d89758..3896534cd 100644 --- a/host/lib/usrp/dboard/db_rfx.cpp +++ b/host/lib/usrp/dboard/db_rfx.cpp @@ -211,6 +211,8 @@ rfx_xcvr::rfx_xcvr( this->get_rx_subtree()->create("enabled").set(true); //always enabled this->get_rx_subtree()->create("use_lo_offset").set(false); this->get_rx_subtree()->create("bandwidth/value").set(2*20.0e6); //20MHz low-pass, we want complex double-sided + this->get_rx_subtree()->create("bandwidth/range") + .set(freq_range_t(2*20.0e6, 2*20.0e6)); //////////////////////////////////////////////////////////////////// // Register TX properties @@ -231,6 +233,8 @@ rfx_xcvr::rfx_xcvr( this->get_tx_subtree()->create("enabled").set(true); //always enabled this->get_tx_subtree()->create("use_lo_offset").set(true); this->get_tx_subtree()->create("bandwidth/value").set(2*20.0e6); //20MHz low-pass, we want complex double-sided + this->get_tx_subtree()->create("bandwidth/range") + .set(freq_range_t(2*20.0e6, 2*20.0e6)); //enable the clocks that we need this->get_iface()->set_clock_enabled(dboard_iface::UNIT_TX, true); diff --git a/host/lib/usrp/dboard/db_tvrx.cpp b/host/lib/usrp/dboard/db_tvrx.cpp index 907d798dd..dfa617e77 100644 --- a/host/lib/usrp/dboard/db_tvrx.cpp +++ b/host/lib/usrp/dboard/db_tvrx.cpp @@ -57,7 +57,7 @@ using namespace boost::assign; **********************************************************************/ static const freq_range_t tvrx_freq_range(50e6, 860e6); -static const prop_names_t tvrx_antennas = list_of("RX"); +static const std::vector tvrx_antennas = list_of("RX"); static const uhd::dict tvrx_freq_ranges = map_list_of ("VHFLO", freq_range_t(50e6, 158e6)) @@ -136,9 +136,6 @@ public: tvrx(ctor_args_t args); ~tvrx(void); - void rx_get(const wax::obj &key, wax::obj &val); - void rx_set(const wax::obj &key, const wax::obj &val); - private: uhd::dict _gains; double _lo_freq; @@ -147,8 +144,8 @@ private: return (this->get_iface()->get_special_props().mangle_i2c_addrs)? 0x61 : 0x60; //ok really? we could rename that call }; - void set_gain(double gain, const std::string &name); - void set_freq(double freq); + double set_gain(double gain, const std::string &name); + double set_freq(double freq); void update_regs(void){ byte_vector_t regs_vector(4); @@ -185,6 +182,39 @@ UHD_STATIC_BLOCK(reg_tvrx_dboard){ * Structors **********************************************************************/ tvrx::tvrx(ctor_args_t args) : rx_dboard_base(args){ + //////////////////////////////////////////////////////////////////// + // Register properties + //////////////////////////////////////////////////////////////////// + this->get_rx_subtree()->create("name") + .set(get_rx_id().to_pp_string()); + BOOST_FOREACH(const std::string &name, get_tvrx_gain_ranges().keys()){ + this->get_rx_subtree()->create("gains/"+name+"/value") + .coerce(boost::bind(&tvrx::set_gain, this, _1, name)) + .set(get_tvrx_gain_ranges()[name].start()); + this->get_rx_subtree()->create("gains/"+name+"/range") + .set(get_tvrx_gain_ranges()[name]); + } + this->get_rx_subtree()->create("freq/value") + .coerce(boost::bind(&tvrx::set_freq, this, _1)) + .set(tvrx_freq_range.start()); + this->get_rx_subtree()->create("freq/range") + .set(tvrx_freq_range); + this->get_rx_subtree()->create("antenna/value") + .set(tvrx_antennas.at(0)); + this->get_rx_subtree()->create >("antenna/options") + .set(tvrx_antennas); + this->get_rx_subtree()->create("connection") + .set("I"); + this->get_rx_subtree()->create("enabled") + .set(true); //always enabled + this->get_rx_subtree()->create("use_lo_offset") + .set(false); + this->get_rx_subtree()->create("bandwidth/value") + .set(6.0e6); + this->get_rx_subtree()->create("bandwidth/range") + .set(freq_range_t(6.0e6, 6.0e6)); + + //enable only the clocks we need this->get_iface()->set_clock_enabled(dboard_iface::UNIT_RX, true); //set the gpio directions and atr controls (identically) @@ -317,7 +347,7 @@ static double if_gain_to_voltage(double gain){ return dac_volts; } -void tvrx::set_gain(double gain, const std::string &name){ +double tvrx::set_gain(double gain, const std::string &name){ assert_has(get_tvrx_gain_ranges().keys(), name, "tvrx gain name"); if (name == "RF"){ this->get_iface()->write_aux_dac(dboard_iface::UNIT_RX, dboard_iface::AUX_DAC_B, rf_gain_to_voltage(gain, _lo_freq)); @@ -327,6 +357,8 @@ void tvrx::set_gain(double gain, const std::string &name){ } else UHD_THROW_INVALID_CODE_PATH(); _gains[name] = gain; + + return gain; } /*! @@ -334,7 +366,7 @@ void tvrx::set_gain(double gain, const std::string &name){ * \param freq the requested frequency */ -void tvrx::set_freq(double freq) { +double tvrx::set_freq(double freq) { freq = tvrx_freq_range.clip(freq); std::string prev_band = get_band(_lo_freq - tvrx_if_freq); std::string new_band = get_band(freq); @@ -367,131 +399,6 @@ void tvrx::set_freq(double freq) { UHD_LOGV(often) << boost::format("set_freq: target LO: %f f_ref: %f divisor: %i actual LO: %f") % target_lo_freq % f_ref % divisor % actual_lo_freq << std::endl; _lo_freq = actual_lo_freq; //for rx props -} - -/*********************************************************************** - * Get the alias frequency of frequency freq when sampled at fs. - * \param freq the frequency of interest - * \param fs the sample rate - * \return the alias frequency - **********************************************************************/ - -static double get_alias(double freq, double fs) { - double alias; - freq = fmod(freq, fs); - if(freq >= (fs/2)) { - alias = freq - fs; - } else { - alias = freq; - } - return alias; -} -/*********************************************************************** - * RX Get and Set - **********************************************************************/ -void tvrx::rx_get(const wax::obj &key_, wax::obj &val){ - named_prop_t key = named_prop_t::extract(key_); - double codec_rate; - - //handle the get request conditioned on the key - switch(key.as()){ - case SUBDEV_PROP_NAME: - val = get_rx_id().to_pp_string(); - return; - - case SUBDEV_PROP_OTHERS: - val = prop_names_t(); //empty - return; - - case SUBDEV_PROP_GAIN: - assert_has(_gains.keys(), key.name, "tvrx gain name"); - val = _gains[key.name]; - return; - - case SUBDEV_PROP_GAIN_RANGE: - assert_has(get_tvrx_gain_ranges().keys(), key.name, "tvrx gain name"); - val = get_tvrx_gain_ranges()[key.name]; - return; - - case SUBDEV_PROP_GAIN_NAMES: - val = prop_names_t(get_tvrx_gain_ranges().keys()); - return; - - case SUBDEV_PROP_FREQ: - /* - * so here we have to do some magic. because the TVRX uses a relatively high IF, - * we have to watch the sample rate to see if the IF will be aliased - * or if it will fall within Nyquist. - */ - codec_rate = this->get_iface()->get_codec_rate(dboard_iface::UNIT_RX); - val = (_lo_freq - tvrx_if_freq) + get_alias(tvrx_if_freq, codec_rate); - UHD_LOGV(often) - << "Getting TVRX freq..." << std::endl - << "\tCodec rate: " << codec_rate << std::endl - << "\tLO freq: " << _lo_freq << std::endl - << "\tIF freq: " << tvrx_if_freq << std::endl - << "\tAlias freq: " << get_alias(tvrx_if_freq, codec_rate) << std::endl - << "\tCalculated freq: " << val.as() << std::endl; - return; - - case SUBDEV_PROP_FREQ_RANGE: - val = tvrx_freq_range; - return; - - case SUBDEV_PROP_ANTENNA: - val = tvrx_antennas.front(); //there's only one - return; - - case SUBDEV_PROP_ANTENNA_NAMES: - val = tvrx_antennas; - return; - - case SUBDEV_PROP_CONNECTION: - val = SUBDEV_CONN_REAL_I; - return; - - case SUBDEV_PROP_ENABLED: - val = true; //always enabled - return; - - case SUBDEV_PROP_USE_LO_OFFSET: - val = false; - return; - - case SUBDEV_PROP_BANDWIDTH: - val = 6.0e6; - return; - - case SUBDEV_PROP_SENSOR_NAMES: - val = std::vector(); //empty - return; - - default: UHD_THROW_PROP_GET_ERROR(); - } -} - -void tvrx::rx_set(const wax::obj &key_, const wax::obj &val){ - named_prop_t key = named_prop_t::extract(key_); - - //handle the get request conditioned on the key - switch(key.as()){ - case SUBDEV_PROP_GAIN: - this->set_gain(val.as(), key.name); - return; - - case SUBDEV_PROP_FREQ: - this->set_freq(val.as()); - return; - - case SUBDEV_PROP_ENABLED: - return; //always enabled - - case SUBDEV_PROP_BANDWIDTH: - UHD_MSG(warning) << "TVRX: No tunable bandwidth, fixed filtered to 6MHz"; - return; - - default: UHD_THROW_PROP_SET_ERROR(); - } + return _lo_freq; } - diff --git a/host/lib/usrp/dboard/db_tvrx2.cpp b/host/lib/usrp/dboard/db_tvrx2.cpp index 23f203b8c..628221527 100644 --- a/host/lib/usrp/dboard/db_tvrx2.cpp +++ b/host/lib/usrp/dboard/db_tvrx2.cpp @@ -704,14 +704,22 @@ static const std::vector tvrx2_tda18272_freq_map = li static const freq_range_t tvrx2_freq_range(42e6, 870e6); +static const freq_range_t tvrx2_bandwidth_range = list_of + (range_t(1.7e6)) + (range_t(6.0e6)) + (range_t(7.0e6)) + (range_t(8.0e6)) + (range_t(10.0e6)) +; + static const uhd::dict tvrx2_sd_name_to_antennas = map_list_of ("RX1", "J100") ("RX2", "J140") ; -static const uhd::dict tvrx2_sd_name_to_conn = map_list_of - ("RX1", SUBDEV_CONN_REAL_Q) - ("RX2", SUBDEV_CONN_REAL_I) +static const uhd::dict tvrx2_sd_name_to_conn = map_list_of + ("RX1", "Q") + ("RX2", "I") ; static const uhd::dict tvrx2_sd_name_to_i2c_addr = map_list_of @@ -745,9 +753,6 @@ public: tvrx2(ctor_args_t args); ~tvrx2(void); - void rx_get(const wax::obj &key, wax::obj &val); - void rx_set(const wax::obj &key, const wax::obj &val); - private: double _freq_scalar; double _lo_freq; @@ -760,12 +765,11 @@ private: bool _enabled; - void set_enabled(void); - void set_disabled(void); + bool set_enabled(bool); - void set_lo_freq(double target_freq); - void set_gain(double gain, const std::string &name); - void set_bandwidth(double bandwidth); + double set_lo_freq(double target_freq); + double set_gain(double gain, const std::string &name); + double set_bandwidth(double bandwidth); void set_scaled_rf_freq(double rf_freq); double get_scaled_rf_freq(void); @@ -825,10 +829,10 @@ private: } /*! - * Is the LO locked? - * \return true for locked + * Get the lock detect status of the LO. + * \return sensor for locked */ - bool get_locked(void){ + sensor_value_t get_locked(void){ read_reg(0x5, 0x5); //return lock detect @@ -838,14 +842,15 @@ private: "TVRX2 (%s): locked %d" ) % (get_subdev_name()) % locked << std::endl; - return locked; + return sensor_value_t("LO", locked, "locked", "unlocked"); } /*! * Read the RSSI from the registers - * \return the rssi in dB(m?) FIXME + * Read the RSSI from the aux adc + * \return the rssi sensor in dB(m?) FIXME */ - double get_rssi(void){ + sensor_value_t get_rssi(void){ //Launch RSSI calculation with MSM statemachine _tda18272hnm_regs.set_reg(0x19, 0x80); //set MSM_byte_1 for rssi calculation _tda18272hnm_regs.set_reg(0x1A, 0x01); //set MSM_byte_2 for launching rssi calculation @@ -859,14 +864,16 @@ private: //calculate the rssi from the voltage double rssi_dBuV = 40.0 + double(((110.0 - 40.0)/128.0) * _tda18272hnm_regs.get_reg(0x7)); - return rssi_dBuV - 107.0; //convert to dBm in 50ohm environment ( -108.8 if 75ohm ) FIXME + double rssi = rssi_dBuV - 107.0; //convert to dBm in 50ohm environment ( -108.8 if 75ohm ) FIXME + + return sensor_value_t("RSSI", rssi, "dBm"); } /*! * Read the Temperature from the registers * \return the temp in degC */ - double get_temp(void){ + sensor_value_t get_temp(void){ //Enable Temperature reading _tda18272hnm_regs.tm_on = tda18272hnm_regs_t::TM_ON_SENSOR_ON; send_reg(0x4, 0x4); @@ -882,7 +889,7 @@ private: _tda18272hnm_regs.tm_on = tda18272hnm_regs_t::TM_ON_SENSOR_OFF; send_reg(0x4, 0x4); - return (double(_tda18272hnm_regs.tm_d)); + return sensor_value_t("TEMP", double(_tda18272hnm_regs.tm_d), "degC"); } }; @@ -930,24 +937,64 @@ tvrx2::tvrx2(ctor_args_t args) : rx_dboard_base(args){ ( 7, tvrx2_tda18272_rfcal_coeffs_t(10) ) ; - //set the gpio directions and atr controls (identically) - this->get_iface()->set_pin_ctrl(dboard_iface::UNIT_RX, 0); // All unused in atr - this->get_iface()->set_gpio_ddr(dboard_iface::UNIT_RX, OUTPUT_MASK); // Set outputs + //set defaults for LO, gains, and filter bandwidth + _bandwidth = 10e6; + + _if_freq = 12.5e6; - double ref_clock=0.0; + _enabled = false; - //configure ref_clock + //send initial register settings + //this->read_reg(0x0, 0x43); + //this->send_reg(0x0, 0x43); - /* - std::vector clock_rates = this->get_iface()->get_clock_rates(dboard_iface::UNIT_RX); - BOOST_FOREACH(ref_clock, uhd::sorted(clock_rates)){ - if (ref_clock < 16.0e6) continue; - if (ref_clock >= 16.0e6) break; + //send magic xtal_cal_dac setting + send_reg(0x65, 0x65); + + //////////////////////////////////////////////////////////////////// + // Register properties + //////////////////////////////////////////////////////////////////// + this->get_rx_subtree()->create("name") + .set(get_rx_id().to_pp_string()); + this->get_rx_subtree()->create("sensors/lo_locked") + .publish(boost::bind(&tvrx2::get_locked, this)); + this->get_rx_subtree()->create("sensors/rssi") + .publish(boost::bind(&tvrx2::get_rssi, this)); + this->get_rx_subtree()->create("sensors/temperature") + .publish(boost::bind(&tvrx2::get_temp, this)); + BOOST_FOREACH(const std::string &name, tvrx2_gain_ranges.keys()){ + this->get_rx_subtree()->create("gains/"+name+"/value") + .coerce(boost::bind(&tvrx2::set_gain, this, _1, name)); + this->get_rx_subtree()->create("gains/"+name+"/range") + .set(tvrx2_gain_ranges[name]); } - this->get_iface()->set_clock_rate(dboard_iface::UNIT_RX, ref_clock); - */ + this->get_rx_subtree()->create("freq/value") + .coerce(boost::bind(&tvrx2::set_lo_freq, this, _1)); + this->get_rx_subtree()->create("freq/range") + .set(tvrx2_freq_range); + this->get_rx_subtree()->create("antenna/value") + .set(tvrx2_sd_name_to_antennas[get_subdev_name()]); + this->get_rx_subtree()->create >("antenna/options") + .set(list_of(tvrx2_sd_name_to_antennas[get_subdev_name()])); + this->get_rx_subtree()->create("connection") + .set(tvrx2_sd_name_to_conn[get_subdev_name()]); + this->get_rx_subtree()->create("enabled") + .coerce(boost::bind(&tvrx2::set_enabled, this, _1)) + .set(_enabled); + this->get_rx_subtree()->create("use_lo_offset") + .set(false); + this->get_rx_subtree()->create("bandwidth/value") + .coerce(boost::bind(&tvrx2::set_bandwidth, this, _1)) + .set(_bandwidth); + this->get_rx_subtree()->create("bandwidth/range") + .set(tvrx2_bandwidth_range); - ref_clock = this->get_iface()->get_clock_rate(dboard_iface::UNIT_RX); + //set the gpio directions and atr controls (identically) + this->get_iface()->set_pin_ctrl(dboard_iface::UNIT_RX, 0); // All unused in atr + this->get_iface()->set_gpio_ddr(dboard_iface::UNIT_RX, OUTPUT_MASK); // Set outputs + + //configure ref_clock + double ref_clock = this->get_iface()->get_clock_rate(dboard_iface::UNIT_RX); if (ref_clock == 64.0e6) { this->get_iface()->set_gpio_out(dboard_iface::UNIT_RX, REFCLOCK_DIV4); @@ -978,22 +1025,6 @@ tvrx2::tvrx2(ctor_args_t args) : rx_dboard_base(args){ "TVRX2 (%s): Refclock %f Hz, scalar = %f" ) % (get_subdev_name()) % (this->get_iface()->get_clock_rate(dboard_iface::UNIT_RX)) % _freq_scalar << std::endl; - //set defaults for LO, gains, and filter bandwidth - _bandwidth = 10e6; - - _if_freq = 12.5e6; - - _lo_freq = tvrx2_freq_range.start(); - - _enabled = false; - - //send initial register settings - //this->read_reg(0x0, 0x43); - //this->send_reg(0x0, 0x43); - - //send magic xtal_cal_dac setting - send_reg(0x65, 0x65); - _tda18272hnm_regs.irq_polarity = tda18272hnm_regs_t::IRQ_POLARITY_RAISED_VCC; _tda18272hnm_regs.irq_clear = tda18272hnm_regs_t::IRQ_CLEAR_TRUE; send_reg(0x37, 0x37); @@ -1013,39 +1044,47 @@ tvrx2::tvrx2(ctor_args_t args) : rx_dboard_base(args){ transition_0(); } -void tvrx2::set_enabled(void){ - //setup tuner parameters - transition_1(); +bool tvrx2::set_enabled(bool enable){ + if (enable == _enabled) return _enabled; - transition_2(int(tvrx2_freq_range.start())); + if (enable and not _enabled){ + //setup tuner parameters + transition_1(); - test_rf_filter_robustness(); + transition_2(int(tvrx2_freq_range.start())); - BOOST_FOREACH(const std::string &name, tvrx2_gain_ranges.keys()){ - set_gain(tvrx2_gain_ranges[name].start(), name); - } + test_rf_filter_robustness(); + + BOOST_FOREACH(const std::string &name, tvrx2_gain_ranges.keys()){ + this->get_rx_subtree()->access("gains/"+name+"/value") + .set(tvrx2_gain_ranges[name].start()); + } + + this->get_rx_subtree()->access("bandwidth/value") + .set(_bandwidth); // default bandwidth from datasheet + + //transition_2 equivalent + this->get_rx_subtree()->access("freq/value") + .set(tvrx2_freq_range.start()); - set_bandwidth(_bandwidth); // default bandwidth from datasheet + //enter standby mode + transition_3(); + _enabled = true; - //transition_2 equivalent - set_lo_freq(tvrx2_freq_range.start()); + } else { + //enter standby mode + transition_3(); + _enabled = false; + } - //enter standby mode - transition_3(); - _enabled = true; + return _enabled; } tvrx2::~tvrx2(void){ UHD_LOGV(often) << boost::format( "TVRX2 (%s): Called Destructor" ) % (get_subdev_name()) << std::endl; - UHD_SAFE_CALL(if (_enabled) set_disabled();) -} - -void tvrx2::set_disabled(void){ - //enter standby mode - transition_3(); - _enabled = false; + UHD_SAFE_CALL(if (_enabled) set_enabled(false);) } @@ -1682,7 +1721,7 @@ void tvrx2::wait_irq(void){ /*********************************************************************** * Tuning **********************************************************************/ -void tvrx2::set_lo_freq(double target_freq){ +double tvrx2::set_lo_freq(double target_freq){ //target_freq = std::clip(target_freq, tvrx2_freq_range.min, tvrx2_freq_range.max); read_reg(0x6, 0x6); @@ -1711,7 +1750,9 @@ void tvrx2::set_lo_freq(double target_freq){ UHD_LOGV(often) << boost::format( "\nTVRX2 (%s): RSSI = %f dBm\n" - ) % (get_subdev_name()) % (get_rssi()) << std::endl; + ) % (get_subdev_name()) % (get_rssi().to_real()) << std::endl; + + return _lo_freq; } /*********************************************************************** @@ -1741,7 +1782,7 @@ static double gain_to_if_gain_dac(double &gain){ return dac_volts; } -void tvrx2::set_gain(double gain, const std::string &name){ +double tvrx2::set_gain(double gain, const std::string &name){ assert_has(tvrx2_gain_ranges.keys(), name, "tvrx2 gain name"); if (name == "IF"){ @@ -1752,6 +1793,8 @@ void tvrx2::set_gain(double gain, const std::string &name){ //shadow gain setting _gains[name] = gain; + + return gain; } /*********************************************************************** @@ -1780,7 +1823,10 @@ static tda18272hnm_regs_t::lp_fc_t bandwidth_to_lp_fc_reg(double &bandwidth){ UHD_THROW_INVALID_CODE_PATH(); } -void tvrx2::set_bandwidth(double bandwidth){ +double tvrx2::set_bandwidth(double bandwidth){ + //clip the input + bandwidth = tvrx2_bandwidth_range.clip(bandwidth); + //compute low pass cutoff frequency setting _tda18272hnm_regs.lp_fc = bandwidth_to_lp_fc_reg(bandwidth); @@ -1793,119 +1839,6 @@ void tvrx2::set_bandwidth(double bandwidth){ UHD_LOGV(often) << boost::format( "TVRX2 (%s) Bandwidth (lp_fc): %f Hz, reg: %d" ) % (get_subdev_name()) % _bandwidth % (int(_tda18272hnm_regs.lp_fc)) << std::endl; -} - -/*********************************************************************** - * RX Get and Set - **********************************************************************/ -void tvrx2::rx_get(const wax::obj &key_, wax::obj &val){ - named_prop_t key = named_prop_t::extract(key_); - - //handle the get request conditioned on the key - switch(key.as()){ - case SUBDEV_PROP_NAME: - val = get_rx_id().to_pp_string(); - return; - - case SUBDEV_PROP_OTHERS: - val = prop_names_t(); //empty - return; - - case SUBDEV_PROP_GAIN: - assert_has(_gains.keys(), key.name, "tvrx2 gain name"); - val = _gains[key.name]; - return; - - case SUBDEV_PROP_GAIN_RANGE: - assert_has(tvrx2_gain_ranges.keys(), key.name, "tvrx2 gain name"); - val = tvrx2_gain_ranges[key.name]; - return; - - case SUBDEV_PROP_GAIN_NAMES: - val = prop_names_t(tvrx2_gain_ranges.keys()); - return; - - case SUBDEV_PROP_FREQ: - val = _lo_freq; - return; - - case SUBDEV_PROP_FREQ_RANGE: - val = tvrx2_freq_range; - return; - - case SUBDEV_PROP_ANTENNA: - val = tvrx2_sd_name_to_antennas[get_subdev_name()]; - return; - - case SUBDEV_PROP_ANTENNA_NAMES: - val = prop_names_t(1, tvrx2_sd_name_to_antennas[get_subdev_name()]); - return; - - case SUBDEV_PROP_CONNECTION: - val = tvrx2_sd_name_to_conn[get_subdev_name()]; - return; - - case SUBDEV_PROP_ENABLED: - val = _enabled; - return; - - case SUBDEV_PROP_USE_LO_OFFSET: - val = false; - return; - - case SUBDEV_PROP_SENSOR: - if (key.name == "lo_locked") - val = sensor_value_t("LO", this->get_locked(), "locked", "unlocked"); - else if (key.name == "rssi") - val = sensor_value_t("RSSI", this->get_rssi(), "dBm"); - else if (key.name == "temperature") - val = sensor_value_t("TEMP", this->get_temp(), "degC"); - else - UHD_THROW_INVALID_CODE_PATH(); - return; - - case SUBDEV_PROP_SENSOR_NAMES:{ - prop_names_t names = list_of("lo_locked")("rssi")("temperature"); - val = names; - } - return; - case SUBDEV_PROP_BANDWIDTH: - val = _bandwidth; - return; - - default: UHD_THROW_PROP_GET_ERROR(); - } + return _bandwidth; } - -void tvrx2::rx_set(const wax::obj &key_, const wax::obj &val){ - named_prop_t key = named_prop_t::extract(key_); - - //handle the get request conditioned on the key - switch(key.as()){ - - case SUBDEV_PROP_FREQ: - this->set_lo_freq(val.as()); - return; - - case SUBDEV_PROP_GAIN: - this->set_gain( val.as(), key.name); - return; - - case SUBDEV_PROP_ANTENNA: - return; - - case SUBDEV_PROP_ENABLED: - if ((val.as())) this->set_enabled(); - else if (not (val.as())) this->set_disabled(); - - return; - - case SUBDEV_PROP_BANDWIDTH: - this->set_bandwidth(val.as()); - return; - - default: UHD_THROW_PROP_SET_ERROR(); - } -} - diff --git a/host/lib/usrp/dboard/db_unknown.cpp b/host/lib/usrp/dboard/db_unknown.cpp index 3a11f1e5b..2ed50cd91 100644 --- a/host/lib/usrp/dboard/db_unknown.cpp +++ b/host/lib/usrp/dboard/db_unknown.cpp @@ -64,17 +64,11 @@ static void warn_if_old_rfx(const dboard_id_t &dboard_id, const std::string &xx) class unknown_rx : public rx_dboard_base{ public: unknown_rx(ctor_args_t args); - - void rx_get(const wax::obj &key, wax::obj &val); - void rx_set(const wax::obj &key, const wax::obj &val); }; class unknown_tx : public tx_dboard_base{ public: unknown_tx(ctor_args_t args); - - void tx_get(const wax::obj &key, wax::obj &val); - void tx_set(const wax::obj &key, const wax::obj &val); }; /*********************************************************************** @@ -98,99 +92,35 @@ UHD_STATIC_BLOCK(reg_unknown_dboards){ **********************************************************************/ unknown_rx::unknown_rx(ctor_args_t args) : rx_dboard_base(args){ warn_if_old_rfx(this->get_rx_id(), "RX"); -} - -void unknown_rx::rx_get(const wax::obj &key_, wax::obj &val){ - named_prop_t key = named_prop_t::extract(key_); - - //handle the get request conditioned on the key - switch(key.as()){ - case SUBDEV_PROP_NAME: - val = "Unknown - " + get_rx_id().to_pp_string(); - return; - - case SUBDEV_PROP_OTHERS: - val = prop_names_t(); //empty - return; - - case SUBDEV_PROP_GAIN: - val = double(0); - return; - - case SUBDEV_PROP_GAIN_RANGE: - val = gain_range_t(0, 0, 0); - return; - - case SUBDEV_PROP_GAIN_NAMES: - val = prop_names_t(); //empty - return; - - case SUBDEV_PROP_FREQ: - val = double(0); - return; - - case SUBDEV_PROP_FREQ_RANGE: - val = freq_range_t(0.0, 0.0); - return; - - case SUBDEV_PROP_ANTENNA: - val = std::string(""); - return; - - case SUBDEV_PROP_ANTENNA_NAMES: - val = prop_names_t(1, ""); //vector of 1 empty string - return; - - case SUBDEV_PROP_SENSOR_NAMES: - val = std::vector(); //empty - return; - - case SUBDEV_PROP_CONNECTION: - val = SUBDEV_CONN_COMPLEX_IQ; - return; - - case SUBDEV_PROP_ENABLED: - val = true; //always enabled - return; - - case SUBDEV_PROP_USE_LO_OFFSET: - val = false; - return; - - case SUBDEV_PROP_BANDWIDTH: - val = 0.0; - return; - - default: UHD_THROW_PROP_GET_ERROR(); - } -} - -void unknown_rx::rx_set(const wax::obj &key_, const wax::obj &val){ - named_prop_t key = named_prop_t::extract(key_); - - //handle the get request conditioned on the key - switch(key.as()){ - - case SUBDEV_PROP_GAIN: - UHD_ASSERT_THROW(val.as() == double(0)); - return; - - case SUBDEV_PROP_ANTENNA: - if (val.as().empty()) return; - throw uhd::value_error("Unknown Daughterboard: No selectable antenna"); - - case SUBDEV_PROP_FREQ: - return; // it wont do you much good, but you can set it - - case SUBDEV_PROP_ENABLED: - return; //always enabled - - case SUBDEV_PROP_BANDWIDTH: - UHD_MSG(warning) << "Unknown Daughterboard: No tunable bandwidth, fixed filtered to 0.0MHz"; - return; - default: UHD_THROW_PROP_SET_ERROR(); - } + //////////////////////////////////////////////////////////////////// + // Register properties + //////////////////////////////////////////////////////////////////// + this->get_rx_subtree()->create("name").set( + std::string(str(boost::format("%s - %s") + % get_rx_id().to_pp_string() + % get_subdev_name() + ))); + this->get_rx_subtree()->create("gains"); //phony property so this dir exists + this->get_rx_subtree()->create("freq/value") + .set(double(0.0)); + this->get_rx_subtree()->create("freq/range") + .set(freq_range_t(double(0.0), double(0.0))); + this->get_rx_subtree()->create("antenna/value") + .set(""); + this->get_rx_subtree()->create >("antenna/options") + .set(list_of("")); + this->get_rx_subtree()->create("sensors"); //phony property so this dir exists + this->get_rx_subtree()->create("connection") + .set("IQ"); + this->get_rx_subtree()->create("enabled") + .set(true); //always enabled + this->get_rx_subtree()->create("use_lo_offset") + .set(false); + this->get_rx_subtree()->create("bandwidth/value") + .set(double(0.0)); + this->get_rx_subtree()->create("bandwidth/range") + .set(freq_range_t(0.0, 0.0)); } /*********************************************************************** @@ -198,97 +128,33 @@ void unknown_rx::rx_set(const wax::obj &key_, const wax::obj &val){ **********************************************************************/ unknown_tx::unknown_tx(ctor_args_t args) : tx_dboard_base(args){ warn_if_old_rfx(this->get_tx_id(), "TX"); -} - -void unknown_tx::tx_get(const wax::obj &key_, wax::obj &val){ - named_prop_t key = named_prop_t::extract(key_); - - //handle the get request conditioned on the key - switch(key.as()){ - case SUBDEV_PROP_NAME: - val = "Unknown - " + get_tx_id().to_pp_string(); - return; - - case SUBDEV_PROP_OTHERS: - val = prop_names_t(); //empty - return; - - case SUBDEV_PROP_GAIN: - val = double(0); - return; - - case SUBDEV_PROP_GAIN_RANGE: - val = gain_range_t(0, 0, 0); - return; - - case SUBDEV_PROP_GAIN_NAMES: - val = prop_names_t(); //empty - return; - - case SUBDEV_PROP_FREQ: - val = double(0); - return; - - case SUBDEV_PROP_FREQ_RANGE: - val = freq_range_t(0.0, 0.0); - return; - - case SUBDEV_PROP_ANTENNA: - val = std::string(""); - return; - - case SUBDEV_PROP_ANTENNA_NAMES: - val = prop_names_t(1, ""); //vector of 1 empty string - return; - - case SUBDEV_PROP_SENSOR_NAMES: - val = std::vector(); //empty - return; - - case SUBDEV_PROP_CONNECTION: - val = SUBDEV_CONN_COMPLEX_IQ; - return; - case SUBDEV_PROP_ENABLED: - val = true; //always enabled - return; - - case SUBDEV_PROP_USE_LO_OFFSET: - val = false; - return; - - case SUBDEV_PROP_BANDWIDTH: - val = 0.0; - return; - - default: UHD_THROW_PROP_GET_ERROR(); - } -} - -void unknown_tx::tx_set(const wax::obj &key_, const wax::obj &val){ - named_prop_t key = named_prop_t::extract(key_); - - //handle the get request conditioned on the key - switch(key.as()){ - - case SUBDEV_PROP_GAIN: - UHD_ASSERT_THROW(val.as() == double(0)); - return; - - case SUBDEV_PROP_ANTENNA: - if (val.as().empty()) return; - throw uhd::value_error("Unknown Daughterboard: No selectable antenna"); - - case SUBDEV_PROP_FREQ: - return; // it wont do you much good, but you can set it - - case SUBDEV_PROP_ENABLED: - return; //always enabled - - case SUBDEV_PROP_BANDWIDTH: - UHD_MSG(warning) << "Unknown Daughterboard: No tunable bandwidth, fixed filtered to 0.0MHz"; - return; - - default: UHD_THROW_PROP_SET_ERROR(); - } + //////////////////////////////////////////////////////////////////// + // Register properties + //////////////////////////////////////////////////////////////////// + this->get_tx_subtree()->create("name").set( + std::string(str(boost::format("%s - %s") + % get_tx_id().to_pp_string() + % get_subdev_name() + ))); + this->get_tx_subtree()->create("gains"); //phony property so this dir exists + this->get_tx_subtree()->create("freq/value") + .set(double(0.0)); + this->get_tx_subtree()->create("freq/range") + .set(freq_range_t(double(0.0), double(0.0))); + this->get_tx_subtree()->create("antenna/value") + .set(""); + this->get_tx_subtree()->create >("antenna/options") + .set(list_of("")); + this->get_tx_subtree()->create("sensors"); //phony property so this dir exists + this->get_tx_subtree()->create("connection") + .set("IQ"); + this->get_tx_subtree()->create("enabled") + .set(true); //always enabled + this->get_tx_subtree()->create("use_lo_offset") + .set(false); + this->get_tx_subtree()->create("bandwidth/value") + .set(double(0.0)); + this->get_tx_subtree()->create("bandwidth/range") + .set(freq_range_t(0.0, 0.0)); } diff --git a/host/lib/usrp/dboard/db_xcvr2450.cpp b/host/lib/usrp/dboard/db_xcvr2450.cpp index bfd4421b8..bdc6aa9fe 100644 --- a/host/lib/usrp/dboard/db_xcvr2450.cpp +++ b/host/lib/usrp/dboard/db_xcvr2450.cpp @@ -76,7 +76,22 @@ static const freq_range_t xcvr_freq_range = list_of (range_t(4.9e9, 6.0e9)) ; -static const prop_names_t xcvr_antennas = list_of("J1")("J2"); +//Multiplied by 2.0 for conversion to complex bandpass from lowpass +static const freq_range_t xcvr_tx_bandwidth_range = list_of + (range_t(2.0*12e6)) + (range_t(2.0*18e6)) + (range_t(2.0*24e6)) +; + +//Multiplied by 2.0 for conversion to complex bandpass from lowpass +static const freq_range_t xcvr_rx_bandwidth_range = list_of + (range_t(2.0*0.9*7.5e6, 2.0*1.1*7.5e6)) + (range_t(2.0*0.9*9.5e6, 2.0*1.1*9.5e6)) + (range_t(2.0*0.9*14e6, 2.0*1.1*14e6)) + (range_t(2.0*0.9*18e6, 2.0*1.1*18e6)) +; + +static const std::vector xcvr_antennas = list_of("J1")("J2"); static const uhd::dict xcvr_tx_gain_ranges = map_list_of ("VGA", gain_range_t(0, 30, 0.5)) @@ -99,12 +114,6 @@ public: xcvr2450(ctor_args_t args); ~xcvr2450(void); - void rx_get(const wax::obj &key, wax::obj &val); - void rx_set(const wax::obj &key, const wax::obj &val); - - void tx_get(const wax::obj &key, wax::obj &val); - void tx_set(const wax::obj &key, const wax::obj &val); - private: double _lo_freq; double _rx_bandwidth, _tx_bandwidth; @@ -113,14 +122,14 @@ private: int _ad9515div; max2829_regs_t _max2829_regs; - void set_lo_freq(double target_freq); - void set_lo_freq_core(double target_freq); + double set_lo_freq(double target_freq); + double set_lo_freq_core(double target_freq); void set_tx_ant(const std::string &ant); void set_rx_ant(const std::string &ant); - void set_tx_gain(double gain, const std::string &name); - void set_rx_gain(double gain, const std::string &name); - void set_rx_bandwidth(double bandwidth); - void set_tx_bandwidth(double bandwidth); + double set_tx_gain(double gain, const std::string &name); + double set_rx_gain(double gain, const std::string &name); + double set_rx_bandwidth(double bandwidth); + double set_tx_bandwidth(double bandwidth); void update_atr(void); void spi_reset(void); @@ -139,18 +148,19 @@ private: static bool is_highband(double freq){return freq > 3e9;} /*! - * Is the LO locked? - * \return true for locked + * Get the lock detect status of the LO. + * \return sensor for locked */ - bool get_locked(void){ - return (this->get_iface()->read_gpio(dboard_iface::UNIT_RX) & LOCKDET_RXIO) != 0; + sensor_value_t get_locked(void){ + const bool locked = (this->get_iface()->read_gpio(dboard_iface::UNIT_RX) & LOCKDET_RXIO) != 0; + return sensor_value_t("LO", locked, "locked", "unlocked"); } /*! * Read the RSSI from the aux adc - * \return the rssi in dB + * \return the rssi sensor in dBm */ - double get_rssi(void){ + sensor_value_t get_rssi(void){ //*FIXME* RSSI depends on LNA Gain Setting (datasheet pg 16 top middle chart) double max_power = 0.0; switch(_max2829_regs.rx_lna_gain){ @@ -165,7 +175,8 @@ private: static const double rssi_dyn_range = 60; //calculate the rssi from the voltage double voltage = this->get_iface()->read_aux_adc(dboard_iface::UNIT_RX, dboard_iface::AUX_ADC_B); - return max_power - rssi_dyn_range*(voltage - min_v)/(max_v - min_v); + double rssi = max_power - rssi_dyn_range*(voltage - min_v)/(max_v - min_v); + return sensor_value_t("RSSI", rssi, "dBm"); } }; @@ -185,15 +196,6 @@ UHD_STATIC_BLOCK(reg_xcvr2450_dboard){ * Structors **********************************************************************/ xcvr2450::xcvr2450(ctor_args_t args) : xcvr_dboard_base(args){ - //enable only the clocks we need - this->get_iface()->set_clock_enabled(dboard_iface::UNIT_TX, true); - - //set the gpio directions and atr controls (identically) - this->get_iface()->set_pin_ctrl(dboard_iface::UNIT_TX, TXIO_MASK); - this->get_iface()->set_pin_ctrl(dboard_iface::UNIT_RX, RXIO_MASK); - this->get_iface()->set_gpio_ddr(dboard_iface::UNIT_TX, TXIO_MASK); - this->get_iface()->set_gpio_ddr(dboard_iface::UNIT_RX, RXIO_MASK); - spi_reset(); //prepare the spi _rx_bandwidth = 9.5e6; @@ -222,16 +224,88 @@ xcvr2450::xcvr2450(ctor_args_t args) : xcvr_dboard_base(args){ this->send_reg(reg); } - //set defaults for LO, gains, antennas - set_lo_freq(2.45e9); - set_rx_ant(xcvr_antennas.at(0)); - set_tx_ant(xcvr_antennas.at(1)); - BOOST_FOREACH(const std::string &name, xcvr_tx_gain_ranges.keys()){ - set_tx_gain(xcvr_tx_gain_ranges[name].start(), name); + //////////////////////////////////////////////////////////////////// + // Register RX properties + //////////////////////////////////////////////////////////////////// + this->get_rx_subtree()->create("name") + .set(get_rx_id().to_pp_string()); + this->get_rx_subtree()->create("sensors/lo_locked") + .publish(boost::bind(&xcvr2450::get_locked, this)); + this->get_rx_subtree()->create("sensors/rssi") + .publish(boost::bind(&xcvr2450::get_rssi, this)); + BOOST_FOREACH(const std::string &name, xcvr_rx_gain_ranges.keys()){ + this->get_rx_subtree()->create("gains/"+name+"/value") + .coerce(boost::bind(&xcvr2450::set_rx_gain, this, _1, name)) + .set(xcvr_rx_gain_ranges[name].start()); + this->get_rx_subtree()->create("gains/"+name+"/range") + .set(xcvr_rx_gain_ranges[name]); } + this->get_rx_subtree()->create("freq/value") + .coerce(boost::bind(&xcvr2450::set_lo_freq, this, _1)) + .set(double(2.45e9)); + this->get_rx_subtree()->create("freq/range") + .set(xcvr_freq_range); + this->get_rx_subtree()->create("antenna/value") + .subscribe(boost::bind(&xcvr2450::set_rx_ant, this, _1)) + .set(xcvr_antennas.at(0)); + this->get_rx_subtree()->create >("antenna/options") + .set(xcvr_antennas); + this->get_rx_subtree()->create("connection") + .set("IQ"); + this->get_rx_subtree()->create("enabled") + .set(true); //always enabled + this->get_rx_subtree()->create("use_lo_offset") + .set(false); + this->get_rx_subtree()->create("bandwidth/value") + .coerce(boost::bind(&xcvr2450::set_rx_bandwidth, this, _1)) //complex bandpass bandwidth + .set(2.0*_rx_bandwidth); //_rx_bandwidth in lowpass, convert to complex bandpass + this->get_rx_subtree()->create("bandwidth/range") + .set(xcvr_rx_bandwidth_range); + + //////////////////////////////////////////////////////////////////// + // Register TX properties + //////////////////////////////////////////////////////////////////// + this->get_tx_subtree()->create("name") + .set(get_tx_id().to_pp_string()); + this->get_tx_subtree()->create("sensors/lo_locked") + .publish(boost::bind(&xcvr2450::get_locked, this)); BOOST_FOREACH(const std::string &name, xcvr_rx_gain_ranges.keys()){ - set_rx_gain(xcvr_rx_gain_ranges[name].start(), name); + this->get_rx_subtree()->create("gains/"+name+"/value") + .coerce(boost::bind(&xcvr2450::set_rx_gain, this, _1, name)) + .set(xcvr_rx_gain_ranges[name].start()); + this->get_rx_subtree()->create("gains/"+name+"/range") + .set(xcvr_rx_gain_ranges[name]); } + this->get_tx_subtree()->create("freq/value") + .coerce(boost::bind(&xcvr2450::set_lo_freq, this, _1)) + .set(double(2.45e9)); + this->get_tx_subtree()->create("freq/range") + .set(xcvr_freq_range); + this->get_tx_subtree()->create("antenna/value") + .subscribe(boost::bind(&xcvr2450::set_tx_ant, this, _1)) + .set(xcvr_antennas.at(1)); + this->get_tx_subtree()->create >("antenna/options") + .set(xcvr_antennas); + this->get_tx_subtree()->create("connection") + .set("IQ"); + this->get_tx_subtree()->create("enabled") + .set(true); //always enabled + this->get_tx_subtree()->create("use_lo_offset") + .set(true); + this->get_tx_subtree()->create("bandwidth/value") + .coerce(boost::bind(&xcvr2450::set_tx_bandwidth, this, _1)) //complex bandpass bandwidth + .set(2.0*_tx_bandwidth); //_tx_bandwidth in lowpass, convert to complex bandpass + this->get_tx_subtree()->create("bandwidth/range") + .set(xcvr_tx_bandwidth_range); + + //enable only the clocks we need + this->get_iface()->set_clock_enabled(dboard_iface::UNIT_TX, true); + + //set the gpio directions and atr controls (identically) + this->get_iface()->set_pin_ctrl(dboard_iface::UNIT_TX, TXIO_MASK); + this->get_iface()->set_pin_ctrl(dboard_iface::UNIT_RX, RXIO_MASK); + this->get_iface()->set_gpio_ddr(dboard_iface::UNIT_TX, TXIO_MASK); + this->get_iface()->set_gpio_ddr(dboard_iface::UNIT_RX, RXIO_MASK); } xcvr2450::~xcvr2450(void){ @@ -249,6 +323,9 @@ void xcvr2450::spi_reset(void){ boost::this_thread::sleep(boost::posix_time::milliseconds(10)); } +/*********************************************************************** + * Update ATR regs which change with Antenna or Freq + **********************************************************************/ void xcvr2450::update_atr(void){ //calculate tx atr pins int band_sel = (xcvr2450::is_highband(_lo_freq))? HB_PA_TXIO : LB_PA_TXIO; @@ -274,17 +351,19 @@ void xcvr2450::update_atr(void){ /*********************************************************************** * Tuning **********************************************************************/ -void xcvr2450::set_lo_freq(double target_freq){ +double xcvr2450::set_lo_freq(double target_freq){ //tune the LO and sleep a bit for lock //if not locked, try some carrier offsets + double actual = 0.0; for (double offset = 0.0; offset <= 3e6; offset+=1e6){ - this->set_lo_freq_core(target_freq + offset); + actual = this->set_lo_freq_core(target_freq + offset); boost::this_thread::sleep(boost::posix_time::milliseconds(50)); - if (this->get_locked()) return; + if (this->get_locked().to_bool()) break; } + return actual; } -void xcvr2450::set_lo_freq_core(double target_freq){ +double xcvr2450::set_lo_freq_core(double target_freq){ //clip the input to the range target_freq = xcvr_freq_range.clip(target_freq); @@ -348,6 +427,8 @@ void xcvr2450::set_lo_freq_core(double target_freq){ this->send_reg(0x5); _max2829_regs.vco_bandswitch = max2829_regs_t::VCO_BANDSWITCH_AUTOMATIC;; this->send_reg(0x5); + + return _lo_freq; } /*********************************************************************** @@ -441,7 +522,7 @@ static int gain_to_rx_lna_reg(double &gain){ return reg; } -void xcvr2450::set_tx_gain(double gain, const std::string &name){ +double xcvr2450::set_tx_gain(double gain, const std::string &name){ assert_has(xcvr_tx_gain_ranges.keys(), name, "xcvr tx gain name"); if (name == "VGA"){ _max2829_regs.tx_vga_gain = gain_to_tx_vga_reg(gain); @@ -453,9 +534,11 @@ void xcvr2450::set_tx_gain(double gain, const std::string &name){ } else UHD_THROW_INVALID_CODE_PATH(); _tx_gains[name] = gain; + + return gain; } -void xcvr2450::set_rx_gain(double gain, const std::string &name){ +double xcvr2450::set_rx_gain(double gain, const std::string &name){ assert_has(xcvr_rx_gain_ranges.keys(), name, "xcvr rx gain name"); if (name == "VGA"){ _max2829_regs.rx_vga_gain = gain_to_rx_vga_reg(gain); @@ -467,6 +550,8 @@ void xcvr2450::set_rx_gain(double gain, const std::string &name){ } else UHD_THROW_INVALID_CODE_PATH(); _rx_gains[name] = gain; + + return gain; } @@ -541,9 +626,12 @@ static max2829_regs_t::rx_lpf_coarse_adj_t bandwidth_to_rx_lpf_coarse_reg(double UHD_THROW_INVALID_CODE_PATH(); } -void xcvr2450::set_rx_bandwidth(double bandwidth){ +double xcvr2450::set_rx_bandwidth(double bandwidth){ double requested_bandwidth = bandwidth; + //convert complex bandpass to lowpass bandwidth + bandwidth = bandwidth/2.0; + //compute coarse low pass cutoff frequency setting _max2829_regs.rx_lpf_coarse_adj = bandwidth_to_rx_lpf_coarse_reg(bandwidth); @@ -559,9 +647,14 @@ void xcvr2450::set_rx_bandwidth(double bandwidth){ UHD_LOGV(often) << boost::format( "XCVR2450 RX Bandwidth (lp_fc): %f Hz, coarse reg: %d, fine reg: %d" ) % _rx_bandwidth % (int(_max2829_regs.rx_lpf_coarse_adj)) % (int(_max2829_regs.rx_lpf_fine_adj)) << std::endl; + + return 2.0*_rx_bandwidth; } -void xcvr2450::set_tx_bandwidth(double bandwidth){ +double xcvr2450::set_tx_bandwidth(double bandwidth){ + //convert complex bandpass to lowpass bandwidth + bandwidth = bandwidth/2.0; + //compute coarse low pass cutoff frequency setting _max2829_regs.tx_lpf_coarse_adj = bandwidth_to_tx_lpf_coarse_reg(bandwidth); @@ -574,219 +667,7 @@ void xcvr2450::set_tx_bandwidth(double bandwidth){ UHD_LOGV(often) << boost::format( "XCVR2450 TX Bandwidth (lp_fc): %f Hz, coarse reg: %d" ) % _tx_bandwidth % (int(_max2829_regs.tx_lpf_coarse_adj)) << std::endl; -} - - -/*********************************************************************** - * RX Get and Set - **********************************************************************/ -void xcvr2450::rx_get(const wax::obj &key_, wax::obj &val){ - named_prop_t key = named_prop_t::extract(key_); - - //handle the get request conditioned on the key - switch(key.as()){ - case SUBDEV_PROP_NAME: - val = get_rx_id().to_pp_string(); - return; - - case SUBDEV_PROP_OTHERS: - val = prop_names_t(); //empty - return; - - case SUBDEV_PROP_GAIN: - assert_has(_rx_gains.keys(), key.name, "xcvr rx gain name"); - val = _rx_gains[key.name]; - return; - - case SUBDEV_PROP_GAIN_RANGE: - assert_has(xcvr_rx_gain_ranges.keys(), key.name, "xcvr rx gain name"); - val = xcvr_rx_gain_ranges[key.name]; - return; - - case SUBDEV_PROP_GAIN_NAMES: - val = prop_names_t(xcvr_rx_gain_ranges.keys()); - return; - - case SUBDEV_PROP_FREQ: - val = _lo_freq; - return; - - case SUBDEV_PROP_FREQ_RANGE: - val = xcvr_freq_range; - return; - - case SUBDEV_PROP_ANTENNA: - val = _rx_ant; - return; - - case SUBDEV_PROP_ANTENNA_NAMES: - val = xcvr_antennas; - return; - - case SUBDEV_PROP_CONNECTION: - val = SUBDEV_CONN_COMPLEX_IQ; - return; - - case SUBDEV_PROP_ENABLED: - val = true; //always enabled - return; - - case SUBDEV_PROP_USE_LO_OFFSET: - val = false; - return; - - case SUBDEV_PROP_SENSOR: - if (key.name == "lo_locked") - val = sensor_value_t("LO", this->get_locked(), "locked", "unlocked"); - else if (key.name == "rssi") - val = sensor_value_t("RSSI", this->get_rssi(), "dBm"); - else - UHD_THROW_INVALID_CODE_PATH(); - return; - - case SUBDEV_PROP_SENSOR_NAMES:{ - prop_names_t names = list_of("lo_locked")("rssi"); - val = names; - } - return; - - case SUBDEV_PROP_BANDWIDTH: - val = 2*_rx_bandwidth; //_tx_bandwidth is low-pass, we want complex double-sided - return; - - default: UHD_THROW_PROP_GET_ERROR(); - } -} - -void xcvr2450::rx_set(const wax::obj &key_, const wax::obj &val){ - named_prop_t key = named_prop_t::extract(key_); - - //handle the get request conditioned on the key - switch(key.as()){ - - case SUBDEV_PROP_FREQ: - this->set_lo_freq(val.as()); - return; - - case SUBDEV_PROP_GAIN: - this->set_rx_gain(val.as(), key.name); - return; - - case SUBDEV_PROP_ANTENNA: - this->set_rx_ant(val.as()); - return; - - case SUBDEV_PROP_BANDWIDTH: - this->set_rx_bandwidth(val.as()/2.0); //complex double-sided, we want low-pass - return; - - case SUBDEV_PROP_ENABLED: - return; //always enabled - default: UHD_THROW_PROP_SET_ERROR(); - } -} - -/*********************************************************************** - * TX Get and Set - **********************************************************************/ -void xcvr2450::tx_get(const wax::obj &key_, wax::obj &val){ - named_prop_t key = named_prop_t::extract(key_); - - //handle the get request conditioned on the key - switch(key.as()){ - case SUBDEV_PROP_NAME: - val = get_tx_id().to_pp_string(); - return; - - case SUBDEV_PROP_OTHERS: - val = prop_names_t(); //empty - return; - - case SUBDEV_PROP_GAIN: - assert_has(_tx_gains.keys(), key.name, "xcvr tx gain name"); - val = _tx_gains[key.name]; - return; - - case SUBDEV_PROP_GAIN_RANGE: - assert_has(xcvr_tx_gain_ranges.keys(), key.name, "xcvr tx gain name"); - val = xcvr_tx_gain_ranges[key.name]; - return; - - case SUBDEV_PROP_GAIN_NAMES: - val = prop_names_t(xcvr_tx_gain_ranges.keys()); - return; - - case SUBDEV_PROP_FREQ: - val = _lo_freq; - return; - - case SUBDEV_PROP_FREQ_RANGE: - val = xcvr_freq_range; - return; - - case SUBDEV_PROP_ANTENNA: - val = _tx_ant; - return; - - case SUBDEV_PROP_ANTENNA_NAMES: - val = xcvr_antennas; - return; - - case SUBDEV_PROP_CONNECTION: - val = SUBDEV_CONN_COMPLEX_QI; - return; - - case SUBDEV_PROP_ENABLED: - val = true; //always enabled - return; - - case SUBDEV_PROP_USE_LO_OFFSET: - val = false; - return; - - case SUBDEV_PROP_SENSOR: - UHD_ASSERT_THROW(key.name == "lo_locked"); - val = sensor_value_t("LO", this->get_locked(), "locked", "unlocked"); - return; - - case SUBDEV_PROP_SENSOR_NAMES: - val = prop_names_t(1, "lo_locked"); - return; - - case SUBDEV_PROP_BANDWIDTH: - val = 2*_tx_bandwidth; //_tx_bandwidth is low-pass, we want complex double-sided - return; - - default: UHD_THROW_PROP_GET_ERROR(); - } -} - -void xcvr2450::tx_set(const wax::obj &key_, const wax::obj &val){ - named_prop_t key = named_prop_t::extract(key_); - - //handle the get request conditioned on the key - switch(key.as()){ - - case SUBDEV_PROP_FREQ: - set_lo_freq(val.as()); - return; - - case SUBDEV_PROP_GAIN: - this->set_tx_gain(val.as(), key.name); - return; - - case SUBDEV_PROP_BANDWIDTH: - this->set_tx_bandwidth(val.as()/2.0); //complex double-sided, we want low-pass - return; - - case SUBDEV_PROP_ANTENNA: - this->set_tx_ant(val.as()); - return; - - case SUBDEV_PROP_ENABLED: - return; //always enabled - - default: UHD_THROW_PROP_SET_ERROR(); - } + //convert lowpass back to complex bandpass bandwidth + return 2.0*_tx_bandwidth; } -- cgit v1.2.3 From 8a8dfe41f26ee276e0aded016a6e7bc8e7010a77 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Wed, 26 Oct 2011 10:42:38 -0700 Subject: basic: disable dboard clocks by default --- host/lib/usrp/dboard/db_basic_and_lf.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'host') diff --git a/host/lib/usrp/dboard/db_basic_and_lf.cpp b/host/lib/usrp/dboard/db_basic_and_lf.cpp index 971ecaeda..53429a8c7 100644 --- a/host/lib/usrp/dboard/db_basic_and_lf.cpp +++ b/host/lib/usrp/dboard/db_basic_and_lf.cpp @@ -131,8 +131,8 @@ basic_rx::basic_rx(ctor_args_t args, double max_freq) : rx_dboard_base(args){ this->get_rx_subtree()->create("bandwidth/range") .set(freq_range_t(subdev_bandwidth_scalar[get_subdev_name()]*_max_freq, subdev_bandwidth_scalar[get_subdev_name()]*_max_freq)); - //enable RX dboard clock - this->get_iface()->set_clock_enabled(dboard_iface::UNIT_RX, true); + //disable RX dboard clock by default + this->get_iface()->set_clock_enabled(dboard_iface::UNIT_RX, false); //set GPIOs to output 0x0000 to decrease noise pickup this->get_iface()->set_pin_ctrl(dboard_iface::UNIT_RX, 0x0000); @@ -180,8 +180,8 @@ basic_tx::basic_tx(ctor_args_t args, double max_freq) : tx_dboard_base(args){ this->get_tx_subtree()->create("bandwidth/range") .set(freq_range_t(subdev_bandwidth_scalar[get_subdev_name()]*_max_freq, subdev_bandwidth_scalar[get_subdev_name()]*_max_freq)); - //enable TX dboard clock - this->get_iface()->set_clock_enabled(dboard_iface::UNIT_TX, true); + //disable TX dboard clock by default + this->get_iface()->set_clock_enabled(dboard_iface::UNIT_TX, false); //set GPIOs to output 0x0000 to decrease noise pickup this->get_iface()->set_pin_ctrl(dboard_iface::UNIT_TX, 0x0000); -- cgit v1.2.3 From a0e9612f7a32c370f26d1b2db2eee7e692a8f8e9 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Wed, 26 Oct 2011 13:00:30 -0700 Subject: sbx: squashed Ben's SBX work --- host/lib/ic_reg_maps/CMakeLists.txt | 5 + host/lib/ic_reg_maps/gen_adf4351_regs.py | 138 ++++++ host/lib/usrp/dboard/CMakeLists.txt | 4 +- host/lib/usrp/dboard/db_sbx.cpp | 785 ------------------------------- host/lib/usrp/dboard/db_sbx_common.cpp | 514 ++++++++++++++++++++ host/lib/usrp/dboard/db_sbx_common.hpp | 233 +++++++++ host/lib/usrp/dboard/db_sbx_version3.cpp | 186 ++++++++ host/lib/usrp/dboard/db_sbx_version4.cpp | 189 ++++++++ 8 files changed, 1268 insertions(+), 786 deletions(-) create mode 100755 host/lib/ic_reg_maps/gen_adf4351_regs.py delete mode 100644 host/lib/usrp/dboard/db_sbx.cpp create mode 100644 host/lib/usrp/dboard/db_sbx_common.cpp create mode 100644 host/lib/usrp/dboard/db_sbx_common.hpp create mode 100644 host/lib/usrp/dboard/db_sbx_version3.cpp create mode 100644 host/lib/usrp/dboard/db_sbx_version4.cpp (limited to 'host') diff --git a/host/lib/ic_reg_maps/CMakeLists.txt b/host/lib/ic_reg_maps/CMakeLists.txt index 46cf5a06a..dc2ab7847 100644 --- a/host/lib/ic_reg_maps/CMakeLists.txt +++ b/host/lib/ic_reg_maps/CMakeLists.txt @@ -27,6 +27,11 @@ LIBUHD_PYTHON_GEN_SOURCE( ${CMAKE_CURRENT_BINARY_DIR}/adf4350_regs.hpp ) +LIBUHD_PYTHON_GEN_SOURCE( + ${CMAKE_CURRENT_SOURCE_DIR}/gen_adf4351_regs.py + ${CMAKE_CURRENT_BINARY_DIR}/adf4351_regs.hpp +) + LIBUHD_PYTHON_GEN_SOURCE( ${CMAKE_CURRENT_SOURCE_DIR}/gen_adf4360_regs.py ${CMAKE_CURRENT_BINARY_DIR}/adf4360_regs.hpp diff --git a/host/lib/ic_reg_maps/gen_adf4351_regs.py b/host/lib/ic_reg_maps/gen_adf4351_regs.py new file mode 100755 index 000000000..607b2979d --- /dev/null +++ b/host/lib/ic_reg_maps/gen_adf4351_regs.py @@ -0,0 +1,138 @@ +#!/usr/bin/env python +# +# 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 . +# + +######################################################################## +# Template for raw text data describing registers +# name addr[bit range inclusive] default optional enums +######################################################################## +REGS_TMPL="""\ +######################################################################## +## address 0 +######################################################################## +frac_12_bit 0[3:14] 0 +int_16_bit 0[15:30] 0x23 +##reserved 0[31] 0 +######################################################################## +## address 1 +######################################################################## +mod_12_bit 1[3:14] 0xfff +phase_12_bit 1[15:26] 0 +prescaler 1[27] 0 4_5, 8_9 +phase_adjust 1[28] 0 +##reserved 1[29:31] 0 +######################################################################## +## address 2 +######################################################################## +counter_reset 2[3] 0 disabled, enabled +cp_three_state 2[4] 0 disabled, enabled +power_down 2[5] 0 disabled, enabled +pd_polarity 2[6] 1 negative, positive +ldp 2[7] 0 10ns, 6ns +ldf 2[8] 0 frac_n, int_n +#set $current_setting_enums = ', '.join(map(lambda x: '_'.join(("%0.2fma"%(round(x*31.27 + 31.27)/100)).split('.')), range(0,16))) +charge_pump_current 2[9:12] 5 $current_setting_enums +double_buffer 2[13] 0 disabled, enabled +r_counter_10_bit 2[14:23] 0 +reference_divide_by_2 2[24] 1 disabled, enabled +reference_doubler 2[25] 0 disabled, enabled +muxout 2[26:28] 1 3state, dvdd, dgnd, rdiv, ndiv, analog_ld, dld, reserved +low_noise_and_spur 2[29:30] 3 low_noise, reserved0, reserved1, low_spur +##reserved 2[31] 0 +######################################################################## +## address 3 +######################################################################## +clock_divider_12_bit 3[3:14] 0 +clock_div_mode 3[15:16] 0 clock_divider_off, fast_lock, resync_enable, reserved +##reserved 3[17] 0 +cycle_slip_reduction 3[18] 0 disabled, enabled +##reserved 3[19:20] 0 +charge_cancel 3[21] 0 +anti_backlash_pulse 3[22] 0 6ns, 3ns +band_select_mode 3[23] 0 low, high +##reserved 3[24:31] 0 +######################################################################## +## address 4 +######################################################################## +output_power 4[3:4] 3 m4dbm, m1dbm, 2dbm, 5dbm +rf_output_enable 4[5] 1 disabled, enabled +aux_output_power 4[6:7] 0 m4dbm, m1dbm, 2dbm, 5dbm +aux_output_enable 4[8] 0 disabled, enabled +aux_output_select 4[9] 1 divided, fundamental +mute_till_lock_detect 4[10] 0 mute_disabled, mute_enabled +vco_power_down 4[11] 0 vco_powered_up, vco_powered_down +band_select_clock_div 4[12:19] 0 +rf_divider_select 4[20:22] 5 div1, div2, div4, div8, div16, div32, div64 +feedback_select 4[23] 1 divided, fundamental +##reserved 4[24:31] 0 +######################################################################## +## address 5 +######################################################################## +##reserved 5[3:18] 0 +##reserved 5[19:20] 0 +##reserved 5[21] 0 +ld_pin_mode 5[22:23] 1 low0, dld, low, high +##reserved 5[24:31] 0 +""" + +######################################################################## +# Template for methods in the body of the struct +######################################################################## +BODY_TMPL="""\ +enum addr_t{ + ADDR_R0 = 0, + ADDR_R1 = 1, + ADDR_R2 = 2, + ADDR_R3 = 3, + ADDR_R4 = 4, + ADDR_R5 = 5 +}; + +boost::uint32_t get_reg(boost::uint8_t addr){ + boost::uint32_t reg = 0; + switch(addr){ + #for $addr in sorted(set(map(lambda r: r.get_addr(), $regs))) + case $addr: + #for $reg in filter(lambda r: r.get_addr() == addr, $regs) + reg |= (boost::uint32_t($reg.get_name()) & $reg.get_mask()) << $reg.get_shift(); + #end for + break; + #end for + } + return reg; +} + +void set_reg(boost::uint8_t addr, boost::uint32_t reg){ + switch(addr){ + #for $addr in sorted(set(map(lambda r: r.get_addr(), $regs))) + case $addr: + #for $reg in filter(lambda r: r.get_addr() == addr, $regs) + $reg.get_name() = $(reg.get_type())((reg >> $reg.get_shift()) & $reg.get_mask()); + #end for + break; + #end for + } +} +""" + +if __name__ == '__main__': + import common; common.generate( + name='adf4351_regs', + regs_tmpl=REGS_TMPL, + body_tmpl=BODY_TMPL, + file=__file__, + ) diff --git a/host/lib/usrp/dboard/CMakeLists.txt b/host/lib/usrp/dboard/CMakeLists.txt index cb71e695b..a865a7858 100644 --- a/host/lib/usrp/dboard/CMakeLists.txt +++ b/host/lib/usrp/dboard/CMakeLists.txt @@ -23,7 +23,9 @@ LIBUHD_APPEND_SOURCES( ${CMAKE_CURRENT_SOURCE_DIR}/db_basic_and_lf.cpp ${CMAKE_CURRENT_SOURCE_DIR}/db_rfx.cpp ${CMAKE_CURRENT_SOURCE_DIR}/db_xcvr2450.cpp - #${CMAKE_CURRENT_SOURCE_DIR}/db_sbx.cpp + #${CMAKE_CURRENT_SOURCE_DIR}/db_sbx_common.cpp + #${CMAKE_CURRENT_SOURCE_DIR}/db_sbx_version3.cpp + #${CMAKE_CURRENT_SOURCE_DIR}/db_sbx_version4.cpp #${CMAKE_CURRENT_SOURCE_DIR}/db_wbx_common.cpp #${CMAKE_CURRENT_SOURCE_DIR}/db_wbx_simple.cpp ${CMAKE_CURRENT_SOURCE_DIR}/db_dbsrx.cpp diff --git a/host/lib/usrp/dboard/db_sbx.cpp b/host/lib/usrp/dboard/db_sbx.cpp deleted file mode 100644 index 40dbd286d..000000000 --- a/host/lib/usrp/dboard/db_sbx.cpp +++ /dev/null @@ -1,785 +0,0 @@ -// -// 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 . -// - -// Common IO Pins -#define LO_LPF_EN (1 << 15) -#define ADF4350_CE (1 << 3) -#define ADF4350_PDBRF (1 << 2) -#define ADF4350_MUXOUT (1 << 1) // INPUT!!! -#define LOCKDET_MASK (1 << 0) // INPUT!!! - -// TX IO Pins -#define TRSW (1 << 14) // 0 = TX, 1 = RX -#define TX_LED_TXRX (1 << 7) // LED for TX Antenna Selection TX/RX -#define TX_LED_LD (1 << 6) // LED for TX Lock Detect -#define DIS_POWER_TX (1 << 5) // on UNIT_TX, 0 powers up TX -#define TX_ENABLE (1 << 4) // on UNIT_TX, 0 disables TX Mixer - -// RX IO Pins -#define LNASW (1 << 14) // 0 = TX/RX, 1 = RX2 -#define RX_LED_RX1RX2 (1 << 7) // LED for RX Antenna Selection RX1/RX2 -#define RX_LED_LD (1 << 6) // LED for RX Lock Detect -#define DIS_POWER_RX (1 << 5) // on UNIT_RX, 0 powers up RX -#define RX_DISABLE (1 << 4) // on UNIT_RX, 1 disables RX Mixer and Baseband - -// RX Attenuator Pins -#define RX_ATTN_SHIFT 8 // lsb of RX Attenuator Control -#define RX_ATTN_MASK (63 << RX_ATTN_SHIFT) // valid bits of RX Attenuator Control - -// TX Attenuator Pins -#define TX_ATTN_SHIFT 8 // lsb of RX Attenuator Control -#define TX_ATTN_MASK (63 << TX_ATTN_SHIFT) // valid bits of RX Attenuator Control - -// Mixer functions -#define TX_MIXER_ENB (ADF4350_PDBRF) -#define TX_MIXER_DIS 0 - -#define RX_MIXER_ENB (ADF4350_PDBRF) -#define RX_MIXER_DIS 0 - -// Pin functions -#define TX_LED_IO (TX_LED_TXRX|TX_LED_LD) // LED gpio lines, pull down for LED -#define TXIO_MASK (LO_LPF_EN|TRSW|ADF4350_CE|ADF4350_PDBRF|TX_ATTN_MASK|DIS_POWER_TX|TX_ENABLE) - -#define RX_LED_IO (RX_LED_RX1RX2|RX_LED_LD) // LED gpio lines, pull down for LED -#define RXIO_MASK (LO_LPF_EN|LNASW|ADF4350_CE|ADF4350_PDBRF|RX_ATTN_MASK|DIS_POWER_RX|RX_DISABLE) - -// Power functions -#define TX_POWER_UP (ADF4350_CE|TX_ENABLE) -#define TX_POWER_DOWN (DIS_POWER_TX) - -#define RX_POWER_UP (ADF4350_CE) -#define RX_POWER_DOWN (DIS_POWER_RX) - -// Antenna constants -#define ANT_TX TRSW //the tx line is transmitting -#define ANT_RX 0 //the tx line is receiving -#define ANT_TXRX 0 //the rx line is on txrx -#define ANT_RX2 LNASW //the rx line in on rx2 -#define ANT_XX LNASW //dont care how the antenna is set - -#include "adf4350_regs.hpp" -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -using namespace uhd; -using namespace uhd::usrp; -using namespace boost::assign; - -/*********************************************************************** - * The SBX dboard constants - **********************************************************************/ -static const freq_range_t sbx_freq_range(400e6, 4.4e9); - -static const freq_range_t sbx_tx_lo_2dbm = list_of - (range_t(0.35e9, 0.37e9)) -; - -static const freq_range_t sbx_enable_tx_lo_filter = list_of - (range_t(0.4e9, 1.5e9)) -; - -static const freq_range_t sbx_enable_rx_lo_filter = list_of - (range_t(0.4e9, 1.5e9)) -; - -static const prop_names_t sbx_tx_antennas = list_of("TX/RX"); - -static const prop_names_t sbx_rx_antennas = list_of("TX/RX")("RX2"); - -static const uhd::dict sbx_tx_gain_ranges = map_list_of - ("PGA0", gain_range_t(0, 31.5, double(0.5))) -; - -static const uhd::dict sbx_rx_gain_ranges = map_list_of - ("PGA0", gain_range_t(0, 31.5, double(0.5))) -; - -/*********************************************************************** - * The SBX dboard - **********************************************************************/ -class sbx_xcvr : public xcvr_dboard_base{ -public: - sbx_xcvr(ctor_args_t args); - ~sbx_xcvr(void); - - void rx_get(const wax::obj &key, wax::obj &val); - void rx_set(const wax::obj &key, const wax::obj &val); - - void tx_get(const wax::obj &key, wax::obj &val); - void tx_set(const wax::obj &key, const wax::obj &val); - -private: - uhd::dict _tx_gains, _rx_gains; - double _rx_lo_freq, _tx_lo_freq; - std::string _tx_ant, _rx_ant; - - void set_rx_lo_freq(double freq); - void set_tx_lo_freq(double freq); - void set_rx_ant(const std::string &ant); - void set_tx_ant(const std::string &ant); - void set_rx_gain(double gain, const std::string &name); - void set_tx_gain(double gain, const std::string &name); - - void update_atr(void); - - /*! - * Set the LO frequency for the particular dboard unit. - * \param unit which unit rx or tx - * \param target_freq the desired frequency in Hz - * \return the actual frequency in Hz - */ - double set_lo_freq(dboard_iface::unit_t unit, double target_freq); - - /*! - * Get the lock detect status of the LO. - * \param unit which unit rx or tx - * \return true for locked - */ - bool get_locked(dboard_iface::unit_t unit){ - return (this->get_iface()->read_gpio(unit) & LOCKDET_MASK) != 0; - } - - /*! - * Flash the LEDs - */ - void flash_leds(void) { - //Remove LED gpios from ATR control temporarily and set to outputs - this->get_iface()->set_pin_ctrl(dboard_iface::UNIT_TX, TXIO_MASK); - this->get_iface()->set_pin_ctrl(dboard_iface::UNIT_RX, RXIO_MASK); - this->get_iface()->set_gpio_ddr(dboard_iface::UNIT_TX, (TXIO_MASK|RX_LED_IO)); - this->get_iface()->set_gpio_ddr(dboard_iface::UNIT_RX, (RXIO_MASK|RX_LED_IO)); - - /* - //flash All LEDs - for (int i = 0; i < 3; i++) { - this->get_iface()->set_gpio_out(dboard_iface::UNIT_RX, RX_LED_IO, RX_LED_IO); - this->get_iface()->set_gpio_out(dboard_iface::UNIT_TX, TX_LED_IO, TX_LED_IO); - - boost::this_thread::sleep(boost::posix_time::milliseconds(100)); - - this->get_iface()->set_gpio_out(dboard_iface::UNIT_RX, 0, RX_LED_IO); - this->get_iface()->set_gpio_out(dboard_iface::UNIT_TX, 0, TX_LED_IO); - - boost::this_thread::sleep(boost::posix_time::milliseconds(100)); - } - */ - - this->get_iface()->set_gpio_out(dboard_iface::UNIT_TX, TX_LED_LD, TX_LED_IO); - boost::this_thread::sleep(boost::posix_time::milliseconds(100)); - - this->get_iface()->set_gpio_out(dboard_iface::UNIT_TX, TX_LED_TXRX|TX_LED_LD, TX_LED_IO); - boost::this_thread::sleep(boost::posix_time::milliseconds(100)); - - this->get_iface()->set_gpio_out(dboard_iface::UNIT_RX, RX_LED_LD, RX_LED_IO); - boost::this_thread::sleep(boost::posix_time::milliseconds(100)); - - this->get_iface()->set_gpio_out(dboard_iface::UNIT_RX, RX_LED_RX1RX2|RX_LED_LD, RX_LED_IO); - boost::this_thread::sleep(boost::posix_time::milliseconds(100)); - - this->get_iface()->set_gpio_out(dboard_iface::UNIT_RX, RX_LED_LD, RX_LED_IO); - boost::this_thread::sleep(boost::posix_time::milliseconds(100)); - - this->get_iface()->set_gpio_out(dboard_iface::UNIT_RX, 0, RX_LED_IO); - boost::this_thread::sleep(boost::posix_time::milliseconds(100)); - - this->get_iface()->set_gpio_out(dboard_iface::UNIT_TX, TX_LED_LD, TX_LED_IO); - boost::this_thread::sleep(boost::posix_time::milliseconds(100)); - - this->get_iface()->set_gpio_out(dboard_iface::UNIT_TX, 0, TX_LED_IO); - boost::this_thread::sleep(boost::posix_time::milliseconds(100)); - - /* - //flash All LEDs - for (int i = 0; i < 3; i++) { - this->get_iface()->set_gpio_out(dboard_iface::UNIT_RX, 0, RX_LED_IO); - this->get_iface()->set_gpio_out(dboard_iface::UNIT_TX, 0, TX_LED_IO); - - boost::this_thread::sleep(boost::posix_time::milliseconds(100)); - - this->get_iface()->set_gpio_out(dboard_iface::UNIT_RX, RX_LED_IO, RX_LED_IO); - this->get_iface()->set_gpio_out(dboard_iface::UNIT_TX, TX_LED_IO, TX_LED_IO); - - boost::this_thread::sleep(boost::posix_time::milliseconds(100)); - } - */ - //Put LED gpios back in ATR control and update atr - this->get_iface()->set_pin_ctrl(dboard_iface::UNIT_TX, (TXIO_MASK|TX_LED_IO)); - this->get_iface()->set_pin_ctrl(dboard_iface::UNIT_RX, (RXIO_MASK|RX_LED_IO)); - this->get_iface()->set_gpio_ddr(dboard_iface::UNIT_TX, (TXIO_MASK|TX_LED_IO)); - this->get_iface()->set_gpio_ddr(dboard_iface::UNIT_RX, (RXIO_MASK|RX_LED_IO)); - } - -}; - -/*********************************************************************** - * Register the SBX dboard (min freq, max freq, rx div2, tx div2) - **********************************************************************/ -static dboard_base::sptr make_sbx(dboard_base::ctor_args_t args){ - return dboard_base::sptr(new sbx_xcvr(args)); -} - -UHD_STATIC_BLOCK(reg_sbx_dboards){ - dboard_manager::register_dboard(0x0054, 0x0055, &make_sbx, "SBX"); -} - -/*********************************************************************** - * Structors - **********************************************************************/ -sbx_xcvr::sbx_xcvr(ctor_args_t args) : xcvr_dboard_base(args){ - - //enable the clocks that we need - this->get_iface()->set_clock_enabled(dboard_iface::UNIT_TX, true); - this->get_iface()->set_clock_enabled(dboard_iface::UNIT_RX, true); - - //set the gpio directions and atr controls (identically) - this->get_iface()->set_pin_ctrl(dboard_iface::UNIT_TX, (TXIO_MASK|TX_LED_IO)); - this->get_iface()->set_pin_ctrl(dboard_iface::UNIT_RX, (RXIO_MASK|RX_LED_IO)); - this->get_iface()->set_gpio_ddr(dboard_iface::UNIT_TX, (TXIO_MASK|TX_LED_IO)); - this->get_iface()->set_gpio_ddr(dboard_iface::UNIT_RX, (RXIO_MASK|RX_LED_IO)); - - //flash LEDs - flash_leds(); - - UHD_LOGV(often) << boost::format( - "SBX GPIO Direction: RX: 0x%08x, TX: 0x%08x" - ) % RXIO_MASK % TXIO_MASK << std::endl; - - //set some default values - set_rx_lo_freq((sbx_freq_range.start() + sbx_freq_range.stop())/2.0); - set_tx_lo_freq((sbx_freq_range.start() + sbx_freq_range.stop())/2.0); - set_rx_ant("RX2"); - - BOOST_FOREACH(const std::string &name, sbx_tx_gain_ranges.keys()){ - set_tx_gain(sbx_tx_gain_ranges[name].start(), name); - } - BOOST_FOREACH(const std::string &name, sbx_rx_gain_ranges.keys()){ - set_rx_gain(sbx_rx_gain_ranges[name].start(), name); - } -} - -sbx_xcvr::~sbx_xcvr(void){ - /* NOP */ -} - -/*********************************************************************** - * Gain Handling - **********************************************************************/ -static int rx_pga0_gain_to_iobits(double &gain){ - //clip the input - gain = sbx_rx_gain_ranges["PGA0"].clip(gain); - - //convert to attenuation and update iobits for atr - double attn = sbx_rx_gain_ranges["PGA0"].stop() - gain; - - //calculate the RX attenuation - int attn_code = int(floor(attn*2)); - int iobits = ((~attn_code) << RX_ATTN_SHIFT) & RX_ATTN_MASK; - - - UHD_LOGV(often) << boost::format( - "SBX TX Attenuation: %f dB, Code: %d, IO Bits %x, Mask: %x" - ) % attn % attn_code % (iobits & RX_ATTN_MASK) % RX_ATTN_MASK << std::endl; - - //the actual gain setting - gain = sbx_rx_gain_ranges["PGA0"].stop() - double(attn_code)/2; - - return iobits; -} - -static int tx_pga0_gain_to_iobits(double &gain){ - //clip the input - gain = sbx_tx_gain_ranges["PGA0"].clip(gain); - - //convert to attenuation and update iobits for atr - double attn = sbx_tx_gain_ranges["PGA0"].stop() - gain; - - //calculate the TX attenuation - int attn_code = int(floor(attn*2)); - int iobits = ((~attn_code) << TX_ATTN_SHIFT) & TX_ATTN_MASK; - - - UHD_LOGV(often) << boost::format( - "SBX TX Attenuation: %f dB, Code: %d, IO Bits %x, Mask: %x" - ) % attn % attn_code % (iobits & TX_ATTN_MASK) % TX_ATTN_MASK << std::endl; - - //the actual gain setting - gain = sbx_tx_gain_ranges["PGA0"].stop() - double(attn_code)/2; - - return iobits; -} - -void sbx_xcvr::set_tx_gain(double gain, const std::string &name){ - assert_has(sbx_tx_gain_ranges.keys(), name, "sbx tx gain name"); - if(name == "PGA0"){ - tx_pga0_gain_to_iobits(gain); - _tx_gains[name] = gain; - - //write the new gain to atr regs - update_atr(); - } - else UHD_THROW_INVALID_CODE_PATH(); -} - -void sbx_xcvr::set_rx_gain(double gain, const std::string &name){ - assert_has(sbx_rx_gain_ranges.keys(), name, "sbx rx gain name"); - if(name == "PGA0"){ - rx_pga0_gain_to_iobits(gain); - _rx_gains[name] = gain; - - //write the new gain to atr regs - update_atr(); - } - else UHD_THROW_INVALID_CODE_PATH(); -} - -/*********************************************************************** - * Antenna Handling - **********************************************************************/ -void sbx_xcvr::update_atr(void){ - //calculate atr pins - int rx_pga0_iobits = rx_pga0_gain_to_iobits(_rx_gains["PGA0"]); - int tx_pga0_iobits = tx_pga0_gain_to_iobits(_tx_gains["PGA0"]); - int rx_lo_lpf_en = (_rx_lo_freq == sbx_enable_rx_lo_filter.clip(_rx_lo_freq)) ? LO_LPF_EN : 0; - int tx_lo_lpf_en = (_tx_lo_freq == sbx_enable_tx_lo_filter.clip(_tx_lo_freq)) ? LO_LPF_EN : 0; - int rx_ld_led = get_locked(dboard_iface::UNIT_RX) ? 0 : RX_LED_LD; - int tx_ld_led = get_locked(dboard_iface::UNIT_TX) ? 0 : TX_LED_LD; - int rx_ant_led = _rx_ant == "TX/RX" ? RX_LED_RX1RX2 : 0; - int tx_ant_led = _rx_ant == "TX/RX" ? 0 : TX_LED_TXRX; - - //setup the tx atr (this does not change with antenna) - this->get_iface()->set_atr_reg(dboard_iface::UNIT_TX, dboard_iface::ATR_REG_IDLE, - tx_pga0_iobits | tx_lo_lpf_en | tx_ld_led | tx_ant_led | TX_POWER_UP | ANT_XX | TX_MIXER_DIS); - this->get_iface()->set_atr_reg(dboard_iface::UNIT_TX, dboard_iface::ATR_REG_TX_ONLY, - tx_pga0_iobits | tx_lo_lpf_en | tx_ld_led | tx_ant_led | TX_POWER_UP | ANT_TX | TX_MIXER_ENB); - this->get_iface()->set_atr_reg(dboard_iface::UNIT_TX, dboard_iface::ATR_REG_FULL_DUPLEX, - tx_pga0_iobits | tx_lo_lpf_en | tx_ld_led | tx_ant_led | TX_POWER_UP | ANT_TX | TX_MIXER_ENB); - - //setup the rx atr (this does not change with antenna) - this->get_iface()->set_atr_reg(dboard_iface::UNIT_RX, dboard_iface::ATR_REG_IDLE, - rx_pga0_iobits | rx_lo_lpf_en | rx_ld_led | rx_ant_led | RX_POWER_UP | ANT_XX | RX_MIXER_DIS); - this->get_iface()->set_atr_reg(dboard_iface::UNIT_RX, dboard_iface::ATR_REG_TX_ONLY, - rx_pga0_iobits | rx_lo_lpf_en | rx_ld_led | rx_ant_led | RX_POWER_UP | ANT_RX2 | RX_MIXER_DIS); - this->get_iface()->set_atr_reg(dboard_iface::UNIT_RX, dboard_iface::ATR_REG_FULL_DUPLEX, - rx_pga0_iobits | rx_lo_lpf_en | rx_ld_led | rx_ant_led | RX_POWER_UP | ANT_RX2 | RX_MIXER_ENB); - - //set the atr regs that change with antenna setting - this->get_iface()->set_atr_reg(dboard_iface::UNIT_TX, dboard_iface::ATR_REG_RX_ONLY, - tx_pga0_iobits | tx_lo_lpf_en | tx_ld_led | tx_ant_led | TX_POWER_UP | TX_MIXER_DIS | - ((_rx_ant == "TX/RX")? ANT_RX : ANT_TX)); - this->get_iface()->set_atr_reg(dboard_iface::UNIT_RX, dboard_iface::ATR_REG_RX_ONLY, - rx_pga0_iobits | rx_lo_lpf_en | rx_ld_led | rx_ant_led | RX_POWER_UP | RX_MIXER_ENB | - ((_rx_ant == "TX/RX")? ANT_TXRX : ANT_RX2)); - - UHD_LOGV(often) << boost::format( - "SBX RXONLY ATR REG: 0x%08x" - ) % (rx_pga0_iobits | RX_POWER_UP | RX_MIXER_ENB | ((_rx_ant == "TX/RX")? ANT_TXRX : ANT_RX2)) << std::endl; -} - -void sbx_xcvr::set_rx_ant(const std::string &ant){ - //validate input - assert_has(sbx_rx_antennas, ant, "sbx rx antenna name"); - - //shadow the setting - _rx_ant = ant; - - //write the new antenna setting to atr regs - update_atr(); -} - -void sbx_xcvr::set_tx_ant(const std::string &ant){ - assert_has(sbx_tx_antennas, ant, "sbx tx antenna name"); - //only one antenna option, do nothing -} - -/*********************************************************************** - * Tuning - **********************************************************************/ -void sbx_xcvr::set_rx_lo_freq(double freq){ - _rx_lo_freq = set_lo_freq(dboard_iface::UNIT_RX, freq); -} - -void sbx_xcvr::set_tx_lo_freq(double freq){ - _tx_lo_freq = set_lo_freq(dboard_iface::UNIT_TX, freq); -} - -double sbx_xcvr::set_lo_freq( - dboard_iface::unit_t unit, - double target_freq -){ - UHD_LOGV(often) << boost::format( - "SBX tune: target frequency %f Mhz" - ) % (target_freq/1e6) << std::endl; - - //clip the input - target_freq = sbx_freq_range.clip(target_freq); - - //map prescaler setting to mininmum integer divider (N) values (pg.18 prescaler) - static const uhd::dict prescaler_to_min_int_div = map_list_of - (0,23) //adf4350_regs_t::PRESCALER_4_5 - (1,75) //adf4350_regs_t::PRESCALER_8_9 - ; - - //map rf divider select output dividers to enums - static const uhd::dict rfdivsel_to_enum = map_list_of - (1, adf4350_regs_t::RF_DIVIDER_SELECT_DIV1) - (2, adf4350_regs_t::RF_DIVIDER_SELECT_DIV2) - (4, adf4350_regs_t::RF_DIVIDER_SELECT_DIV4) - (8, adf4350_regs_t::RF_DIVIDER_SELECT_DIV8) - (16, adf4350_regs_t::RF_DIVIDER_SELECT_DIV16) - ; - - double actual_freq, pfd_freq; - double ref_freq = this->get_iface()->get_clock_rate(unit); - int R=0, BS=0, N=0, FRAC=0, MOD=0; - int RFdiv = 1; - adf4350_regs_t::reference_divide_by_2_t T = adf4350_regs_t::REFERENCE_DIVIDE_BY_2_DISABLED; - adf4350_regs_t::reference_doubler_t D = adf4350_regs_t::REFERENCE_DOUBLER_DISABLED; - - //Reference doubler for 50% duty cycle - // if ref_freq < 12.5MHz enable regs.reference_divide_by_2 - if(ref_freq <= 12.5e6) D = adf4350_regs_t::REFERENCE_DOUBLER_ENABLED; - - //increase RF divider until acceptable VCO frequency - //start with target_freq*2 because mixer has divide by 2 - double vco_freq = target_freq; - while (vco_freq < 2.2e9) { - vco_freq *= 2; - RFdiv *= 2; - } - - //use 8/9 prescaler for vco_freq > 3 GHz (pg.18 prescaler) - adf4350_regs_t::prescaler_t prescaler = vco_freq > 3e9 ? adf4350_regs_t::PRESCALER_8_9 : adf4350_regs_t::PRESCALER_4_5; - - /* - * The goal here is to loop though possible R dividers, - * band select clock dividers, N (int) dividers, and FRAC - * (frac) dividers. - * - * Calculate the N and F dividers for each set of values. - * The loop exists when it meets all of the constraints. - * The resulting loop values are loaded into the registers. - * - * from pg.21 - * - * f_pfd = f_ref*(1+D)/(R*(1+T)) - * f_vco = (N + (FRAC/MOD))*f_pfd - * N = f_vco/f_pfd - FRAC/MOD = f_vco*((R*(T+1))/(f_ref*(1+D))) - FRAC/MOD - * f_rf = f_vco/RFdiv) - * f_actual = f_rf/2 - */ - for(R = 1; R <= 1023; R+=1){ - //PFD input frequency = f_ref/R ... ignoring Reference doubler/divide-by-2 (D & T) - pfd_freq = ref_freq*(1+D)/(R*(1+T)); - - //keep the PFD frequency at or below 25MHz (Loop Filter Bandwidth) - if (pfd_freq > 25e6) continue; - - //ignore fractional part of tuning - N = int(std::floor(vco_freq/pfd_freq)); - - //keep N > minimum int divider requirement - if (N < prescaler_to_min_int_div[prescaler]) continue; - - for(BS=1; BS <= 255; BS+=1){ - //keep the band select frequency at or below 100KHz - //constraint on band select clock - if (pfd_freq/BS > 100e3) continue; - goto done_loop; - } - } done_loop: - - //Fractional-N calculation - MOD = 4095; //max fractional accuracy - FRAC = int((vco_freq/pfd_freq - N)*MOD); - - //Reference divide-by-2 for 50% duty cycle - // if R even, move one divide by 2 to to regs.reference_divide_by_2 - if(R % 2 == 0){ - T = adf4350_regs_t::REFERENCE_DIVIDE_BY_2_ENABLED; - R /= 2; - } - - //actual frequency calculation - actual_freq = double((N + (double(FRAC)/double(MOD)))*ref_freq*(1+int(D))/(R*(1+int(T)))/RFdiv); - - UHD_LOGV(often) - << boost::format("SBX Intermediates: ref=%0.2f, outdiv=%f, fbdiv=%f") % (ref_freq*(1+int(D))/(R*(1+int(T)))) % double(RFdiv*2) % double(N + double(FRAC)/double(MOD)) << std::endl - << boost::format("SBX tune: R=%d, BS=%d, N=%d, FRAC=%d, MOD=%d, T=%d, D=%d, RFdiv=%d, LD=%d" - ) % R % BS % N % FRAC % MOD % T % D % RFdiv % get_locked(unit)<< std::endl - << boost::format("SBX Frequencies (MHz): REQ=%0.2f, ACT=%0.2f, VCO=%0.2f, PFD=%0.2f, BAND=%0.2f" - ) % (target_freq/1e6) % (actual_freq/1e6) % (vco_freq/1e6) % (pfd_freq/1e6) % (pfd_freq/BS/1e6) << std::endl; - - //load the register values - adf4350_regs_t regs; - - if ((unit == dboard_iface::UNIT_TX) and (actual_freq == sbx_tx_lo_2dbm.clip(actual_freq))) - regs.output_power = adf4350_regs_t::OUTPUT_POWER_2DBM; - else - regs.output_power = adf4350_regs_t::OUTPUT_POWER_5DBM; - - regs.frac_12_bit = FRAC; - regs.int_16_bit = N; - regs.mod_12_bit = MOD; - regs.prescaler = prescaler; - regs.r_counter_10_bit = R; - regs.reference_divide_by_2 = T; - regs.reference_doubler = D; - regs.band_select_clock_div = BS; - UHD_ASSERT_THROW(rfdivsel_to_enum.has_key(RFdiv)); - regs.rf_divider_select = rfdivsel_to_enum[RFdiv]; - - //write the registers - //correct power-up sequence to write registers (5, 4, 3, 2, 1, 0) - int addr; - - for(addr=5; addr>=0; addr--){ - UHD_LOGV(often) << boost::format( - "SBX SPI Reg (0x%02x): 0x%08x" - ) % addr % regs.get_reg(addr) << std::endl; - this->get_iface()->write_spi( - unit, spi_config_t::EDGE_RISE, - regs.get_reg(addr), 32 - ); - } - - //return the actual frequency - UHD_LOGV(often) << boost::format( - "SBX tune: actual frequency %f Mhz" - ) % (actual_freq/1e6) << std::endl; - return actual_freq; -} - -/*********************************************************************** - * RX Get and Set - **********************************************************************/ -void sbx_xcvr::rx_get(const wax::obj &key_, wax::obj &val){ - named_prop_t key = named_prop_t::extract(key_); - - //handle the get request conditioned on the key - switch(key.as()){ - case SUBDEV_PROP_NAME: - val = get_rx_id().to_pp_string(); - return; - - case SUBDEV_PROP_OTHERS: - val = prop_names_t(); //empty - return; - - case SUBDEV_PROP_GAIN: - assert_has(_rx_gains.keys(), key.name, "sbx rx gain name"); - val = _rx_gains[key.name]; - return; - - case SUBDEV_PROP_GAIN_RANGE: - assert_has(sbx_rx_gain_ranges.keys(), key.name, "sbx rx gain name"); - val = sbx_rx_gain_ranges[key.name]; - return; - - case SUBDEV_PROP_GAIN_NAMES: - val = prop_names_t(sbx_rx_gain_ranges.keys()); - return; - - case SUBDEV_PROP_FREQ: - val = _rx_lo_freq; - return; - - case SUBDEV_PROP_FREQ_RANGE: - val = sbx_freq_range; - return; - - case SUBDEV_PROP_ANTENNA: - val = _rx_ant; - return; - - case SUBDEV_PROP_ANTENNA_NAMES: - val = sbx_rx_antennas; - return; - - case SUBDEV_PROP_CONNECTION: - val = SUBDEV_CONN_COMPLEX_IQ; - return; - - case SUBDEV_PROP_USE_LO_OFFSET: - val = false; - return; - - case SUBDEV_PROP_ENABLED: - val = true; //always enabled - return; - - case SUBDEV_PROP_SENSOR: - UHD_ASSERT_THROW(key.name == "lo_locked"); - val = sensor_value_t("LO", this->get_locked(dboard_iface::UNIT_RX), "locked", "unlocked"); - return; - - case SUBDEV_PROP_SENSOR_NAMES: - val = prop_names_t(1, "lo_locked"); - return; - - case SUBDEV_PROP_BANDWIDTH: - val = 2*20.0e6; //20MHz low-pass, we want complex double-sided - return; - - default: UHD_THROW_PROP_GET_ERROR(); - } -} - -void sbx_xcvr::rx_set(const wax::obj &key_, const wax::obj &val){ - named_prop_t key = named_prop_t::extract(key_); - - //handle the get request conditioned on the key - switch(key.as()){ - - case SUBDEV_PROP_FREQ: - this->set_rx_lo_freq(val.as()); - return; - - case SUBDEV_PROP_GAIN: - this->set_rx_gain(val.as(), key.name); - return; - - case SUBDEV_PROP_ANTENNA: - this->set_rx_ant(val.as()); - return; - - case SUBDEV_PROP_ENABLED: - return; //always enabled - - case SUBDEV_PROP_BANDWIDTH: - UHD_MSG(warning) << "SBX: No tunable bandwidth, fixed filtered to 40MHz"; - return; - - default: UHD_THROW_PROP_SET_ERROR(); - } -} - -/*********************************************************************** - * TX Get and Set - **********************************************************************/ -void sbx_xcvr::tx_get(const wax::obj &key_, wax::obj &val){ - named_prop_t key = named_prop_t::extract(key_); - - //handle the get request conditioned on the key - switch(key.as()){ - case SUBDEV_PROP_NAME: - val = get_tx_id().to_pp_string(); - return; - - case SUBDEV_PROP_OTHERS: - val = prop_names_t(); //empty - return; - - case SUBDEV_PROP_GAIN: - assert_has(_tx_gains.keys(), key.name, "sbx tx gain name"); - val = _tx_gains[key.name]; - return; - - case SUBDEV_PROP_GAIN_RANGE: - assert_has(sbx_tx_gain_ranges.keys(), key.name, "sbx tx gain name"); - val = sbx_tx_gain_ranges[key.name]; - return; - - case SUBDEV_PROP_GAIN_NAMES: - val = prop_names_t(sbx_tx_gain_ranges.keys()); - return; - - case SUBDEV_PROP_FREQ: - val = _tx_lo_freq; - return; - - case SUBDEV_PROP_FREQ_RANGE: - val = sbx_freq_range; - return; - - case SUBDEV_PROP_ANTENNA: - val = std::string("TX/RX"); - return; - - case SUBDEV_PROP_ANTENNA_NAMES: - val = sbx_tx_antennas; - return; - - case SUBDEV_PROP_CONNECTION: - val = SUBDEV_CONN_COMPLEX_QI; - return; - - case SUBDEV_PROP_USE_LO_OFFSET: - val = false; - return; - - case SUBDEV_PROP_ENABLED: - val = true; //always enabled - return; - - case SUBDEV_PROP_SENSOR: - UHD_ASSERT_THROW(key.name == "lo_locked"); - val = sensor_value_t("LO", this->get_locked(dboard_iface::UNIT_TX), "locked", "unlocked"); - return; - - case SUBDEV_PROP_SENSOR_NAMES: - val = prop_names_t(1, "lo_locked"); - return; - - case SUBDEV_PROP_BANDWIDTH: - val = 2*20.0e6; //20MHz low-pass, we want complex double-sided - return; - - default: UHD_THROW_PROP_GET_ERROR(); - } -} - -void sbx_xcvr::tx_set(const wax::obj &key_, const wax::obj &val){ - named_prop_t key = named_prop_t::extract(key_); - - //handle the get request conditioned on the key - switch(key.as()){ - - case SUBDEV_PROP_FREQ: - this->set_tx_lo_freq(val.as()); - return; - - case SUBDEV_PROP_GAIN: - this->set_tx_gain(val.as(), key.name); - return; - - case SUBDEV_PROP_ANTENNA: - this->set_tx_ant(val.as()); - return; - - case SUBDEV_PROP_ENABLED: - return; //always enabled - - case SUBDEV_PROP_BANDWIDTH: - UHD_MSG(warning) << "SBX: No tunable bandwidth, fixed filtered to 40MHz"; - return; - - default: UHD_THROW_PROP_SET_ERROR(); - } -} diff --git a/host/lib/usrp/dboard/db_sbx_common.cpp b/host/lib/usrp/dboard/db_sbx_common.cpp new file mode 100644 index 000000000..51a0f0100 --- /dev/null +++ b/host/lib/usrp/dboard/db_sbx_common.cpp @@ -0,0 +1,514 @@ +// +// 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 . +// + +#include "db_sbx_common.hpp" +#include "adf4350_regs.hpp" + +using namespace uhd; +using namespace uhd::usrp; +using namespace boost::assign; + + +/*********************************************************************** + * Register the SBX dboard (min freq, max freq, rx div2, tx div2) + **********************************************************************/ +static dboard_base::sptr make_sbx(dboard_base::ctor_args_t args){ + return dboard_base::sptr(new sbx_xcvr(args)); +} + +UHD_STATIC_BLOCK(reg_sbx_dboards){ + dboard_manager::register_dboard(0x0054, 0x0055, &make_sbx, "SBX"); + dboard_manager::register_dboard(0x0065, 0x0064, &make_sbx, "SBX v4"); +} + + +/*********************************************************************** + * Gain Handling + **********************************************************************/ +static int rx_pga0_gain_to_iobits(double &gain){ + //clip the input + gain = sbx_rx_gain_ranges["PGA0"].clip(gain); + + //convert to attenuation and update iobits for atr + double attn = sbx_rx_gain_ranges["PGA0"].stop() - gain; + + //calculate the RX attenuation + int attn_code = int(floor(attn*2)); + int iobits = ((~attn_code) << RX_ATTN_SHIFT) & RX_ATTN_MASK; + + UHD_LOGV(often) << boost::format( + "SBX TX Attenuation: %f dB, Code: %d, IO Bits %x, Mask: %x" + ) % attn % attn_code % (iobits & RX_ATTN_MASK) % RX_ATTN_MASK << std::endl; + + //the actual gain setting + gain = sbx_rx_gain_ranges["PGA0"].stop() - double(attn_code)/2; + + return iobits; +} + +static int tx_pga0_gain_to_iobits(double &gain){ + //clip the input + gain = sbx_tx_gain_ranges["PGA0"].clip(gain); + + //convert to attenuation and update iobits for atr + double attn = sbx_tx_gain_ranges["PGA0"].stop() - gain; + + //calculate the TX attenuation + int attn_code = int(floor(attn*2)); + int iobits = ((~attn_code) << TX_ATTN_SHIFT) & TX_ATTN_MASK; + + UHD_LOGV(often) << boost::format( + "SBX TX Attenuation: %f dB, Code: %d, IO Bits %x, Mask: %x" + ) % attn % attn_code % (iobits & TX_ATTN_MASK) % TX_ATTN_MASK << std::endl; + + //the actual gain setting + gain = sbx_tx_gain_ranges["PGA0"].stop() - double(attn_code)/2; + + return iobits; +} + +void sbx_xcvr::set_tx_gain(double gain, const std::string &name){ + assert_has(sbx_tx_gain_ranges.keys(), name, "sbx tx gain name"); + if(name == "PGA0"){ + tx_pga0_gain_to_iobits(gain); + _tx_gains[name] = gain; + + //write the new gain to atr regs + update_atr(); + } + else UHD_THROW_INVALID_CODE_PATH(); +} + +void sbx_xcvr::set_rx_gain(double gain, const std::string &name){ + assert_has(sbx_rx_gain_ranges.keys(), name, "sbx rx gain name"); + if(name == "PGA0"){ + rx_pga0_gain_to_iobits(gain); + _rx_gains[name] = gain; + + //write the new gain to atr regs + update_atr(); + } + else UHD_THROW_INVALID_CODE_PATH(); +} + + +/*********************************************************************** + * Structors + **********************************************************************/ +sbx_xcvr::sbx_xcvr(ctor_args_t args) : xcvr_dboard_base(args){ + switch(get_rx_id().to_uint16()) { + case 0x054: + db_actual = sbx_versionx_sptr(new sbx_version3(this)); + break; + case 0x065: + db_actual = sbx_versionx_sptr(new sbx_version4(this)); + break; + default: + /* We didn't recognize the version of the board... */ + UHD_THROW_INVALID_CODE_PATH(); + } + + //enable the clocks that we need + this->get_iface()->set_clock_enabled(dboard_iface::UNIT_TX, true); + this->get_iface()->set_clock_enabled(dboard_iface::UNIT_RX, true); + + //set the gpio directions and atr controls (identically) + this->get_iface()->set_pin_ctrl(dboard_iface::UNIT_TX, (TXIO_MASK|TX_LED_IO)); + this->get_iface()->set_pin_ctrl(dboard_iface::UNIT_RX, (RXIO_MASK|RX_LED_IO)); + this->get_iface()->set_gpio_ddr(dboard_iface::UNIT_TX, (TXIO_MASK|TX_LED_IO)); + this->get_iface()->set_gpio_ddr(dboard_iface::UNIT_RX, (RXIO_MASK|RX_LED_IO)); + + //flash LEDs + flash_leds(); + + UHD_LOGV(often) << boost::format( + "SBX GPIO Direction: RX: 0x%08x, TX: 0x%08x" + ) % RXIO_MASK % TXIO_MASK << std::endl; + + //set some default values + set_rx_lo_freq((sbx_freq_range.start() + sbx_freq_range.stop())/2.0); + set_tx_lo_freq((sbx_freq_range.start() + sbx_freq_range.stop())/2.0); + set_rx_ant("RX2"); + + BOOST_FOREACH(const std::string &name, sbx_tx_gain_ranges.keys()){ + set_tx_gain(sbx_tx_gain_ranges[name].start(), name); + } + BOOST_FOREACH(const std::string &name, sbx_rx_gain_ranges.keys()){ + set_rx_gain(sbx_rx_gain_ranges[name].start(), name); + } +} + +sbx_xcvr::~sbx_xcvr(void){ + /* NOP */ +} + +/*********************************************************************** + * Antenna Handling + **********************************************************************/ +void sbx_xcvr::update_atr(void){ + //calculate atr pins + int rx_pga0_iobits = rx_pga0_gain_to_iobits(_rx_gains["PGA0"]); + int tx_pga0_iobits = tx_pga0_gain_to_iobits(_tx_gains["PGA0"]); + int rx_lo_lpf_en = (_rx_lo_freq == sbx_enable_rx_lo_filter.clip(_rx_lo_freq)) ? LO_LPF_EN : 0; + int tx_lo_lpf_en = (_tx_lo_freq == sbx_enable_tx_lo_filter.clip(_tx_lo_freq)) ? LO_LPF_EN : 0; + int rx_ld_led = get_locked(dboard_iface::UNIT_RX) ? 0 : RX_LED_LD; + int tx_ld_led = get_locked(dboard_iface::UNIT_TX) ? 0 : TX_LED_LD; + int rx_ant_led = _rx_ant == "TX/RX" ? RX_LED_RX1RX2 : 0; + int tx_ant_led = _rx_ant == "TX/RX" ? 0 : TX_LED_TXRX; + + //setup the tx atr (this does not change with antenna) + this->get_iface()->set_atr_reg(dboard_iface::UNIT_TX, dboard_iface::ATR_REG_IDLE, + tx_pga0_iobits | tx_lo_lpf_en | tx_ld_led | tx_ant_led | TX_POWER_UP | ANT_XX | TX_MIXER_DIS); + this->get_iface()->set_atr_reg(dboard_iface::UNIT_TX, dboard_iface::ATR_REG_TX_ONLY, + tx_pga0_iobits | tx_lo_lpf_en | tx_ld_led | tx_ant_led | TX_POWER_UP | ANT_TX | TX_MIXER_ENB); + this->get_iface()->set_atr_reg(dboard_iface::UNIT_TX, dboard_iface::ATR_REG_FULL_DUPLEX, + tx_pga0_iobits | tx_lo_lpf_en | tx_ld_led | tx_ant_led | TX_POWER_UP | ANT_TX | TX_MIXER_ENB); + + //setup the rx atr (this does not change with antenna) + this->get_iface()->set_atr_reg(dboard_iface::UNIT_RX, dboard_iface::ATR_REG_IDLE, + rx_pga0_iobits | rx_lo_lpf_en | rx_ld_led | rx_ant_led | RX_POWER_UP | ANT_XX | RX_MIXER_DIS); + this->get_iface()->set_atr_reg(dboard_iface::UNIT_RX, dboard_iface::ATR_REG_TX_ONLY, + rx_pga0_iobits | rx_lo_lpf_en | rx_ld_led | rx_ant_led | RX_POWER_UP | ANT_RX2 | RX_MIXER_DIS); + this->get_iface()->set_atr_reg(dboard_iface::UNIT_RX, dboard_iface::ATR_REG_FULL_DUPLEX, + rx_pga0_iobits | rx_lo_lpf_en | rx_ld_led | rx_ant_led | RX_POWER_UP | ANT_RX2 | RX_MIXER_ENB); + + //set the atr regs that change with antenna setting + this->get_iface()->set_atr_reg(dboard_iface::UNIT_TX, dboard_iface::ATR_REG_RX_ONLY, + tx_pga0_iobits | tx_lo_lpf_en | tx_ld_led | tx_ant_led | TX_POWER_UP | TX_MIXER_DIS | + ((_rx_ant == "TX/RX")? ANT_RX : ANT_TX)); + this->get_iface()->set_atr_reg(dboard_iface::UNIT_RX, dboard_iface::ATR_REG_RX_ONLY, + rx_pga0_iobits | rx_lo_lpf_en | rx_ld_led | rx_ant_led | RX_POWER_UP | RX_MIXER_ENB | + ((_rx_ant == "TX/RX")? ANT_TXRX : ANT_RX2)); + + UHD_LOGV(often) << boost::format( + "SBX RXONLY ATR REG: 0x%08x" + ) % (rx_pga0_iobits | RX_POWER_UP | RX_MIXER_ENB | ((_rx_ant == "TX/RX")? ANT_TXRX : ANT_RX2)) << std::endl; +} + +void sbx_xcvr::set_rx_ant(const std::string &ant){ + //validate input + assert_has(sbx_rx_antennas, ant, "sbx rx antenna name"); + + //shadow the setting + _rx_ant = ant; + + //write the new antenna setting to atr regs + update_atr(); +} + +void sbx_xcvr::set_tx_ant(const std::string &ant){ + assert_has(sbx_tx_antennas, ant, "sbx tx antenna name"); + //only one antenna option, do nothing +} + +/*********************************************************************** + * Tuning + **********************************************************************/ +void sbx_xcvr::set_rx_lo_freq(double freq){ + _rx_lo_freq = db_actual->set_lo_freq(dboard_iface::UNIT_RX, freq); +} + +void sbx_xcvr::set_tx_lo_freq(double freq){ + _tx_lo_freq = db_actual->set_lo_freq(dboard_iface::UNIT_TX, freq); +} + + +double sbx_xcvr::set_lo_freq(dboard_iface::unit_t unit, double target_freq) { + return db_actual->set_lo_freq(unit, target_freq); +} + +/*********************************************************************** + * RX Get and Set + **********************************************************************/ +void sbx_xcvr::rx_get(const wax::obj &key_, wax::obj &val){ + named_prop_t key = named_prop_t::extract(key_); + + //handle the get request conditioned on the key + switch(key.as()){ + case SUBDEV_PROP_NAME: + val = get_rx_id().to_pp_string(); + return; + + case SUBDEV_PROP_OTHERS: + val = prop_names_t(); //empty + return; + + case SUBDEV_PROP_GAIN: + assert_has(_rx_gains.keys(), key.name, "sbx rx gain name"); + val = _rx_gains[key.name]; + return; + + case SUBDEV_PROP_GAIN_RANGE: + assert_has(sbx_rx_gain_ranges.keys(), key.name, "sbx rx gain name"); + val = sbx_rx_gain_ranges[key.name]; + return; + + case SUBDEV_PROP_GAIN_NAMES: + val = prop_names_t(sbx_rx_gain_ranges.keys()); + return; + + case SUBDEV_PROP_FREQ: + val = _rx_lo_freq; + return; + + case SUBDEV_PROP_FREQ_RANGE: + val = sbx_freq_range; + return; + + case SUBDEV_PROP_ANTENNA: + val = _rx_ant; + return; + + case SUBDEV_PROP_ANTENNA_NAMES: + val = sbx_rx_antennas; + return; + + case SUBDEV_PROP_CONNECTION: + val = SUBDEV_CONN_COMPLEX_IQ; + return; + + case SUBDEV_PROP_USE_LO_OFFSET: + val = false; + return; + + case SUBDEV_PROP_ENABLED: + val = true; //always enabled + return; + + case SUBDEV_PROP_SENSOR: + UHD_ASSERT_THROW(key.name == "lo_locked"); + val = sensor_value_t("LO", this->get_locked(dboard_iface::UNIT_RX), "locked", "unlocked"); + return; + + case SUBDEV_PROP_SENSOR_NAMES: + val = prop_names_t(1, "lo_locked"); + return; + + case SUBDEV_PROP_BANDWIDTH: + val = 2*20.0e6; //20MHz low-pass, we want complex double-sided + return; + + default: UHD_THROW_PROP_GET_ERROR(); + } +} + +void sbx_xcvr::rx_set(const wax::obj &key_, const wax::obj &val){ + named_prop_t key = named_prop_t::extract(key_); + + //handle the get request conditioned on the key + switch(key.as()){ + + case SUBDEV_PROP_FREQ: + this->set_rx_lo_freq(val.as()); + return; + + case SUBDEV_PROP_GAIN: + this->set_rx_gain(val.as(), key.name); + return; + + case SUBDEV_PROP_ANTENNA: + this->set_rx_ant(val.as()); + return; + + case SUBDEV_PROP_ENABLED: + return; //always enabled + + case SUBDEV_PROP_BANDWIDTH: + UHD_MSG(warning) << "SBX: No tunable bandwidth, fixed filtered to 40MHz"; + return; + + default: UHD_THROW_PROP_SET_ERROR(); + } +} + +/*********************************************************************** + * TX Get and Set + **********************************************************************/ +void sbx_xcvr::tx_get(const wax::obj &key_, wax::obj &val){ + named_prop_t key = named_prop_t::extract(key_); + + //handle the get request conditioned on the key + switch(key.as()){ + case SUBDEV_PROP_NAME: + val = get_tx_id().to_pp_string(); + return; + + case SUBDEV_PROP_OTHERS: + val = prop_names_t(); //empty + return; + + case SUBDEV_PROP_GAIN: + assert_has(_tx_gains.keys(), key.name, "sbx tx gain name"); + val = _tx_gains[key.name]; + return; + + case SUBDEV_PROP_GAIN_RANGE: + assert_has(sbx_tx_gain_ranges.keys(), key.name, "sbx tx gain name"); + val = sbx_tx_gain_ranges[key.name]; + return; + + case SUBDEV_PROP_GAIN_NAMES: + val = prop_names_t(sbx_tx_gain_ranges.keys()); + return; + + case SUBDEV_PROP_FREQ: + val = _tx_lo_freq; + return; + + case SUBDEV_PROP_FREQ_RANGE: + val = sbx_freq_range; + return; + + case SUBDEV_PROP_ANTENNA: + val = std::string("TX/RX"); + return; + + case SUBDEV_PROP_ANTENNA_NAMES: + val = sbx_tx_antennas; + return; + + case SUBDEV_PROP_CONNECTION: + val = SUBDEV_CONN_COMPLEX_QI; + return; + + case SUBDEV_PROP_USE_LO_OFFSET: + val = false; + return; + + case SUBDEV_PROP_ENABLED: + val = true; //always enabled + return; + + case SUBDEV_PROP_SENSOR: + UHD_ASSERT_THROW(key.name == "lo_locked"); + val = sensor_value_t("LO", this->get_locked(dboard_iface::UNIT_TX), "locked", "unlocked"); + return; + + case SUBDEV_PROP_SENSOR_NAMES: + val = prop_names_t(1, "lo_locked"); + return; + + case SUBDEV_PROP_BANDWIDTH: + val = 2*20.0e6; //20MHz low-pass, we want complex double-sided + return; + + default: UHD_THROW_PROP_GET_ERROR(); + } +} + +void sbx_xcvr::tx_set(const wax::obj &key_, const wax::obj &val){ + named_prop_t key = named_prop_t::extract(key_); + + //handle the get request conditioned on the key + switch(key.as()){ + + case SUBDEV_PROP_FREQ: + this->set_tx_lo_freq(val.as()); + return; + + case SUBDEV_PROP_GAIN: + this->set_tx_gain(val.as(), key.name); + return; + + case SUBDEV_PROP_ANTENNA: + this->set_tx_ant(val.as()); + return; + + case SUBDEV_PROP_ENABLED: + return; //always enabled + + case SUBDEV_PROP_BANDWIDTH: + UHD_MSG(warning) << "SBX: No tunable bandwidth, fixed filtered to 40MHz"; + return; + + default: UHD_THROW_PROP_SET_ERROR(); + } +} + + +bool sbx_xcvr::get_locked(dboard_iface::unit_t unit) { + return (this->get_iface()->read_gpio(unit) & LOCKDET_MASK) != 0; +} + + +void sbx_xcvr::flash_leds(void) { + //Remove LED gpios from ATR control temporarily and set to outputs + this->get_iface()->set_pin_ctrl(dboard_iface::UNIT_TX, TXIO_MASK); + this->get_iface()->set_pin_ctrl(dboard_iface::UNIT_RX, RXIO_MASK); + this->get_iface()->set_gpio_ddr(dboard_iface::UNIT_TX, (TXIO_MASK|RX_LED_IO)); + this->get_iface()->set_gpio_ddr(dboard_iface::UNIT_RX, (RXIO_MASK|RX_LED_IO)); + + /* + //flash All LEDs + for (int i = 0; i < 3; i++) { + this->get_iface()->set_gpio_out(dboard_iface::UNIT_RX, RX_LED_IO, RX_LED_IO); + this->get_iface()->set_gpio_out(dboard_iface::UNIT_TX, TX_LED_IO, TX_LED_IO); + + boost::this_thread::sleep(boost::posix_time::milliseconds(100)); + + this->get_iface()->set_gpio_out(dboard_iface::UNIT_RX, 0, RX_LED_IO); + this->get_iface()->set_gpio_out(dboard_iface::UNIT_TX, 0, TX_LED_IO); + + boost::this_thread::sleep(boost::posix_time::milliseconds(100)); + } + */ + + this->get_iface()->set_gpio_out(dboard_iface::UNIT_TX, TX_LED_LD, TX_LED_IO); + boost::this_thread::sleep(boost::posix_time::milliseconds(100)); + + this->get_iface()->set_gpio_out(dboard_iface::UNIT_TX, TX_LED_TXRX|TX_LED_LD, TX_LED_IO); + boost::this_thread::sleep(boost::posix_time::milliseconds(100)); + + this->get_iface()->set_gpio_out(dboard_iface::UNIT_RX, RX_LED_LD, RX_LED_IO); + boost::this_thread::sleep(boost::posix_time::milliseconds(100)); + + this->get_iface()->set_gpio_out(dboard_iface::UNIT_RX, RX_LED_RX1RX2|RX_LED_LD, RX_LED_IO); + boost::this_thread::sleep(boost::posix_time::milliseconds(100)); + + this->get_iface()->set_gpio_out(dboard_iface::UNIT_RX, RX_LED_LD, RX_LED_IO); + boost::this_thread::sleep(boost::posix_time::milliseconds(100)); + + this->get_iface()->set_gpio_out(dboard_iface::UNIT_RX, 0, RX_LED_IO); + boost::this_thread::sleep(boost::posix_time::milliseconds(100)); + + this->get_iface()->set_gpio_out(dboard_iface::UNIT_TX, TX_LED_LD, TX_LED_IO); + boost::this_thread::sleep(boost::posix_time::milliseconds(100)); + + this->get_iface()->set_gpio_out(dboard_iface::UNIT_TX, 0, TX_LED_IO); + boost::this_thread::sleep(boost::posix_time::milliseconds(100)); + + /* + //flash All LEDs + for (int i = 0; i < 3; i++) { + this->get_iface()->set_gpio_out(dboard_iface::UNIT_RX, 0, RX_LED_IO); + this->get_iface()->set_gpio_out(dboard_iface::UNIT_TX, 0, TX_LED_IO); + + boost::this_thread::sleep(boost::posix_time::milliseconds(100)); + + this->get_iface()->set_gpio_out(dboard_iface::UNIT_RX, RX_LED_IO, RX_LED_IO); + this->get_iface()->set_gpio_out(dboard_iface::UNIT_TX, TX_LED_IO, TX_LED_IO); + + boost::this_thread::sleep(boost::posix_time::milliseconds(100)); + } + */ + //Put LED gpios back in ATR control and update atr + this->get_iface()->set_pin_ctrl(dboard_iface::UNIT_TX, (TXIO_MASK|TX_LED_IO)); + this->get_iface()->set_pin_ctrl(dboard_iface::UNIT_RX, (RXIO_MASK|RX_LED_IO)); + this->get_iface()->set_gpio_ddr(dboard_iface::UNIT_TX, (TXIO_MASK|TX_LED_IO)); + this->get_iface()->set_gpio_ddr(dboard_iface::UNIT_RX, (RXIO_MASK|RX_LED_IO)); +} + diff --git a/host/lib/usrp/dboard/db_sbx_common.hpp b/host/lib/usrp/dboard/db_sbx_common.hpp new file mode 100644 index 000000000..5ff84811a --- /dev/null +++ b/host/lib/usrp/dboard/db_sbx_common.hpp @@ -0,0 +1,233 @@ +// +// 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 . +// + + + +// Common IO Pins +#define LO_LPF_EN (1 << 15) +#define SYNTH_CE (1 << 3) +#define SYNTH_PDBRF (1 << 2) +#define SYNTH_MUXOUT (1 << 1) // INPUT!!! +#define LOCKDET_MASK (1 << 0) // INPUT!!! + +// TX IO Pins +#define TRSW (1 << 14) // 0 = TX, 1 = RX +#define TX_LED_TXRX (1 << 7) // LED for TX Antenna Selection TX/RX +#define TX_LED_LD (1 << 6) // LED for TX Lock Detect +#define DIS_POWER_TX (1 << 5) // on UNIT_TX, 0 powers up TX +#define TX_ENABLE (1 << 4) // on UNIT_TX, 0 disables TX Mixer + +// RX IO Pins +#define LNASW (1 << 14) // 0 = TX/RX, 1 = RX2 +#define RX_LED_RX1RX2 (1 << 7) // LED for RX Antenna Selection RX1/RX2 +#define RX_LED_LD (1 << 6) // LED for RX Lock Detect +#define DIS_POWER_RX (1 << 5) // on UNIT_RX, 0 powers up RX +#define RX_DISABLE (1 << 4) // on UNIT_RX, 1 disables RX Mixer and Baseband + +// RX Attenuator Pins +#define RX_ATTN_SHIFT 8 // lsb of RX Attenuator Control +#define RX_ATTN_MASK (63 << RX_ATTN_SHIFT) // valid bits of RX Attenuator Control + +// TX Attenuator Pins +#define TX_ATTN_SHIFT 8 // lsb of RX Attenuator Control +#define TX_ATTN_MASK (63 << TX_ATTN_SHIFT) // valid bits of RX Attenuator Control + +// Mixer functions +#define TX_MIXER_ENB (SYNTH_PDBRF) +#define TX_MIXER_DIS 0 + +#define RX_MIXER_ENB (SYNTH_PDBRF) +#define RX_MIXER_DIS 0 + +// Pin functions +#define TX_LED_IO (TX_LED_TXRX|TX_LED_LD) // LED gpio lines, pull down for LED +#define TXIO_MASK (LO_LPF_EN|TRSW|SYNTH_CE|SYNTH_PDBRF|TX_ATTN_MASK|DIS_POWER_TX|TX_ENABLE) + +#define RX_LED_IO (RX_LED_RX1RX2|RX_LED_LD) // LED gpio lines, pull down for LED +#define RXIO_MASK (LO_LPF_EN|LNASW|SYNTH_CE|SYNTH_PDBRF|RX_ATTN_MASK|DIS_POWER_RX|RX_DISABLE) + +// Power functions +#define TX_POWER_UP (SYNTH_CE|TX_ENABLE) +#define TX_POWER_DOWN (DIS_POWER_TX) + +#define RX_POWER_UP (SYNTH_CE) +#define RX_POWER_DOWN (DIS_POWER_RX) + +// Antenna constants +#define ANT_TX TRSW //the tx line is transmitting +#define ANT_RX 0 //the tx line is receiving +#define ANT_TXRX 0 //the rx line is on txrx +#define ANT_RX2 LNASW //the rx line in on rx2 +#define ANT_XX LNASW //dont care how the antenna is set + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +using namespace uhd; +using namespace uhd::usrp; +using namespace boost::assign; + + +/*********************************************************************** + * The SBX dboard constants + **********************************************************************/ +static const freq_range_t sbx_freq_range(400e6, 4.4e9); + +static const freq_range_t sbx_tx_lo_2dbm = list_of + (range_t(0.35e9, 0.37e9)) +; + +static const freq_range_t sbx_enable_tx_lo_filter = list_of + (range_t(0.4e9, 1.5e9)) +; + +static const freq_range_t sbx_enable_rx_lo_filter = list_of + (range_t(0.4e9, 1.5e9)) +; + +static const prop_names_t sbx_tx_antennas = list_of("TX/RX"); + +static const prop_names_t sbx_rx_antennas = list_of("TX/RX")("RX2"); + +static const uhd::dict sbx_tx_gain_ranges = map_list_of + ("PGA0", gain_range_t(0, 31.5, double(0.5))) +; + +static const uhd::dict sbx_rx_gain_ranges = map_list_of + ("PGA0", gain_range_t(0, 31.5, double(0.5))) +; + +/*********************************************************************** + * The SBX dboard + **********************************************************************/ +class sbx_xcvr : public xcvr_dboard_base{ +public: + sbx_xcvr(ctor_args_t args); + ~sbx_xcvr(void); + + void rx_get(const wax::obj &key, wax::obj &val); + void rx_set(const wax::obj &key, const wax::obj &val); + + void tx_get(const wax::obj &key, wax::obj &val); + void tx_set(const wax::obj &key, const wax::obj &val); + +protected: + + uhd::dict _tx_gains, _rx_gains; + double _rx_lo_freq, _tx_lo_freq; + std::string _tx_ant, _rx_ant; + + void set_rx_lo_freq(double freq); + void set_tx_lo_freq(double freq); + void set_rx_ant(const std::string &ant); + void set_tx_ant(const std::string &ant); + void set_rx_gain(double gain, const std::string &name); + void set_tx_gain(double gain, const std::string &name); + + void update_atr(void); + + /*! + * Set the LO frequency for the particular dboard unit. + * \param unit which unit rx or tx + * \param target_freq the desired frequency in Hz + * \return the actual frequency in Hz + */ + virtual double set_lo_freq(dboard_iface::unit_t unit, double target_freq); + + /*! + * Get the lock detect status of the LO. + * \param unit which unit rx or tx + * \return true for locked + */ + bool get_locked(dboard_iface::unit_t unit); + + /*! + * Flash the LEDs + */ + void flash_leds(void); + + /*! + * Version-agnostic ABC that wraps version-specific implementations of the + * WBX base daughterboard. + * + * This class is an abstract base class, and thus is impossible to + * instantiate. + */ + class sbx_versionx { + public: + sbx_versionx() {} + ~sbx_versionx(void) {} + + virtual double set_lo_freq(dboard_iface::unit_t unit, double target_freq) = 0; + }; + + /*! + * Version 3 of the SBX Daughterboard + */ + class sbx_version3 : public sbx_versionx { + public: + sbx_version3(sbx_xcvr *_self_sbx_xcvr); + ~sbx_version3(void); + + double set_lo_freq(dboard_iface::unit_t unit, double target_freq); + + /*! This is the registered instance of the wrapper class, sbx_base. */ + sbx_xcvr *self_base; + }; + + /*! + * Version 4 of the SBX Daughterboard + * + * The only difference in the fourth revision is the ADF4351 vs the ADF4350. + */ + class sbx_version4 : public sbx_versionx { + public: + sbx_version4(sbx_xcvr *_self_sbx_xcvr); + ~sbx_version4(void); + + double set_lo_freq(dboard_iface::unit_t unit, double target_freq); + + /*! This is the registered instance of the wrapper class, sbx_base. */ + sbx_xcvr *self_base; + }; + + /*! + * Handle to the version-specific implementation of the SBX. + * + * Since many of this class's functions are dependent on the version of the + * SBX board, this class will instantiate an object of the appropriate + * sbx_version* subclass, and invoke any relevant functions through that + * object. This pointer is set to the proper object at construction time. + */ + typedef boost::shared_ptr sbx_versionx_sptr; + sbx_versionx_sptr db_actual; +}; + diff --git a/host/lib/usrp/dboard/db_sbx_version3.cpp b/host/lib/usrp/dboard/db_sbx_version3.cpp new file mode 100644 index 000000000..b5aad8aa5 --- /dev/null +++ b/host/lib/usrp/dboard/db_sbx_version3.cpp @@ -0,0 +1,186 @@ +// +// 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 . +// + + +#include "adf4350_regs.hpp" +#include "db_sbx_common.hpp" + + +using namespace uhd; +using namespace uhd::usrp; +using namespace boost::assign; + +/*********************************************************************** + * Structors + **********************************************************************/ +sbx_xcvr::sbx_version3::sbx_version3(sbx_xcvr *_self_sbx_xcvr) { + //register the handle to our base SBX class + self_base = _self_sbx_xcvr; +} + +sbx_xcvr::sbx_version3::~sbx_version3(void){ + /* NOP */ +} + + +/*********************************************************************** + * Tuning + **********************************************************************/ +double sbx_xcvr::sbx_version3::set_lo_freq(dboard_iface::unit_t unit, double target_freq) { + UHD_LOGV(often) << boost::format( + "SBX tune: target frequency %f Mhz" + ) % (target_freq/1e6) << std::endl; + + //clip the input + target_freq = sbx_freq_range.clip(target_freq); + + //map prescaler setting to mininmum integer divider (N) values (pg.18 prescaler) + static const uhd::dict prescaler_to_min_int_div = map_list_of + (0,23) //adf4350_regs_t::PRESCALER_4_5 + (1,75) //adf4350_regs_t::PRESCALER_8_9 + ; + + //map rf divider select output dividers to enums + static const uhd::dict rfdivsel_to_enum = map_list_of + (1, adf4350_regs_t::RF_DIVIDER_SELECT_DIV1) + (2, adf4350_regs_t::RF_DIVIDER_SELECT_DIV2) + (4, adf4350_regs_t::RF_DIVIDER_SELECT_DIV4) + (8, adf4350_regs_t::RF_DIVIDER_SELECT_DIV8) + (16, adf4350_regs_t::RF_DIVIDER_SELECT_DIV16) + ; + + double actual_freq, pfd_freq; + double ref_freq = self_base->get_iface()->get_clock_rate(unit); + int R=0, BS=0, N=0, FRAC=0, MOD=0; + int RFdiv = 1; + adf4350_regs_t::reference_divide_by_2_t T = adf4350_regs_t::REFERENCE_DIVIDE_BY_2_DISABLED; + adf4350_regs_t::reference_doubler_t D = adf4350_regs_t::REFERENCE_DOUBLER_DISABLED; + + //Reference doubler for 50% duty cycle + // if ref_freq < 12.5MHz enable regs.reference_divide_by_2 + if(ref_freq <= 12.5e6) D = adf4350_regs_t::REFERENCE_DOUBLER_ENABLED; + + //increase RF divider until acceptable VCO frequency + //start with target_freq*2 because mixer has divide by 2 + double vco_freq = target_freq; + while (vco_freq < 2.2e9) { + vco_freq *= 2; + RFdiv *= 2; + } + + //use 8/9 prescaler for vco_freq > 3 GHz (pg.18 prescaler) + adf4350_regs_t::prescaler_t prescaler = vco_freq > 3e9 ? adf4350_regs_t::PRESCALER_8_9 : adf4350_regs_t::PRESCALER_4_5; + + /* + * The goal here is to loop though possible R dividers, + * band select clock dividers, N (int) dividers, and FRAC + * (frac) dividers. + * + * Calculate the N and F dividers for each set of values. + * The loop exists when it meets all of the constraints. + * The resulting loop values are loaded into the registers. + * + * from pg.21 + * + * f_pfd = f_ref*(1+D)/(R*(1+T)) + * f_vco = (N + (FRAC/MOD))*f_pfd + * N = f_vco/f_pfd - FRAC/MOD = f_vco*((R*(T+1))/(f_ref*(1+D))) - FRAC/MOD + * f_rf = f_vco/RFdiv) + * f_actual = f_rf/2 + */ + for(R = 1; R <= 1023; R+=1){ + //PFD input frequency = f_ref/R ... ignoring Reference doubler/divide-by-2 (D & T) + pfd_freq = ref_freq*(1+D)/(R*(1+T)); + + //keep the PFD frequency at or below 25MHz (Loop Filter Bandwidth) + if (pfd_freq > 25e6) continue; + + //ignore fractional part of tuning + N = int(std::floor(vco_freq/pfd_freq)); + + //keep N > minimum int divider requirement + if (N < prescaler_to_min_int_div[prescaler]) continue; + + for(BS=1; BS <= 255; BS+=1){ + //keep the band select frequency at or below 100KHz + //constraint on band select clock + if (pfd_freq/BS > 100e3) continue; + goto done_loop; + } + } done_loop: + + //Fractional-N calculation + MOD = 4095; //max fractional accuracy + FRAC = int((vco_freq/pfd_freq - N)*MOD); + + //Reference divide-by-2 for 50% duty cycle + // if R even, move one divide by 2 to to regs.reference_divide_by_2 + if(R % 2 == 0){ + T = adf4350_regs_t::REFERENCE_DIVIDE_BY_2_ENABLED; + R /= 2; + } + + //actual frequency calculation + actual_freq = double((N + (double(FRAC)/double(MOD)))*ref_freq*(1+int(D))/(R*(1+int(T)))/RFdiv); + + UHD_LOGV(often) + << boost::format("SBX Intermediates: ref=%0.2f, outdiv=%f, fbdiv=%f") % (ref_freq*(1+int(D))/(R*(1+int(T)))) % double(RFdiv*2) % double(N + double(FRAC)/double(MOD)) << std::endl + << boost::format("SBX tune: R=%d, BS=%d, N=%d, FRAC=%d, MOD=%d, T=%d, D=%d, RFdiv=%d, LD=%d" + ) % R % BS % N % FRAC % MOD % T % D % RFdiv % self_base->get_locked(unit)<< std::endl + << boost::format("SBX Frequencies (MHz): REQ=%0.2f, ACT=%0.2f, VCO=%0.2f, PFD=%0.2f, BAND=%0.2f" + ) % (target_freq/1e6) % (actual_freq/1e6) % (vco_freq/1e6) % (pfd_freq/1e6) % (pfd_freq/BS/1e6) << std::endl; + + //load the register values + adf4350_regs_t regs; + + if ((unit == dboard_iface::UNIT_TX) and (actual_freq == sbx_tx_lo_2dbm.clip(actual_freq))) + regs.output_power = adf4350_regs_t::OUTPUT_POWER_2DBM; + else + regs.output_power = adf4350_regs_t::OUTPUT_POWER_5DBM; + + regs.frac_12_bit = FRAC; + regs.int_16_bit = N; + regs.mod_12_bit = MOD; + regs.prescaler = prescaler; + regs.r_counter_10_bit = R; + regs.reference_divide_by_2 = T; + regs.reference_doubler = D; + regs.band_select_clock_div = BS; + UHD_ASSERT_THROW(rfdivsel_to_enum.has_key(RFdiv)); + regs.rf_divider_select = rfdivsel_to_enum[RFdiv]; + + //write the registers + //correct power-up sequence to write registers (5, 4, 3, 2, 1, 0) + int addr; + + for(addr=5; addr>=0; addr--){ + UHD_LOGV(often) << boost::format( + "SBX SPI Reg (0x%02x): 0x%08x" + ) % addr % regs.get_reg(addr) << std::endl; + self_base->get_iface()->write_spi( + unit, spi_config_t::EDGE_RISE, + regs.get_reg(addr), 32 + ); + } + + //return the actual frequency + UHD_LOGV(often) << boost::format( + "SBX tune: actual frequency %f Mhz" + ) % (actual_freq/1e6) << std::endl; + return actual_freq; +} + diff --git a/host/lib/usrp/dboard/db_sbx_version4.cpp b/host/lib/usrp/dboard/db_sbx_version4.cpp new file mode 100644 index 000000000..ea0acb699 --- /dev/null +++ b/host/lib/usrp/dboard/db_sbx_version4.cpp @@ -0,0 +1,189 @@ +// +// 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 . +// + + +#include "adf4351_regs.hpp" +#include "db_sbx_common.hpp" + + +using namespace uhd; +using namespace uhd::usrp; +using namespace boost::assign; + +/*********************************************************************** + * Structors + **********************************************************************/ +sbx_xcvr::sbx_version4::sbx_version4(sbx_xcvr *_self_sbx_xcvr) { + //register the handle to our base SBX class + self_base = _self_sbx_xcvr; +} + + +sbx_xcvr::sbx_version4::~sbx_version4(void){ + /* NOP */ +} + + +/*********************************************************************** + * Tuning + **********************************************************************/ +double sbx_xcvr::sbx_version4::set_lo_freq(dboard_iface::unit_t unit, double target_freq) { + UHD_LOGV(often) << boost::format( + "SBX tune: target frequency %f Mhz" + ) % (target_freq/1e6) << std::endl; + + //clip the input + target_freq = sbx_freq_range.clip(target_freq); + + //map prescaler setting to mininmum integer divider (N) values (pg.18 prescaler) + static const uhd::dict prescaler_to_min_int_div = map_list_of + (0,23) //adf4351_regs_t::PRESCALER_4_5 + (1,75) //adf4351_regs_t::PRESCALER_8_9 + ; + + //map rf divider select output dividers to enums + static const uhd::dict rfdivsel_to_enum = map_list_of + (1, adf4351_regs_t::RF_DIVIDER_SELECT_DIV1) + (2, adf4351_regs_t::RF_DIVIDER_SELECT_DIV2) + (4, adf4351_regs_t::RF_DIVIDER_SELECT_DIV4) + (8, adf4351_regs_t::RF_DIVIDER_SELECT_DIV8) + (16, adf4351_regs_t::RF_DIVIDER_SELECT_DIV16) + (32, adf4351_regs_t::RF_DIVIDER_SELECT_DIV16) + (64, adf4351_regs_t::RF_DIVIDER_SELECT_DIV16) + ; + + double actual_freq, pfd_freq; + double ref_freq = self_base->get_iface()->get_clock_rate(unit); + int R=0, BS=0, N=0, FRAC=0, MOD=0; + int RFdiv = 1; + adf4351_regs_t::reference_divide_by_2_t T = adf4351_regs_t::REFERENCE_DIVIDE_BY_2_DISABLED; + adf4351_regs_t::reference_doubler_t D = adf4351_regs_t::REFERENCE_DOUBLER_DISABLED; + + //Reference doubler for 50% duty cycle + // if ref_freq < 12.5MHz enable regs.reference_divide_by_2 + if(ref_freq <= 12.5e6) D = adf4351_regs_t::REFERENCE_DOUBLER_ENABLED; + + //increase RF divider until acceptable VCO frequency + //start with target_freq*2 because mixer has divide by 2 + double vco_freq = target_freq; + while (vco_freq < 2.2e9) { + vco_freq *= 2; + RFdiv *= 2; + } + + //use 8/9 prescaler for vco_freq > 3 GHz (pg.18 prescaler) + adf4351_regs_t::prescaler_t prescaler = vco_freq > 3e9 ? adf4351_regs_t::PRESCALER_8_9 : adf4351_regs_t::PRESCALER_4_5; + + /* + * The goal here is to loop though possible R dividers, + * band select clock dividers, N (int) dividers, and FRAC + * (frac) dividers. + * + * Calculate the N and F dividers for each set of values. + * The loop exists when it meets all of the constraints. + * The resulting loop values are loaded into the registers. + * + * from pg.21 + * + * f_pfd = f_ref*(1+D)/(R*(1+T)) + * f_vco = (N + (FRAC/MOD))*f_pfd + * N = f_vco/f_pfd - FRAC/MOD = f_vco*((R*(T+1))/(f_ref*(1+D))) - FRAC/MOD + * f_rf = f_vco/RFdiv) + * f_actual = f_rf/2 + */ + for(R = 1; R <= 1023; R+=1){ + //PFD input frequency = f_ref/R ... ignoring Reference doubler/divide-by-2 (D & T) + pfd_freq = ref_freq*(1+D)/(R*(1+T)); + + //keep the PFD frequency at or below 25MHz (Loop Filter Bandwidth) + if (pfd_freq > 25e6) continue; + + //ignore fractional part of tuning + N = int(std::floor(vco_freq/pfd_freq)); + + //keep N > minimum int divider requirement + if (N < prescaler_to_min_int_div[prescaler]) continue; + + for(BS=1; BS <= 255; BS+=1){ + //keep the band select frequency at or below 100KHz + //constraint on band select clock + if (pfd_freq/BS > 100e3) continue; + goto done_loop; + } + } done_loop: + + //Fractional-N calculation + MOD = 4095; //max fractional accuracy + FRAC = int((vco_freq/pfd_freq - N)*MOD); + + //Reference divide-by-2 for 50% duty cycle + // if R even, move one divide by 2 to to regs.reference_divide_by_2 + if(R % 2 == 0){ + T = adf4351_regs_t::REFERENCE_DIVIDE_BY_2_ENABLED; + R /= 2; + } + + //actual frequency calculation + actual_freq = double((N + (double(FRAC)/double(MOD)))*ref_freq*(1+int(D))/(R*(1+int(T)))/RFdiv); + + UHD_LOGV(often) + << boost::format("SBX Intermediates: ref=%0.2f, outdiv=%f, fbdiv=%f") % (ref_freq*(1+int(D))/(R*(1+int(T)))) % double(RFdiv*2) % double(N + double(FRAC)/double(MOD)) << std::endl + << boost::format("SBX tune: R=%d, BS=%d, N=%d, FRAC=%d, MOD=%d, T=%d, D=%d, RFdiv=%d, LD=%d" + ) % R % BS % N % FRAC % MOD % T % D % RFdiv % self_base->get_locked(unit)<< std::endl + << boost::format("SBX Frequencies (MHz): REQ=%0.2f, ACT=%0.2f, VCO=%0.2f, PFD=%0.2f, BAND=%0.2f" + ) % (target_freq/1e6) % (actual_freq/1e6) % (vco_freq/1e6) % (pfd_freq/1e6) % (pfd_freq/BS/1e6) << std::endl; + + //load the register values + adf4351_regs_t regs; + + if ((unit == dboard_iface::UNIT_TX) and (actual_freq == sbx_tx_lo_2dbm.clip(actual_freq))) + regs.output_power = adf4351_regs_t::OUTPUT_POWER_2DBM; + else + regs.output_power = adf4351_regs_t::OUTPUT_POWER_5DBM; + + regs.frac_12_bit = FRAC; + regs.int_16_bit = N; + regs.mod_12_bit = MOD; + regs.prescaler = prescaler; + regs.r_counter_10_bit = R; + regs.reference_divide_by_2 = T; + regs.reference_doubler = D; + regs.band_select_clock_div = BS; + UHD_ASSERT_THROW(rfdivsel_to_enum.has_key(RFdiv)); + regs.rf_divider_select = rfdivsel_to_enum[RFdiv]; + + //write the registers + //correct power-up sequence to write registers (5, 4, 3, 2, 1, 0) + int addr; + + for(addr=5; addr>=0; addr--){ + UHD_LOGV(often) << boost::format( + "SBX SPI Reg (0x%02x): 0x%08x" + ) % addr % regs.get_reg(addr) << std::endl; + self_base->get_iface()->write_spi( + unit, spi_config_t::EDGE_RISE, + regs.get_reg(addr), 32 + ); + } + + //return the actual frequency + UHD_LOGV(often) << boost::format( + "SBX tune: actual frequency %f Mhz" + ) % (actual_freq/1e6) << std::endl; + return actual_freq; +} + -- cgit v1.2.3 From aa0513375eb60a594f323b82d6f06c7b69c574fc Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Wed, 26 Oct 2011 12:58:43 -0700 Subject: wbx: squashed Ben's WBX work --- host/lib/ic_reg_maps/gen_adf4350_regs.py | 1 + host/lib/usrp/dboard/CMakeLists.txt | 3 + host/lib/usrp/dboard/db_wbx_common.cpp | 486 +++---------------------------- host/lib/usrp/dboard/db_wbx_common.hpp | 172 ++++++++++- host/lib/usrp/dboard/db_wbx_simple.cpp | 47 ++- host/lib/usrp/dboard/db_wbx_version2.cpp | 394 +++++++++++++++++++++++++ host/lib/usrp/dboard/db_wbx_version3.cpp | 401 +++++++++++++++++++++++++ host/lib/usrp/dboard/db_wbx_version4.cpp | 404 +++++++++++++++++++++++++ 8 files changed, 1447 insertions(+), 461 deletions(-) create mode 100644 host/lib/usrp/dboard/db_wbx_version2.cpp create mode 100644 host/lib/usrp/dboard/db_wbx_version3.cpp create mode 100644 host/lib/usrp/dboard/db_wbx_version4.cpp (limited to 'host') diff --git a/host/lib/ic_reg_maps/gen_adf4350_regs.py b/host/lib/ic_reg_maps/gen_adf4350_regs.py index bccdb2edf..fce2f569b 100755 --- a/host/lib/ic_reg_maps/gen_adf4350_regs.py +++ b/host/lib/ic_reg_maps/gen_adf4350_regs.py @@ -51,6 +51,7 @@ reference_divide_by_2 2[24] 1 disabled, enabled reference_doubler 2[25] 0 disabled, enabled muxout 2[26:28] 1 3state, dvdd, dgnd, rdiv, ndiv, analog_ld, dld, reserved low_noise_and_spur 2[29:30] 3 low_noise, reserved0, reserved1, low_spur +##reserved 2[31] 0 ######################################################################## ## address 3 ######################################################################## diff --git a/host/lib/usrp/dboard/CMakeLists.txt b/host/lib/usrp/dboard/CMakeLists.txt index a865a7858..744285ac3 100644 --- a/host/lib/usrp/dboard/CMakeLists.txt +++ b/host/lib/usrp/dboard/CMakeLists.txt @@ -27,6 +27,9 @@ LIBUHD_APPEND_SOURCES( #${CMAKE_CURRENT_SOURCE_DIR}/db_sbx_version3.cpp #${CMAKE_CURRENT_SOURCE_DIR}/db_sbx_version4.cpp #${CMAKE_CURRENT_SOURCE_DIR}/db_wbx_common.cpp + #${CMAKE_CURRENT_SOURCE_DIR}/db_wbx_version2.cpp + #${CMAKE_CURRENT_SOURCE_DIR}/db_wbx_version3.cpp + #${CMAKE_CURRENT_SOURCE_DIR}/db_wbx_version4.cpp #${CMAKE_CURRENT_SOURCE_DIR}/db_wbx_simple.cpp ${CMAKE_CURRENT_SOURCE_DIR}/db_dbsrx.cpp ${CMAKE_CURRENT_SOURCE_DIR}/db_unknown.cpp diff --git a/host/lib/usrp/dboard/db_wbx_common.cpp b/host/lib/usrp/dboard/db_wbx_common.cpp index c7f8ba55d..63f70e3d5 100644 --- a/host/lib/usrp/dboard/db_wbx_common.cpp +++ b/host/lib/usrp/dboard/db_wbx_common.cpp @@ -15,151 +15,22 @@ // along with this program. If not, see . // -// Common IO Pins -#define ADF4350_CE (1 << 3) -#define ADF4350_PDBRF (1 << 2) -#define ADF4350_MUXOUT (1 << 1) // INPUT!!! -#define LOCKDET_MASK (1 << 0) // INPUT!!! - -// TX IO Pins -#define TX_PUP_5V (1 << 7) // enables 5.0V power supply -#define TX_PUP_3V (1 << 6) // enables 3.3V supply -#define TXMOD_EN (1 << 4) // on UNIT_TX, 1 enables TX Modulator - -// RX IO Pins -#define RX_PUP_5V (1 << 7) // enables 5.0V power supply -#define RX_PUP_3V (1 << 6) // enables 3.3V supply -#define RXBB_PDB (1 << 4) // on UNIT_RX, 1 powers up RX baseband - -// RX Attenuator Pins -#define RX_ATTN_SHIFT 8 // lsb of RX Attenuator Control -#define RX_ATTN_MASK (63 << RX_ATTN_SHIFT) // valid bits of RX Attenuator Control - -// TX Attenuator Pins (v3 only) -#define TX_ATTN_16 (1 << 14) -#define TX_ATTN_8 (1 << 5) -#define TX_ATTN_4 (1 << 4) -#define TX_ATTN_2 (1 << 3) -#define TX_ATTN_1 (1 << 1) -#define TX_ATTN_MASK (TX_ATTN_16|TX_ATTN_8|TX_ATTN_4|TX_ATTN_2|TX_ATTN_1) // valid bits of TX Attenuator Control - -// Mixer functions -#define TX_MIXER_ENB (TXMOD_EN|ADF4350_PDBRF) // for v3, TXMOD_EN tied to ADF4350_PDBRF rather than separate -#define TX_MIXER_DIS 0 - -#define RX_MIXER_ENB (RXBB_PDB|ADF4350_PDBRF) -#define RX_MIXER_DIS 0 - -// Power functions -#define TX_POWER_UP (TX_PUP_5V|TX_PUP_3V) // high enables power supply -#define TX_POWER_DOWN 0 - -#define RX_POWER_UP (RX_PUP_5V|RX_PUP_3V|ADF4350_CE) // high enables power supply -#define RX_POWER_DOWN 0 - #include "db_wbx_common.hpp" #include "adf4350_regs.hpp" -#include #include #include #include #include #include #include -#include -#include -#include -#include using namespace uhd; using namespace uhd::usrp; using namespace boost::assign; -/*********************************************************************** - * The WBX Common dboard constants - **********************************************************************/ -static const uhd::dict wbx_tx_gain_ranges = map_list_of - ("PGA0", gain_range_t(0, 25, 0.05)) -; - -static const uhd::dict wbx_v3_tx_gain_ranges = map_list_of - ("PGA0", gain_range_t(0, 31, 1.0)) -; - -static const uhd::dict wbx_rx_gain_ranges = map_list_of - ("PGA0", gain_range_t(0, 31.5, 0.5)) -; - -/*********************************************************************** - * WBX Common Implementation - **********************************************************************/ -wbx_base::wbx_base(ctor_args_t args) : xcvr_dboard_base(args){ - - //enable the clocks that we need - this->get_iface()->set_clock_enabled(dboard_iface::UNIT_TX, true); - this->get_iface()->set_clock_enabled(dboard_iface::UNIT_RX, true); - - //v3 has different io bits for attenuator control - int v3_iobits = is_v3() ? TX_ATTN_MASK : ADF4350_CE; - int v3_tx_mod = is_v3() ? ADF4350_PDBRF : TXMOD_EN|ADF4350_PDBRF; - - //set the gpio directions and atr controls - this->get_iface()->set_pin_ctrl(dboard_iface::UNIT_TX, v3_tx_mod); - this->get_iface()->set_pin_ctrl(dboard_iface::UNIT_RX, RXBB_PDB|ADF4350_PDBRF); - this->get_iface()->set_gpio_ddr(dboard_iface::UNIT_TX, TX_PUP_5V|TX_PUP_3V|v3_tx_mod|v3_iobits); - this->get_iface()->set_gpio_ddr(dboard_iface::UNIT_RX, RX_PUP_5V|RX_PUP_3V|ADF4350_CE|RXBB_PDB|ADF4350_PDBRF|RX_ATTN_MASK); - - //setup ATR for the mixer enables (always enabled to prevent phase slip between bursts) - this->get_iface()->set_atr_reg(dboard_iface::UNIT_TX, dboard_iface::ATR_REG_IDLE, v3_tx_mod, TX_MIXER_DIS | v3_tx_mod); - this->get_iface()->set_atr_reg(dboard_iface::UNIT_TX, dboard_iface::ATR_REG_RX_ONLY, v3_tx_mod, TX_MIXER_DIS | v3_tx_mod); - this->get_iface()->set_atr_reg(dboard_iface::UNIT_TX, dboard_iface::ATR_REG_TX_ONLY, v3_tx_mod, TX_MIXER_DIS | v3_tx_mod); - this->get_iface()->set_atr_reg(dboard_iface::UNIT_TX, dboard_iface::ATR_REG_FULL_DUPLEX, v3_tx_mod, TX_MIXER_DIS | v3_tx_mod); - - this->get_iface()->set_atr_reg(dboard_iface::UNIT_RX, dboard_iface::ATR_REG_IDLE, RX_MIXER_ENB, RX_MIXER_DIS | RX_MIXER_ENB); - this->get_iface()->set_atr_reg(dboard_iface::UNIT_RX, dboard_iface::ATR_REG_TX_ONLY, RX_MIXER_ENB, RX_MIXER_DIS | RX_MIXER_ENB); - this->get_iface()->set_atr_reg(dboard_iface::UNIT_RX, dboard_iface::ATR_REG_RX_ONLY, RX_MIXER_ENB, RX_MIXER_DIS | RX_MIXER_ENB); - this->get_iface()->set_atr_reg(dboard_iface::UNIT_RX, dboard_iface::ATR_REG_FULL_DUPLEX, RX_MIXER_ENB, RX_MIXER_DIS | RX_MIXER_ENB); - - //set some default values - if (is_v3()) { - BOOST_FOREACH(const std::string &name, wbx_v3_tx_gain_ranges.keys()){ - set_tx_gain(wbx_v3_tx_gain_ranges[name].start(), name); - } - } - else { - BOOST_FOREACH(const std::string &name, wbx_tx_gain_ranges.keys()){ - set_tx_gain(wbx_tx_gain_ranges[name].start(), name); - } - } - - BOOST_FOREACH(const std::string &name, wbx_rx_gain_ranges.keys()){ - set_rx_gain(wbx_rx_gain_ranges[name].start(), name); - } - set_rx_enabled(false); - set_tx_enabled(false); -} - -wbx_base::~wbx_base(void){ - /* NOP */ -} - -/*********************************************************************** - * Enables - **********************************************************************/ -void wbx_base::set_rx_enabled(bool enb){ - this->get_iface()->set_gpio_out(dboard_iface::UNIT_RX, - (enb)? RX_POWER_UP : RX_POWER_DOWN, RX_POWER_UP | RX_POWER_DOWN - ); -} - -void wbx_base::set_tx_enabled(bool enb){ - this->get_iface()->set_gpio_out(dboard_iface::UNIT_TX, - (enb)? TX_POWER_UP | ADF4350_CE : TX_POWER_DOWN, TX_POWER_UP | TX_POWER_DOWN | (is_v3() ? 0 : ADF4350_CE) - ); -} /*********************************************************************** - * Gain Handling + * Gain-related functions **********************************************************************/ static int rx_pga0_gain_to_iobits(double &gain){ //clip the input @@ -182,79 +53,50 @@ static int rx_pga0_gain_to_iobits(double &gain){ return iobits; } -//v3 TX gains -static int tx_pga0_gain_to_iobits(double &gain){ - //clip the input - gain = wbx_v3_tx_gain_ranges["PGA0"].clip(gain); - - //convert to attenuation - double attn = wbx_v3_tx_gain_ranges["PGA0"].stop() - gain; - //calculate the attenuation - int attn_code = boost::math::iround(attn); - int iobits = ( - (attn_code & 16 ? 0 : TX_ATTN_16) | - (attn_code & 8 ? 0 : TX_ATTN_8) | - (attn_code & 4 ? 0 : TX_ATTN_4) | - (attn_code & 2 ? 0 : TX_ATTN_2) | - (attn_code & 1 ? 0 : TX_ATTN_1) - ) & TX_ATTN_MASK; - - UHD_LOGV(often) << boost::format( - "WBX TX Attenuation: %f dB, Code: %d, IO Bits %x, Mask: %x" - ) % attn % attn_code % (iobits & TX_ATTN_MASK) % TX_ATTN_MASK << std::endl; - - //the actual gain setting - gain = wbx_v3_tx_gain_ranges["PGA0"].stop() - double(attn_code); - - return iobits; +/*********************************************************************** + * WBX Common Implementation + **********************************************************************/ +wbx_base::wbx_base(ctor_args_t args) : xcvr_dboard_base(args){ + switch(get_rx_id().to_uint16()) { + case 0x053: + db_actual = wbx_versionx_sptr(new wbx_version2(this)); + return; + case 0x057: + db_actual = wbx_versionx_sptr(new wbx_version3(this)); + return; + case 0x063: + db_actual = wbx_versionx_sptr(new wbx_version4(this)); + return; + default: + /* We didn't recognize the version of the board... */ + UHD_THROW_INVALID_CODE_PATH(); + } } -//Pre v3 TX gains -static double tx_pga0_gain_to_dac_volts(double &gain){ - //clip the input - gain = wbx_tx_gain_ranges["PGA0"].clip(gain); - - //voltage level constants - static const double max_volts = 0.5, min_volts = 1.4; - static const double slope = (max_volts-min_volts)/wbx_tx_gain_ranges["PGA0"].stop(); - - //calculate the voltage for the aux dac - double dac_volts = gain*slope + min_volts; - UHD_LOGV(often) << boost::format( - "WBX TX Gain: %f dB, dac_volts: %f V" - ) % gain % dac_volts << std::endl; +wbx_base::~wbx_base(void){ + /* NOP */ +} - //the actual gain setting - gain = (dac_volts - min_volts)/slope; +/*********************************************************************** + * Enables + **********************************************************************/ +void wbx_base::set_rx_enabled(bool enb){ + this->get_iface()->set_gpio_out(dboard_iface::UNIT_RX, + (enb)? RX_POWER_UP : RX_POWER_DOWN, RX_POWER_UP | RX_POWER_DOWN + ); +} - return dac_volts; +void wbx_base::set_tx_enabled(bool enb){ + db_actual->set_tx_enabled(enb); } +/*********************************************************************** + * Gain Handling + **********************************************************************/ void wbx_base::set_tx_gain(double gain, const std::string &name){ - if (is_v3()) { - assert_has(wbx_v3_tx_gain_ranges.keys(), name, "wbx tx gain name"); - if(name == "PGA0"){ - boost::uint16_t io_bits = tx_pga0_gain_to_iobits(gain); - _tx_gains[name] = gain; - - //write the new gain to tx gpio outputs - this->get_iface()->set_gpio_out(dboard_iface::UNIT_TX, io_bits, TX_ATTN_MASK); - } - else UHD_THROW_INVALID_CODE_PATH(); - } - else { - assert_has(wbx_tx_gain_ranges.keys(), name, "wbx tx gain name"); - if(name == "PGA0"){ - double dac_volts = tx_pga0_gain_to_dac_volts(gain); - _tx_gains[name] = gain; - - //write the new voltage to the aux dac - this->get_iface()->write_aux_dac(dboard_iface::UNIT_TX, dboard_iface::AUX_DAC_A, dac_volts); - } - else UHD_THROW_INVALID_CODE_PATH(); - } + db_actual->set_tx_gain(gain, name); } void wbx_base::set_rx_gain(double gain, const std::string &name){ @@ -272,183 +114,18 @@ void wbx_base::set_rx_gain(double gain, const std::string &name){ /*********************************************************************** * Tuning **********************************************************************/ -double wbx_base::set_lo_freq( - dboard_iface::unit_t unit, - double target_freq -){ - UHD_LOGV(often) << boost::format( - "WBX tune: target frequency %f Mhz" - ) % (target_freq/1e6) << std::endl; - - //map prescaler setting to mininmum integer divider (N) values (pg.18 prescaler) - static const uhd::dict prescaler_to_min_int_div = map_list_of - (0,23) //adf4350_regs_t::PRESCALER_4_5 - (1,75) //adf4350_regs_t::PRESCALER_8_9 - ; - - //map rf divider select output dividers to enums - static const uhd::dict rfdivsel_to_enum = map_list_of - (1, adf4350_regs_t::RF_DIVIDER_SELECT_DIV1) - (2, adf4350_regs_t::RF_DIVIDER_SELECT_DIV2) - (4, adf4350_regs_t::RF_DIVIDER_SELECT_DIV4) - (8, adf4350_regs_t::RF_DIVIDER_SELECT_DIV8) - (16, adf4350_regs_t::RF_DIVIDER_SELECT_DIV16) - ; - - double actual_freq, pfd_freq; - double ref_freq = this->get_iface()->get_clock_rate(unit); - int R=0, BS=0, N=0, FRAC=0, MOD=0; - int RFdiv = 1; - adf4350_regs_t::reference_divide_by_2_t T = adf4350_regs_t::REFERENCE_DIVIDE_BY_2_DISABLED; - adf4350_regs_t::reference_doubler_t D = adf4350_regs_t::REFERENCE_DOUBLER_DISABLED; - - //Reference doubler for 50% duty cycle - // if ref_freq < 12.5MHz enable regs.reference_divide_by_2 - if(ref_freq <= 12.5e6) D = adf4350_regs_t::REFERENCE_DOUBLER_ENABLED; - - //increase RF divider until acceptable VCO frequency - //start with target_freq*2 because mixer has divide by 2 - double vco_freq = target_freq*2; - while (vco_freq < 2.2e9) { - vco_freq *= 2; - RFdiv *= 2; - } - - //use 8/9 prescaler for vco_freq > 3 GHz (pg.18 prescaler) - adf4350_regs_t::prescaler_t prescaler = vco_freq > 3e9 ? adf4350_regs_t::PRESCALER_8_9 : adf4350_regs_t::PRESCALER_4_5; - - /* - * The goal here is to loop though possible R dividers, - * band select clock dividers, N (int) dividers, and FRAC - * (frac) dividers. - * - * Calculate the N and F dividers for each set of values. - * The loop exists when it meets all of the constraints. - * The resulting loop values are loaded into the registers. - * - * from pg.21 - * - * f_pfd = f_ref*(1+D)/(R*(1+T)) - * f_vco = (N + (FRAC/MOD))*f_pfd - * N = f_vco/f_pfd - FRAC/MOD = f_vco*((R*(T+1))/(f_ref*(1+D))) - FRAC/MOD - * f_rf = f_vco/RFdiv) - * f_actual = f_rf/2 - */ - for(R = 1; R <= 1023; R+=1){ - //PFD input frequency = f_ref/R ... ignoring Reference doubler/divide-by-2 (D & T) - pfd_freq = ref_freq*(1+D)/(R*(1+T)); - - //keep the PFD frequency at or below 25MHz (Loop Filter Bandwidth) - if (pfd_freq > 25e6) continue; - - //ignore fractional part of tuning - N = int(std::floor(vco_freq/pfd_freq)); - - //keep N > minimum int divider requirement - if (N < prescaler_to_min_int_div[prescaler]) continue; - - for(BS=1; BS <= 255; BS+=1){ - //keep the band select frequency at or below 100KHz - //constraint on band select clock - if (pfd_freq/BS > 100e3) continue; - goto done_loop; - } - } done_loop: - - //Fractional-N calculation - MOD = 4095; //max fractional accuracy - FRAC = int((vco_freq/pfd_freq - N)*MOD); - - //Reference divide-by-2 for 50% duty cycle - // if R even, move one divide by 2 to to regs.reference_divide_by_2 - if(R % 2 == 0){ - T = adf4350_regs_t::REFERENCE_DIVIDE_BY_2_ENABLED; - R /= 2; - } - - //actual frequency calculation - actual_freq = double((N + (double(FRAC)/double(MOD)))*ref_freq*(1+int(D))/(R*(1+int(T)))/RFdiv/2); - - - UHD_LOGV(often) - << boost::format("WBX Intermediates: ref=%0.2f, outdiv=%f, fbdiv=%f") % (ref_freq*(1+int(D))/(R*(1+int(T)))) % double(RFdiv*2) % double(N + double(FRAC)/double(MOD)) << std::endl - - << boost::format("WBX tune: R=%d, BS=%d, N=%d, FRAC=%d, MOD=%d, T=%d, D=%d, RFdiv=%d, LD=%d" - ) % R % BS % N % FRAC % MOD % T % D % RFdiv % get_locked(unit)<< std::endl - << boost::format("WBX Frequencies (MHz): REQ=%0.2f, ACT=%0.2f, VCO=%0.2f, PFD=%0.2f, BAND=%0.2f" - ) % (target_freq/1e6) % (actual_freq/1e6) % (vco_freq/1e6) % (pfd_freq/1e6) % (pfd_freq/BS/1e6) << std::endl; - - //load the register values - adf4350_regs_t regs; - - regs.frac_12_bit = FRAC; - regs.int_16_bit = N; - regs.mod_12_bit = MOD; - regs.prescaler = prescaler; - regs.r_counter_10_bit = R; - regs.reference_divide_by_2 = T; - regs.reference_doubler = D; - regs.band_select_clock_div = BS; - UHD_ASSERT_THROW(rfdivsel_to_enum.has_key(RFdiv)); - regs.rf_divider_select = rfdivsel_to_enum[RFdiv]; - - if (unit == dboard_iface::UNIT_RX) { - freq_range_t rx_lo_5dbm = list_of - (range_t(0.05e9, 1.4e9)) - ; - - freq_range_t rx_lo_2dbm = list_of - (range_t(1.4e9, 2.2e9)) - ; - - if (actual_freq == rx_lo_5dbm.clip(actual_freq)) regs.output_power = adf4350_regs_t::OUTPUT_POWER_5DBM; - - if (actual_freq == rx_lo_2dbm.clip(actual_freq)) regs.output_power = adf4350_regs_t::OUTPUT_POWER_2DBM; - - } else if (unit == dboard_iface::UNIT_TX) { - freq_range_t tx_lo_5dbm = list_of - (range_t(0.05e9, 1.7e9)) - (range_t(1.9e9, 2.2e9)) - ; - - freq_range_t tx_lo_m1dbm = list_of - (range_t(1.7e9, 1.9e9)) - ; - - if (actual_freq == tx_lo_5dbm.clip(actual_freq)) regs.output_power = adf4350_regs_t::OUTPUT_POWER_5DBM; - - if (actual_freq == tx_lo_m1dbm.clip(actual_freq)) regs.output_power = adf4350_regs_t::OUTPUT_POWER_M1DBM; - - } - - //write the registers - //correct power-up sequence to write registers (5, 4, 3, 2, 1, 0) - int addr; - - for(addr=5; addr>=0; addr--){ - UHD_LOGV(often) << boost::format( - "WBX SPI Reg (0x%02x): 0x%08x" - ) % addr % regs.get_reg(addr) << std::endl; - this->get_iface()->write_spi( - unit, spi_config_t::EDGE_RISE, - regs.get_reg(addr), 32 - ); - } +freq_range_t wbx_base::get_freq_range(void) { + return db_actual->get_freq_range(); +} - //return the actual frequency - UHD_LOGV(often) << boost::format( - "WBX tune: actual frequency %f Mhz" - ) % (actual_freq/1e6) << std::endl; - return actual_freq; +double wbx_base::set_lo_freq(dboard_iface::unit_t unit, double target_freq) { + return db_actual->set_lo_freq(unit, target_freq); } bool wbx_base::get_locked(dboard_iface::unit_t unit){ return (this->get_iface()->read_gpio(unit) & LOCKDET_MASK) != 0; } -bool wbx_base::is_v3(void){ - return get_rx_id().to_uint16() == 0x057; -} /*********************************************************************** * RX Get and Set @@ -552,84 +229,7 @@ void wbx_base::rx_set(const wax::obj &key_, const wax::obj &val){ * TX Get and Set **********************************************************************/ void wbx_base::tx_get(const wax::obj &key_, wax::obj &val){ - named_prop_t key = named_prop_t::extract(key_); - - //handle the get request conditioned on the key - switch(key.as()){ - case SUBDEV_PROP_NAME: - val = get_tx_id().to_pp_string(); - return; - - case SUBDEV_PROP_OTHERS: - val = prop_names_t(); //empty - return; - - case SUBDEV_PROP_GAIN: - assert_has(_tx_gains.keys(), key.name, "wbx tx gain name"); - val = _tx_gains[key.name]; - return; - - case SUBDEV_PROP_GAIN_RANGE: - if (is_v3()) { - assert_has(wbx_v3_tx_gain_ranges.keys(), key.name, "wbx tx gain name"); - val = wbx_v3_tx_gain_ranges[key.name]; - } - else { - assert_has(wbx_tx_gain_ranges.keys(), key.name, "wbx tx gain name"); - val = wbx_tx_gain_ranges[key.name]; - } - return; - - case SUBDEV_PROP_GAIN_NAMES: - if (is_v3()) - val = prop_names_t(wbx_v3_tx_gain_ranges.keys()); - else - val = prop_names_t(wbx_tx_gain_ranges.keys()); - return; - - case SUBDEV_PROP_FREQ: - val = 0.0; - return; - - case SUBDEV_PROP_FREQ_RANGE: - val = freq_range_t(0.0, 0.0, 0.0); - return; - - case SUBDEV_PROP_ANTENNA: - val = std::string(""); - return; - - case SUBDEV_PROP_ANTENNA_NAMES: - val = prop_names_t(1, ""); - return; - - case SUBDEV_PROP_CONNECTION: - val = SUBDEV_CONN_COMPLEX_IQ; - return; - - case SUBDEV_PROP_ENABLED: - val = _tx_enabled; - return; - - case SUBDEV_PROP_USE_LO_OFFSET: - val = false; - return; - - case SUBDEV_PROP_SENSOR: - UHD_ASSERT_THROW(key.name == "lo_locked"); - val = sensor_value_t("LO", this->get_locked(dboard_iface::UNIT_TX), "locked", "unlocked"); - return; - - case SUBDEV_PROP_SENSOR_NAMES: - val = prop_names_t(1, "lo_locked"); - return; - - case SUBDEV_PROP_BANDWIDTH: - val = 2*20.0e6; //20MHz low-pass, we want complex double-sided - return; - - default: UHD_THROW_PROP_GET_ERROR(); - } + db_actual->tx_get(key_, val); } void wbx_base::tx_set(const wax::obj &key_, const wax::obj &val){ @@ -654,3 +254,5 @@ void wbx_base::tx_set(const wax::obj &key_, const wax::obj &val){ default: UHD_THROW_PROP_SET_ERROR(); } } + + diff --git a/host/lib/usrp/dboard/db_wbx_common.hpp b/host/lib/usrp/dboard/db_wbx_common.hpp index 5d33ddce9..57e2a0fe6 100644 --- a/host/lib/usrp/dboard/db_wbx_common.hpp +++ b/host/lib/usrp/dboard/db_wbx_common.hpp @@ -18,14 +18,74 @@ #ifndef INCLUDED_LIBUHD_USRP_DBOARD_DB_WBX_COMMON_HPP #define INCLUDED_LIBUHD_USRP_DBOARD_DB_WBX_COMMON_HPP -#include "adf4350_regs.hpp" +// Common IO Pins +#define ADF4350_CE (1 << 3) +#define ADF4350_PDBRF (1 << 2) +#define ADF4350_MUXOUT (1 << 1) // INPUT!!! +#define ADF4351_CE (1 << 3) +#define ADF4351_PDBRF (1 << 2) +#define ADF4351_MUXOUT (1 << 1) // INPUT!!! + +#define LOCKDET_MASK (1 << 0) // INPUT!!! + +// TX IO Pins +#define TX_PUP_5V (1 << 7) // enables 5.0V power supply +#define TX_PUP_3V (1 << 6) // enables 3.3V supply +#define TXMOD_EN (1 << 4) // on UNIT_TX, 1 enables TX Modulator + +// RX IO Pins +#define RX_PUP_5V (1 << 7) // enables 5.0V power supply +#define RX_PUP_3V (1 << 6) // enables 3.3V supply +#define RXBB_PDB (1 << 4) // on UNIT_RX, 1 powers up RX baseband + +// RX Attenuator Pins +#define RX_ATTN_SHIFT 8 // lsb of RX Attenuator Control +#define RX_ATTN_MASK (63 << RX_ATTN_SHIFT) // valid bits of RX Attenuator Control + +// TX Attenuator Pins (v3 only) +#define TX_ATTN_16 (1 << 14) +#define TX_ATTN_8 (1 << 5) +#define TX_ATTN_4 (1 << 4) +#define TX_ATTN_2 (1 << 3) +#define TX_ATTN_1 (1 << 1) +#define TX_ATTN_MASK (TX_ATTN_16|TX_ATTN_8|TX_ATTN_4|TX_ATTN_2|TX_ATTN_1) // valid bits of TX Attenuator Control + +// Mixer functions +#define TX_MIXER_ENB (TXMOD_EN|ADF4350_PDBRF) // for v3, TXMOD_EN tied to ADF4350_PDBRF rather than separate +#define TX_MIXER_DIS 0 + +#define RX_MIXER_ENB (RXBB_PDB|ADF4350_PDBRF) +#define RX_MIXER_DIS 0 + +// Power functions +#define TX_POWER_UP (TX_PUP_5V|TX_PUP_3V) // high enables power supply +#define TX_POWER_DOWN 0 + +#define RX_POWER_UP (RX_PUP_5V|RX_PUP_3V|ADF4350_CE) // high enables power supply +#define RX_POWER_DOWN 0 + + #include #include +#include #include +#include #include +#include +#include +#include +#include namespace uhd{ namespace usrp{ + +/*********************************************************************** + * The WBX Common dboard constants + **********************************************************************/ +static const uhd::dict wbx_rx_gain_ranges = boost::assign::map_list_of + ("PGA0", gain_range_t(0, 31.5, 0.5)); + + /*********************************************************************** * The WBX dboard base class **********************************************************************/ @@ -41,11 +101,17 @@ protected: virtual void set_rx_enabled(bool enb); virtual void set_tx_enabled(bool enb); - void rx_get(const wax::obj &key, wax::obj &val); - void rx_set(const wax::obj &key, const wax::obj &val); + virtual void rx_get(const wax::obj &key, wax::obj &val); + virtual void rx_set(const wax::obj &key, const wax::obj &val); - void tx_get(const wax::obj &key, wax::obj &val); - void tx_set(const wax::obj &key, const wax::obj &val); + virtual void tx_get(const wax::obj &key, wax::obj &val); + virtual void tx_set(const wax::obj &key, const wax::obj &val); + + /*! + * Retrieve the frequency range of the board. + * \return the frequency range as a freq_range_t + */ + virtual freq_range_t get_freq_range(void); /*! * Set the LO frequency for the particular dboard unit. @@ -57,22 +123,110 @@ protected: /*! * Get the lock detect status of the LO. + * + * This operation is identical for all versions of the WBX board. * \param unit which unit rx or tx * \return true for locked */ virtual bool get_locked(dboard_iface::unit_t unit); + /*! - * Detect if this a v3 WBX - * \return true for locked + * Version-agnostic ABC that wraps version-specific implementations of the + * WBX base daughterboard. + * + * This class is an abstract base class, and thus is impossible to + * instantiate. */ - virtual bool is_v3(void); + class wbx_versionx { + public: + wbx_versionx() {} + ~wbx_versionx(void) {} + + virtual void set_tx_gain(double gain, const std::string &name) = 0; + virtual void set_tx_enabled(bool enb) = 0; + virtual void tx_get(const wax::obj &key, wax::obj &val) = 0; + virtual freq_range_t get_freq_range(void) = 0; + virtual double set_lo_freq(dboard_iface::unit_t unit, double target_freq) = 0; + }; + + + /*! + * Version 2 of the WBX Daughterboard + * + * Basically the original release of the DB. + */ + class wbx_version2 : public wbx_versionx { + public: + wbx_version2(wbx_base *_self_wbx_base); + ~wbx_version2(void); + + void set_tx_gain(double gain, const std::string &name); + void set_tx_enabled(bool enb); + void tx_get(const wax::obj &key, wax::obj &val); + freq_range_t get_freq_range(void); + double set_lo_freq(dboard_iface::unit_t unit, double target_freq); + + /*! This is the registered instance of the wrapper class, wbx_base. */ + wbx_base *self_base; + }; + + /*! + * Version 3 of the WBX Daughterboard + * + * Fixed a problem with the AGC from Version 2. + */ + class wbx_version3 : public wbx_versionx { + public: + wbx_version3(wbx_base *_self_wbx_base); + ~wbx_version3(void); + + void set_tx_gain(double gain, const std::string &name); + void set_tx_enabled(bool enb); + void tx_get(const wax::obj &key, wax::obj &val); + freq_range_t get_freq_range(void); + double set_lo_freq(dboard_iface::unit_t unit, double target_freq); + + /*! This is the registered instance of the wrapper class, wbx_base. */ + wbx_base *self_base; + }; + + /*! + * Version 4 of the WBX Daughterboard + * + * Upgrades the Frequnecy Synthensizer from ADF4350 to ADF4351. + */ + class wbx_version4 : public wbx_versionx { + public: + wbx_version4(wbx_base *_self_wbx_base); + ~wbx_version4(void); + + void set_tx_gain(double gain, const std::string &name); + void set_tx_enabled(bool enb); + void tx_get(const wax::obj &key, wax::obj &val); + freq_range_t get_freq_range(void); + double set_lo_freq(dboard_iface::unit_t unit, double target_freq); + + /*! This is the registered instance of the wrapper class, wbx_base. */ + wbx_base *self_base; + }; + + /*! + * Handle to the version-specific implementation of the WBX. + * + * Since many of this class's functions are dependent on the version of the + * WBX board, this class will instantiate an object of the appropriate + * wbx_version_* subclass, and invoke any relevant functions through that + * object. This pointer is set to the proper object at construction time. + */ + typedef boost::shared_ptr wbx_versionx_sptr; + wbx_versionx_sptr db_actual; -private: uhd::dict _tx_gains, _rx_gains; bool _rx_enabled, _tx_enabled; }; + }} //namespace uhd::usrp #endif /* INCLUDED_LIBUHD_USRP_DBOARD_DB_WBX_COMMON_HPP */ diff --git a/host/lib/usrp/dboard/db_wbx_simple.cpp b/host/lib/usrp/dboard/db_wbx_simple.cpp index 990bacbc8..789146854 100644 --- a/host/lib/usrp/dboard/db_wbx_simple.cpp +++ b/host/lib/usrp/dboard/db_wbx_simple.cpp @@ -32,15 +32,17 @@ using namespace uhd; using namespace uhd::usrp; using namespace boost::assign; + /*********************************************************************** * The WBX Simple dboard constants **********************************************************************/ -static const freq_range_t wbx_freq_range(68.75e6, 2.2e9); - static const prop_names_t wbx_tx_antennas = list_of("TX/RX"); static const prop_names_t wbx_rx_antennas = list_of("TX/RX")("RX2"); +//this will get set by a version-specific function call +static freq_range_t wbx_freq_range(0.0, 0.0); + /*********************************************************************** * The WBX simple implementation **********************************************************************/ @@ -72,13 +74,19 @@ static dboard_base::sptr make_wbx_simple(dboard_base::ctor_args_t args){ return dboard_base::sptr(new wbx_simple(args)); } +/*********************************************************************** + * ID Numbers for WBX daughterboard combinations. + **********************************************************************/ UHD_STATIC_BLOCK(reg_wbx_simple_dboards){ dboard_manager::register_dboard(0x0053, 0x0052, &make_wbx_simple, "WBX"); dboard_manager::register_dboard(0x0053, 0x004f, &make_wbx_simple, "WBX + Simple GDB"); dboard_manager::register_dboard(0x0057, 0x0056, &make_wbx_simple, "WBX v3"); dboard_manager::register_dboard(0x0057, 0x004f, &make_wbx_simple, "WBX v3 + Simple GDB"); + dboard_manager::register_dboard(0x0063, 0x0062, &make_wbx_simple, "WBX v4"); + dboard_manager::register_dboard(0x0063, 0x004f, &make_wbx_simple, "WBX v4 + Simple GDB"); } + /*********************************************************************** * Structors **********************************************************************/ @@ -100,6 +108,9 @@ wbx_simple::wbx_simple(ctor_args_t args) : wbx_base(args){ this->get_iface()->set_atr_reg(dboard_iface::UNIT_RX, dboard_iface::ATR_REG_TX_ONLY, ANT_RX2, ANTSW_IO); this->get_iface()->set_atr_reg(dboard_iface::UNIT_RX, dboard_iface::ATR_REG_FULL_DUPLEX, ANT_RX2, ANTSW_IO); + //get the frequency range of our WBX db + wbx_freq_range = this->get_freq_range(); + //set some default values set_rx_lo_freq((wbx_freq_range.start() + wbx_freq_range.stop())/2.0); set_tx_lo_freq((wbx_freq_range.start() + wbx_freq_range.stop())/2.0); @@ -149,11 +160,19 @@ void wbx_simple::rx_get(const wax::obj &key_, wax::obj &val){ //handle the get request conditioned on the key switch(key.as()){ case SUBDEV_PROP_NAME: - if (is_v3()) - val = std::string("WBX v3 RX + Simple GDB"); - else + switch(get_rx_id().to_uint16()) { + case 0x053: val = std::string("WBX RX + Simple GDB"); - return; + return; + case 0x057: + val = std::string("WBX v3 RX + Simple GDB"); + return; + case 0x063: + val = std::string("WBX v4 RX + Simple GDB"); + return; + default: + UHD_THROW_INVALID_CODE_PATH(); + } case SUBDEV_PROP_FREQ: val = _rx_lo_freq; @@ -206,11 +225,19 @@ void wbx_simple::tx_get(const wax::obj &key_, wax::obj &val){ //handle the get request conditioned on the key switch(key.as()){ case SUBDEV_PROP_NAME: - if (is_v3()) - val = std::string("WBX v3 TX + Simple GDB"); - else + switch(get_rx_id().to_uint16()) { + case 0x053: val = std::string("WBX TX + Simple GDB"); - return; + return; + case 0x057: + val = std::string("WBX v3 TX + Simple GDB"); + return; + case 0x063: + val = std::string("WBX v4 TX + Simple GDB"); + return; + default: + UHD_THROW_INVALID_CODE_PATH(); + } case SUBDEV_PROP_FREQ: val = _tx_lo_freq; diff --git a/host/lib/usrp/dboard/db_wbx_version2.cpp b/host/lib/usrp/dboard/db_wbx_version2.cpp new file mode 100644 index 000000000..0b57a6e2d --- /dev/null +++ b/host/lib/usrp/dboard/db_wbx_version2.cpp @@ -0,0 +1,394 @@ +// +// 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 . +// + +#include "db_wbx_common.hpp" +#include "adf4350_regs.hpp" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace uhd; +using namespace uhd::usrp; +using namespace boost::assign; + + +/*********************************************************************** + * WBX Version 2 Constants + **********************************************************************/ +static const uhd::dict wbx_v2_tx_gain_ranges = map_list_of + ("PGA0", gain_range_t(0, 25, 0.05)) +; + +static const freq_range_t wbx_v2_freq_range(68.75e6, 2.2e9); + +/*********************************************************************** + * Gain-related functions + **********************************************************************/ +static double tx_pga0_gain_to_dac_volts(double &gain){ + //clip the input + gain = wbx_v2_tx_gain_ranges["PGA0"].clip(gain); + + //voltage level constants + static const double max_volts = 0.5, min_volts = 1.4; + static const double slope = (max_volts-min_volts)/wbx_v2_tx_gain_ranges["PGA0"].stop(); + + //calculate the voltage for the aux dac + double dac_volts = gain*slope + min_volts; + + UHD_LOGV(often) << boost::format( + "WBX TX Gain: %f dB, dac_volts: %f V" + ) % gain % dac_volts << std::endl; + + //the actual gain setting + gain = (dac_volts - min_volts)/slope; + + return dac_volts; +} + + +/*********************************************************************** + * WBX Version 2 Implementation + **********************************************************************/ +wbx_base::wbx_version2::wbx_version2(wbx_base *_self_wbx_base) { + //register our handle on the primary wbx_base instance + self_base = _self_wbx_base; + + //enable the clocks that we need + self_base->get_iface()->set_clock_enabled(dboard_iface::UNIT_TX, true); + self_base->get_iface()->set_clock_enabled(dboard_iface::UNIT_RX, true); + + //set attenuator control bits + int v2_iobits = ADF4350_CE; + int v2_tx_mod = TXMOD_EN|ADF4350_PDBRF; + + //set the gpio directions and atr controls + self_base->get_iface()->set_pin_ctrl(dboard_iface::UNIT_TX, v2_tx_mod); + self_base->get_iface()->set_pin_ctrl(dboard_iface::UNIT_RX, RXBB_PDB|ADF4350_PDBRF); + self_base->get_iface()->set_gpio_ddr(dboard_iface::UNIT_TX, TX_PUP_5V|TX_PUP_3V|v2_tx_mod|v2_iobits); + self_base->get_iface()->set_gpio_ddr(dboard_iface::UNIT_RX, RX_PUP_5V|RX_PUP_3V|ADF4350_CE|RXBB_PDB|ADF4350_PDBRF|RX_ATTN_MASK); + + //setup ATR for the mixer enables (always enabled to prevent phase slip between bursts) + self_base->get_iface()->set_atr_reg(dboard_iface::UNIT_TX, dboard_iface::ATR_REG_IDLE, v2_tx_mod, TX_MIXER_DIS | v2_tx_mod); + self_base->get_iface()->set_atr_reg(dboard_iface::UNIT_TX, dboard_iface::ATR_REG_RX_ONLY, v2_tx_mod, TX_MIXER_DIS | v2_tx_mod); + self_base->get_iface()->set_atr_reg(dboard_iface::UNIT_TX, dboard_iface::ATR_REG_TX_ONLY, v2_tx_mod, TX_MIXER_DIS | v2_tx_mod); + self_base->get_iface()->set_atr_reg(dboard_iface::UNIT_TX, dboard_iface::ATR_REG_FULL_DUPLEX, v2_tx_mod, TX_MIXER_DIS | v2_tx_mod); + + self_base->get_iface()->set_atr_reg(dboard_iface::UNIT_RX, dboard_iface::ATR_REG_IDLE, RX_MIXER_ENB, RX_MIXER_DIS | RX_MIXER_ENB); + self_base->get_iface()->set_atr_reg(dboard_iface::UNIT_RX, dboard_iface::ATR_REG_TX_ONLY, RX_MIXER_ENB, RX_MIXER_DIS | RX_MIXER_ENB); + self_base->get_iface()->set_atr_reg(dboard_iface::UNIT_RX, dboard_iface::ATR_REG_RX_ONLY, RX_MIXER_ENB, RX_MIXER_DIS | RX_MIXER_ENB); + self_base->get_iface()->set_atr_reg(dboard_iface::UNIT_RX, dboard_iface::ATR_REG_FULL_DUPLEX, RX_MIXER_ENB, RX_MIXER_DIS | RX_MIXER_ENB); + + BOOST_FOREACH(const std::string &name, wbx_v2_tx_gain_ranges.keys()) { + set_tx_gain(wbx_v2_tx_gain_ranges[name].start(), name); + } + + BOOST_FOREACH(const std::string &name, wbx_rx_gain_ranges.keys()) { + self_base->set_rx_gain(wbx_rx_gain_ranges[name].start(), name); + } + + self_base->set_rx_enabled(false); + set_tx_enabled(false); +} + +wbx_base::wbx_version2::~wbx_version2(void){ + /* NOP */ +} + +/*********************************************************************** + * Enables + **********************************************************************/ + +void wbx_base::wbx_version2::set_tx_enabled(bool enb){ + self_base->get_iface()->set_gpio_out(dboard_iface::UNIT_TX, + (enb)? TX_POWER_UP | ADF4350_CE : TX_POWER_DOWN, TX_POWER_UP | TX_POWER_DOWN | ADF4350_CE); +} + + +/*********************************************************************** + * Gain Handling + **********************************************************************/ +void wbx_base::wbx_version2::set_tx_gain(double gain, const std::string &name){ + assert_has(wbx_v2_tx_gain_ranges.keys(), name, "wbx tx gain name"); + if(name == "PGA0"){ + double dac_volts = tx_pga0_gain_to_dac_volts(gain); + self_base->_tx_gains[name] = gain; + + //write the new voltage to the aux dac + self_base->get_iface()->write_aux_dac(dboard_iface::UNIT_TX, dboard_iface::AUX_DAC_A, dac_volts); + } + else UHD_THROW_INVALID_CODE_PATH(); +} + + +/*********************************************************************** + * Tuning + **********************************************************************/ +freq_range_t wbx_base::wbx_version2::get_freq_range(void) { + return wbx_v2_freq_range; +} + +double wbx_base::wbx_version2::set_lo_freq(dboard_iface::unit_t unit, double target_freq) { + UHD_LOGV(often) << boost::format( + "WBX tune: target frequency %f Mhz" + ) % (target_freq/1e6) << std::endl; + + //map prescaler setting to mininmum integer divider (N) values (pg.18 prescaler) + static const uhd::dict prescaler_to_min_int_div = map_list_of + (0,23) //adf4350_regs_t::PRESCALER_4_5 + (1,75) //adf4350_regs_t::PRESCALER_8_9 + ; + + //map rf divider select output dividers to enums + static const uhd::dict rfdivsel_to_enum = map_list_of + (1, adf4350_regs_t::RF_DIVIDER_SELECT_DIV1) + (2, adf4350_regs_t::RF_DIVIDER_SELECT_DIV2) + (4, adf4350_regs_t::RF_DIVIDER_SELECT_DIV4) + (8, adf4350_regs_t::RF_DIVIDER_SELECT_DIV8) + (16, adf4350_regs_t::RF_DIVIDER_SELECT_DIV16) + ; + + double actual_freq, pfd_freq; + double ref_freq = self_base->get_iface()->get_clock_rate(unit); + int R=0, BS=0, N=0, FRAC=0, MOD=0; + int RFdiv = 1; + adf4350_regs_t::reference_divide_by_2_t T = adf4350_regs_t::REFERENCE_DIVIDE_BY_2_DISABLED; + adf4350_regs_t::reference_doubler_t D = adf4350_regs_t::REFERENCE_DOUBLER_DISABLED; + + //Reference doubler for 50% duty cycle + // if ref_freq < 12.5MHz enable regs.reference_divide_by_2 + if(ref_freq <= 12.5e6) D = adf4350_regs_t::REFERENCE_DOUBLER_ENABLED; + + //increase RF divider until acceptable VCO frequency + //start with target_freq*2 because mixer has divide by 2 + double vco_freq = target_freq*2; + while (vco_freq < 2.2e9) { + vco_freq *= 2; + RFdiv *= 2; + } + + //use 8/9 prescaler for vco_freq > 3 GHz (pg.18 prescaler) + adf4350_regs_t::prescaler_t prescaler = vco_freq > 3e9 ? adf4350_regs_t::PRESCALER_8_9 : adf4350_regs_t::PRESCALER_4_5; + + /* + * The goal here is to loop though possible R dividers, + * band select clock dividers, N (int) dividers, and FRAC + * (frac) dividers. + * + * Calculate the N and F dividers for each set of values. + * The loop exists when it meets all of the constraints. + * The resulting loop values are loaded into the registers. + * + * from pg.21 + * + * f_pfd = f_ref*(1+D)/(R*(1+T)) + * f_vco = (N + (FRAC/MOD))*f_pfd + * N = f_vco/f_pfd - FRAC/MOD = f_vco*((R*(T+1))/(f_ref*(1+D))) - FRAC/MOD + * f_rf = f_vco/RFdiv) + * f_actual = f_rf/2 + */ + for(R = 1; R <= 1023; R+=1){ + //PFD input frequency = f_ref/R ... ignoring Reference doubler/divide-by-2 (D & T) + pfd_freq = ref_freq*(1+D)/(R*(1+T)); + + //keep the PFD frequency at or below 25MHz (Loop Filter Bandwidth) + if (pfd_freq > 25e6) continue; + + //ignore fractional part of tuning + N = int(std::floor(vco_freq/pfd_freq)); + + //keep N > minimum int divider requirement + if (N < prescaler_to_min_int_div[prescaler]) continue; + + for(BS=1; BS <= 255; BS+=1){ + //keep the band select frequency at or below 100KHz + //constraint on band select clock + if (pfd_freq/BS > 100e3) continue; + goto done_loop; + } + } done_loop: + + //Fractional-N calculation + MOD = 4095; //max fractional accuracy + FRAC = int((vco_freq/pfd_freq - N)*MOD); + + //Reference divide-by-2 for 50% duty cycle + // if R even, move one divide by 2 to to regs.reference_divide_by_2 + if(R % 2 == 0){ + T = adf4350_regs_t::REFERENCE_DIVIDE_BY_2_ENABLED; + R /= 2; + } + + //actual frequency calculation + actual_freq = double((N + (double(FRAC)/double(MOD)))*ref_freq*(1+int(D))/(R*(1+int(T)))/RFdiv/2); + + + UHD_LOGV(often) + << boost::format("WBX Intermediates: ref=%0.2f, outdiv=%f, fbdiv=%f") % (ref_freq*(1+int(D))/(R*(1+int(T)))) % double(RFdiv*2) % double(N + double(FRAC)/double(MOD)) << std::endl + + << boost::format("WBX tune: R=%d, BS=%d, N=%d, FRAC=%d, MOD=%d, T=%d, D=%d, RFdiv=%d, LD=%d" + ) % R % BS % N % FRAC % MOD % T % D % RFdiv % self_base->get_locked(unit)<< std::endl + << boost::format("WBX Frequencies (MHz): REQ=%0.2f, ACT=%0.2f, VCO=%0.2f, PFD=%0.2f, BAND=%0.2f" + ) % (target_freq/1e6) % (actual_freq/1e6) % (vco_freq/1e6) % (pfd_freq/1e6) % (pfd_freq/BS/1e6) << std::endl; + + //load the register values + adf4350_regs_t regs; + + regs.frac_12_bit = FRAC; + regs.int_16_bit = N; + regs.mod_12_bit = MOD; + regs.prescaler = prescaler; + regs.r_counter_10_bit = R; + regs.reference_divide_by_2 = T; + regs.reference_doubler = D; + regs.band_select_clock_div = BS; + UHD_ASSERT_THROW(rfdivsel_to_enum.has_key(RFdiv)); + regs.rf_divider_select = rfdivsel_to_enum[RFdiv]; + + if (unit == dboard_iface::UNIT_RX) { + freq_range_t rx_lo_5dbm = list_of + (range_t(0.05e9, 1.4e9)) + ; + + freq_range_t rx_lo_2dbm = list_of + (range_t(1.4e9, 2.2e9)) + ; + + if (actual_freq == rx_lo_5dbm.clip(actual_freq)) regs.output_power = adf4350_regs_t::OUTPUT_POWER_5DBM; + + if (actual_freq == rx_lo_2dbm.clip(actual_freq)) regs.output_power = adf4350_regs_t::OUTPUT_POWER_2DBM; + + } else if (unit == dboard_iface::UNIT_TX) { + freq_range_t tx_lo_5dbm = list_of + (range_t(0.05e9, 1.7e9)) + (range_t(1.9e9, 2.2e9)) + ; + + freq_range_t tx_lo_m1dbm = list_of + (range_t(1.7e9, 1.9e9)) + ; + + if (actual_freq == tx_lo_5dbm.clip(actual_freq)) regs.output_power = adf4350_regs_t::OUTPUT_POWER_5DBM; + + if (actual_freq == tx_lo_m1dbm.clip(actual_freq)) regs.output_power = adf4350_regs_t::OUTPUT_POWER_M1DBM; + + } + + //write the registers + //correct power-up sequence to write registers (5, 4, 3, 2, 1, 0) + int addr; + + for(addr=5; addr>=0; addr--){ + UHD_LOGV(often) << boost::format( + "WBX SPI Reg (0x%02x): 0x%08x" + ) % addr % regs.get_reg(addr) << std::endl; + self_base->get_iface()->write_spi( + unit, spi_config_t::EDGE_RISE, + regs.get_reg(addr), 32 + ); + } + + //return the actual frequency + UHD_LOGV(often) << boost::format( + "WBX tune: actual frequency %f Mhz" + ) % (actual_freq/1e6) << std::endl; + return actual_freq; +} + + +/*********************************************************************** + * TX Get and Set + **********************************************************************/ +void wbx_base::wbx_version2::tx_get(const wax::obj &key_, wax::obj &val){ + named_prop_t key = named_prop_t::extract(key_); + + //handle the get request conditioned on the key + switch(key.as()){ + case SUBDEV_PROP_NAME: + val = self_base->get_tx_id().to_pp_string(); + return; + + case SUBDEV_PROP_OTHERS: + val = prop_names_t(); //empty + return; + + case SUBDEV_PROP_GAIN: + assert_has(self_base->_tx_gains.keys(), key.name, "wbx tx gain name"); + val = self_base->_tx_gains[key.name]; + return; + + case SUBDEV_PROP_GAIN_RANGE: + assert_has(wbx_v2_tx_gain_ranges.keys(), key.name, "wbx tx gain name"); + val = wbx_v2_tx_gain_ranges[key.name]; + return; + + case SUBDEV_PROP_GAIN_NAMES: + val = prop_names_t(wbx_v2_tx_gain_ranges.keys()); + return; + + case SUBDEV_PROP_FREQ: + val = 0.0; + return; + + case SUBDEV_PROP_FREQ_RANGE: + val = freq_range_t(0.0, 0.0, 0.0); + return; + + case SUBDEV_PROP_ANTENNA: + val = std::string(""); + return; + + case SUBDEV_PROP_ANTENNA_NAMES: + val = prop_names_t(1, ""); + return; + + case SUBDEV_PROP_CONNECTION: + val = SUBDEV_CONN_COMPLEX_IQ; + return; + + case SUBDEV_PROP_ENABLED: + val = self_base->_tx_enabled; + return; + + case SUBDEV_PROP_USE_LO_OFFSET: + val = false; + return; + + case SUBDEV_PROP_SENSOR: + UHD_ASSERT_THROW(key.name == "lo_locked"); + val = sensor_value_t("LO", self_base->get_locked(dboard_iface::UNIT_TX), "locked", "unlocked"); + return; + + case SUBDEV_PROP_SENSOR_NAMES: + val = prop_names_t(1, "lo_locked"); + return; + + case SUBDEV_PROP_BANDWIDTH: + val = 2*20.0e6; //20MHz low-pass, we want complex double-sided + return; + + default: UHD_THROW_PROP_GET_ERROR(); + } +} + diff --git a/host/lib/usrp/dboard/db_wbx_version3.cpp b/host/lib/usrp/dboard/db_wbx_version3.cpp new file mode 100644 index 000000000..3c5cdf5ba --- /dev/null +++ b/host/lib/usrp/dboard/db_wbx_version3.cpp @@ -0,0 +1,401 @@ +// +// 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 . +// + +#include "db_wbx_common.hpp" +#include "adf4350_regs.hpp" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace uhd; +using namespace uhd::usrp; +using namespace boost::assign; + + +/*********************************************************************** + * WBX Version 3 Constants + **********************************************************************/ +static const uhd::dict wbx_v3_tx_gain_ranges = map_list_of + ("PGA0", gain_range_t(0, 31, 1.0)) +; + +static const freq_range_t wbx_v3_freq_range(68.75e6, 2.2e9); + +/*********************************************************************** + * Gain-related functions + **********************************************************************/ +static int tx_pga0_gain_to_iobits(double &gain){ + //clip the input + gain = wbx_v3_tx_gain_ranges["PGA0"].clip(gain); + + //convert to attenuation + double attn = wbx_v3_tx_gain_ranges["PGA0"].stop() - gain; + + //calculate the attenuation + int attn_code = boost::math::iround(attn); + int iobits = ( + (attn_code & 16 ? 0 : TX_ATTN_16) | + (attn_code & 8 ? 0 : TX_ATTN_8) | + (attn_code & 4 ? 0 : TX_ATTN_4) | + (attn_code & 2 ? 0 : TX_ATTN_2) | + (attn_code & 1 ? 0 : TX_ATTN_1) + ) & TX_ATTN_MASK; + + UHD_LOGV(often) << boost::format( + "WBX TX Attenuation: %f dB, Code: %d, IO Bits %x, Mask: %x" + ) % attn % attn_code % (iobits & TX_ATTN_MASK) % TX_ATTN_MASK << std::endl; + + //the actual gain setting + gain = wbx_v3_tx_gain_ranges["PGA0"].stop() - double(attn_code); + + return iobits; +} + + +/*********************************************************************** + * WBX Common Implementation + **********************************************************************/ +wbx_base::wbx_version3::wbx_version3(wbx_base *_self_wbx_base) { + //register our handle on the primary wbx_base instance + self_base = _self_wbx_base; + + //enable the clocks that we need + self_base->get_iface()->set_clock_enabled(dboard_iface::UNIT_TX, true); + self_base->get_iface()->set_clock_enabled(dboard_iface::UNIT_RX, true); + + //set attenuator control bits + int v3_iobits = TX_ATTN_MASK; + int v3_tx_mod = ADF4350_PDBRF; + + //set the gpio directions and atr controls + self_base->get_iface()->set_pin_ctrl(dboard_iface::UNIT_TX, v3_tx_mod); + self_base->get_iface()->set_pin_ctrl(dboard_iface::UNIT_RX, RXBB_PDB|ADF4350_PDBRF); + self_base->get_iface()->set_gpio_ddr(dboard_iface::UNIT_TX, TX_PUP_5V|TX_PUP_3V|v3_tx_mod|v3_iobits); + self_base->get_iface()->set_gpio_ddr(dboard_iface::UNIT_RX, RX_PUP_5V|RX_PUP_3V|ADF4350_CE|RXBB_PDB|ADF4350_PDBRF|RX_ATTN_MASK); + + //setup ATR for the mixer enables (always enabled to prevent phase slip between bursts) + self_base->get_iface()->set_atr_reg(dboard_iface::UNIT_TX, dboard_iface::ATR_REG_IDLE, v3_tx_mod, TX_MIXER_DIS | v3_tx_mod); + self_base->get_iface()->set_atr_reg(dboard_iface::UNIT_TX, dboard_iface::ATR_REG_RX_ONLY, v3_tx_mod, TX_MIXER_DIS | v3_tx_mod); + self_base->get_iface()->set_atr_reg(dboard_iface::UNIT_TX, dboard_iface::ATR_REG_TX_ONLY, v3_tx_mod, TX_MIXER_DIS | v3_tx_mod); + self_base->get_iface()->set_atr_reg(dboard_iface::UNIT_TX, dboard_iface::ATR_REG_FULL_DUPLEX, v3_tx_mod, TX_MIXER_DIS | v3_tx_mod); + + self_base->get_iface()->set_atr_reg(dboard_iface::UNIT_RX, dboard_iface::ATR_REG_IDLE, RX_MIXER_ENB, RX_MIXER_DIS | RX_MIXER_ENB); + self_base->get_iface()->set_atr_reg(dboard_iface::UNIT_RX, dboard_iface::ATR_REG_TX_ONLY, RX_MIXER_ENB, RX_MIXER_DIS | RX_MIXER_ENB); + self_base->get_iface()->set_atr_reg(dboard_iface::UNIT_RX, dboard_iface::ATR_REG_RX_ONLY, RX_MIXER_ENB, RX_MIXER_DIS | RX_MIXER_ENB); + self_base->get_iface()->set_atr_reg(dboard_iface::UNIT_RX, dboard_iface::ATR_REG_FULL_DUPLEX, RX_MIXER_ENB, RX_MIXER_DIS | RX_MIXER_ENB); + + //set some default values + BOOST_FOREACH(const std::string &name, wbx_v3_tx_gain_ranges.keys()){ + set_tx_gain(wbx_v3_tx_gain_ranges[name].start(), name); + } + + BOOST_FOREACH(const std::string &name, wbx_rx_gain_ranges.keys()){ + self_base->set_rx_gain(wbx_rx_gain_ranges[name].start(), name); + } + + self_base->set_rx_enabled(false); + set_tx_enabled(false); +} + +wbx_base::wbx_version3::~wbx_version3(void){ + /* NOP */ +} + + +/*********************************************************************** + * Enables + **********************************************************************/ +void wbx_base::wbx_version3::set_tx_enabled(bool enb){ + self_base->get_iface()->set_gpio_out(dboard_iface::UNIT_TX, + (enb)? TX_POWER_UP | ADF4350_CE : TX_POWER_DOWN, TX_POWER_UP | TX_POWER_DOWN | 0); +} + + +/*********************************************************************** + * Gain Handling + **********************************************************************/ +void wbx_base::wbx_version3::set_tx_gain(double gain, const std::string &name){ + assert_has(wbx_v3_tx_gain_ranges.keys(), name, "wbx tx gain name"); + if(name == "PGA0"){ + boost::uint16_t io_bits = tx_pga0_gain_to_iobits(gain); + self_base->_tx_gains[name] = gain; + + //write the new gain to tx gpio outputs + self_base->get_iface()->set_gpio_out(dboard_iface::UNIT_TX, io_bits, TX_ATTN_MASK); + } + else UHD_THROW_INVALID_CODE_PATH(); +} + + +/*********************************************************************** + * Tuning + **********************************************************************/ +freq_range_t wbx_base::wbx_version3::get_freq_range(void) { + return wbx_v3_freq_range; +} + +double wbx_base::wbx_version3::set_lo_freq(dboard_iface::unit_t unit, double target_freq) { + UHD_LOGV(often) << boost::format( + "WBX tune: target frequency %f Mhz" + ) % (target_freq/1e6) << std::endl; + + //map prescaler setting to mininmum integer divider (N) values (pg.18 prescaler) + static const uhd::dict prescaler_to_min_int_div = map_list_of + (0,23) //adf4350_regs_t::PRESCALER_4_5 + (1,75) //adf4350_regs_t::PRESCALER_8_9 + ; + + //map rf divider select output dividers to enums + static const uhd::dict rfdivsel_to_enum = map_list_of + (1, adf4350_regs_t::RF_DIVIDER_SELECT_DIV1) + (2, adf4350_regs_t::RF_DIVIDER_SELECT_DIV2) + (4, adf4350_regs_t::RF_DIVIDER_SELECT_DIV4) + (8, adf4350_regs_t::RF_DIVIDER_SELECT_DIV8) + (16, adf4350_regs_t::RF_DIVIDER_SELECT_DIV16) + ; + + double actual_freq, pfd_freq; + double ref_freq = self_base->get_iface()->get_clock_rate(unit); + int R=0, BS=0, N=0, FRAC=0, MOD=0; + int RFdiv = 1; + adf4350_regs_t::reference_divide_by_2_t T = adf4350_regs_t::REFERENCE_DIVIDE_BY_2_DISABLED; + adf4350_regs_t::reference_doubler_t D = adf4350_regs_t::REFERENCE_DOUBLER_DISABLED; + + //Reference doubler for 50% duty cycle + // if ref_freq < 12.5MHz enable regs.reference_divide_by_2 + if(ref_freq <= 12.5e6) D = adf4350_regs_t::REFERENCE_DOUBLER_ENABLED; + + //increase RF divider until acceptable VCO frequency + //start with target_freq*2 because mixer has divide by 2 + double vco_freq = target_freq*2; + while (vco_freq < 2.2e9) { + vco_freq *= 2; + RFdiv *= 2; + } + + //use 8/9 prescaler for vco_freq > 3 GHz (pg.18 prescaler) + adf4350_regs_t::prescaler_t prescaler = vco_freq > 3e9 ? adf4350_regs_t::PRESCALER_8_9 : adf4350_regs_t::PRESCALER_4_5; + + /* + * The goal here is to loop though possible R dividers, + * band select clock dividers, N (int) dividers, and FRAC + * (frac) dividers. + * + * Calculate the N and F dividers for each set of values. + * The loop exists when it meets all of the constraints. + * The resulting loop values are loaded into the registers. + * + * from pg.21 + * + * f_pfd = f_ref*(1+D)/(R*(1+T)) + * f_vco = (N + (FRAC/MOD))*f_pfd + * N = f_vco/f_pfd - FRAC/MOD = f_vco*((R*(T+1))/(f_ref*(1+D))) - FRAC/MOD + * f_rf = f_vco/RFdiv) + * f_actual = f_rf/2 + */ + for(R = 1; R <= 1023; R+=1){ + //PFD input frequency = f_ref/R ... ignoring Reference doubler/divide-by-2 (D & T) + pfd_freq = ref_freq*(1+D)/(R*(1+T)); + + //keep the PFD frequency at or below 25MHz (Loop Filter Bandwidth) + if (pfd_freq > 25e6) continue; + + //ignore fractional part of tuning + N = int(std::floor(vco_freq/pfd_freq)); + + //keep N > minimum int divider requirement + if (N < prescaler_to_min_int_div[prescaler]) continue; + + for(BS=1; BS <= 255; BS+=1){ + //keep the band select frequency at or below 100KHz + //constraint on band select clock + if (pfd_freq/BS > 100e3) continue; + goto done_loop; + } + } done_loop: + + //Fractional-N calculation + MOD = 4095; //max fractional accuracy + FRAC = int((vco_freq/pfd_freq - N)*MOD); + + //Reference divide-by-2 for 50% duty cycle + // if R even, move one divide by 2 to to regs.reference_divide_by_2 + if(R % 2 == 0){ + T = adf4350_regs_t::REFERENCE_DIVIDE_BY_2_ENABLED; + R /= 2; + } + + //actual frequency calculation + actual_freq = double((N + (double(FRAC)/double(MOD)))*ref_freq*(1+int(D))/(R*(1+int(T)))/RFdiv/2); + + + UHD_LOGV(often) + << boost::format("WBX Intermediates: ref=%0.2f, outdiv=%f, fbdiv=%f") % (ref_freq*(1+int(D))/(R*(1+int(T)))) % double(RFdiv*2) % double(N + double(FRAC)/double(MOD)) << std::endl + + << boost::format("WBX tune: R=%d, BS=%d, N=%d, FRAC=%d, MOD=%d, T=%d, D=%d, RFdiv=%d, LD=%d" + ) % R % BS % N % FRAC % MOD % T % D % RFdiv % self_base->get_locked(unit)<< std::endl + << boost::format("WBX Frequencies (MHz): REQ=%0.2f, ACT=%0.2f, VCO=%0.2f, PFD=%0.2f, BAND=%0.2f" + ) % (target_freq/1e6) % (actual_freq/1e6) % (vco_freq/1e6) % (pfd_freq/1e6) % (pfd_freq/BS/1e6) << std::endl; + + //load the register values + adf4350_regs_t regs; + + regs.frac_12_bit = FRAC; + regs.int_16_bit = N; + regs.mod_12_bit = MOD; + regs.prescaler = prescaler; + regs.r_counter_10_bit = R; + regs.reference_divide_by_2 = T; + regs.reference_doubler = D; + regs.band_select_clock_div = BS; + UHD_ASSERT_THROW(rfdivsel_to_enum.has_key(RFdiv)); + regs.rf_divider_select = rfdivsel_to_enum[RFdiv]; + + if (unit == dboard_iface::UNIT_RX) { + freq_range_t rx_lo_5dbm = list_of + (range_t(0.05e9, 1.4e9)) + ; + + freq_range_t rx_lo_2dbm = list_of + (range_t(1.4e9, 2.2e9)) + ; + + if (actual_freq == rx_lo_5dbm.clip(actual_freq)) regs.output_power = adf4350_regs_t::OUTPUT_POWER_5DBM; + + if (actual_freq == rx_lo_2dbm.clip(actual_freq)) regs.output_power = adf4350_regs_t::OUTPUT_POWER_2DBM; + + } else if (unit == dboard_iface::UNIT_TX) { + freq_range_t tx_lo_5dbm = list_of + (range_t(0.05e9, 1.7e9)) + (range_t(1.9e9, 2.2e9)) + ; + + freq_range_t tx_lo_m1dbm = list_of + (range_t(1.7e9, 1.9e9)) + ; + + if (actual_freq == tx_lo_5dbm.clip(actual_freq)) regs.output_power = adf4350_regs_t::OUTPUT_POWER_5DBM; + + if (actual_freq == tx_lo_m1dbm.clip(actual_freq)) regs.output_power = adf4350_regs_t::OUTPUT_POWER_M1DBM; + + } + + //write the registers + //correct power-up sequence to write registers (5, 4, 3, 2, 1, 0) + int addr; + + for(addr=5; addr>=0; addr--){ + UHD_LOGV(often) << boost::format( + "WBX SPI Reg (0x%02x): 0x%08x" + ) % addr % regs.get_reg(addr) << std::endl; + self_base->get_iface()->write_spi( + unit, spi_config_t::EDGE_RISE, + regs.get_reg(addr), 32 + ); + } + + //return the actual frequency + UHD_LOGV(often) << boost::format( + "WBX tune: actual frequency %f Mhz" + ) % (actual_freq/1e6) << std::endl; + return actual_freq; +} + + +/*********************************************************************** + * TX Get and Set + **********************************************************************/ +void wbx_base::wbx_version3::tx_get(const wax::obj &key_, wax::obj &val){ + named_prop_t key = named_prop_t::extract(key_); + + //handle the get request conditioned on the key + switch(key.as()){ + case SUBDEV_PROP_NAME: + val = self_base->get_tx_id().to_pp_string(); + return; + + case SUBDEV_PROP_OTHERS: + val = prop_names_t(); //empty + return; + + case SUBDEV_PROP_GAIN: + assert_has(self_base->_tx_gains.keys(), key.name, "wbx tx gain name"); + val = self_base->_tx_gains[key.name]; + return; + + case SUBDEV_PROP_GAIN_RANGE: + assert_has(wbx_v3_tx_gain_ranges.keys(), key.name, "wbx tx gain name"); + val = wbx_v3_tx_gain_ranges[key.name]; + return; + + case SUBDEV_PROP_GAIN_NAMES: + val = prop_names_t(wbx_v3_tx_gain_ranges.keys()); + return; + + case SUBDEV_PROP_FREQ: + val = 0.0; + return; + + case SUBDEV_PROP_FREQ_RANGE: + val = freq_range_t(0.0, 0.0, 0.0); + return; + + case SUBDEV_PROP_ANTENNA: + val = std::string(""); + return; + + case SUBDEV_PROP_ANTENNA_NAMES: + val = prop_names_t(1, ""); + return; + + case SUBDEV_PROP_CONNECTION: + val = SUBDEV_CONN_COMPLEX_IQ; + return; + + case SUBDEV_PROP_ENABLED: + val = self_base->_tx_enabled; + return; + + case SUBDEV_PROP_USE_LO_OFFSET: + val = false; + return; + + case SUBDEV_PROP_SENSOR: + UHD_ASSERT_THROW(key.name == "lo_locked"); + val = sensor_value_t("LO", self_base->get_locked(dboard_iface::UNIT_TX), "locked", "unlocked"); + return; + + case SUBDEV_PROP_SENSOR_NAMES: + val = prop_names_t(1, "lo_locked"); + return; + + case SUBDEV_PROP_BANDWIDTH: + val = 2*20.0e6; //20MHz low-pass, we want complex double-sided + return; + + default: UHD_THROW_PROP_GET_ERROR(); + } +} + diff --git a/host/lib/usrp/dboard/db_wbx_version4.cpp b/host/lib/usrp/dboard/db_wbx_version4.cpp new file mode 100644 index 000000000..b5104c9f1 --- /dev/null +++ b/host/lib/usrp/dboard/db_wbx_version4.cpp @@ -0,0 +1,404 @@ +// +// 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 . +// + +#include "db_wbx_common.hpp" +#include "adf4351_regs.hpp" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace uhd; +using namespace uhd::usrp; +using namespace boost::assign; + + +/*********************************************************************** + * WBX Version 3 Constants + **********************************************************************/ +static const uhd::dict wbx_v4_gain_ranges = map_list_of + ("PGA0", gain_range_t(0, 31, 1.0)) +; + +static const freq_range_t wbx_v4_freq_range(50.0e6, 2.2e9); + + +/*********************************************************************** + * Gain-related functions + **********************************************************************/ +static int tx_pga0_gain_to_iobits(double &gain){ + //clip the input + gain = wbx_v4_gain_ranges["PGA0"].clip(gain); + + //convert to attenuation + double attn = wbx_v4_gain_ranges["PGA0"].stop() - gain; + + //calculate the attenuation + int attn_code = boost::math::iround(attn); + int iobits = ( + (attn_code & 16 ? 0 : TX_ATTN_16) | + (attn_code & 8 ? 0 : TX_ATTN_8) | + (attn_code & 4 ? 0 : TX_ATTN_4) | + (attn_code & 2 ? 0 : TX_ATTN_2) | + (attn_code & 1 ? 0 : TX_ATTN_1) + ) & TX_ATTN_MASK; + + UHD_LOGV(often) << boost::format( + "WBX TX Attenuation: %f dB, Code: %d, IO Bits %x, Mask: %x" + ) % attn % attn_code % (iobits & TX_ATTN_MASK) % TX_ATTN_MASK << std::endl; + + //the actual gain setting + gain = wbx_v4_gain_ranges["PGA0"].stop() - double(attn_code); + + return iobits; +} + + +/*********************************************************************** + * WBX Common Implementation + **********************************************************************/ +wbx_base::wbx_version4::wbx_version4(wbx_base *_self_wbx_base) { + //register our handle on the primary wbx_base instance + self_base = _self_wbx_base; + + //enable the clocks that we need + self_base->get_iface()->set_clock_enabled(dboard_iface::UNIT_TX, true); + self_base->get_iface()->set_clock_enabled(dboard_iface::UNIT_RX, true); + + //set attenuator control bits + int v4_iobits = TX_ATTN_MASK; + int v4_tx_mod = ADF4351_PDBRF; + + //set the gpio directions and atr controls + self_base->get_iface()->set_pin_ctrl(dboard_iface::UNIT_TX, v4_tx_mod); + self_base->get_iface()->set_pin_ctrl(dboard_iface::UNIT_RX, RXBB_PDB|ADF4351_PDBRF); + self_base->get_iface()->set_gpio_ddr(dboard_iface::UNIT_TX, TX_PUP_5V|TX_PUP_3V|v4_tx_mod|v4_iobits); + self_base->get_iface()->set_gpio_ddr(dboard_iface::UNIT_RX, RX_PUP_5V|RX_PUP_3V|ADF4351_CE|RXBB_PDB|ADF4351_PDBRF|RX_ATTN_MASK); + + //setup ATR for the mixer enables (always enabled to prevent phase slip between bursts) + self_base->get_iface()->set_atr_reg(dboard_iface::UNIT_TX, dboard_iface::ATR_REG_IDLE, v4_tx_mod, TX_MIXER_DIS | v4_tx_mod); + self_base->get_iface()->set_atr_reg(dboard_iface::UNIT_TX, dboard_iface::ATR_REG_RX_ONLY, v4_tx_mod, TX_MIXER_DIS | v4_tx_mod); + self_base->get_iface()->set_atr_reg(dboard_iface::UNIT_TX, dboard_iface::ATR_REG_TX_ONLY, v4_tx_mod, TX_MIXER_DIS | v4_tx_mod); + self_base->get_iface()->set_atr_reg(dboard_iface::UNIT_TX, dboard_iface::ATR_REG_FULL_DUPLEX, v4_tx_mod, TX_MIXER_DIS | v4_tx_mod); + + self_base->get_iface()->set_atr_reg(dboard_iface::UNIT_RX, dboard_iface::ATR_REG_IDLE, RX_MIXER_ENB, RX_MIXER_DIS | RX_MIXER_ENB); + self_base->get_iface()->set_atr_reg(dboard_iface::UNIT_RX, dboard_iface::ATR_REG_TX_ONLY, RX_MIXER_ENB, RX_MIXER_DIS | RX_MIXER_ENB); + self_base->get_iface()->set_atr_reg(dboard_iface::UNIT_RX, dboard_iface::ATR_REG_RX_ONLY, RX_MIXER_ENB, RX_MIXER_DIS | RX_MIXER_ENB); + self_base->get_iface()->set_atr_reg(dboard_iface::UNIT_RX, dboard_iface::ATR_REG_FULL_DUPLEX, RX_MIXER_ENB, RX_MIXER_DIS | RX_MIXER_ENB); + + //set some default values + BOOST_FOREACH(const std::string &name, wbx_v4_gain_ranges.keys()){ + set_tx_gain(wbx_v4_gain_ranges[name].start(), name); + } + + BOOST_FOREACH(const std::string &name, wbx_rx_gain_ranges.keys()){ + self_base->set_rx_gain(wbx_rx_gain_ranges[name].start(), name); + } + + self_base->set_rx_enabled(false); + set_tx_enabled(false); +} + +wbx_base::wbx_version4::~wbx_version4(void){ + /* NOP */ +} + + +/*********************************************************************** + * Enables + **********************************************************************/ +void wbx_base::wbx_version4::set_tx_enabled(bool enb) { + self_base->get_iface()->set_gpio_out(dboard_iface::UNIT_TX, + (enb)? TX_POWER_UP | ADF4351_CE : TX_POWER_DOWN, TX_POWER_UP | TX_POWER_DOWN | 0); +} + + +/*********************************************************************** + * Gain Handling + **********************************************************************/ +void wbx_base::wbx_version4::set_tx_gain(double gain, const std::string &name) { + assert_has(wbx_v4_gain_ranges.keys(), name, "wbx tx gain name"); + if(name == "PGA0"){ + boost::uint16_t io_bits = tx_pga0_gain_to_iobits(gain); + self_base->_tx_gains[name] = gain; + + //write the new gain to tx gpio outputs + self_base->get_iface()->set_gpio_out(dboard_iface::UNIT_TX, io_bits, TX_ATTN_MASK); + } + else UHD_THROW_INVALID_CODE_PATH(); +} + + +/*********************************************************************** + * Tuning + **********************************************************************/ +freq_range_t wbx_base::wbx_version4::get_freq_range(void) { + return wbx_v4_freq_range; +} + +double wbx_base::wbx_version4::set_lo_freq(dboard_iface::unit_t unit, double target_freq) { + UHD_LOGV(often) << boost::format( + "WBX tune: target frequency %f Mhz" + ) % (target_freq/1e6) << std::endl; + + //map prescaler setting to mininmum integer divider (N) values (pg.18 prescaler) + static const uhd::dict prescaler_to_min_int_div = map_list_of + (0,23) //adf4351_regs_t::PRESCALER_4_5 + (1,75) //adf4351_regs_t::PRESCALER_8_9 + ; + + //map rf divider select output dividers to enums + static const uhd::dict rfdivsel_to_enum = map_list_of + (1, adf4351_regs_t::RF_DIVIDER_SELECT_DIV1) + (2, adf4351_regs_t::RF_DIVIDER_SELECT_DIV2) + (4, adf4351_regs_t::RF_DIVIDER_SELECT_DIV4) + (8, adf4351_regs_t::RF_DIVIDER_SELECT_DIV8) + (16, adf4351_regs_t::RF_DIVIDER_SELECT_DIV16) + (32, adf4351_regs_t::RF_DIVIDER_SELECT_DIV32) + (64, adf4351_regs_t::RF_DIVIDER_SELECT_DIV64) + ; + + double actual_freq, pfd_freq; + double ref_freq = self_base->get_iface()->get_clock_rate(unit); + int R=0, BS=0, N=0, FRAC=0, MOD=0; + int RFdiv = 1; + adf4351_regs_t::reference_divide_by_2_t T = adf4351_regs_t::REFERENCE_DIVIDE_BY_2_DISABLED; + adf4351_regs_t::reference_doubler_t D = adf4351_regs_t::REFERENCE_DOUBLER_DISABLED; + + //Reference doubler for 50% duty cycle + // if ref_freq < 12.5MHz enable regs.reference_divide_by_2 + if(ref_freq <= 12.5e6) D = adf4351_regs_t::REFERENCE_DOUBLER_ENABLED; + + //increase RF divider until acceptable VCO frequency + //start with target_freq*2 because mixer has divide by 2 + double vco_freq = target_freq*2; + while (vco_freq < 2.2e9) { + vco_freq *= 2; + RFdiv *= 2; + } + + //use 8/9 prescaler for vco_freq > 3 GHz (pg.18 prescaler) + adf4351_regs_t::prescaler_t prescaler = vco_freq > 3e9 ? adf4351_regs_t::PRESCALER_8_9 : adf4351_regs_t::PRESCALER_4_5; + + /* + * The goal here is to loop though possible R dividers, + * band select clock dividers, N (int) dividers, and FRAC + * (frac) dividers. + * + * Calculate the N and F dividers for each set of values. + * The loop exits when it meets all of the constraints. + * The resulting loop values are loaded into the registers. + * + * from pg.21 + * + * f_pfd = f_ref*(1+D)/(R*(1+T)) + * f_vco = (N + (FRAC/MOD))*f_pfd + * N = f_vco/f_pfd - FRAC/MOD = f_vco*((R*(T+1))/(f_ref*(1+D))) - FRAC/MOD + * f_rf = f_vco/RFdiv) + * f_actual = f_rf/2 + */ + for(R = 1; R <= 1023; R+=1){ + //PFD input frequency = f_ref/R ... ignoring Reference doubler/divide-by-2 (D & T) + pfd_freq = ref_freq*(1+D)/(R*(1+T)); + + //keep the PFD frequency at or below 25MHz (Loop Filter Bandwidth) + if (pfd_freq > 25e6) continue; + + //ignore fractional part of tuning + N = int(std::floor(vco_freq/pfd_freq)); + + //keep N > minimum int divider requirement + if (N < prescaler_to_min_int_div[prescaler]) continue; + + for(BS=1; BS <= 255; BS+=1){ + //keep the band select frequency at or below 100KHz + //constraint on band select clock + if (pfd_freq/BS > 100e3) continue; + goto done_loop; + } + } done_loop: + + //Fractional-N calculation + MOD = 4095; //max fractional accuracy + FRAC = int((vco_freq/pfd_freq - N)*MOD); + + //Reference divide-by-2 for 50% duty cycle + // if R even, move one divide by 2 to to regs.reference_divide_by_2 + if(R % 2 == 0){ + T = adf4351_regs_t::REFERENCE_DIVIDE_BY_2_ENABLED; + R /= 2; + } + + //actual frequency calculation + actual_freq = double((N + (double(FRAC)/double(MOD)))*ref_freq*(1+int(D))/(R*(1+int(T)))/RFdiv/2); + + + UHD_LOGV(often) + << boost::format("WBX Intermediates: ref=%0.2f, outdiv=%f, fbdiv=%f") % (ref_freq*(1+int(D))/(R*(1+int(T)))) % double(RFdiv*2) % double(N + double(FRAC)/double(MOD)) << std::endl + + << boost::format("WBX tune: R=%d, BS=%d, N=%d, FRAC=%d, MOD=%d, T=%d, D=%d, RFdiv=%d, LD=%d" + ) % R % BS % N % FRAC % MOD % T % D % RFdiv % self_base->get_locked(unit)<< std::endl + << boost::format("WBX Frequencies (MHz): REQ=%0.2f, ACT=%0.2f, VCO=%0.2f, PFD=%0.2f, BAND=%0.2f" + ) % (target_freq/1e6) % (actual_freq/1e6) % (vco_freq/1e6) % (pfd_freq/1e6) % (pfd_freq/BS/1e6) << std::endl; + + //load the register values + adf4351_regs_t regs; + + regs.frac_12_bit = FRAC; + regs.int_16_bit = N; + regs.mod_12_bit = MOD; + regs.prescaler = prescaler; + regs.r_counter_10_bit = R; + regs.reference_divide_by_2 = T; + regs.reference_doubler = D; + regs.band_select_clock_div = BS; + UHD_ASSERT_THROW(rfdivsel_to_enum.has_key(RFdiv)); + regs.rf_divider_select = rfdivsel_to_enum[RFdiv]; + + if (unit == dboard_iface::UNIT_RX) { + freq_range_t rx_lo_5dbm = list_of + (range_t(0.05e9, 1.4e9)) + ; + + freq_range_t rx_lo_2dbm = list_of + (range_t(1.4e9, 2.2e9)) + ; + + if (actual_freq == rx_lo_5dbm.clip(actual_freq)) regs.output_power = adf4351_regs_t::OUTPUT_POWER_5DBM; + + if (actual_freq == rx_lo_2dbm.clip(actual_freq)) regs.output_power = adf4351_regs_t::OUTPUT_POWER_2DBM; + + } else if (unit == dboard_iface::UNIT_TX) { + freq_range_t tx_lo_5dbm = list_of + (range_t(0.05e9, 1.7e9)) + (range_t(1.9e9, 2.2e9)) + ; + + freq_range_t tx_lo_m1dbm = list_of + (range_t(1.7e9, 1.9e9)) + ; + + if (actual_freq == tx_lo_5dbm.clip(actual_freq)) regs.output_power = adf4351_regs_t::OUTPUT_POWER_5DBM; + + if (actual_freq == tx_lo_m1dbm.clip(actual_freq)) regs.output_power = adf4351_regs_t::OUTPUT_POWER_M1DBM; + + } + + //write the registers + //correct power-up sequence to write registers (5, 4, 3, 2, 1, 0) + int addr; + + for(addr=5; addr>=0; addr--){ + UHD_LOGV(often) << boost::format( + "WBX SPI Reg (0x%02x): 0x%08x" + ) % addr % regs.get_reg(addr) << std::endl; + self_base->get_iface()->write_spi( + unit, spi_config_t::EDGE_RISE, + regs.get_reg(addr), 32 + ); + } + + //return the actual frequency + UHD_LOGV(often) << boost::format( + "WBX tune: actual frequency %f Mhz" + ) % (actual_freq/1e6) << std::endl; + return actual_freq; +} + + +/*********************************************************************** + * TX Get and Set + **********************************************************************/ +void wbx_base::wbx_version4::tx_get(const wax::obj &key_, wax::obj &val){ + named_prop_t key = named_prop_t::extract(key_); + + //handle the get request conditioned on the key + switch(key.as()){ + case SUBDEV_PROP_NAME: + val = self_base->get_tx_id().to_pp_string(); + return; + + case SUBDEV_PROP_OTHERS: + val = prop_names_t(); //empty + return; + + case SUBDEV_PROP_GAIN: + assert_has(self_base->_tx_gains.keys(), key.name, "wbx tx gain name"); + val = self_base->_tx_gains[key.name]; + return; + + case SUBDEV_PROP_GAIN_RANGE: + assert_has(wbx_v4_gain_ranges.keys(), key.name, "wbx tx gain name"); + val = wbx_v4_gain_ranges[key.name]; + return; + + case SUBDEV_PROP_GAIN_NAMES: + val = prop_names_t(wbx_v4_gain_ranges.keys()); + return; + + case SUBDEV_PROP_FREQ: + val = 0.0; + return; + + case SUBDEV_PROP_FREQ_RANGE: + val = freq_range_t(0.0, 0.0, 0.0); + return; + + case SUBDEV_PROP_ANTENNA: + val = std::string(""); + return; + + case SUBDEV_PROP_ANTENNA_NAMES: + val = prop_names_t(1, ""); + return; + + case SUBDEV_PROP_CONNECTION: + val = SUBDEV_CONN_COMPLEX_IQ; + return; + + case SUBDEV_PROP_ENABLED: + val = self_base->_tx_enabled; + return; + + case SUBDEV_PROP_USE_LO_OFFSET: + val = false; + return; + + case SUBDEV_PROP_SENSOR: + UHD_ASSERT_THROW(key.name == "lo_locked"); + val = sensor_value_t("LO", self_base->get_locked(dboard_iface::UNIT_TX), "locked", "unlocked"); + return; + + case SUBDEV_PROP_SENSOR_NAMES: + val = prop_names_t(1, "lo_locked"); + return; + + case SUBDEV_PROP_BANDWIDTH: + val = 2*20.0e6; //20MHz low-pass, we want complex double-sided + return; + + default: UHD_THROW_PROP_GET_ERROR(); + } +} + -- cgit v1.2.3 From 8e398397ed55ae4df014902352c66429fda2e2c0 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Wed, 26 Oct 2011 13:15:44 -0700 Subject: sbx: bring SBX into the tree --- host/lib/usrp/dboard/CMakeLists.txt | 6 +- host/lib/usrp/dboard/db_sbx_common.cpp | 295 +++++++------------------------ host/lib/usrp/dboard/db_sbx_common.hpp | 16 +- host/lib/usrp/dboard/db_sbx_version3.cpp | 4 +- host/lib/usrp/dboard/db_sbx_version4.cpp | 4 +- 5 files changed, 79 insertions(+), 246 deletions(-) (limited to 'host') diff --git a/host/lib/usrp/dboard/CMakeLists.txt b/host/lib/usrp/dboard/CMakeLists.txt index 744285ac3..50662a96e 100644 --- a/host/lib/usrp/dboard/CMakeLists.txt +++ b/host/lib/usrp/dboard/CMakeLists.txt @@ -23,9 +23,9 @@ LIBUHD_APPEND_SOURCES( ${CMAKE_CURRENT_SOURCE_DIR}/db_basic_and_lf.cpp ${CMAKE_CURRENT_SOURCE_DIR}/db_rfx.cpp ${CMAKE_CURRENT_SOURCE_DIR}/db_xcvr2450.cpp - #${CMAKE_CURRENT_SOURCE_DIR}/db_sbx_common.cpp - #${CMAKE_CURRENT_SOURCE_DIR}/db_sbx_version3.cpp - #${CMAKE_CURRENT_SOURCE_DIR}/db_sbx_version4.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/db_sbx_common.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/db_sbx_version3.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/db_sbx_version4.cpp #${CMAKE_CURRENT_SOURCE_DIR}/db_wbx_common.cpp #${CMAKE_CURRENT_SOURCE_DIR}/db_wbx_version2.cpp #${CMAKE_CURRENT_SOURCE_DIR}/db_wbx_version3.cpp diff --git a/host/lib/usrp/dboard/db_sbx_common.cpp b/host/lib/usrp/dboard/db_sbx_common.cpp index 51a0f0100..27b930f81 100644 --- a/host/lib/usrp/dboard/db_sbx_common.cpp +++ b/host/lib/usrp/dboard/db_sbx_common.cpp @@ -81,7 +81,7 @@ static int tx_pga0_gain_to_iobits(double &gain){ return iobits; } -void sbx_xcvr::set_tx_gain(double gain, const std::string &name){ +double sbx_xcvr::set_tx_gain(double gain, const std::string &name){ assert_has(sbx_tx_gain_ranges.keys(), name, "sbx tx gain name"); if(name == "PGA0"){ tx_pga0_gain_to_iobits(gain); @@ -91,9 +91,10 @@ void sbx_xcvr::set_tx_gain(double gain, const std::string &name){ update_atr(); } else UHD_THROW_INVALID_CODE_PATH(); + return _tx_gains[name]; } -void sbx_xcvr::set_rx_gain(double gain, const std::string &name){ +double sbx_xcvr::set_rx_gain(double gain, const std::string &name){ assert_has(sbx_rx_gain_ranges.keys(), name, "sbx rx gain name"); if(name == "PGA0"){ rx_pga0_gain_to_iobits(gain); @@ -103,6 +104,7 @@ void sbx_xcvr::set_rx_gain(double gain, const std::string &name){ update_atr(); } else UHD_THROW_INVALID_CODE_PATH(); + return _rx_gains[name]; } @@ -122,6 +124,64 @@ sbx_xcvr::sbx_xcvr(ctor_args_t args) : xcvr_dboard_base(args){ UHD_THROW_INVALID_CODE_PATH(); } + //////////////////////////////////////////////////////////////////// + // Register RX properties + //////////////////////////////////////////////////////////////////// + this->get_rx_subtree()->create("name").set("SBX RX"); + this->get_rx_subtree()->create("sensors/lo_locked") + .publish(boost::bind(&sbx_xcvr::get_locked, this, dboard_iface::UNIT_RX)); + BOOST_FOREACH(const std::string &name, sbx_rx_gain_ranges.keys()){ + this->get_rx_subtree()->create("gains/"+name+"/value") + .coerce(boost::bind(&sbx_xcvr::set_rx_gain, this, _1, name)) + .set(sbx_rx_gain_ranges[name].start()); + this->get_rx_subtree()->create("gains/"+name+"/range") + .set(sbx_rx_gain_ranges[name]); + } + this->get_rx_subtree()->create("freq/value") + .coerce(boost::bind(&sbx_xcvr::set_lo_freq, this, dboard_iface::UNIT_RX, _1)) + .set((sbx_freq_range.start() + sbx_freq_range.stop())/2.0); + this->get_rx_subtree()->create("freq/range").set(sbx_freq_range); + this->get_rx_subtree()->create("antenna/value") + .subscribe(boost::bind(&sbx_xcvr::set_rx_ant, this, _1)) + .set("RX2"); + this->get_rx_subtree()->create >("antenna/options") + .set(sbx_rx_antennas); + this->get_rx_subtree()->create("connection").set("IQ"); + this->get_rx_subtree()->create("enabled").set(true); //always enabled + this->get_rx_subtree()->create("use_lo_offset").set(false); + this->get_rx_subtree()->create("bandwidth/value").set(2*20.0e6); //20MHz low-pass, we want complex double-sided + this->get_rx_subtree()->create("bandwidth/range") + .set(freq_range_t(2*20.0e6, 2*20.0e6)); + + //////////////////////////////////////////////////////////////////// + // Register TX properties + //////////////////////////////////////////////////////////////////// + this->get_tx_subtree()->create("name").set("SBX TX"); + this->get_tx_subtree()->create("sensors/lo_locked") + .publish(boost::bind(&sbx_xcvr::get_locked, this, dboard_iface::UNIT_TX)); + BOOST_FOREACH(const std::string &name, sbx_tx_gain_ranges.keys()){ + this->get_tx_subtree()->create("gains/"+name+"/value") + .coerce(boost::bind(&sbx_xcvr::set_tx_gain, this, _1, name)) + .set(sbx_tx_gain_ranges[name].start()); + this->get_tx_subtree()->create("gains/"+name+"/range") + .set(sbx_tx_gain_ranges[name]); + } + this->get_tx_subtree()->create("freq/value") + .coerce(boost::bind(&sbx_xcvr::set_lo_freq, this, dboard_iface::UNIT_TX, _1)) + .set((sbx_freq_range.start() + sbx_freq_range.stop())/2.0); + this->get_tx_subtree()->create("freq/range").set(sbx_freq_range); + this->get_tx_subtree()->create("antenna/value") + .subscribe(boost::bind(&sbx_xcvr::set_tx_ant, this, _1)) + .set(sbx_tx_antennas.at(0)); + this->get_tx_subtree()->create >("antenna/options") + .set(sbx_tx_antennas); + this->get_tx_subtree()->create("connection").set("QI"); + this->get_tx_subtree()->create("enabled").set(true); //always enabled + this->get_tx_subtree()->create("use_lo_offset").set(false); + this->get_tx_subtree()->create("bandwidth/value").set(2*20.0e6); //20MHz low-pass, we want complex double-sided + this->get_tx_subtree()->create("bandwidth/range") + .set(freq_range_t(2*20.0e6, 2*20.0e6)); + //enable the clocks that we need this->get_iface()->set_clock_enabled(dboard_iface::UNIT_TX, true); this->get_iface()->set_clock_enabled(dboard_iface::UNIT_RX, true); @@ -138,18 +198,6 @@ sbx_xcvr::sbx_xcvr(ctor_args_t args) : xcvr_dboard_base(args){ UHD_LOGV(often) << boost::format( "SBX GPIO Direction: RX: 0x%08x, TX: 0x%08x" ) % RXIO_MASK % TXIO_MASK << std::endl; - - //set some default values - set_rx_lo_freq((sbx_freq_range.start() + sbx_freq_range.stop())/2.0); - set_tx_lo_freq((sbx_freq_range.start() + sbx_freq_range.stop())/2.0); - set_rx_ant("RX2"); - - BOOST_FOREACH(const std::string &name, sbx_tx_gain_ranges.keys()){ - set_tx_gain(sbx_tx_gain_ranges[name].start(), name); - } - BOOST_FOREACH(const std::string &name, sbx_rx_gain_ranges.keys()){ - set_rx_gain(sbx_rx_gain_ranges[name].start(), name); - } } sbx_xcvr::~sbx_xcvr(void){ @@ -165,8 +213,8 @@ void sbx_xcvr::update_atr(void){ int tx_pga0_iobits = tx_pga0_gain_to_iobits(_tx_gains["PGA0"]); int rx_lo_lpf_en = (_rx_lo_freq == sbx_enable_rx_lo_filter.clip(_rx_lo_freq)) ? LO_LPF_EN : 0; int tx_lo_lpf_en = (_tx_lo_freq == sbx_enable_tx_lo_filter.clip(_tx_lo_freq)) ? LO_LPF_EN : 0; - int rx_ld_led = get_locked(dboard_iface::UNIT_RX) ? 0 : RX_LED_LD; - int tx_ld_led = get_locked(dboard_iface::UNIT_TX) ? 0 : TX_LED_LD; + int rx_ld_led = get_locked(dboard_iface::UNIT_RX).to_bool() ? 0 : RX_LED_LD; + int tx_ld_led = get_locked(dboard_iface::UNIT_TX).to_bool() ? 0 : TX_LED_LD; int rx_ant_led = _rx_ant == "TX/RX" ? RX_LED_RX1RX2 : 0; int tx_ant_led = _rx_ant == "TX/RX" ? 0 : TX_LED_TXRX; @@ -226,222 +274,13 @@ void sbx_xcvr::set_tx_lo_freq(double freq){ _tx_lo_freq = db_actual->set_lo_freq(dboard_iface::UNIT_TX, freq); } - double sbx_xcvr::set_lo_freq(dboard_iface::unit_t unit, double target_freq) { return db_actual->set_lo_freq(unit, target_freq); } -/*********************************************************************** - * RX Get and Set - **********************************************************************/ -void sbx_xcvr::rx_get(const wax::obj &key_, wax::obj &val){ - named_prop_t key = named_prop_t::extract(key_); - - //handle the get request conditioned on the key - switch(key.as()){ - case SUBDEV_PROP_NAME: - val = get_rx_id().to_pp_string(); - return; - - case SUBDEV_PROP_OTHERS: - val = prop_names_t(); //empty - return; - - case SUBDEV_PROP_GAIN: - assert_has(_rx_gains.keys(), key.name, "sbx rx gain name"); - val = _rx_gains[key.name]; - return; - - case SUBDEV_PROP_GAIN_RANGE: - assert_has(sbx_rx_gain_ranges.keys(), key.name, "sbx rx gain name"); - val = sbx_rx_gain_ranges[key.name]; - return; - - case SUBDEV_PROP_GAIN_NAMES: - val = prop_names_t(sbx_rx_gain_ranges.keys()); - return; - - case SUBDEV_PROP_FREQ: - val = _rx_lo_freq; - return; - - case SUBDEV_PROP_FREQ_RANGE: - val = sbx_freq_range; - return; - - case SUBDEV_PROP_ANTENNA: - val = _rx_ant; - return; - - case SUBDEV_PROP_ANTENNA_NAMES: - val = sbx_rx_antennas; - return; - - case SUBDEV_PROP_CONNECTION: - val = SUBDEV_CONN_COMPLEX_IQ; - return; - - case SUBDEV_PROP_USE_LO_OFFSET: - val = false; - return; - - case SUBDEV_PROP_ENABLED: - val = true; //always enabled - return; - - case SUBDEV_PROP_SENSOR: - UHD_ASSERT_THROW(key.name == "lo_locked"); - val = sensor_value_t("LO", this->get_locked(dboard_iface::UNIT_RX), "locked", "unlocked"); - return; - - case SUBDEV_PROP_SENSOR_NAMES: - val = prop_names_t(1, "lo_locked"); - return; - - case SUBDEV_PROP_BANDWIDTH: - val = 2*20.0e6; //20MHz low-pass, we want complex double-sided - return; - - default: UHD_THROW_PROP_GET_ERROR(); - } -} - -void sbx_xcvr::rx_set(const wax::obj &key_, const wax::obj &val){ - named_prop_t key = named_prop_t::extract(key_); - - //handle the get request conditioned on the key - switch(key.as()){ - - case SUBDEV_PROP_FREQ: - this->set_rx_lo_freq(val.as()); - return; - - case SUBDEV_PROP_GAIN: - this->set_rx_gain(val.as(), key.name); - return; - - case SUBDEV_PROP_ANTENNA: - this->set_rx_ant(val.as()); - return; - - case SUBDEV_PROP_ENABLED: - return; //always enabled - - case SUBDEV_PROP_BANDWIDTH: - UHD_MSG(warning) << "SBX: No tunable bandwidth, fixed filtered to 40MHz"; - return; - - default: UHD_THROW_PROP_SET_ERROR(); - } -} - -/*********************************************************************** - * TX Get and Set - **********************************************************************/ -void sbx_xcvr::tx_get(const wax::obj &key_, wax::obj &val){ - named_prop_t key = named_prop_t::extract(key_); - - //handle the get request conditioned on the key - switch(key.as()){ - case SUBDEV_PROP_NAME: - val = get_tx_id().to_pp_string(); - return; - - case SUBDEV_PROP_OTHERS: - val = prop_names_t(); //empty - return; - - case SUBDEV_PROP_GAIN: - assert_has(_tx_gains.keys(), key.name, "sbx tx gain name"); - val = _tx_gains[key.name]; - return; - - case SUBDEV_PROP_GAIN_RANGE: - assert_has(sbx_tx_gain_ranges.keys(), key.name, "sbx tx gain name"); - val = sbx_tx_gain_ranges[key.name]; - return; - - case SUBDEV_PROP_GAIN_NAMES: - val = prop_names_t(sbx_tx_gain_ranges.keys()); - return; - - case SUBDEV_PROP_FREQ: - val = _tx_lo_freq; - return; - - case SUBDEV_PROP_FREQ_RANGE: - val = sbx_freq_range; - return; - - case SUBDEV_PROP_ANTENNA: - val = std::string("TX/RX"); - return; - - case SUBDEV_PROP_ANTENNA_NAMES: - val = sbx_tx_antennas; - return; - - case SUBDEV_PROP_CONNECTION: - val = SUBDEV_CONN_COMPLEX_QI; - return; - - case SUBDEV_PROP_USE_LO_OFFSET: - val = false; - return; - - case SUBDEV_PROP_ENABLED: - val = true; //always enabled - return; - - case SUBDEV_PROP_SENSOR: - UHD_ASSERT_THROW(key.name == "lo_locked"); - val = sensor_value_t("LO", this->get_locked(dboard_iface::UNIT_TX), "locked", "unlocked"); - return; - - case SUBDEV_PROP_SENSOR_NAMES: - val = prop_names_t(1, "lo_locked"); - return; - - case SUBDEV_PROP_BANDWIDTH: - val = 2*20.0e6; //20MHz low-pass, we want complex double-sided - return; - - default: UHD_THROW_PROP_GET_ERROR(); - } -} - -void sbx_xcvr::tx_set(const wax::obj &key_, const wax::obj &val){ - named_prop_t key = named_prop_t::extract(key_); - - //handle the get request conditioned on the key - switch(key.as()){ - - case SUBDEV_PROP_FREQ: - this->set_tx_lo_freq(val.as()); - return; - - case SUBDEV_PROP_GAIN: - this->set_tx_gain(val.as(), key.name); - return; - - case SUBDEV_PROP_ANTENNA: - this->set_tx_ant(val.as()); - return; - - case SUBDEV_PROP_ENABLED: - return; //always enabled - - case SUBDEV_PROP_BANDWIDTH: - UHD_MSG(warning) << "SBX: No tunable bandwidth, fixed filtered to 40MHz"; - return; - - default: UHD_THROW_PROP_SET_ERROR(); - } -} - - -bool sbx_xcvr::get_locked(dboard_iface::unit_t unit) { - return (this->get_iface()->read_gpio(unit) & LOCKDET_MASK) != 0; +sensor_value_t sbx_xcvr::get_locked(dboard_iface::unit_t unit) { + const bool locked = (this->get_iface()->read_gpio(unit) & LOCKDET_MASK) != 0; + return sensor_value_t("LO", locked, "locked", "unlocked"); } diff --git a/host/lib/usrp/dboard/db_sbx_common.hpp b/host/lib/usrp/dboard/db_sbx_common.hpp index 5ff84811a..c90cce456 100644 --- a/host/lib/usrp/dboard/db_sbx_common.hpp +++ b/host/lib/usrp/dboard/db_sbx_common.hpp @@ -113,9 +113,9 @@ static const freq_range_t sbx_enable_rx_lo_filter = list_of (range_t(0.4e9, 1.5e9)) ; -static const prop_names_t sbx_tx_antennas = list_of("TX/RX"); +static const std::vector sbx_tx_antennas = list_of("TX/RX"); -static const prop_names_t sbx_rx_antennas = list_of("TX/RX")("RX2"); +static const std::vector sbx_rx_antennas = list_of("TX/RX")("RX2"); static const uhd::dict sbx_tx_gain_ranges = map_list_of ("PGA0", gain_range_t(0, 31.5, double(0.5))) @@ -133,12 +133,6 @@ public: sbx_xcvr(ctor_args_t args); ~sbx_xcvr(void); - void rx_get(const wax::obj &key, wax::obj &val); - void rx_set(const wax::obj &key, const wax::obj &val); - - void tx_get(const wax::obj &key, wax::obj &val); - void tx_set(const wax::obj &key, const wax::obj &val); - protected: uhd::dict _tx_gains, _rx_gains; @@ -149,8 +143,8 @@ protected: void set_tx_lo_freq(double freq); void set_rx_ant(const std::string &ant); void set_tx_ant(const std::string &ant); - void set_rx_gain(double gain, const std::string &name); - void set_tx_gain(double gain, const std::string &name); + double set_rx_gain(double gain, const std::string &name); + double set_tx_gain(double gain, const std::string &name); void update_atr(void); @@ -167,7 +161,7 @@ protected: * \param unit which unit rx or tx * \return true for locked */ - bool get_locked(dboard_iface::unit_t unit); + sensor_value_t get_locked(dboard_iface::unit_t unit); /*! * Flash the LEDs diff --git a/host/lib/usrp/dboard/db_sbx_version3.cpp b/host/lib/usrp/dboard/db_sbx_version3.cpp index b5aad8aa5..6e20d5882 100644 --- a/host/lib/usrp/dboard/db_sbx_version3.cpp +++ b/host/lib/usrp/dboard/db_sbx_version3.cpp @@ -139,8 +139,8 @@ double sbx_xcvr::sbx_version3::set_lo_freq(dboard_iface::unit_t unit, double tar UHD_LOGV(often) << boost::format("SBX Intermediates: ref=%0.2f, outdiv=%f, fbdiv=%f") % (ref_freq*(1+int(D))/(R*(1+int(T)))) % double(RFdiv*2) % double(N + double(FRAC)/double(MOD)) << std::endl - << boost::format("SBX tune: R=%d, BS=%d, N=%d, FRAC=%d, MOD=%d, T=%d, D=%d, RFdiv=%d, LD=%d" - ) % R % BS % N % FRAC % MOD % T % D % RFdiv % self_base->get_locked(unit)<< std::endl + << boost::format("SBX tune: R=%d, BS=%d, N=%d, FRAC=%d, MOD=%d, T=%d, D=%d, RFdiv=%d, LD=%s" + ) % R % BS % N % FRAC % MOD % T % D % RFdiv % self_base->get_locked(unit).to_pp_string() << std::endl << boost::format("SBX Frequencies (MHz): REQ=%0.2f, ACT=%0.2f, VCO=%0.2f, PFD=%0.2f, BAND=%0.2f" ) % (target_freq/1e6) % (actual_freq/1e6) % (vco_freq/1e6) % (pfd_freq/1e6) % (pfd_freq/BS/1e6) << std::endl; diff --git a/host/lib/usrp/dboard/db_sbx_version4.cpp b/host/lib/usrp/dboard/db_sbx_version4.cpp index ea0acb699..d22e83b51 100644 --- a/host/lib/usrp/dboard/db_sbx_version4.cpp +++ b/host/lib/usrp/dboard/db_sbx_version4.cpp @@ -142,8 +142,8 @@ double sbx_xcvr::sbx_version4::set_lo_freq(dboard_iface::unit_t unit, double tar UHD_LOGV(often) << boost::format("SBX Intermediates: ref=%0.2f, outdiv=%f, fbdiv=%f") % (ref_freq*(1+int(D))/(R*(1+int(T)))) % double(RFdiv*2) % double(N + double(FRAC)/double(MOD)) << std::endl - << boost::format("SBX tune: R=%d, BS=%d, N=%d, FRAC=%d, MOD=%d, T=%d, D=%d, RFdiv=%d, LD=%d" - ) % R % BS % N % FRAC % MOD % T % D % RFdiv % self_base->get_locked(unit)<< std::endl + << boost::format("SBX tune: R=%d, BS=%d, N=%d, FRAC=%d, MOD=%d, T=%d, D=%d, RFdiv=%d, LD=%s" + ) % R % BS % N % FRAC % MOD % T % D % RFdiv % self_base->get_locked(unit).to_pp_string() << std::endl << boost::format("SBX Frequencies (MHz): REQ=%0.2f, ACT=%0.2f, VCO=%0.2f, PFD=%0.2f, BAND=%0.2f" ) % (target_freq/1e6) % (actual_freq/1e6) % (vco_freq/1e6) % (pfd_freq/1e6) % (pfd_freq/BS/1e6) << std::endl; -- cgit v1.2.3 From 3c07f1d606296c0a6813a3a577e918926e43c478 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Wed, 26 Oct 2011 18:04:55 -0700 Subject: wbx: bring WBX into the tree --- host/lib/usrp/dboard/CMakeLists.txt | 10 +- host/lib/usrp/dboard/db_wbx_common.cpp | 190 +++++++------------------------ host/lib/usrp/dboard/db_wbx_common.hpp | 57 ++++------ host/lib/usrp/dboard/db_wbx_simple.cpp | 185 ++++-------------------------- host/lib/usrp/dboard/db_wbx_version2.cpp | 130 +++++---------------- host/lib/usrp/dboard/db_wbx_version3.cpp | 130 +++++---------------- host/lib/usrp/dboard/db_wbx_version4.cpp | 140 ++++++----------------- 7 files changed, 188 insertions(+), 654 deletions(-) (limited to 'host') diff --git a/host/lib/usrp/dboard/CMakeLists.txt b/host/lib/usrp/dboard/CMakeLists.txt index 50662a96e..b000c7f33 100644 --- a/host/lib/usrp/dboard/CMakeLists.txt +++ b/host/lib/usrp/dboard/CMakeLists.txt @@ -26,11 +26,11 @@ LIBUHD_APPEND_SOURCES( ${CMAKE_CURRENT_SOURCE_DIR}/db_sbx_common.cpp ${CMAKE_CURRENT_SOURCE_DIR}/db_sbx_version3.cpp ${CMAKE_CURRENT_SOURCE_DIR}/db_sbx_version4.cpp - #${CMAKE_CURRENT_SOURCE_DIR}/db_wbx_common.cpp - #${CMAKE_CURRENT_SOURCE_DIR}/db_wbx_version2.cpp - #${CMAKE_CURRENT_SOURCE_DIR}/db_wbx_version3.cpp - #${CMAKE_CURRENT_SOURCE_DIR}/db_wbx_version4.cpp - #${CMAKE_CURRENT_SOURCE_DIR}/db_wbx_simple.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/db_wbx_common.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/db_wbx_version2.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/db_wbx_version3.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/db_wbx_version4.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/db_wbx_simple.cpp ${CMAKE_CURRENT_SOURCE_DIR}/db_dbsrx.cpp ${CMAKE_CURRENT_SOURCE_DIR}/db_unknown.cpp ${CMAKE_CURRENT_SOURCE_DIR}/db_tvrx.cpp diff --git a/host/lib/usrp/dboard/db_wbx_common.cpp b/host/lib/usrp/dboard/db_wbx_common.cpp index 63f70e3d5..daf6dbc98 100644 --- a/host/lib/usrp/dboard/db_wbx_common.cpp +++ b/host/lib/usrp/dboard/db_wbx_common.cpp @@ -58,6 +58,44 @@ static int rx_pga0_gain_to_iobits(double &gain){ * WBX Common Implementation **********************************************************************/ wbx_base::wbx_base(ctor_args_t args) : xcvr_dboard_base(args){ + + //enable the clocks that we need + this->get_iface()->set_clock_enabled(dboard_iface::UNIT_TX, true); + this->get_iface()->set_clock_enabled(dboard_iface::UNIT_RX, true); + + //////////////////////////////////////////////////////////////////// + // Register RX properties + //////////////////////////////////////////////////////////////////// + this->get_rx_subtree()->create("sensors/lo_locked") + .publish(boost::bind(&wbx_base::get_locked, this, dboard_iface::UNIT_RX)); + BOOST_FOREACH(const std::string &name, wbx_rx_gain_ranges.keys()){ + this->get_rx_subtree()->create("gains/"+name+"/value") + .coerce(boost::bind(&wbx_base::set_rx_gain, this, _1, name)) + .set(wbx_rx_gain_ranges[name].start()); + this->get_rx_subtree()->create("gains/"+name+"/range") + .set(wbx_rx_gain_ranges[name]); + } + this->get_rx_subtree()->create("connection").set("IQ"); + this->get_rx_subtree()->create("enabled") + .subscribe(boost::bind(&wbx_base::set_rx_enabled, this, _1)) + .set(true); //start enabled + this->get_rx_subtree()->create("use_lo_offset").set(false); + this->get_rx_subtree()->create("bandwidth/value").set(2*20.0e6); //20MHz low-pass, we want complex double-sided + this->get_rx_subtree()->create("bandwidth/range") + .set(freq_range_t(2*20.0e6, 2*20.0e6)); + + //////////////////////////////////////////////////////////////////// + // Register TX properties + //////////////////////////////////////////////////////////////////// + this->get_tx_subtree()->create("sensors/lo_locked") + .publish(boost::bind(&wbx_base::get_locked, this, dboard_iface::UNIT_TX)); + this->get_tx_subtree()->create("connection").set("IQ"); + this->get_tx_subtree()->create("use_lo_offset").set(false); + this->get_tx_subtree()->create("bandwidth/value").set(2*20.0e6); //20MHz low-pass, we want complex double-sided + this->get_tx_subtree()->create("bandwidth/range") + .set(freq_range_t(2*20.0e6, 2*20.0e6)); + + // instantiate subclass foo switch(get_rx_id().to_uint16()) { case 0x053: db_actual = wbx_versionx_sptr(new wbx_version2(this)); @@ -72,6 +110,7 @@ wbx_base::wbx_base(ctor_args_t args) : xcvr_dboard_base(args){ /* We didn't recognize the version of the board... */ UHD_THROW_INVALID_CODE_PATH(); } + } @@ -88,18 +127,10 @@ void wbx_base::set_rx_enabled(bool enb){ ); } -void wbx_base::set_tx_enabled(bool enb){ - db_actual->set_tx_enabled(enb); -} - /*********************************************************************** * Gain Handling **********************************************************************/ -void wbx_base::set_tx_gain(double gain, const std::string &name){ - db_actual->set_tx_gain(gain, name); -} - -void wbx_base::set_rx_gain(double gain, const std::string &name){ +double wbx_base::set_rx_gain(double gain, const std::string &name){ assert_has(wbx_rx_gain_ranges.keys(), name, "wbx rx gain name"); if(name == "PGA0"){ boost::uint16_t io_bits = rx_pga0_gain_to_iobits(gain); @@ -109,150 +140,17 @@ void wbx_base::set_rx_gain(double gain, const std::string &name){ this->get_iface()->set_gpio_out(dboard_iface::UNIT_RX, io_bits, RX_ATTN_MASK); } else UHD_THROW_INVALID_CODE_PATH(); + return _rx_gains[name]; //returned shadowed } /*********************************************************************** * Tuning **********************************************************************/ -freq_range_t wbx_base::get_freq_range(void) { - return db_actual->get_freq_range(); -} - double wbx_base::set_lo_freq(dboard_iface::unit_t unit, double target_freq) { return db_actual->set_lo_freq(unit, target_freq); } -bool wbx_base::get_locked(dboard_iface::unit_t unit){ - return (this->get_iface()->read_gpio(unit) & LOCKDET_MASK) != 0; +sensor_value_t wbx_base::get_locked(dboard_iface::unit_t unit){ + const bool locked = (this->get_iface()->read_gpio(unit) & LOCKDET_MASK) != 0; + return sensor_value_t("LO", locked, "locked", "unlocked"); } - - -/*********************************************************************** - * RX Get and Set - **********************************************************************/ -void wbx_base::rx_get(const wax::obj &key_, wax::obj &val){ - named_prop_t key = named_prop_t::extract(key_); - - //handle the get request conditioned on the key - switch(key.as()){ - case SUBDEV_PROP_NAME: - val = get_rx_id().to_pp_string(); - return; - - case SUBDEV_PROP_OTHERS: - val = prop_names_t(); //empty - return; - - case SUBDEV_PROP_GAIN: - assert_has(_rx_gains.keys(), key.name, "wbx rx gain name"); - val = _rx_gains[key.name]; - return; - - case SUBDEV_PROP_GAIN_RANGE: - assert_has(wbx_rx_gain_ranges.keys(), key.name, "wbx rx gain name"); - val = wbx_rx_gain_ranges[key.name]; - return; - - case SUBDEV_PROP_GAIN_NAMES: - val = prop_names_t(wbx_rx_gain_ranges.keys()); - return; - - case SUBDEV_PROP_FREQ: - val = 0.0; - return; - - case SUBDEV_PROP_FREQ_RANGE: - val = freq_range_t(0.0, 0.0, 0.0);; - return; - - case SUBDEV_PROP_ANTENNA: - val = std::string(""); - return; - - case SUBDEV_PROP_ANTENNA_NAMES: - val = prop_names_t(1, ""); - return; - - case SUBDEV_PROP_CONNECTION: - val = SUBDEV_CONN_COMPLEX_IQ; - return; - - case SUBDEV_PROP_ENABLED: - val = _rx_enabled; - return; - - case SUBDEV_PROP_USE_LO_OFFSET: - val = false; - return; - - case SUBDEV_PROP_SENSOR: - UHD_ASSERT_THROW(key.name == "lo_locked"); - val = sensor_value_t("LO", this->get_locked(dboard_iface::UNIT_RX), "locked", "unlocked"); - return; - - case SUBDEV_PROP_SENSOR_NAMES: - val = prop_names_t(1, "lo_locked"); - return; - - case SUBDEV_PROP_BANDWIDTH: - val = 2*20.0e6; //20MHz low-pass, we want complex double-sided - return; - - default: UHD_THROW_PROP_GET_ERROR(); - } -} - -void wbx_base::rx_set(const wax::obj &key_, const wax::obj &val){ - named_prop_t key = named_prop_t::extract(key_); - - //handle the get request conditioned on the key - switch(key.as()){ - - case SUBDEV_PROP_GAIN: - this->set_rx_gain(val.as(), key.name); - return; - - case SUBDEV_PROP_ENABLED: - _rx_enabled = val.as(); - this->set_rx_enabled(_rx_enabled); - return; - - case SUBDEV_PROP_BANDWIDTH: - UHD_MSG(warning) << "WBX: No tunable bandwidth, fixed filtered to 40MHz"; - return; - - default: UHD_THROW_PROP_SET_ERROR(); - } -} - -/*********************************************************************** - * TX Get and Set - **********************************************************************/ -void wbx_base::tx_get(const wax::obj &key_, wax::obj &val){ - db_actual->tx_get(key_, val); -} - -void wbx_base::tx_set(const wax::obj &key_, const wax::obj &val){ - named_prop_t key = named_prop_t::extract(key_); - - //handle the get request conditioned on the key - switch(key.as()){ - - case SUBDEV_PROP_GAIN: - this->set_tx_gain(val.as(), key.name); - return; - - case SUBDEV_PROP_ENABLED: - _tx_enabled = val.as(); - this->set_tx_enabled(_tx_enabled); - return; - - case SUBDEV_PROP_BANDWIDTH: - UHD_MSG(warning) << "WBX: No tunable bandwidth, fixed filtered to 40MHz"; - return; - - default: UHD_THROW_PROP_SET_ERROR(); - } -} - - diff --git a/host/lib/usrp/dboard/db_wbx_common.hpp b/host/lib/usrp/dboard/db_wbx_common.hpp index 57e2a0fe6..3e41e04b7 100644 --- a/host/lib/usrp/dboard/db_wbx_common.hpp +++ b/host/lib/usrp/dboard/db_wbx_common.hpp @@ -67,6 +67,7 @@ #include #include +#include #include #include #include @@ -75,6 +76,7 @@ #include #include #include +#include namespace uhd{ namespace usrp{ @@ -95,23 +97,9 @@ public: virtual ~wbx_base(void); protected: - virtual void set_rx_gain(double gain, const std::string &name); - virtual void set_tx_gain(double gain, const std::string &name); + virtual double set_rx_gain(double gain, const std::string &name); virtual void set_rx_enabled(bool enb); - virtual void set_tx_enabled(bool enb); - - virtual void rx_get(const wax::obj &key, wax::obj &val); - virtual void rx_set(const wax::obj &key, const wax::obj &val); - - virtual void tx_get(const wax::obj &key, wax::obj &val); - virtual void tx_set(const wax::obj &key, const wax::obj &val); - - /*! - * Retrieve the frequency range of the board. - * \return the frequency range as a freq_range_t - */ - virtual freq_range_t get_freq_range(void); /*! * Set the LO frequency for the particular dboard unit. @@ -128,8 +116,7 @@ protected: * \param unit which unit rx or tx * \return true for locked */ - virtual bool get_locked(dboard_iface::unit_t unit); - + virtual sensor_value_t get_locked(dboard_iface::unit_t unit); /*! * Version-agnostic ABC that wraps version-specific implementations of the @@ -143,11 +130,20 @@ protected: wbx_versionx() {} ~wbx_versionx(void) {} - virtual void set_tx_gain(double gain, const std::string &name) = 0; + virtual double set_tx_gain(double gain, const std::string &name) = 0; virtual void set_tx_enabled(bool enb) = 0; - virtual void tx_get(const wax::obj &key, wax::obj &val) = 0; - virtual freq_range_t get_freq_range(void) = 0; virtual double set_lo_freq(dboard_iface::unit_t unit, double target_freq) = 0; + + /*! This is the registered instance of the wrapper class, wbx_base. */ + wbx_base *self_base; + + property_tree::sptr get_rx_subtree(void){ + return self_base->get_rx_subtree(); + } + + property_tree::sptr get_tx_subtree(void){ + return self_base->get_tx_subtree(); + } }; @@ -161,14 +157,9 @@ protected: wbx_version2(wbx_base *_self_wbx_base); ~wbx_version2(void); - void set_tx_gain(double gain, const std::string &name); + double set_tx_gain(double gain, const std::string &name); void set_tx_enabled(bool enb); - void tx_get(const wax::obj &key, wax::obj &val); - freq_range_t get_freq_range(void); double set_lo_freq(dboard_iface::unit_t unit, double target_freq); - - /*! This is the registered instance of the wrapper class, wbx_base. */ - wbx_base *self_base; }; /*! @@ -181,14 +172,9 @@ protected: wbx_version3(wbx_base *_self_wbx_base); ~wbx_version3(void); - void set_tx_gain(double gain, const std::string &name); + double set_tx_gain(double gain, const std::string &name); void set_tx_enabled(bool enb); - void tx_get(const wax::obj &key, wax::obj &val); - freq_range_t get_freq_range(void); double set_lo_freq(dboard_iface::unit_t unit, double target_freq); - - /*! This is the registered instance of the wrapper class, wbx_base. */ - wbx_base *self_base; }; /*! @@ -201,14 +187,9 @@ protected: wbx_version4(wbx_base *_self_wbx_base); ~wbx_version4(void); - void set_tx_gain(double gain, const std::string &name); + double set_tx_gain(double gain, const std::string &name); void set_tx_enabled(bool enb); - void tx_get(const wax::obj &key, wax::obj &val); - freq_range_t get_freq_range(void); double set_lo_freq(dboard_iface::unit_t unit, double target_freq); - - /*! This is the registered instance of the wrapper class, wbx_base. */ - wbx_base *self_base; }; /*! diff --git a/host/lib/usrp/dboard/db_wbx_simple.cpp b/host/lib/usrp/dboard/db_wbx_simple.cpp index 789146854..1ac2a1704 100644 --- a/host/lib/usrp/dboard/db_wbx_simple.cpp +++ b/host/lib/usrp/dboard/db_wbx_simple.cpp @@ -40,9 +40,6 @@ static const prop_names_t wbx_tx_antennas = list_of("TX/RX"); static const prop_names_t wbx_rx_antennas = list_of("TX/RX")("RX2"); -//this will get set by a version-specific function call -static freq_range_t wbx_freq_range(0.0, 0.0); - /*********************************************************************** * The WBX simple implementation **********************************************************************/ @@ -51,17 +48,7 @@ public: wbx_simple(ctor_args_t args); ~wbx_simple(void); - void rx_get(const wax::obj &key, wax::obj &val); - void rx_set(const wax::obj &key, const wax::obj &val); - - void tx_get(const wax::obj &key, wax::obj &val); - void tx_set(const wax::obj &key, const wax::obj &val); - private: - void set_rx_lo_freq(double freq); - void set_tx_lo_freq(double freq); - double _rx_lo_freq, _tx_lo_freq; - void set_rx_ant(const std::string &ant); void set_tx_ant(const std::string &ant); std::string _rx_ant; @@ -86,12 +73,33 @@ UHD_STATIC_BLOCK(reg_wbx_simple_dboards){ dboard_manager::register_dboard(0x0063, 0x004f, &make_wbx_simple, "WBX v4 + Simple GDB"); } - /*********************************************************************** * Structors **********************************************************************/ wbx_simple::wbx_simple(ctor_args_t args) : wbx_base(args){ + //////////////////////////////////////////////////////////////////// + // Register RX properties + //////////////////////////////////////////////////////////////////// + this->get_rx_subtree()->access("name").set( + this->get_rx_subtree()->access("name").get() + " + Simple GDB"); + this->get_rx_subtree()->create("antenna/value") + .subscribe(boost::bind(&wbx_simple::set_rx_ant, this, _1)) + .set("RX2"); + this->get_rx_subtree()->create >("antenna/options") + .set(wbx_rx_antennas); + + //////////////////////////////////////////////////////////////////// + // Register TX properties + //////////////////////////////////////////////////////////////////// + this->get_tx_subtree()->access("name").set( + this->get_tx_subtree()->access("name").get() + " + Simple GDB"); + this->get_tx_subtree()->create("antenna/value") + .subscribe(boost::bind(&wbx_simple::set_tx_ant, this, _1)) + .set(wbx_tx_antennas.at(0)); + this->get_tx_subtree()->create >("antenna/options") + .set(wbx_tx_antennas); + //set the gpio directions and atr controls (antenna switches all under ATR) this->get_iface()->set_pin_ctrl(dboard_iface::UNIT_TX, ANTSW_IO, ANTSW_IO); this->get_iface()->set_pin_ctrl(dboard_iface::UNIT_RX, ANTSW_IO, ANTSW_IO); @@ -107,14 +115,6 @@ wbx_simple::wbx_simple(ctor_args_t args) : wbx_base(args){ this->get_iface()->set_atr_reg(dboard_iface::UNIT_RX, dboard_iface::ATR_REG_IDLE, ANT_TXRX, ANTSW_IO); this->get_iface()->set_atr_reg(dboard_iface::UNIT_RX, dboard_iface::ATR_REG_TX_ONLY, ANT_RX2, ANTSW_IO); this->get_iface()->set_atr_reg(dboard_iface::UNIT_RX, dboard_iface::ATR_REG_FULL_DUPLEX, ANT_RX2, ANTSW_IO); - - //get the frequency range of our WBX db - wbx_freq_range = this->get_freq_range(); - - //set some default values - set_rx_lo_freq((wbx_freq_range.start() + wbx_freq_range.stop())/2.0); - set_tx_lo_freq((wbx_freq_range.start() + wbx_freq_range.stop())/2.0); - set_rx_ant("RX2"); } wbx_simple::~wbx_simple(void){ @@ -139,144 +139,3 @@ void wbx_simple::set_tx_ant(const std::string &ant){ assert_has(wbx_tx_antennas, ant, "wbx tx antenna name"); //only one antenna option, do nothing } - -/*********************************************************************** - * Tuning - **********************************************************************/ -void wbx_simple::set_rx_lo_freq(double freq){ - _rx_lo_freq = set_lo_freq(dboard_iface::UNIT_RX, wbx_freq_range.clip(freq)); -} - -void wbx_simple::set_tx_lo_freq(double freq){ - _tx_lo_freq = set_lo_freq(dboard_iface::UNIT_TX, wbx_freq_range.clip(freq)); -} - -/*********************************************************************** - * RX Get and Set - **********************************************************************/ -void wbx_simple::rx_get(const wax::obj &key_, wax::obj &val){ - named_prop_t key = named_prop_t::extract(key_); - - //handle the get request conditioned on the key - switch(key.as()){ - case SUBDEV_PROP_NAME: - switch(get_rx_id().to_uint16()) { - case 0x053: - val = std::string("WBX RX + Simple GDB"); - return; - case 0x057: - val = std::string("WBX v3 RX + Simple GDB"); - return; - case 0x063: - val = std::string("WBX v4 RX + Simple GDB"); - return; - default: - UHD_THROW_INVALID_CODE_PATH(); - } - - case SUBDEV_PROP_FREQ: - val = _rx_lo_freq; - return; - - case SUBDEV_PROP_FREQ_RANGE: - val = wbx_freq_range; - return; - - case SUBDEV_PROP_ANTENNA: - val = _rx_ant; - return; - - case SUBDEV_PROP_ANTENNA_NAMES: - val = wbx_rx_antennas; - return; - - default: - //call into the base class for other properties - wbx_base::rx_get(key_, val); - } -} - -void wbx_simple::rx_set(const wax::obj &key_, const wax::obj &val){ - named_prop_t key = named_prop_t::extract(key_); - - //handle the get request conditioned on the key - switch(key.as()){ - - case SUBDEV_PROP_FREQ: - this->set_rx_lo_freq(val.as()); - return; - - case SUBDEV_PROP_ANTENNA: - this->set_rx_ant(val.as()); - return; - - default: - //call into the base class for other properties - wbx_base::rx_set(key_, val); - } -} - -/*********************************************************************** - * TX Get and Set - **********************************************************************/ -void wbx_simple::tx_get(const wax::obj &key_, wax::obj &val){ - named_prop_t key = named_prop_t::extract(key_); - - //handle the get request conditioned on the key - switch(key.as()){ - case SUBDEV_PROP_NAME: - switch(get_rx_id().to_uint16()) { - case 0x053: - val = std::string("WBX TX + Simple GDB"); - return; - case 0x057: - val = std::string("WBX v3 TX + Simple GDB"); - return; - case 0x063: - val = std::string("WBX v4 TX + Simple GDB"); - return; - default: - UHD_THROW_INVALID_CODE_PATH(); - } - - case SUBDEV_PROP_FREQ: - val = _tx_lo_freq; - return; - - case SUBDEV_PROP_FREQ_RANGE: - val = wbx_freq_range; - return; - - case SUBDEV_PROP_ANTENNA: - val = std::string("TX/RX"); - return; - - case SUBDEV_PROP_ANTENNA_NAMES: - val = wbx_tx_antennas; - return; - - default: - //call into the base class for other properties - wbx_base::tx_get(key_, val); - } -} - -void wbx_simple::tx_set(const wax::obj &key_, const wax::obj &val){ - named_prop_t key = named_prop_t::extract(key_); - - //handle the get request conditioned on the key - switch(key.as()){ - - case SUBDEV_PROP_FREQ: - this->set_tx_lo_freq(val.as()); - return; - - case SUBDEV_PROP_ANTENNA: - this->set_tx_ant(val.as()); - return; - - default: - //call into the base class for other properties - wbx_base::tx_set(key_, val); - } -} diff --git a/host/lib/usrp/dboard/db_wbx_version2.cpp b/host/lib/usrp/dboard/db_wbx_version2.cpp index 0b57a6e2d..d8a2b7e93 100644 --- a/host/lib/usrp/dboard/db_wbx_version2.cpp +++ b/host/lib/usrp/dboard/db_wbx_version2.cpp @@ -75,9 +75,33 @@ wbx_base::wbx_version2::wbx_version2(wbx_base *_self_wbx_base) { //register our handle on the primary wbx_base instance self_base = _self_wbx_base; - //enable the clocks that we need - self_base->get_iface()->set_clock_enabled(dboard_iface::UNIT_TX, true); - self_base->get_iface()->set_clock_enabled(dboard_iface::UNIT_RX, true); + //////////////////////////////////////////////////////////////////// + // Register RX properties + //////////////////////////////////////////////////////////////////// + this->get_rx_subtree()->create("name").set("WBX RX v2"); + this->get_rx_subtree()->create("freq/value") + .coerce(boost::bind(&wbx_base::wbx_version2::set_lo_freq, this, dboard_iface::UNIT_RX, _1)) + .set((wbx_v2_freq_range.start() + wbx_v2_freq_range.stop())/2.0); + this->get_rx_subtree()->create("freq/range").set(wbx_v2_freq_range); + + //////////////////////////////////////////////////////////////////// + // Register TX properties + //////////////////////////////////////////////////////////////////// + this->get_tx_subtree()->create("name").set("WBX TX v2"); + BOOST_FOREACH(const std::string &name, wbx_v2_tx_gain_ranges.keys()){ + self_base->get_tx_subtree()->create("gains/"+name+"/value") + .coerce(boost::bind(&wbx_base::wbx_version2::set_tx_gain, this, _1, name)) + .set(wbx_v2_tx_gain_ranges[name].start()); + self_base->get_tx_subtree()->create("gains/"+name+"/range") + .set(wbx_v2_tx_gain_ranges[name]); + } + this->get_rx_subtree()->create("freq/value") + .coerce(boost::bind(&wbx_base::wbx_version2::set_lo_freq, this, dboard_iface::UNIT_TX, _1)) + .set((wbx_v2_freq_range.start() + wbx_v2_freq_range.stop())/2.0); + this->get_tx_subtree()->create("freq/range").set(wbx_v2_freq_range); + this->get_tx_subtree()->create("enabled") + .subscribe(boost::bind(&wbx_base::wbx_version2::set_tx_enabled, this, _1)) + .set(true); //start enabled //set attenuator control bits int v2_iobits = ADF4350_CE; @@ -99,17 +123,6 @@ wbx_base::wbx_version2::wbx_version2(wbx_base *_self_wbx_base) { self_base->get_iface()->set_atr_reg(dboard_iface::UNIT_RX, dboard_iface::ATR_REG_TX_ONLY, RX_MIXER_ENB, RX_MIXER_DIS | RX_MIXER_ENB); self_base->get_iface()->set_atr_reg(dboard_iface::UNIT_RX, dboard_iface::ATR_REG_RX_ONLY, RX_MIXER_ENB, RX_MIXER_DIS | RX_MIXER_ENB); self_base->get_iface()->set_atr_reg(dboard_iface::UNIT_RX, dboard_iface::ATR_REG_FULL_DUPLEX, RX_MIXER_ENB, RX_MIXER_DIS | RX_MIXER_ENB); - - BOOST_FOREACH(const std::string &name, wbx_v2_tx_gain_ranges.keys()) { - set_tx_gain(wbx_v2_tx_gain_ranges[name].start(), name); - } - - BOOST_FOREACH(const std::string &name, wbx_rx_gain_ranges.keys()) { - self_base->set_rx_gain(wbx_rx_gain_ranges[name].start(), name); - } - - self_base->set_rx_enabled(false); - set_tx_enabled(false); } wbx_base::wbx_version2::~wbx_version2(void){ @@ -119,7 +132,6 @@ wbx_base::wbx_version2::~wbx_version2(void){ /*********************************************************************** * Enables **********************************************************************/ - void wbx_base::wbx_version2::set_tx_enabled(bool enb){ self_base->get_iface()->set_gpio_out(dboard_iface::UNIT_TX, (enb)? TX_POWER_UP | ADF4350_CE : TX_POWER_DOWN, TX_POWER_UP | TX_POWER_DOWN | ADF4350_CE); @@ -129,7 +141,7 @@ void wbx_base::wbx_version2::set_tx_enabled(bool enb){ /*********************************************************************** * Gain Handling **********************************************************************/ -void wbx_base::wbx_version2::set_tx_gain(double gain, const std::string &name){ +double wbx_base::wbx_version2::set_tx_gain(double gain, const std::string &name){ assert_has(wbx_v2_tx_gain_ranges.keys(), name, "wbx tx gain name"); if(name == "PGA0"){ double dac_volts = tx_pga0_gain_to_dac_volts(gain); @@ -139,16 +151,13 @@ void wbx_base::wbx_version2::set_tx_gain(double gain, const std::string &name){ self_base->get_iface()->write_aux_dac(dboard_iface::UNIT_TX, dboard_iface::AUX_DAC_A, dac_volts); } else UHD_THROW_INVALID_CODE_PATH(); + return self_base->_tx_gains[name]; //shadowed } /*********************************************************************** * Tuning **********************************************************************/ -freq_range_t wbx_base::wbx_version2::get_freq_range(void) { - return wbx_v2_freq_range; -} - double wbx_base::wbx_version2::set_lo_freq(dboard_iface::unit_t unit, double target_freq) { UHD_LOGV(often) << boost::format( "WBX tune: target frequency %f Mhz" @@ -247,8 +256,8 @@ double wbx_base::wbx_version2::set_lo_freq(dboard_iface::unit_t unit, double tar UHD_LOGV(often) << boost::format("WBX Intermediates: ref=%0.2f, outdiv=%f, fbdiv=%f") % (ref_freq*(1+int(D))/(R*(1+int(T)))) % double(RFdiv*2) % double(N + double(FRAC)/double(MOD)) << std::endl - << boost::format("WBX tune: R=%d, BS=%d, N=%d, FRAC=%d, MOD=%d, T=%d, D=%d, RFdiv=%d, LD=%d" - ) % R % BS % N % FRAC % MOD % T % D % RFdiv % self_base->get_locked(unit)<< std::endl + << boost::format("WBX tune: R=%d, BS=%d, N=%d, FRAC=%d, MOD=%d, T=%d, D=%d, RFdiv=%d, LD=%s" + ) % R % BS % N % FRAC % MOD % T % D % RFdiv % self_base->get_locked(unit).to_pp_string() << std::endl << boost::format("WBX Frequencies (MHz): REQ=%0.2f, ACT=%0.2f, VCO=%0.2f, PFD=%0.2f, BAND=%0.2f" ) % (target_freq/1e6) % (actual_freq/1e6) % (vco_freq/1e6) % (pfd_freq/1e6) % (pfd_freq/BS/1e6) << std::endl; @@ -315,80 +324,3 @@ double wbx_base::wbx_version2::set_lo_freq(dboard_iface::unit_t unit, double tar ) % (actual_freq/1e6) << std::endl; return actual_freq; } - - -/*********************************************************************** - * TX Get and Set - **********************************************************************/ -void wbx_base::wbx_version2::tx_get(const wax::obj &key_, wax::obj &val){ - named_prop_t key = named_prop_t::extract(key_); - - //handle the get request conditioned on the key - switch(key.as()){ - case SUBDEV_PROP_NAME: - val = self_base->get_tx_id().to_pp_string(); - return; - - case SUBDEV_PROP_OTHERS: - val = prop_names_t(); //empty - return; - - case SUBDEV_PROP_GAIN: - assert_has(self_base->_tx_gains.keys(), key.name, "wbx tx gain name"); - val = self_base->_tx_gains[key.name]; - return; - - case SUBDEV_PROP_GAIN_RANGE: - assert_has(wbx_v2_tx_gain_ranges.keys(), key.name, "wbx tx gain name"); - val = wbx_v2_tx_gain_ranges[key.name]; - return; - - case SUBDEV_PROP_GAIN_NAMES: - val = prop_names_t(wbx_v2_tx_gain_ranges.keys()); - return; - - case SUBDEV_PROP_FREQ: - val = 0.0; - return; - - case SUBDEV_PROP_FREQ_RANGE: - val = freq_range_t(0.0, 0.0, 0.0); - return; - - case SUBDEV_PROP_ANTENNA: - val = std::string(""); - return; - - case SUBDEV_PROP_ANTENNA_NAMES: - val = prop_names_t(1, ""); - return; - - case SUBDEV_PROP_CONNECTION: - val = SUBDEV_CONN_COMPLEX_IQ; - return; - - case SUBDEV_PROP_ENABLED: - val = self_base->_tx_enabled; - return; - - case SUBDEV_PROP_USE_LO_OFFSET: - val = false; - return; - - case SUBDEV_PROP_SENSOR: - UHD_ASSERT_THROW(key.name == "lo_locked"); - val = sensor_value_t("LO", self_base->get_locked(dboard_iface::UNIT_TX), "locked", "unlocked"); - return; - - case SUBDEV_PROP_SENSOR_NAMES: - val = prop_names_t(1, "lo_locked"); - return; - - case SUBDEV_PROP_BANDWIDTH: - val = 2*20.0e6; //20MHz low-pass, we want complex double-sided - return; - - default: UHD_THROW_PROP_GET_ERROR(); - } -} - diff --git a/host/lib/usrp/dboard/db_wbx_version3.cpp b/host/lib/usrp/dboard/db_wbx_version3.cpp index 3c5cdf5ba..4473bf1ae 100644 --- a/host/lib/usrp/dboard/db_wbx_version3.cpp +++ b/host/lib/usrp/dboard/db_wbx_version3.cpp @@ -81,9 +81,33 @@ wbx_base::wbx_version3::wbx_version3(wbx_base *_self_wbx_base) { //register our handle on the primary wbx_base instance self_base = _self_wbx_base; - //enable the clocks that we need - self_base->get_iface()->set_clock_enabled(dboard_iface::UNIT_TX, true); - self_base->get_iface()->set_clock_enabled(dboard_iface::UNIT_RX, true); + //////////////////////////////////////////////////////////////////// + // Register RX properties + //////////////////////////////////////////////////////////////////// + this->get_rx_subtree()->create("name").set("WBX RX v3"); + this->get_rx_subtree()->create("freq/value") + .coerce(boost::bind(&wbx_base::wbx_version3::set_lo_freq, this, dboard_iface::UNIT_RX, _1)) + .set((wbx_v3_freq_range.start() + wbx_v3_freq_range.stop())/2.0); + this->get_rx_subtree()->create("freq/range").set(wbx_v3_freq_range); + + //////////////////////////////////////////////////////////////////// + // Register TX properties + //////////////////////////////////////////////////////////////////// + this->get_tx_subtree()->create("name").set("WBX TX v3"); + BOOST_FOREACH(const std::string &name, wbx_v3_tx_gain_ranges.keys()){ + self_base->get_tx_subtree()->create("gains/"+name+"/value") + .coerce(boost::bind(&wbx_base::wbx_version3::set_tx_gain, this, _1, name)) + .set(wbx_v3_tx_gain_ranges[name].start()); + self_base->get_tx_subtree()->create("gains/"+name+"/range") + .set(wbx_v3_tx_gain_ranges[name]); + } + this->get_rx_subtree()->create("freq/value") + .coerce(boost::bind(&wbx_base::wbx_version3::set_lo_freq, this, dboard_iface::UNIT_TX, _1)) + .set((wbx_v3_freq_range.start() + wbx_v3_freq_range.stop())/2.0); + this->get_tx_subtree()->create("freq/range").set(wbx_v3_freq_range); + this->get_tx_subtree()->create("enabled") + .subscribe(boost::bind(&wbx_base::wbx_version3::set_tx_enabled, this, _1)) + .set(true); //start enabled //set attenuator control bits int v3_iobits = TX_ATTN_MASK; @@ -105,18 +129,6 @@ wbx_base::wbx_version3::wbx_version3(wbx_base *_self_wbx_base) { self_base->get_iface()->set_atr_reg(dboard_iface::UNIT_RX, dboard_iface::ATR_REG_TX_ONLY, RX_MIXER_ENB, RX_MIXER_DIS | RX_MIXER_ENB); self_base->get_iface()->set_atr_reg(dboard_iface::UNIT_RX, dboard_iface::ATR_REG_RX_ONLY, RX_MIXER_ENB, RX_MIXER_DIS | RX_MIXER_ENB); self_base->get_iface()->set_atr_reg(dboard_iface::UNIT_RX, dboard_iface::ATR_REG_FULL_DUPLEX, RX_MIXER_ENB, RX_MIXER_DIS | RX_MIXER_ENB); - - //set some default values - BOOST_FOREACH(const std::string &name, wbx_v3_tx_gain_ranges.keys()){ - set_tx_gain(wbx_v3_tx_gain_ranges[name].start(), name); - } - - BOOST_FOREACH(const std::string &name, wbx_rx_gain_ranges.keys()){ - self_base->set_rx_gain(wbx_rx_gain_ranges[name].start(), name); - } - - self_base->set_rx_enabled(false); - set_tx_enabled(false); } wbx_base::wbx_version3::~wbx_version3(void){ @@ -136,7 +148,7 @@ void wbx_base::wbx_version3::set_tx_enabled(bool enb){ /*********************************************************************** * Gain Handling **********************************************************************/ -void wbx_base::wbx_version3::set_tx_gain(double gain, const std::string &name){ +double wbx_base::wbx_version3::set_tx_gain(double gain, const std::string &name){ assert_has(wbx_v3_tx_gain_ranges.keys(), name, "wbx tx gain name"); if(name == "PGA0"){ boost::uint16_t io_bits = tx_pga0_gain_to_iobits(gain); @@ -146,16 +158,13 @@ void wbx_base::wbx_version3::set_tx_gain(double gain, const std::string &name){ self_base->get_iface()->set_gpio_out(dboard_iface::UNIT_TX, io_bits, TX_ATTN_MASK); } else UHD_THROW_INVALID_CODE_PATH(); + return self_base->_tx_gains[name]; //shadow } /*********************************************************************** * Tuning **********************************************************************/ -freq_range_t wbx_base::wbx_version3::get_freq_range(void) { - return wbx_v3_freq_range; -} - double wbx_base::wbx_version3::set_lo_freq(dboard_iface::unit_t unit, double target_freq) { UHD_LOGV(often) << boost::format( "WBX tune: target frequency %f Mhz" @@ -254,8 +263,8 @@ double wbx_base::wbx_version3::set_lo_freq(dboard_iface::unit_t unit, double tar UHD_LOGV(often) << boost::format("WBX Intermediates: ref=%0.2f, outdiv=%f, fbdiv=%f") % (ref_freq*(1+int(D))/(R*(1+int(T)))) % double(RFdiv*2) % double(N + double(FRAC)/double(MOD)) << std::endl - << boost::format("WBX tune: R=%d, BS=%d, N=%d, FRAC=%d, MOD=%d, T=%d, D=%d, RFdiv=%d, LD=%d" - ) % R % BS % N % FRAC % MOD % T % D % RFdiv % self_base->get_locked(unit)<< std::endl + << boost::format("WBX tune: R=%d, BS=%d, N=%d, FRAC=%d, MOD=%d, T=%d, D=%d, RFdiv=%d, LD=%s" + ) % R % BS % N % FRAC % MOD % T % D % RFdiv % self_base->get_locked(unit).to_pp_string() << std::endl << boost::format("WBX Frequencies (MHz): REQ=%0.2f, ACT=%0.2f, VCO=%0.2f, PFD=%0.2f, BAND=%0.2f" ) % (target_freq/1e6) % (actual_freq/1e6) % (vco_freq/1e6) % (pfd_freq/1e6) % (pfd_freq/BS/1e6) << std::endl; @@ -322,80 +331,3 @@ double wbx_base::wbx_version3::set_lo_freq(dboard_iface::unit_t unit, double tar ) % (actual_freq/1e6) << std::endl; return actual_freq; } - - -/*********************************************************************** - * TX Get and Set - **********************************************************************/ -void wbx_base::wbx_version3::tx_get(const wax::obj &key_, wax::obj &val){ - named_prop_t key = named_prop_t::extract(key_); - - //handle the get request conditioned on the key - switch(key.as()){ - case SUBDEV_PROP_NAME: - val = self_base->get_tx_id().to_pp_string(); - return; - - case SUBDEV_PROP_OTHERS: - val = prop_names_t(); //empty - return; - - case SUBDEV_PROP_GAIN: - assert_has(self_base->_tx_gains.keys(), key.name, "wbx tx gain name"); - val = self_base->_tx_gains[key.name]; - return; - - case SUBDEV_PROP_GAIN_RANGE: - assert_has(wbx_v3_tx_gain_ranges.keys(), key.name, "wbx tx gain name"); - val = wbx_v3_tx_gain_ranges[key.name]; - return; - - case SUBDEV_PROP_GAIN_NAMES: - val = prop_names_t(wbx_v3_tx_gain_ranges.keys()); - return; - - case SUBDEV_PROP_FREQ: - val = 0.0; - return; - - case SUBDEV_PROP_FREQ_RANGE: - val = freq_range_t(0.0, 0.0, 0.0); - return; - - case SUBDEV_PROP_ANTENNA: - val = std::string(""); - return; - - case SUBDEV_PROP_ANTENNA_NAMES: - val = prop_names_t(1, ""); - return; - - case SUBDEV_PROP_CONNECTION: - val = SUBDEV_CONN_COMPLEX_IQ; - return; - - case SUBDEV_PROP_ENABLED: - val = self_base->_tx_enabled; - return; - - case SUBDEV_PROP_USE_LO_OFFSET: - val = false; - return; - - case SUBDEV_PROP_SENSOR: - UHD_ASSERT_THROW(key.name == "lo_locked"); - val = sensor_value_t("LO", self_base->get_locked(dboard_iface::UNIT_TX), "locked", "unlocked"); - return; - - case SUBDEV_PROP_SENSOR_NAMES: - val = prop_names_t(1, "lo_locked"); - return; - - case SUBDEV_PROP_BANDWIDTH: - val = 2*20.0e6; //20MHz low-pass, we want complex double-sided - return; - - default: UHD_THROW_PROP_GET_ERROR(); - } -} - diff --git a/host/lib/usrp/dboard/db_wbx_version4.cpp b/host/lib/usrp/dboard/db_wbx_version4.cpp index b5104c9f1..981e4f4d2 100644 --- a/host/lib/usrp/dboard/db_wbx_version4.cpp +++ b/host/lib/usrp/dboard/db_wbx_version4.cpp @@ -37,7 +37,7 @@ using namespace boost::assign; /*********************************************************************** * WBX Version 3 Constants **********************************************************************/ -static const uhd::dict wbx_v4_gain_ranges = map_list_of +static const uhd::dict wbx_v4_tx_gain_ranges = map_list_of ("PGA0", gain_range_t(0, 31, 1.0)) ; @@ -49,10 +49,10 @@ static const freq_range_t wbx_v4_freq_range(50.0e6, 2.2e9); **********************************************************************/ static int tx_pga0_gain_to_iobits(double &gain){ //clip the input - gain = wbx_v4_gain_ranges["PGA0"].clip(gain); + gain = wbx_v4_tx_gain_ranges["PGA0"].clip(gain); //convert to attenuation - double attn = wbx_v4_gain_ranges["PGA0"].stop() - gain; + double attn = wbx_v4_tx_gain_ranges["PGA0"].stop() - gain; //calculate the attenuation int attn_code = boost::math::iround(attn); @@ -69,7 +69,7 @@ static int tx_pga0_gain_to_iobits(double &gain){ ) % attn % attn_code % (iobits & TX_ATTN_MASK) % TX_ATTN_MASK << std::endl; //the actual gain setting - gain = wbx_v4_gain_ranges["PGA0"].stop() - double(attn_code); + gain = wbx_v4_tx_gain_ranges["PGA0"].stop() - double(attn_code); return iobits; } @@ -82,9 +82,33 @@ wbx_base::wbx_version4::wbx_version4(wbx_base *_self_wbx_base) { //register our handle on the primary wbx_base instance self_base = _self_wbx_base; - //enable the clocks that we need - self_base->get_iface()->set_clock_enabled(dboard_iface::UNIT_TX, true); - self_base->get_iface()->set_clock_enabled(dboard_iface::UNIT_RX, true); + //////////////////////////////////////////////////////////////////// + // Register RX properties + //////////////////////////////////////////////////////////////////// + this->get_rx_subtree()->create("name").set("WBX RX v4"); + this->get_rx_subtree()->create("freq/value") + .coerce(boost::bind(&wbx_base::wbx_version4::set_lo_freq, this, dboard_iface::UNIT_RX, _1)) + .set((wbx_v4_freq_range.start() + wbx_v4_freq_range.stop())/2.0); + this->get_rx_subtree()->create("freq/range").set(wbx_v4_freq_range); + + //////////////////////////////////////////////////////////////////// + // Register TX properties + //////////////////////////////////////////////////////////////////// + this->get_tx_subtree()->create("name").set("WBX TX v4"); + BOOST_FOREACH(const std::string &name, wbx_v4_tx_gain_ranges.keys()){ + self_base->get_tx_subtree()->create("gains/"+name+"/value") + .coerce(boost::bind(&wbx_base::wbx_version4::set_tx_gain, this, _1, name)) + .set(wbx_v4_tx_gain_ranges[name].start()); + self_base->get_tx_subtree()->create("gains/"+name+"/range") + .set(wbx_v4_tx_gain_ranges[name]); + } + this->get_rx_subtree()->create("freq/value") + .coerce(boost::bind(&wbx_base::wbx_version4::set_lo_freq, this, dboard_iface::UNIT_TX, _1)) + .set((wbx_v4_freq_range.start() + wbx_v4_freq_range.stop())/2.0); + this->get_tx_subtree()->create("freq/range").set(wbx_v4_freq_range); + this->get_tx_subtree()->create("enabled") + .subscribe(boost::bind(&wbx_base::wbx_version4::set_tx_enabled, this, _1)) + .set(true); //start enabled //set attenuator control bits int v4_iobits = TX_ATTN_MASK; @@ -106,18 +130,6 @@ wbx_base::wbx_version4::wbx_version4(wbx_base *_self_wbx_base) { self_base->get_iface()->set_atr_reg(dboard_iface::UNIT_RX, dboard_iface::ATR_REG_TX_ONLY, RX_MIXER_ENB, RX_MIXER_DIS | RX_MIXER_ENB); self_base->get_iface()->set_atr_reg(dboard_iface::UNIT_RX, dboard_iface::ATR_REG_RX_ONLY, RX_MIXER_ENB, RX_MIXER_DIS | RX_MIXER_ENB); self_base->get_iface()->set_atr_reg(dboard_iface::UNIT_RX, dboard_iface::ATR_REG_FULL_DUPLEX, RX_MIXER_ENB, RX_MIXER_DIS | RX_MIXER_ENB); - - //set some default values - BOOST_FOREACH(const std::string &name, wbx_v4_gain_ranges.keys()){ - set_tx_gain(wbx_v4_gain_ranges[name].start(), name); - } - - BOOST_FOREACH(const std::string &name, wbx_rx_gain_ranges.keys()){ - self_base->set_rx_gain(wbx_rx_gain_ranges[name].start(), name); - } - - self_base->set_rx_enabled(false); - set_tx_enabled(false); } wbx_base::wbx_version4::~wbx_version4(void){ @@ -137,8 +149,8 @@ void wbx_base::wbx_version4::set_tx_enabled(bool enb) { /*********************************************************************** * Gain Handling **********************************************************************/ -void wbx_base::wbx_version4::set_tx_gain(double gain, const std::string &name) { - assert_has(wbx_v4_gain_ranges.keys(), name, "wbx tx gain name"); +double wbx_base::wbx_version4::set_tx_gain(double gain, const std::string &name) { + assert_has(wbx_v4_tx_gain_ranges.keys(), name, "wbx tx gain name"); if(name == "PGA0"){ boost::uint16_t io_bits = tx_pga0_gain_to_iobits(gain); self_base->_tx_gains[name] = gain; @@ -147,16 +159,13 @@ void wbx_base::wbx_version4::set_tx_gain(double gain, const std::string &name) { self_base->get_iface()->set_gpio_out(dboard_iface::UNIT_TX, io_bits, TX_ATTN_MASK); } else UHD_THROW_INVALID_CODE_PATH(); + return self_base->_tx_gains[name]; } /*********************************************************************** * Tuning **********************************************************************/ -freq_range_t wbx_base::wbx_version4::get_freq_range(void) { - return wbx_v4_freq_range; -} - double wbx_base::wbx_version4::set_lo_freq(dboard_iface::unit_t unit, double target_freq) { UHD_LOGV(often) << boost::format( "WBX tune: target frequency %f Mhz" @@ -257,8 +266,8 @@ double wbx_base::wbx_version4::set_lo_freq(dboard_iface::unit_t unit, double tar UHD_LOGV(often) << boost::format("WBX Intermediates: ref=%0.2f, outdiv=%f, fbdiv=%f") % (ref_freq*(1+int(D))/(R*(1+int(T)))) % double(RFdiv*2) % double(N + double(FRAC)/double(MOD)) << std::endl - << boost::format("WBX tune: R=%d, BS=%d, N=%d, FRAC=%d, MOD=%d, T=%d, D=%d, RFdiv=%d, LD=%d" - ) % R % BS % N % FRAC % MOD % T % D % RFdiv % self_base->get_locked(unit)<< std::endl + << boost::format("WBX tune: R=%d, BS=%d, N=%d, FRAC=%d, MOD=%d, T=%d, D=%d, RFdiv=%d, LD=%s" + ) % R % BS % N % FRAC % MOD % T % D % RFdiv % self_base->get_locked(unit).to_pp_string() << std::endl << boost::format("WBX Frequencies (MHz): REQ=%0.2f, ACT=%0.2f, VCO=%0.2f, PFD=%0.2f, BAND=%0.2f" ) % (target_freq/1e6) % (actual_freq/1e6) % (vco_freq/1e6) % (pfd_freq/1e6) % (pfd_freq/BS/1e6) << std::endl; @@ -325,80 +334,3 @@ double wbx_base::wbx_version4::set_lo_freq(dboard_iface::unit_t unit, double tar ) % (actual_freq/1e6) << std::endl; return actual_freq; } - - -/*********************************************************************** - * TX Get and Set - **********************************************************************/ -void wbx_base::wbx_version4::tx_get(const wax::obj &key_, wax::obj &val){ - named_prop_t key = named_prop_t::extract(key_); - - //handle the get request conditioned on the key - switch(key.as()){ - case SUBDEV_PROP_NAME: - val = self_base->get_tx_id().to_pp_string(); - return; - - case SUBDEV_PROP_OTHERS: - val = prop_names_t(); //empty - return; - - case SUBDEV_PROP_GAIN: - assert_has(self_base->_tx_gains.keys(), key.name, "wbx tx gain name"); - val = self_base->_tx_gains[key.name]; - return; - - case SUBDEV_PROP_GAIN_RANGE: - assert_has(wbx_v4_gain_ranges.keys(), key.name, "wbx tx gain name"); - val = wbx_v4_gain_ranges[key.name]; - return; - - case SUBDEV_PROP_GAIN_NAMES: - val = prop_names_t(wbx_v4_gain_ranges.keys()); - return; - - case SUBDEV_PROP_FREQ: - val = 0.0; - return; - - case SUBDEV_PROP_FREQ_RANGE: - val = freq_range_t(0.0, 0.0, 0.0); - return; - - case SUBDEV_PROP_ANTENNA: - val = std::string(""); - return; - - case SUBDEV_PROP_ANTENNA_NAMES: - val = prop_names_t(1, ""); - return; - - case SUBDEV_PROP_CONNECTION: - val = SUBDEV_CONN_COMPLEX_IQ; - return; - - case SUBDEV_PROP_ENABLED: - val = self_base->_tx_enabled; - return; - - case SUBDEV_PROP_USE_LO_OFFSET: - val = false; - return; - - case SUBDEV_PROP_SENSOR: - UHD_ASSERT_THROW(key.name == "lo_locked"); - val = sensor_value_t("LO", self_base->get_locked(dboard_iface::UNIT_TX), "locked", "unlocked"); - return; - - case SUBDEV_PROP_SENSOR_NAMES: - val = prop_names_t(1, "lo_locked"); - return; - - case SUBDEV_PROP_BANDWIDTH: - val = 2*20.0e6; //20MHz low-pass, we want complex double-sided - return; - - default: UHD_THROW_PROP_GET_ERROR(); - } -} - -- cgit v1.2.3 From 45d7e5105e393a7c62bb2df40521fccb834e0110 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Wed, 26 Oct 2011 18:18:56 -0700 Subject: wbx: fixed typo because it should tx --- host/lib/usrp/dboard/db_wbx_version2.cpp | 2 +- host/lib/usrp/dboard/db_wbx_version3.cpp | 2 +- host/lib/usrp/dboard/db_wbx_version4.cpp | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) (limited to 'host') diff --git a/host/lib/usrp/dboard/db_wbx_version2.cpp b/host/lib/usrp/dboard/db_wbx_version2.cpp index d8a2b7e93..e25cb2e4c 100644 --- a/host/lib/usrp/dboard/db_wbx_version2.cpp +++ b/host/lib/usrp/dboard/db_wbx_version2.cpp @@ -95,7 +95,7 @@ wbx_base::wbx_version2::wbx_version2(wbx_base *_self_wbx_base) { self_base->get_tx_subtree()->create("gains/"+name+"/range") .set(wbx_v2_tx_gain_ranges[name]); } - this->get_rx_subtree()->create("freq/value") + this->get_tx_subtree()->create("freq/value") .coerce(boost::bind(&wbx_base::wbx_version2::set_lo_freq, this, dboard_iface::UNIT_TX, _1)) .set((wbx_v2_freq_range.start() + wbx_v2_freq_range.stop())/2.0); this->get_tx_subtree()->create("freq/range").set(wbx_v2_freq_range); diff --git a/host/lib/usrp/dboard/db_wbx_version3.cpp b/host/lib/usrp/dboard/db_wbx_version3.cpp index 4473bf1ae..70981ce94 100644 --- a/host/lib/usrp/dboard/db_wbx_version3.cpp +++ b/host/lib/usrp/dboard/db_wbx_version3.cpp @@ -101,7 +101,7 @@ wbx_base::wbx_version3::wbx_version3(wbx_base *_self_wbx_base) { self_base->get_tx_subtree()->create("gains/"+name+"/range") .set(wbx_v3_tx_gain_ranges[name]); } - this->get_rx_subtree()->create("freq/value") + this->get_tx_subtree()->create("freq/value") .coerce(boost::bind(&wbx_base::wbx_version3::set_lo_freq, this, dboard_iface::UNIT_TX, _1)) .set((wbx_v3_freq_range.start() + wbx_v3_freq_range.stop())/2.0); this->get_tx_subtree()->create("freq/range").set(wbx_v3_freq_range); diff --git a/host/lib/usrp/dboard/db_wbx_version4.cpp b/host/lib/usrp/dboard/db_wbx_version4.cpp index 981e4f4d2..faaf9e3fd 100644 --- a/host/lib/usrp/dboard/db_wbx_version4.cpp +++ b/host/lib/usrp/dboard/db_wbx_version4.cpp @@ -102,7 +102,7 @@ wbx_base::wbx_version4::wbx_version4(wbx_base *_self_wbx_base) { self_base->get_tx_subtree()->create("gains/"+name+"/range") .set(wbx_v4_tx_gain_ranges[name]); } - this->get_rx_subtree()->create("freq/value") + this->get_tx_subtree()->create("freq/value") .coerce(boost::bind(&wbx_base::wbx_version4::set_lo_freq, this, dboard_iface::UNIT_TX, _1)) .set((wbx_v4_freq_range.start() + wbx_v4_freq_range.stop())/2.0); this->get_tx_subtree()->create("freq/range").set(wbx_v4_freq_range); -- cgit v1.2.3 From f13e6effb973bcd35896f58af952f6192faae252 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Mon, 7 Nov 2011 14:34:20 -0800 Subject: uhd: bumped version number for next branch work --- host/cmake/Modules/UHDVersion.cmake | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'host') diff --git a/host/cmake/Modules/UHDVersion.cmake b/host/cmake/Modules/UHDVersion.cmake index 2aca64891..adc653d87 100644 --- a/host/cmake/Modules/UHDVersion.cmake +++ b/host/cmake/Modules/UHDVersion.cmake @@ -26,8 +26,8 @@ FIND_PACKAGE(Git QUIET) # - increment patch on for bug fixes and docs ######################################################################## SET(UHD_VERSION_MAJOR 003) -SET(UHD_VERSION_MINOR 003) -SET(UHD_VERSION_PATCH 001) +SET(UHD_VERSION_MINOR 004) +SET(UHD_VERSION_PATCH 000) ######################################################################## # Version information discovery through git log -- cgit v1.2.3 From 7c503ad1fab5fd6218847b1d030881b4d048379f Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Mon, 7 Nov 2011 14:34:40 -0800 Subject: uhd: modify examples to use new time/clock source API --- host/examples/rx_ascii_art_dft.cpp | 15 ++------------- host/examples/rx_multi_samples.cpp | 7 +++---- host/examples/rx_samples_to_file.cpp | 15 ++------------- host/examples/rx_samples_to_udp.cpp | 15 ++------------- host/examples/tx_samples_from_file.cpp | 15 ++------------- host/examples/tx_waveforms.cpp | 15 ++------------- 6 files changed, 13 insertions(+), 69 deletions(-) (limited to 'host') diff --git a/host/examples/rx_ascii_art_dft.cpp b/host/examples/rx_ascii_art_dft.cpp index 2e5bbba9d..cba72472a 100644 --- a/host/examples/rx_ascii_art_dft.cpp +++ b/host/examples/rx_ascii_art_dft.cpp @@ -54,7 +54,7 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){ ("frame-rate", po::value(&frame_rate)->default_value(5), "frame rate of the display (fps)") ("ref-lvl", po::value(&ref_lvl)->default_value(0), "reference level for the display (dB)") ("dyn-rng", po::value(&dyn_rng)->default_value(60), "dynamic range for the display (dB)") - ("ref", po::value(&ref)->default_value("INTERNAL"), "waveform type (INTERNAL, EXTERNAL, MIMO)") + ("ref", po::value(&ref)->default_value("internal"), "waveform type (internal, external, mimo)") ; po::variables_map vm; po::store(po::parse_command_line(argc, argv, desc), vm); @@ -72,18 +72,7 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){ uhd::usrp::multi_usrp::sptr usrp = uhd::usrp::multi_usrp::make(args); //Lock mboard clocks - if (ref == "MIMO") { - uhd::clock_config_t clock_config; - clock_config.ref_source = uhd::clock_config_t::REF_MIMO; - clock_config.pps_source = uhd::clock_config_t::PPS_MIMO; - usrp->set_clock_config(clock_config, 0); - } - else if (ref == "EXTERNAL") { - usrp->set_clock_config(uhd::clock_config_t::external(), 0); - } - else if (ref == "INTERNAL") { - usrp->set_clock_config(uhd::clock_config_t::internal(), 0); - } + usrp->set_clock_source(ref); //always select the subdevice first, the channel mapping affects the other settings if (vm.count("subdev")) usrp->set_rx_subdev_spec(subdev); diff --git a/host/examples/rx_multi_samples.cpp b/host/examples/rx_multi_samples.cpp index 7561f1285..42ef33d70 100644 --- a/host/examples/rx_multi_samples.cpp +++ b/host/examples/rx_multi_samples.cpp @@ -92,6 +92,7 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){ usrp->set_time_now(uhd::time_spec_t(0.0)); } else if (sync == "pps"){ + usrp->set_time_source("external"); usrp->set_time_unknown_pps(uhd::time_spec_t(0.0)); boost::this_thread::sleep(boost::posix_time::seconds(1)); //wait for pps sync pulse } @@ -99,10 +100,8 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){ UHD_ASSERT_THROW(usrp->get_num_mboards() == 2); //make mboard 1 a slave over the MIMO Cable - uhd::clock_config_t clock_config; - clock_config.ref_source = uhd::clock_config_t::REF_MIMO; - clock_config.pps_source = uhd::clock_config_t::PPS_MIMO; - usrp->set_clock_config(clock_config, 1); + usrp->set_clock_source("mimo", 1); + usrp->set_time_source("mimo", 1); //set time on the master (mboard 0) usrp->set_time_now(uhd::time_spec_t(0.0), 0); diff --git a/host/examples/rx_samples_to_file.cpp b/host/examples/rx_samples_to_file.cpp index 605439748..ed242b07a 100644 --- a/host/examples/rx_samples_to_file.cpp +++ b/host/examples/rx_samples_to_file.cpp @@ -99,7 +99,7 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){ ("ant", po::value(&ant), "daughterboard antenna selection") ("subdev", po::value(&subdev), "daughterboard subdevice specification") ("bw", po::value(&bw), "daughterboard IF filter bandwidth in Hz") - ("ref", po::value(&ref)->default_value("INTERNAL"), "waveform type (INTERNAL, EXTERNAL, MIMO)") + ("ref", po::value(&ref)->default_value("internal"), "waveform type (internal, external, mimo)") ; po::variables_map vm; po::store(po::parse_command_line(argc, argv, desc), vm); @@ -117,18 +117,7 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){ uhd::usrp::multi_usrp::sptr usrp = uhd::usrp::multi_usrp::make(args); //Lock mboard clocks - if (ref == "MIMO") { - uhd::clock_config_t clock_config; - clock_config.ref_source = uhd::clock_config_t::REF_MIMO; - clock_config.pps_source = uhd::clock_config_t::PPS_MIMO; - usrp->set_clock_config(clock_config, 0); - } - else if (ref == "EXTERNAL") { - usrp->set_clock_config(uhd::clock_config_t::external(), 0); - } - else if (ref == "INTERNAL") { - usrp->set_clock_config(uhd::clock_config_t::internal(), 0); - } + usrp->set_clock_source(ref); //always select the subdevice first, the channel mapping affects the other settings if (vm.count("subdev")) usrp->set_rx_subdev_spec(subdev); diff --git a/host/examples/rx_samples_to_udp.cpp b/host/examples/rx_samples_to_udp.cpp index cf7fd493a..c456f05c3 100644 --- a/host/examples/rx_samples_to_udp.cpp +++ b/host/examples/rx_samples_to_udp.cpp @@ -51,7 +51,7 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){ ("bw", po::value(&bw), "daughterboard IF filter bandwidth in Hz") ("port", po::value(&port)->default_value("7124"), "server udp port") ("addr", po::value(&addr)->default_value("192.168.1.10"), "resolvable server address") - ("ref", po::value(&ref)->default_value("INTERNAL"), "waveform type (INTERNAL, EXTERNAL, MIMO)") + ("ref", po::value(&ref)->default_value("internal"), "waveform type (internal, external, mimo)") ; po::variables_map vm; po::store(po::parse_command_line(argc, argv, desc), vm); @@ -70,18 +70,7 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){ std::cout << boost::format("Using Device: %s") % usrp->get_pp_string() << std::endl; //Lock mboard clocks - if (ref == "MIMO") { - uhd::clock_config_t clock_config; - clock_config.ref_source = uhd::clock_config_t::REF_MIMO; - clock_config.pps_source = uhd::clock_config_t::PPS_MIMO; - usrp->set_clock_config(clock_config, 0); - } - else if (ref == "EXTERNAL") { - usrp->set_clock_config(uhd::clock_config_t::external(), 0); - } - else if (ref == "INTERNAL") { - usrp->set_clock_config(uhd::clock_config_t::internal(), 0); - } + usrp->set_clock_source(ref); //set the rx sample rate std::cout << boost::format("Setting RX Rate: %f Msps...") % (rate/1e6) << std::endl; diff --git a/host/examples/tx_samples_from_file.cpp b/host/examples/tx_samples_from_file.cpp index 964c6cea8..8e3614f6c 100644 --- a/host/examples/tx_samples_from_file.cpp +++ b/host/examples/tx_samples_from_file.cpp @@ -79,7 +79,7 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){ ("ant", po::value(&ant), "daughterboard antenna selection") ("subdev", po::value(&subdev), "daughterboard subdevice specification") ("bw", po::value(&bw), "daughterboard IF filter bandwidth in Hz") - ("ref", po::value(&ref)->default_value("INTERNAL"), "waveform type (INTERNAL, EXTERNAL, MIMO)") + ("ref", po::value(&ref)->default_value("internal"), "waveform type (internal, external, mimo)") ; po::variables_map vm; po::store(po::parse_command_line(argc, argv, desc), vm); @@ -97,18 +97,7 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){ uhd::usrp::multi_usrp::sptr usrp = uhd::usrp::multi_usrp::make(args); //Lock mboard clocks - if (ref == "MIMO") { - uhd::clock_config_t clock_config; - clock_config.ref_source = uhd::clock_config_t::REF_MIMO; - clock_config.pps_source = uhd::clock_config_t::PPS_MIMO; - usrp->set_clock_config(clock_config, 0); - } - else if (ref == "EXTERNAL") { - usrp->set_clock_config(uhd::clock_config_t::external(), 0); - } - else if (ref == "INTERNAL") { - usrp->set_clock_config(uhd::clock_config_t::internal(), 0); - } + usrp->set_clock_source(ref); //always select the subdevice first, the channel mapping affects the other settings if (vm.count("subdev")) usrp->set_tx_subdev_spec(subdev); diff --git a/host/examples/tx_waveforms.cpp b/host/examples/tx_waveforms.cpp index 4abca5dae..5b17e0595 100644 --- a/host/examples/tx_waveforms.cpp +++ b/host/examples/tx_waveforms.cpp @@ -110,7 +110,7 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){ ("bw", po::value(&bw), "daughterboard IF filter bandwidth in Hz") ("wave-type", po::value(&wave_type)->default_value("CONST"), "waveform type (CONST, SQUARE, RAMP, SINE)") ("wave-freq", po::value(&wave_freq)->default_value(0), "waveform frequency in Hz") - ("ref", po::value(&ref)->default_value("INTERNAL"), "waveform type (INTERNAL, EXTERNAL, MIMO)") + ("ref", po::value(&ref)->default_value("internal"), "waveform type (internal, external, mimo)") ; po::variables_map vm; po::store(po::parse_command_line(argc, argv, desc), vm); @@ -128,18 +128,7 @@ int UHD_SAFE_MAIN(int argc, char *argv[]){ uhd::usrp::multi_usrp::sptr usrp = uhd::usrp::multi_usrp::make(args); //Lock mboard clocks - if (ref == "MIMO") { - uhd::clock_config_t clock_config; - clock_config.ref_source = uhd::clock_config_t::REF_MIMO; - clock_config.pps_source = uhd::clock_config_t::PPS_MIMO; - usrp->set_clock_config(clock_config, 0); - } - else if (ref == "EXTERNAL") { - usrp->set_clock_config(uhd::clock_config_t::external(), 0); - } - else if (ref == "INTERNAL") { - usrp->set_clock_config(uhd::clock_config_t::internal(), 0); - } + usrp->set_clock_source(ref); //always select the subdevice first, the channel mapping affects the other settings if (vm.count("subdev")) usrp->set_tx_subdev_spec(subdev); -- cgit v1.2.3 From f1434d7c52728cbf80e954b4c9414a94eec4c9ce Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Mon, 7 Nov 2011 15:10:19 -0800 Subject: usrp2: fix channel mapping calculation --- host/lib/usrp/usrp2/io_impl.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'host') diff --git a/host/lib/usrp/usrp2/io_impl.cpp b/host/lib/usrp/usrp2/io_impl.cpp index d144c08bf..8018875ec 100644 --- a/host/lib/usrp/usrp2/io_impl.cpp +++ b/host/lib/usrp/usrp2/io_impl.cpp @@ -405,7 +405,7 @@ rx_streamer::sptr usrp2_impl::get_rx_stream(const uhd::stream_args_t &args_){ BOOST_FOREACH(const std::string &mb, _mbc.keys()){ num_chan_so_far += _mbc[mb].rx_chan_occ; if (chan < num_chan_so_far){ - const size_t dsp = num_chan_so_far - chan - 1; + const size_t dsp = chan + _mbc[mb].rx_chan_occ - num_chan_so_far; _mbc[mb].rx_dsps[dsp]->set_nsamps_per_packet(spp); //seems to be a good place to set this _mbc[mb].rx_dsps[dsp]->set_format(args.otw_format, sc8_scalar); my_streamer->set_xport_chan_get_buff(chan_i, boost::bind( @@ -473,7 +473,7 @@ tx_streamer::sptr usrp2_impl::get_tx_stream(const uhd::stream_args_t &args_){ BOOST_FOREACH(const std::string &mb, _mbc.keys()){ num_chan_so_far += _mbc[mb].tx_chan_occ; if (chan < num_chan_so_far){ - const size_t dsp = num_chan_so_far - chan - 1; + const size_t dsp = chan + _mbc[mb].tx_chan_occ - num_chan_so_far; my_streamer->set_xport_chan_get_buff(chan_i, boost::bind( &usrp2_impl::io_impl::get_send_buff, _io_impl.get(), abs, _1 )); -- cgit v1.2.3 From d28e3ac765273d7684386c1985802000d22eeea6 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Mon, 7 Nov 2011 16:34:13 -0800 Subject: uhd: dont pass 0 sample buffs to converter (avoid segfaults) --- host/lib/convert/gen_convert_general.py | 1 - host/lib/transport/super_recv_packet_handler.hpp | 4 +++- host/lib/transport/super_send_packet_handler.hpp | 4 +++- 3 files changed, 6 insertions(+), 3 deletions(-) (limited to 'host') diff --git a/host/lib/convert/gen_convert_general.py b/host/lib/convert/gen_convert_general.py index eafb145e6..52b4212b4 100644 --- a/host/lib/convert/gen_convert_general.py +++ b/host/lib/convert/gen_convert_general.py @@ -72,7 +72,6 @@ DECLARE_CONVERTER(sc16_item32_$(end), 1, $(cpu_type), 1, PRIORITY_GENERAL){ } DECLARE_CONVERTER(sc8_item32_$(end), 1, $(cpu_type), 1, PRIORITY_GENERAL){ - if (nsamps == 0) return; //otherwise segfault const item32_t *input = reinterpret_cast(size_t(inputs[0]) & ~0x3); $(cpu_type)_t *output = reinterpret_cast<$(cpu_type)_t *>(outputs[0]); $(cpu_type)_t dummy; diff --git a/host/lib/transport/super_recv_packet_handler.hpp b/host/lib/transport/super_recv_packet_handler.hpp index 48b0acdb9..57aae96b1 100644 --- a/host/lib/transport/super_recv_packet_handler.hpp +++ b/host/lib/transport/super_recv_packet_handler.hpp @@ -523,7 +523,9 @@ private: } //copy-convert the samples from the recv buffer - _converter(buff_info.copy_buff, _io_buffs, nsamps_to_copy_per_io_buff, _scale_factor); + if (nsamps_to_copy_per_io_buff != 0) _converter( + buff_info.copy_buff, _io_buffs, nsamps_to_copy_per_io_buff, _scale_factor + ); //update the rx copy buffer to reflect the bytes copied buff_info.copy_buff += bytes_to_copy; diff --git a/host/lib/transport/super_send_packet_handler.hpp b/host/lib/transport/super_send_packet_handler.hpp index 5696b5d39..c3ffcc861 100644 --- a/host/lib/transport/super_send_packet_handler.hpp +++ b/host/lib/transport/super_send_packet_handler.hpp @@ -239,7 +239,9 @@ private: otw_mem += if_packet_info.num_header_words32; //copy-convert the samples into the send buffer - _converter(_io_buffs, otw_mem, nsamps_per_buff, _scale_factor); + if (nsamps_per_buff != 0) _converter( + _io_buffs, otw_mem, nsamps_per_buff, _scale_factor + ); //commit the samples to the zero-copy interface size_t num_bytes_total = (_header_offset_words32+if_packet_info.num_packet_words32)*sizeof(boost::uint32_t); -- cgit v1.2.3 From 9d4350d74ea926999780ded0016c5ad51874ebec Mon Sep 17 00:00:00 2001 From: Jason Abele Date: Mon, 7 Nov 2011 15:28:16 -0800 Subject: Updated typos in XCVR2450 dboard property tree code --- host/lib/usrp/dboard/db_xcvr2450.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'host') diff --git a/host/lib/usrp/dboard/db_xcvr2450.cpp b/host/lib/usrp/dboard/db_xcvr2450.cpp index bdc6aa9fe..cf1637335 100644 --- a/host/lib/usrp/dboard/db_xcvr2450.cpp +++ b/host/lib/usrp/dboard/db_xcvr2450.cpp @@ -269,12 +269,12 @@ xcvr2450::xcvr2450(ctor_args_t args) : xcvr_dboard_base(args){ .set(get_tx_id().to_pp_string()); this->get_tx_subtree()->create("sensors/lo_locked") .publish(boost::bind(&xcvr2450::get_locked, this)); - BOOST_FOREACH(const std::string &name, xcvr_rx_gain_ranges.keys()){ - this->get_rx_subtree()->create("gains/"+name+"/value") - .coerce(boost::bind(&xcvr2450::set_rx_gain, this, _1, name)) - .set(xcvr_rx_gain_ranges[name].start()); - this->get_rx_subtree()->create("gains/"+name+"/range") - .set(xcvr_rx_gain_ranges[name]); + BOOST_FOREACH(const std::string &name, xcvr_tx_gain_ranges.keys()){ + this->get_tx_subtree()->create("gains/"+name+"/value") + .coerce(boost::bind(&xcvr2450::set_tx_gain, this, _1, name)) + .set(xcvr_tx_gain_ranges[name].start()); + this->get_tx_subtree()->create("gains/"+name+"/range") + .set(xcvr_tx_gain_ranges[name]); } this->get_tx_subtree()->create("freq/value") .coerce(boost::bind(&xcvr2450::set_lo_freq, this, _1)) -- cgit v1.2.3 From 902818f50bbd486138a7d4cd2ce9ba3661f4a732 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Mon, 7 Nov 2011 16:53:47 -0800 Subject: uhd: removed wax and props utils --- host/include/uhd/CMakeLists.txt | 1 - host/include/uhd/deprecated.hpp | 170 --------------------------------- host/include/uhd/utils/CMakeLists.txt | 1 - host/include/uhd/utils/props.hpp | 81 ---------------- host/include/uhd/wax.hpp | 2 - host/lib/deprecated.cpp | 152 ----------------------------- host/lib/usrp/dboard/db_wbx_common.hpp | 1 - host/lib/usrp/dboard/db_wbx_simple.cpp | 4 +- host/lib/usrp/gps_ctrl.cpp | 3 +- host/lib/utils/CMakeLists.txt | 1 - host/lib/utils/props.cpp | 40 -------- 11 files changed, 3 insertions(+), 453 deletions(-) delete mode 100644 host/include/uhd/utils/props.hpp delete mode 100644 host/include/uhd/wax.hpp delete mode 100644 host/lib/utils/props.cpp (limited to 'host') diff --git a/host/include/uhd/CMakeLists.txt b/host/include/uhd/CMakeLists.txt index 2b0c6ec14..1df04d577 100644 --- a/host/include/uhd/CMakeLists.txt +++ b/host/include/uhd/CMakeLists.txt @@ -32,7 +32,6 @@ INSTALL(FILES property_tree.hpp stream.hpp version.hpp - wax.hpp DESTINATION ${INCLUDE_DIR}/uhd COMPONENT headers ) diff --git a/host/include/uhd/deprecated.hpp b/host/include/uhd/deprecated.hpp index d918836f1..95cce58e9 100644 --- a/host/include/uhd/deprecated.hpp +++ b/host/include/uhd/deprecated.hpp @@ -2,176 +2,6 @@ //-- deprecated interfaces below, to be removed when the API is changed //---------------------------------------------------------------------- -// -// 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_WAX_HPP -#define INCLUDED_WAX_HPP - -#include -#include -#include -#include -#include - -/*! - * WAX - it's a metaphor! - * - * The WAX framework allows an object to have generic/anyobj properties. - * These properties can be addressed through generic/anyobj identifiers. - * - * The WAX object itself is an anytype container much like boost::any. - * To retrieve the value of the appropriate type, use my_obj.as(). - * - * Proprties may be referenced though the [] overloaded operator. - * The [] operator returns a special proxy that allows for assigment. - * Also, the [] operators may be chained as in the folowing examples: - * my_obj[prop1][prop2][prop3] = value; - * value = my_obj[prop1][prop2][prop3].as(); - * - * Property nesting occurs when a WAX object gets another object's link. - * This special link is obtained through a call to my_obj.get_link(). - * - * Note: Do not put a class derived from wax::obj into an stl container. - * MSVC will compile the code, but the binaries will crash at runtime. - * Rather, use pointers or smart pointers to instances of the derived class. - */ - -namespace wax{ - - /*! - * WAX object base class: - * - * A wax obj has two major purposes: - * 1) to act as a polymorphic container, just like boost any - * 2) to provide a nested set/get properties interface - * - * Internally, the polymorphic container is handled by a boost any. - * For properties, a subclass should override the set and get methods. - * For property nesting, wax obj subclasses return special links - * to other wax obj subclasses, and the api handles the magic. - */ - class UHD_API obj{ - public: - - /*! - * Default constructor: - * The contents will be empty. - */ - obj(void); - - /*! - * Copy constructor: - * The contents will be cloned. - * \param o another wax::obj - */ - obj(const obj &o); - - /*! - * Templated any type constructor: - * The contents can be anything. - * Uses the boost::any to handle the magic. - * \param o an object of any type - */ - template obj(const T &o){ - _contents = o; - } - - /*! - * Destructor. - */ - virtual ~obj(void); - - /*! - * The chaining operator: - * This operator allows access objs with properties. - * A call to the [] operator will return a new proxy obj. - * The proxy object is an obj with special proxy contents. - * Assignment and casting can be used on this special object - * to access the property referenced by the obj key. - * \param key a key to identify a property within this obj - * \return a special wax obj that proxies the obj and key - */ - obj operator[](const obj &key); - - /*! - * The assignment operator: - * This operator allows for assignment of new contents. - * In the special case where this obj contains a proxy, - * the value will be set to the proxy's property reference. - * \param val the new value to assign to the wax obj - * \return a reference to this obj (*this) - */ - obj & operator=(const obj &val); - - /*! - * Get a link in the chain: - * When a wax obj returns another wax obj as part of a get call, - * the return value should be set to the result of this method. - * Doing so will ensure chain-ability of the returned object. - * \return an obj containing a valid link to a wax obj - */ - obj get_link(void) const; - - /*! - * Get the type of the contents of this obj. - * \return a reference to the type_info - */ - const std::type_info & type(void) const; - - /*! - * Cast this obj into the desired type. - * Usage: myobj.as() - * - * \return an object of the desired type - * \throw wax::bad_cast when the cast fails - */ - template T as(void) const{ - try{ - return boost::any_cast(resolve()); - } - catch(const boost::bad_any_cast &e){ - throw uhd::type_error(std::string("") + "Cannot wax cast " + type().name() + " to " + typeid(T).name() + " " + e.what()); - } - } - - private: - //private interface (override in subclasses) - virtual void get(const obj &, obj &); - virtual void set(const obj &, const obj &); - - /*! - * Resolve the contents of this obj. - * In the case where this obj is a proxy, - * the referenced property will be resolved. - * Otherwise, just get the private contents. - * \return a boost any type with contents - */ - boost::any resolve(void) const; - - //private contents of this obj - boost::any _contents; - - }; - -} //namespace wax - -#endif /* INCLUDED_WAX_HPP */ - // // Copyright 2010 Ettus Research LLC // diff --git a/host/include/uhd/utils/CMakeLists.txt b/host/include/uhd/utils/CMakeLists.txt index 0bf98fb67..48b8db885 100644 --- a/host/include/uhd/utils/CMakeLists.txt +++ b/host/include/uhd/utils/CMakeLists.txt @@ -26,7 +26,6 @@ INSTALL(FILES log.hpp msg.hpp pimpl.hpp - props.hpp safe_call.hpp safe_main.hpp static.hpp diff --git a/host/include/uhd/utils/props.hpp b/host/include/uhd/utils/props.hpp deleted file mode 100644 index 81737423a..000000000 --- a/host/include/uhd/utils/props.hpp +++ /dev/null @@ -1,81 +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 . -// - -#ifndef INCLUDED_UHD_UTILS_PROPS_HPP -#define INCLUDED_UHD_UTILS_PROPS_HPP - -#include -#include -#include -#include -#include - -namespace uhd{ - - //! The type for a vector of property names - typedef std::vector prop_names_t; - - /*! - * A named prop struct holds a key and a name. - * Allows properties to be sub-sectioned by name. - */ - struct UHD_API named_prop_t{ - const wax::obj key; - const std::string name; - - //! Convert the key to the specified type - template inline T as(void){ - return key.as(); - } - - /*! - * Utility function to convert generic key into a named prop. - * If the key was already a named prop, the prop will be split. - * Otherwise, the key will be the key, and the name will be used. - * \param key a reference to the prop object - * \param name a reference to the name object - * \return a named property struct with key and name - */ - static named_prop_t extract( - const wax::obj &key, const std::string &name = "" - ); - - /*! - * Create a new named prop from key and name. - * \param key the property key - * \param name the string name - */ - named_prop_t(const wax::obj &key, const std::string &name); - }; - - /*! - * Throw when getting a not-implemented or write-only property. - * Throw-site information will be included with this error. - */ - #define UHD_THROW_PROP_GET_ERROR() \ - throw uhd::key_error(UHD_THROW_SITE_INFO("cannot get this property")) - - /*! - * Throw when setting a not-implemented or read-only property. - * Throw-site information will be included with this error. - */ - #define UHD_THROW_PROP_SET_ERROR() \ - throw uhd::key_error(UHD_THROW_SITE_INFO("cannot set this property")) - -} //namespace uhd - -#endif /* INCLUDED_UHD_UTILS_PROPS_HPP */ diff --git a/host/include/uhd/wax.hpp b/host/include/uhd/wax.hpp deleted file mode 100644 index a55e5465d..000000000 --- a/host/include/uhd/wax.hpp +++ /dev/null @@ -1,2 +0,0 @@ -//The wax API has been deprecated in favor of the properties interface -#include diff --git a/host/lib/deprecated.cpp b/host/lib/deprecated.cpp index b659d1be5..0fc751eeb 100644 --- a/host/lib/deprecated.cpp +++ b/host/lib/deprecated.cpp @@ -2,158 +2,6 @@ //-- deprecated interfaces below, to be removed when the API is changed //---------------------------------------------------------------------- -// -// 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 - -/*! - * The link args for internal use within this cpp file: - * - * It contains a link (in this case a pointer) to a wax object. - * Only the methods in this file may create or parse link args. - * The get_link method is the creator of a link args object. - * The [] operator will resolve the link and make the [] call. - * - * TODO: register the link args with the wax obj that it links to. - * That way, if the obj destructs, the link can be invalidated. - * The operator() will throw, rather than dereferencing bad memory. - */ -class link_args_t{ -public: - link_args_t(const wax::obj *obj_ptr) : _obj_ptr(obj_ptr){ - /* NOP */ - } - wax::obj & operator()(void) const{ - //recursively resolve link args to get at original pointer - if (_obj_ptr->type() == typeid(link_args_t)){ - return _obj_ptr->as()(); - } - return *const_cast(_obj_ptr); - } -private: - const wax::obj *_obj_ptr; -}; - -/*! - * The proxy args for internal use within this cpp file: - * - * It contains a link and a key for setting/getting a property. - * Only the methods in this file may create or parse proxy args. - * Class methods have special handling for the case when the - * wax obj contains an instance of the proxy args. - */ -class proxy_args_t{ -public: - proxy_args_t(const wax::obj *obj_ptr, const wax::obj &key) : _key(key){ - _obj_link = obj_ptr->get_link(); - } - wax::obj & operator()(void) const{ - return _obj_link.as()(); - } - const wax::obj & key(void) const{ - return _key; - } -private: - wax::obj _obj_link; - const wax::obj _key; -}; - -/*********************************************************************** - * Structors - **********************************************************************/ -wax::obj::obj(void){ - /* NOP */ -} - -wax::obj::obj(const obj &o){ - _contents = o._contents; -} - -wax::obj::~obj(void){ - /* NOP */ -} - -/*********************************************************************** - * Special Operators - **********************************************************************/ -wax::obj wax::obj::operator[](const obj &key){ - if (_contents.type() == typeid(proxy_args_t)){ - obj val = resolve(); - //check if its a special link and call - if (val.type() == typeid(link_args_t)){ - return val.as()()[key]; - } - //unknown obj - throw uhd::type_error("cannot use [] on non wax::obj link"); - } - else{ - return proxy_args_t(this, key); - } -} - -wax::obj & wax::obj::operator=(const obj &val){ - if (_contents.type() == typeid(proxy_args_t)){ - proxy_args_t proxy_args = boost::any_cast(_contents); - proxy_args().set(proxy_args.key(), val); - } - else{ - _contents = val._contents; - } - return *this; -} - -/*********************************************************************** - * Public Methods - **********************************************************************/ -wax::obj wax::obj::get_link(void) const{ - return link_args_t(this); -} - -const std::type_info & wax::obj::type(void) const{ - return resolve().type(); -} - -/*********************************************************************** - * Private Methods - **********************************************************************/ -boost::any wax::obj::resolve(void) const{ - if (_contents.type() == typeid(proxy_args_t)){ - obj val; - proxy_args_t proxy_args = boost::any_cast(_contents); - proxy_args().get(proxy_args.key(), val); - return val.resolve(); - } - else{ - return _contents; - } -} - -void wax::obj::get(const obj &, obj &){ - throw uhd::type_error("Cannot call get on wax obj base class"); -} - -void wax::obj::set(const obj &, const obj &){ - throw uhd::type_error("Cannot call set on wax obj base class"); -} - #include #include #include diff --git a/host/lib/usrp/dboard/db_wbx_common.hpp b/host/lib/usrp/dboard/db_wbx_common.hpp index 3e41e04b7..e7eb3f31a 100644 --- a/host/lib/usrp/dboard/db_wbx_common.hpp +++ b/host/lib/usrp/dboard/db_wbx_common.hpp @@ -69,7 +69,6 @@ #include #include #include -#include #include #include #include diff --git a/host/lib/usrp/dboard/db_wbx_simple.cpp b/host/lib/usrp/dboard/db_wbx_simple.cpp index 1ac2a1704..f46ea70d1 100644 --- a/host/lib/usrp/dboard/db_wbx_simple.cpp +++ b/host/lib/usrp/dboard/db_wbx_simple.cpp @@ -36,9 +36,9 @@ using namespace boost::assign; /*********************************************************************** * The WBX Simple dboard constants **********************************************************************/ -static const prop_names_t wbx_tx_antennas = list_of("TX/RX"); +static const std::vector wbx_tx_antennas = list_of("TX/RX"); -static const prop_names_t wbx_rx_antennas = list_of("TX/RX")("RX2"); +static const std::vector wbx_rx_antennas = list_of("TX/RX")("RX2"); /*********************************************************************** * The WBX simple implementation diff --git a/host/lib/usrp/gps_ctrl.cpp b/host/lib/usrp/gps_ctrl.cpp index c645d2948..45fa1f39e 100644 --- a/host/lib/usrp/gps_ctrl.cpp +++ b/host/lib/usrp/gps_ctrl.cpp @@ -17,7 +17,6 @@ #include #include -#include #include #include #include @@ -121,7 +120,7 @@ public: return sensor_value_t("GPS lock status", locked(), "locked", "unlocked"); } else { - UHD_THROW_PROP_GET_ERROR(); + throw uhd::value_error("gps ctrl get_sensor unknown key: " + key); } } diff --git a/host/lib/utils/CMakeLists.txt b/host/lib/utils/CMakeLists.txt index fd3249099..19dde9a56 100644 --- a/host/lib/utils/CMakeLists.txt +++ b/host/lib/utils/CMakeLists.txt @@ -134,7 +134,6 @@ LIBUHD_APPEND_SOURCES( ${CMAKE_CURRENT_SOURCE_DIR}/log.cpp ${CMAKE_CURRENT_SOURCE_DIR}/msg.cpp ${CMAKE_CURRENT_SOURCE_DIR}/paths.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/props.cpp ${CMAKE_CURRENT_SOURCE_DIR}/static.cpp ${CMAKE_CURRENT_SOURCE_DIR}/tasks.cpp ${CMAKE_CURRENT_SOURCE_DIR}/thread_priority.cpp diff --git a/host/lib/utils/props.cpp b/host/lib/utils/props.cpp deleted file mode 100644 index fc9f8e63f..000000000 --- a/host/lib/utils/props.cpp +++ /dev/null @@ -1,40 +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 . -// - -#include - -using namespace uhd; - -named_prop_t::named_prop_t( - const wax::obj &key, - const std::string &name -): - key(key), - name(name) -{ - /* NOP */ -} - -named_prop_t named_prop_t::extract( - const wax::obj &key, - const std::string &name -){ - if (key.type() == typeid(named_prop_t)){ - return key.as(); - } - return named_prop_t(key, name); -} -- cgit v1.2.3