aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--host/include/uhd/rfnoc/radio_ctrl.hpp95
-rw-r--r--host/lib/rfnoc/radio_ctrl_impl.cpp46
-rw-r--r--host/lib/rfnoc/radio_ctrl_impl.hpp13
-rw-r--r--host/lib/usrp/x300/x300_radio_ctrl_impl.cpp192
-rw-r--r--host/lib/usrp/x300/x300_radio_ctrl_impl.hpp13
5 files changed, 359 insertions, 0 deletions
diff --git a/host/include/uhd/rfnoc/radio_ctrl.hpp b/host/include/uhd/rfnoc/radio_ctrl.hpp
index 67ea4c069..d8e3d94e8 100644
--- a/host/include/uhd/rfnoc/radio_ctrl.hpp
+++ b/host/include/uhd/rfnoc/radio_ctrl.hpp
@@ -18,6 +18,7 @@
#ifndef INCLUDED_LIBUHD_RFNOC_RADIO_CTRL_HPP
#define INCLUDED_LIBUHD_RFNOC_RADIO_CTRL_HPP
+#include <uhd/types/ranges.hpp>
#include <uhd/types/direction.hpp>
#include <uhd/rfnoc/source_block_ctrl_base.hpp>
#include <uhd/rfnoc/sink_block_ctrl_base.hpp>
@@ -43,6 +44,16 @@ public:
virtual ~radio_ctrl(){}
+
+ //! A wildcard channel index
+ static const size_t ALL_CHANS = size_t(~0);
+
+ //! A wildcard gain element name
+ static const std::string ALL_GAINS;
+
+ //! A wildcard local oscillator element name
+ static const std::string ALL_LOS;
+
/************************************************************************
* API calls
***********************************************************************/
@@ -201,6 +212,90 @@ public:
virtual time_spec_t get_time_last_pps() = 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(const size_t chan) = 0;
+
+ /*!
+ * Get a list of possible LO sources.
+ * Channels which do not have controllable LO sources
+ * will return "internal".
+ * \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, const size_t chan) = 0;
+
+ /*!
+ * Get the LO frequency range of the RX LO.
+ * If the channel does not have independently configurable LOs
+ * the rf frequency range will be returned.
+ * \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, const size_t chan) = 0;
+
+ /*!
+ * Set the LO source for a channel.
+ * 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, const size_t chan) = 0;
+
+ /*!
+ * Get the currently set LO source.
+ * Channels without controllable LO sources will return
+ * "internal"
+ * \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, const size_t chan) = 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, const size_t chan) = 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, const size_t chan) = 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, const size_t chan) = 0;
+
+ /*!
+ * Get the current RX LO frequency (Advanced).
+ * If the channel does not have independently configurable LOs
+ * the current rf frequency will be returned.
+ * \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, const size_t chan) = 0;
+
+ /*!
* Set the time source for this radio.
*
* May affect other radio blocks.
diff --git a/host/lib/rfnoc/radio_ctrl_impl.cpp b/host/lib/rfnoc/radio_ctrl_impl.cpp
index a143bb248..1caa9bb99 100644
--- a/host/lib/rfnoc/radio_ctrl_impl.cpp
+++ b/host/lib/rfnoc/radio_ctrl_impl.cpp
@@ -29,6 +29,7 @@ using namespace uhd;
using namespace uhd::rfnoc;
static const size_t BYTES_PER_SAMPLE = 4;
+const std::string radio_ctrl::ALL_LOS = "all";
/****************************************************************************
* Structors and init
@@ -242,6 +243,51 @@ double radio_ctrl_impl::get_rx_bandwidth(const size_t chan) /* const */
{
return _rx_bandwidth[chan];
}
+
+std::vector<std::string> radio_ctrl_impl::get_rx_lo_names(const size_t /* chan */)
+{
+ return std::vector<std::string>();
+}
+
+std::vector<std::string> radio_ctrl_impl::get_rx_lo_sources(const std::string & /* name */, const size_t /* chan */)
+{
+ return std::vector<std::string>();
+}
+
+freq_range_t radio_ctrl_impl::get_rx_lo_freq_range(const std::string & /* name */, const size_t /* chan */)
+{
+ return freq_range_t();
+}
+
+void radio_ctrl_impl::set_rx_lo_source(const std::string & /* src */, const std::string & /* name */, const size_t /* chan */)
+{
+ throw uhd::not_implemented_error("set_rx_lo_source is not supported on this radio");
+}
+
+const std::string radio_ctrl_impl::get_rx_lo_source(const std::string & /* name */, const size_t /* chan */)
+{
+ return "internal";
+}
+
+void radio_ctrl_impl::set_rx_lo_export_enabled(bool /* enabled */, const std::string & /* name */, const size_t /* chan */)
+{
+ throw uhd::not_implemented_error("set_rx_lo_export_enabled is not supported on this radio");
+}
+
+bool radio_ctrl_impl::get_rx_lo_export_enabled(const std::string & /* name */, const size_t /* chan */)
+{
+ return false; // Not exporting non-existant LOs
+}
+
+double radio_ctrl_impl::set_rx_lo_freq(double /* freq */, const std::string & /* name */, const size_t /* chan */)
+{
+ throw uhd::not_implemented_error("set_rx_lo_freq is not supported on this radio");
+}
+
+double radio_ctrl_impl::get_rx_lo_freq(const std::string & /* name */, const size_t /* chan */)
+{
+ return 0;
+}
/***********************************************************************
* RX Streamer-related methods (from source_block_ctrl_base)
diff --git a/host/lib/rfnoc/radio_ctrl_impl.hpp b/host/lib/rfnoc/radio_ctrl_impl.hpp
index b31239482..21d7da1f1 100644
--- a/host/lib/rfnoc/radio_ctrl_impl.hpp
+++ b/host/lib/rfnoc/radio_ctrl_impl.hpp
@@ -71,6 +71,19 @@ public:
virtual double get_rx_gain(const size_t) /* const */;
virtual double get_rx_bandwidth(const size_t) /* const */;
+ virtual std::vector<std::string> get_rx_lo_names(const size_t chan);
+ virtual std::vector<std::string> get_rx_lo_sources(const std::string &name, const size_t chan);
+ virtual freq_range_t get_rx_lo_freq_range(const std::string &name, const size_t chan);
+
+ virtual void set_rx_lo_source(const std::string &src, const std::string &name, const size_t chan);
+ virtual const std::string get_rx_lo_source(const std::string &name, const size_t chan);
+
+ virtual void set_rx_lo_export_enabled(bool enabled, const std::string &name, const size_t chan);
+ virtual bool get_rx_lo_export_enabled(const std::string &name, const size_t chan);
+
+ virtual double set_rx_lo_freq(double freq, const std::string &name, const size_t chan);
+ virtual double get_rx_lo_freq(const std::string &name, const size_t chan);
+
void set_time_now(const time_spec_t &time_spec);
void set_time_next_pps(const time_spec_t &time_spec);
void set_time_sync(const uhd::time_spec_t &time);
diff --git a/host/lib/usrp/x300/x300_radio_ctrl_impl.cpp b/host/lib/usrp/x300/x300_radio_ctrl_impl.cpp
index c84b2ba44..8692871b8 100644
--- a/host/lib/usrp/x300/x300_radio_ctrl_impl.cpp
+++ b/host/lib/usrp/x300/x300_radio_ctrl_impl.cpp
@@ -275,6 +275,198 @@ double x300_radio_ctrl_impl::set_rx_gain(const double gain, const size_t chan)
}
+std::vector<std::string> x300_radio_ctrl_impl::get_rx_lo_names(const size_t chan)
+{
+ fs_path rx_fe_fe_root = fs_path("dboards" / _radio_slot / "rx_frontends" / _rx_fe_map.at(chan).db_fe_name);
+
+ std::vector<std::string> lo_names;
+ if (_tree->exists(rx_fe_fe_root / "los")) {
+ for(const std::string &name: _tree->list(rx_fe_fe_root / "los")) {
+ lo_names.push_back(name);
+ }
+ }
+ return lo_names;
+}
+
+std::vector<std::string> x300_radio_ctrl_impl::get_rx_lo_sources(const std::string &name, const size_t chan)
+{
+ fs_path rx_fe_fe_root = fs_path("dboards" / _radio_slot / "rx_frontends" / _rx_fe_map.at(chan).db_fe_name);
+
+ if (_tree->exists(rx_fe_fe_root / "los")) {
+ if (name == ALL_LOS) {
+ if (_tree->exists(rx_fe_fe_root / "los" / ALL_LOS)) {
+ //Special value ALL_LOS support atomically sets the source for all LOs
+ return _tree->access< std::vector<std::string> >(rx_fe_fe_root / "los" / ALL_LOS / "source" / "options").get();
+ } else {
+ return std::vector<std::string>();
+ }
+ } else {
+ if (_tree->exists(rx_fe_fe_root / "los")) {
+ return _tree->access< std::vector<std::string> >(rx_fe_fe_root / "los" / name / "source" / "options").get();
+ } else {
+ throw uhd::runtime_error("Could not find LO stage " + name);
+ }
+ }
+ } else {
+ // If the daughterboard doesn't expose it's LO(s) then it can only be internal
+ return std::vector<std::string> (1, "internal");
+ }
+}
+
+void x300_radio_ctrl_impl::set_rx_lo_source(const std::string &src, const std::string &name, const size_t chan)
+{
+ fs_path rx_fe_fe_root = fs_path("dboards" / _radio_slot / "rx_frontends" / _rx_fe_map.at(chan).db_fe_name);
+
+ if (_tree->exists(rx_fe_fe_root / "los")) {
+ if (name == ALL_LOS) {
+ if (_tree->exists(rx_fe_fe_root / "los" / ALL_LOS)) {
+ //Special value ALL_LOS support atomically sets the source for all LOs
+ _tree->access<std::string>(rx_fe_fe_root / "los" / ALL_LOS / "source" / "value").set(src);
+ } else {
+ for(const std::string &n: _tree->list(rx_fe_fe_root / "los")) {
+ this->set_rx_lo_source(src, n, chan);
+ }
+ }
+ } else {
+ if (_tree->exists(rx_fe_fe_root / "los")) {
+ _tree->access<std::string>(rx_fe_fe_root / "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 x300_radio_ctrl_impl::get_rx_lo_source(const std::string &name, const size_t chan)
+{
+ fs_path rx_fe_fe_root = fs_path("dboards" / _radio_slot / "rx_frontends" / _rx_fe_map.at(chan).db_fe_name);
+
+ if (_tree->exists(rx_fe_fe_root / "los")) {
+ if (name == ALL_LOS) {
+ //Special value ALL_LOS support atomically sets the source for all LOs
+ return _tree->access<std::string>(rx_fe_fe_root / "los" / ALL_LOS / "source" / "value").get();
+ } else {
+ if (_tree->exists(rx_fe_fe_root / "los")) {
+ return _tree->access<std::string>(rx_fe_fe_root / "los" / name / "source" / "value").get();
+ } else {
+ throw uhd::runtime_error("Could not find LO stage " + name);
+ }
+ }
+ } else {
+ // If the daughterboard doesn't expose it's LO(s) then it can only be internal
+ return "internal";
+ }
+}
+
+void x300_radio_ctrl_impl::set_rx_lo_export_enabled(bool enabled, const std::string &name, const size_t chan)
+{
+ fs_path rx_fe_fe_root = fs_path("dboards" / _radio_slot / "rx_frontends" / _rx_fe_map.at(chan).db_fe_name);
+
+ if (_tree->exists(rx_fe_fe_root / "los")) {
+ if (name == ALL_LOS) {
+ if (_tree->exists(rx_fe_fe_root / "los" / ALL_LOS)) {
+ //Special value ALL_LOS support atomically sets the source for all LOs
+ _tree->access<bool>(rx_fe_fe_root / "los" / ALL_LOS / "export").set(enabled);
+ } else {
+ for(const std::string &n: _tree->list(rx_fe_fe_root / "los")) {
+ this->set_rx_lo_export_enabled(enabled, n, chan);
+ }
+ }
+ } else {
+ if (_tree->exists(rx_fe_fe_root / "los")) {
+ _tree->access<bool>(rx_fe_fe_root / "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 x300_radio_ctrl_impl::get_rx_lo_export_enabled(const std::string &name, const size_t chan)
+{
+ fs_path rx_fe_fe_root = fs_path("dboards" / _radio_slot / "rx_frontends" / _rx_fe_map.at(chan).db_fe_name);
+
+ if (_tree->exists(rx_fe_fe_root / "los")) {
+ if (name == ALL_LOS) {
+ //Special value ALL_LOS support atomically sets the source for all LOs
+ return _tree->access<bool>(rx_fe_fe_root / "los" / ALL_LOS / "export").get();
+ } else {
+ if (_tree->exists(rx_fe_fe_root / "los")) {
+ return _tree->access<bool>(rx_fe_fe_root / "los" / name / "export").get();
+ } else {
+ throw uhd::runtime_error("Could not find LO stage " + name);
+ }
+ }
+ } else {
+ // If the daughterboard doesn't expose it's LO(s), assume it cannot export
+ return false;
+ }
+}
+
+double x300_radio_ctrl_impl::set_rx_lo_freq(double freq, const std::string &name, const size_t chan)
+{
+ fs_path rx_fe_fe_root = fs_path("dboards" / _radio_slot / "rx_frontends" / _rx_fe_map.at(chan).db_fe_name);
+
+ if (_tree->exists(rx_fe_fe_root / "los")) {
+ if (name == ALL_LOS) {
+ throw uhd::runtime_error("LO frequency must be set for each stage individually");
+ } else {
+ if (_tree->exists(rx_fe_fe_root / "los")) {
+ _tree->access<double>(rx_fe_fe_root / "los" / name / "freq" / "value").set(freq);
+ return _tree->access<double>(rx_fe_fe_root / "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 x300_radio_ctrl_impl::get_rx_lo_freq(const std::string &name, const size_t chan)
+{
+ fs_path rx_fe_fe_root = fs_path("dboards" / _radio_slot / "rx_frontends" / _rx_fe_map.at(chan).db_fe_name);
+
+ if (_tree->exists(rx_fe_fe_root / "los")) {
+ if (name == ALL_LOS) {
+ throw uhd::runtime_error("LO frequency must be retrieved for each stage individually");
+ } else {
+ if (_tree->exists(rx_fe_fe_root / "los")) {
+ return _tree->access<double>(rx_fe_fe_root / "los" / name / "freq" / "value").get();
+ } else {
+ throw uhd::runtime_error("Could not find LO stage " + name);
+ }
+ }
+ } else {
+ // Return actual RF frequency if the daughterboard doesn't expose it's LO(s)
+ return _tree->access<double>(rx_fe_fe_root / "freq" /" value").get();
+ }
+}
+
+freq_range_t x300_radio_ctrl_impl::get_rx_lo_freq_range(const std::string &name, const size_t chan)
+{
+ fs_path rx_fe_fe_root = fs_path("dboards" / _radio_slot / "rx_frontends" / _rx_fe_map.at(chan).db_fe_name);
+
+ if (_tree->exists(rx_fe_fe_root / "los")) {
+ if (name == ALL_LOS) {
+ throw uhd::runtime_error("LO frequency range must be retrieved for each stage individually");
+ } else {
+ if (_tree->exists(rx_fe_fe_root / "los")) {
+ return _tree->access<freq_range_t>(rx_fe_fe_root / "los" / name / "freq" / "range").get();
+ } else {
+ throw uhd::runtime_error("Could not find LO stage " + name);
+ }
+ }
+ } else {
+ // Return the actual RF range if the daughterboard doesn't expose it's LO(s)
+ return _tree->access<meta_range_t>(rx_fe_fe_root / "freq" / "range").get();
+ }
+}
+
template <typename map_type>
static size_t _get_chan_from_map(std::map<size_t, map_type> map, const std::string &fe)
{
diff --git a/host/lib/usrp/x300/x300_radio_ctrl_impl.hpp b/host/lib/usrp/x300/x300_radio_ctrl_impl.hpp
index 80cd94215..27633fa9a 100644
--- a/host/lib/usrp/x300/x300_radio_ctrl_impl.hpp
+++ b/host/lib/usrp/x300/x300_radio_ctrl_impl.hpp
@@ -64,6 +64,19 @@ public:
double set_tx_gain(const double gain, const size_t chan);
double set_rx_gain(const double gain, const size_t chan);
+ std::vector<std::string> get_rx_lo_names(const size_t chan);
+ std::vector<std::string> get_rx_lo_sources(const std::string &name, const size_t chan);
+ freq_range_t get_rx_lo_freq_range(const std::string &name, const size_t chan);
+
+ void set_rx_lo_source(const std::string &src, const std::string &name, const size_t chan);
+ const std::string get_rx_lo_source(const std::string &name, const size_t chan);
+
+ void set_rx_lo_export_enabled(bool enabled, const std::string &name, const size_t chan);
+ bool get_rx_lo_export_enabled(const std::string &name, const size_t chan);
+
+ double set_rx_lo_freq(double freq, const std::string &name, const size_t chan);
+ double get_rx_lo_freq(const std::string &name, const size_t chan);
+
size_t get_chan_from_dboard_fe(const std::string &fe, const direction_t dir);
std::string get_dboard_fe_from_chan(const size_t chan, const direction_t dir);