aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDerek Kozel <derek.kozel@ettus.com>2016-07-19 09:27:38 -0700
committerMartin Braun <martin.braun@ettus.com>2016-07-19 09:28:03 -0700
commitb4412c79c026fef94affe8e7c9a1518ab4954183 (patch)
tree20f26a99b858f0e53f2742b30698056b257d11d5
parent890a8e10d65dd35e2ad3449bf3a3dce79ccb6083 (diff)
downloaduhd-b4412c79c026fef94affe8e7c9a1518ab4954183.tar.gz
uhd-b4412c79c026fef94affe8e7c9a1518ab4954183.tar.bz2
uhd-b4412c79c026fef94affe8e7c9a1518ab4954183.zip
multi_usrp: Added LO control API
-rw-r--r--host/include/uhd/usrp/multi_usrp.hpp80
-rw-r--r--host/lib/usrp/multi_usrp.cpp161
2 files changed, 241 insertions, 0 deletions
diff --git a/host/include/uhd/usrp/multi_usrp.hpp b/host/include/uhd/usrp/multi_usrp.hpp
index 715a57242..ab757be8a 100644
--- a/host/include/uhd/usrp/multi_usrp.hpp
+++ b/host/include/uhd/usrp/multi_usrp.hpp
@@ -31,6 +31,7 @@
#define UHD_USRP_MULTI_USRP_GPIO_API
#define UHD_USRP_MULTI_USRP_REGISTER_API
#define UHD_USRP_MULTI_USRP_FILTER_API
+#define UHD_USRP_MULTI_USRP_LO_CONFIG_API
#include <uhd/config.hpp>
#include <uhd/device.hpp>
@@ -112,6 +113,9 @@ public:
//! A wildcard gain element name
static const std::string ALL_GAINS;
+ //! A wildcard gain element name
+ static const std::string ALL_LOS;
+
/*!
* Make a new multi usrp from the device address.
* \param dev_addr the device address
@@ -487,6 +491,82 @@ public:
virtual freq_range_t get_fe_rx_freq_range(size_t chan = 0) = 0;
/*!
+ * Get a list of possible LO stage names
+ * \param chan the channel index 0 to N-1
+ * \return a vector of strings for possible LO names
+ */
+ virtual std::vector<std::string> get_rx_lo_names(size_t chan = 0) = 0;
+
+ /*!
+ * Set the LO source for the usrp device.
+ * For usrps that support selectable LOs, this function
+ * allows switching between them.
+ * Typical options for source: internal, external.
+ * \param src a string representing the LO source
+ * \param name the name of the LO stage to update
+ * \param chan the channel index 0 to N-1
+ */
+ virtual void set_rx_lo_source(const std::string &src, const std::string &name = ALL_LOS, size_t chan = 0) = 0;
+
+ /*!
+ * Get the currently set LO source.
+ * \param name the name of the LO stage to query
+ * \param chan the channel index 0 to N-1
+ * \return the configured LO source
+ */
+ virtual const std::string get_rx_lo_source(const std::string &name = ALL_LOS, size_t chan = 0) = 0;
+
+ /*!
+ * Get a list of possible LO sources.
+ * \param name the name of the LO stage to query
+ * \param chan the channel index 0 to N-1
+ * \return a vector of strings for possible settings
+ */
+ virtual std::vector<std::string> get_rx_lo_sources(const std::string &name = ALL_LOS, size_t chan = 0) = 0;
+
+ /*!
+ * Set whether the LO used by the usrp device is exported
+ * For usrps that support exportable LOs, this function
+ * configures if the LO used by chan is exported or not.
+ * \param enabled if true then export the LO
+ * \param name the name of the LO stage to update
+ * \param chan the channel index 0 to N-1 for the source channel
+ */
+ virtual void set_rx_lo_export_enabled(bool enabled, const std::string &name = ALL_LOS, size_t chan = 0) = 0;
+
+ /*!
+ * Returns true if the currently selected LO is being exported.
+ * \param name the name of the LO stage to query
+ * \param chan the channel index 0 to N-1
+ */
+ virtual bool get_rx_lo_export_enabled(const std::string &name = ALL_LOS, size_t chan = 0) = 0;
+
+ /*!
+ * Set the RX LO frequency (Advanced).
+ * \param freq the frequency to set the LO to
+ * \param name the name of the LO stage to update
+ * \param chan the channel index 0 to N-1
+ * \return a coerced LO frequency
+ */
+ virtual double set_rx_lo_freq(double freq, const std::string &name, size_t chan = 0) = 0;
+
+ /*!
+ * Get the current RX LO frequency (Advanced).
+ * \param name the name of the LO stage to query
+ * \param chan the channel index 0 to N-1
+ * \return the configured LO frequency
+ */
+ virtual double get_rx_lo_freq(const std::string &name, size_t chan = 0) = 0;
+
+ /*!
+ * Get the LO frequency range of the RX LO.
+ * \param name the name of the LO stage to query
+ * \param chan the channel index 0 to N-1
+ * \return a frequency range object
+ */
+ virtual freq_range_t get_rx_lo_freq_range(const std::string &name, size_t chan = 0) = 0;
+
+ /*!
* Set the RX gain value for the specified gain element.
* For an empty name, distribute across all gain elements.
* \param gain the gain in dB
diff --git a/host/lib/usrp/multi_usrp.cpp b/host/lib/usrp/multi_usrp.cpp
index dbc0ebed2..e0811e667 100644
--- a/host/lib/usrp/multi_usrp.cpp
+++ b/host/lib/usrp/multi_usrp.cpp
@@ -39,6 +39,7 @@ using namespace uhd;
using namespace uhd::usrp;
const std::string multi_usrp::ALL_GAINS = "";
+const std::string multi_usrp::ALL_LOS = "all";
UHD_INLINE std::string string_vector_to_string(std::vector<std::string> values, std::string delimiter = std::string(" "))
{
@@ -832,6 +833,166 @@ public:
return _tree->access<meta_range_t>(rx_rf_fe_root(chan) / "freq" / "range").get();
}
+ std::vector<std::string> get_rx_lo_names(size_t chan = 0){
+ std::vector<std::string> lo_names;
+ if (_tree->exists(rx_rf_fe_root(chan) / "los")) {
+ BOOST_FOREACH(const std::string &name, _tree->list(rx_rf_fe_root(chan) / "los")) {
+ lo_names.push_back(name);
+ }
+ }
+ return lo_names;
+ }
+
+ void set_rx_lo_source(const std::string &src, const std::string &name = ALL_LOS, size_t chan = 0){
+ if (_tree->exists(rx_rf_fe_root(chan) / "los")) {
+ if (name == ALL_LOS) {
+ if (_tree->exists(rx_rf_fe_root(chan) / "los" / ALL_LOS)) {
+ //Special value ALL_LOS support atomically sets the source for all LOs
+ _tree->access<std::string>(rx_rf_fe_root(chan) / "los" / ALL_LOS / "source" / "value").set(src);
+ } else {
+ BOOST_FOREACH(const std::string &n, _tree->list(rx_rf_fe_root(chan) / "los")) {
+ this->set_rx_lo_source(src, n, chan);
+ }
+ }
+ } else {
+ if (_tree->exists(rx_rf_fe_root(chan) / "los")) {
+ _tree->access<std::string>(rx_rf_fe_root(chan) / "los" / name / "source" / "value").set(src);
+ } else {
+ throw uhd::runtime_error("Could not find LO stage " + name);
+ }
+ }
+ } else {
+ throw uhd::runtime_error("This device does not support manual configuration of LOs");
+ }
+ }
+
+ const std::string get_rx_lo_source(const std::string &name = ALL_LOS, size_t chan = 0){
+ if (_tree->exists(rx_rf_fe_root(chan) / "los")) {
+ if (name == ALL_LOS) {
+ //Special value ALL_LOS support atomically sets the source for all LOs
+ return _tree->access<std::string>(rx_rf_fe_root(chan) / "los" / ALL_LOS / "source" / "value").get();
+ } else {
+ if (_tree->exists(rx_rf_fe_root(chan) / "los")) {
+ return _tree->access<std::string>(rx_rf_fe_root(chan) / "los" / name / "source" / "value").get();
+ } else {
+ throw uhd::runtime_error("Could not find LO stage " + name);
+ }
+ }
+ } else {
+ throw uhd::runtime_error("This device does not support manual configuration of LOs");
+ }
+ }
+
+ std::vector<std::string> get_rx_lo_sources(const std::string &name = ALL_LOS, size_t chan = 0) {
+ if (_tree->exists(rx_rf_fe_root(chan) / "los")) {
+ if (name == ALL_LOS) {
+ if (_tree->exists(rx_rf_fe_root(chan) / "los" / ALL_LOS)) {
+ //Special value ALL_LOS support atomically sets the source for all LOs
+ return _tree->access< std::vector<std::string> >(rx_rf_fe_root(chan) / "los" / ALL_LOS / "source" / "options").get();
+ } else {
+ return std::vector<std::string>();
+ }
+ } else {
+ if (_tree->exists(rx_rf_fe_root(chan) / "los")) {
+ return _tree->access< std::vector<std::string> >(rx_rf_fe_root(chan) / "los" / name / "source" / "options").get();
+ } else {
+ throw uhd::runtime_error("Could not find LO stage " + name);
+ }
+ }
+ } else {
+ throw uhd::runtime_error("This device does not support manual configuration of LOs");
+ }
+ }
+
+ void set_rx_lo_export_enabled(bool enabled, const std::string &name = ALL_LOS, size_t chan = 0){
+ if (_tree->exists(rx_rf_fe_root(chan) / "los")) {
+ if (name == ALL_LOS) {
+ if (_tree->exists(rx_rf_fe_root(chan) / "los" / ALL_LOS)) {
+ //Special value ALL_LOS support atomically sets the source for all LOs
+ _tree->access<bool>(rx_rf_fe_root(chan) / "los" / ALL_LOS / "export").set(enabled);
+ } else {
+ BOOST_FOREACH(const std::string &n, _tree->list(rx_rf_fe_root(chan) / "los")) {
+ this->set_rx_lo_export_enabled(enabled, n, chan);
+ }
+ }
+ } else {
+ if (_tree->exists(rx_rf_fe_root(chan) / "los")) {
+ _tree->access<bool>(rx_rf_fe_root(chan) / "los" / name / "export").set(enabled);
+ } else {
+ throw uhd::runtime_error("Could not find LO stage " + name);
+ }
+ }
+ } else {
+ throw uhd::runtime_error("This device does not support manual configuration of LOs");
+ }
+ }
+
+ bool get_rx_lo_export_enabled(const std::string &name = ALL_LOS, size_t chan = 0){
+ if (_tree->exists(rx_rf_fe_root(chan) / "los")) {
+ if (name == ALL_LOS) {
+ //Special value ALL_LOS support atomically sets the source for all LOs
+ return _tree->access<bool>(rx_rf_fe_root(chan) / "los" / ALL_LOS / "export").get();
+ } else {
+ if (_tree->exists(rx_rf_fe_root(chan) / "los")) {
+ return _tree->access<bool>(rx_rf_fe_root(chan) / "los" / name / "export").get();
+ } else {
+ throw uhd::runtime_error("Could not find LO stage " + name);
+ }
+ }
+ } else {
+ throw uhd::runtime_error("This device does not support manual configuration of LOs");
+ }
+ }
+
+ double set_rx_lo_freq(double freq, const std::string &name = ALL_LOS, size_t chan = 0){
+ if (_tree->exists(rx_rf_fe_root(chan) / "los")) {
+ if (name == ALL_LOS) {
+ throw uhd::runtime_error("LO frequency must be set for each stage individually");
+ } else {
+ if (_tree->exists(rx_rf_fe_root(chan) / "los")) {
+ _tree->access<double>(rx_rf_fe_root(chan) / "los" / name / "freq" / "value").set(freq);
+ return _tree->access<double>(rx_rf_fe_root(chan) / "los" / name / "freq" / "value").get();
+ } else {
+ throw uhd::runtime_error("Could not find LO stage " + name);
+ }
+ }
+ } else {
+ throw uhd::runtime_error("This device does not support manual configuration of LOs");
+ }
+ }
+
+ double get_rx_lo_freq(const std::string &name = ALL_LOS, size_t chan = 0){
+ if (_tree->exists(rx_rf_fe_root(chan) / "los")) {
+ if (name == ALL_LOS) {
+ throw uhd::runtime_error("LO frequency must be retrieved for each stage individually");
+ } else {
+ if (_tree->exists(rx_rf_fe_root(chan) / "los")) {
+ return _tree->access<double>(rx_rf_fe_root(chan) / "los" / name / "freq" / "value").get();
+ } else {
+ throw uhd::runtime_error("Could not find LO stage " + name);
+ }
+ }
+ } else {
+ throw uhd::runtime_error("This device does not support manual configuration of LOs");
+ }
+ }
+
+ freq_range_t get_rx_lo_freq_range(const std::string &name = ALL_LOS, size_t chan = 0){
+ if (_tree->exists(rx_rf_fe_root(chan) / "los")) {
+ if (name == ALL_LOS) {
+ throw uhd::runtime_error("LO frequency range must be retrieved for each stage individually");
+ } else {
+ if (_tree->exists(rx_rf_fe_root(chan) / "los")) {
+ return _tree->access<freq_range_t>(rx_rf_fe_root(chan) / "los" / name / "freq" / "range").get();
+ } else {
+ throw uhd::runtime_error("Could not find LO stage " + name);
+ }
+ }
+ } else {
+ throw uhd::runtime_error("This device does not support manual configuration of LOs");
+ }
+ }
+
void set_rx_gain(double gain, const std::string &name, size_t chan){
/* Check if any AGC mode is enable and if so warn the user */
if (chan != ALL_CHANS) {