aboutsummaryrefslogtreecommitdiffstats
path: root/host/lib/usrp
diff options
context:
space:
mode:
authorMartin Braun <martin.braun@ettus.com>2017-12-05 11:17:03 -0800
committerMartin Braun <martin.braun@ettus.com>2017-12-06 10:59:28 -0800
commit77adcffe0689f120fee71854ec0f627a32991f79 (patch)
treef53f89049a2e5f8f543ccf01139d2a37d27b6125 /host/lib/usrp
parent8a9da7c66aaec826e756ab2411b9d40aa3f1f10c (diff)
downloaduhd-77adcffe0689f120fee71854ec0f627a32991f79.tar.gz
uhd-77adcffe0689f120fee71854ec0f627a32991f79.tar.bz2
uhd-77adcffe0689f120fee71854ec0f627a32991f79.zip
multi_usrp: Expose APIs for TX LO controls
Reviewed-By: Ashish Chaudhari <ashish@ettus.com> Reviewed-By: Derek Kozel <derek.kozel@ettus.com>
Diffstat (limited to 'host/lib/usrp')
-rw-r--r--host/lib/usrp/multi_usrp.cpp220
1 files changed, 220 insertions, 0 deletions
diff --git a/host/lib/usrp/multi_usrp.cpp b/host/lib/usrp/multi_usrp.cpp
index 3dcfe3bd9..d7d925f3c 100644
--- a/host/lib/usrp/multi_usrp.cpp
+++ b/host/lib/usrp/multi_usrp.cpp
@@ -870,6 +870,9 @@ public:
return _tree->access<meta_range_t>(rx_rf_fe_root(chan) / "freq" / "range").get();
}
+ /**************************************************************************
+ * LO controls
+ *************************************************************************/
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")) {
@@ -1035,6 +1038,223 @@ public:
}
}
+ std::vector<std::string> get_tx_lo_names(const size_t chan = 0){
+ std::vector<std::string> lo_names;
+ if (_tree->exists(tx_rf_fe_root(chan) / "los")) {
+ for (const std::string &name : _tree->list(tx_rf_fe_root(chan) / "los")) {
+ lo_names.push_back(name);
+ }
+ }
+ return lo_names;
+ }
+
+ void set_tx_lo_source(
+ const std::string &src,
+ const std::string &name = ALL_LOS,
+ const size_t chan = 0
+ ) {
+ if (_tree->exists(tx_rf_fe_root(chan) / "los")) {
+ if (name == ALL_LOS) {
+ if (_tree->exists(tx_rf_fe_root(chan) / "los" / ALL_LOS)) {
+ // Special value ALL_LOS support atomically sets the source
+ // for all LOs
+ _tree->access<std::string>(
+ tx_rf_fe_root(chan) / "los" / ALL_LOS /
+ "source" / "value"
+ ).set(src);
+ } else {
+ for (const auto &n : _tree->list(tx_rf_fe_root(chan) / "los")) {
+ this->set_tx_lo_source(src, n, chan);
+ }
+ }
+ } else {
+ if (_tree->exists(tx_rf_fe_root(chan) / "los")) {
+ _tree->access<std::string>(
+ tx_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_tx_lo_source(
+ const std::string &name = ALL_LOS,
+ const size_t chan = 0
+ ) {
+ if (_tree->exists(tx_rf_fe_root(chan) / "los")) {
+ if (_tree->exists(tx_rf_fe_root(chan) / "los")) {
+ return _tree->access<std::string>(
+ tx_rf_fe_root(chan) / "los" / name / "source" / "value"
+ ).get();
+ } else {
+ throw uhd::runtime_error("Could not find LO stage " + name);
+ }
+ } else {
+ // If the daughterboard doesn't expose its LO(s) then it can only
+ // be internal
+ return "internal";
+ }
+ }
+
+ std::vector<std::string> get_tx_lo_sources(
+ const std::string &name = ALL_LOS,
+ const size_t chan = 0
+ ) {
+ if (_tree->exists(tx_rf_fe_root(chan) / "los")) {
+ if (name == ALL_LOS) {
+ if (_tree->exists(tx_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>>(
+ tx_rf_fe_root(chan) / "los" / ALL_LOS /
+ "source" / "options"
+ ).get();
+ } else {
+ return std::vector<std::string>();
+ }
+ } else {
+ if (_tree->exists(tx_rf_fe_root(chan) / "los")) {
+ return _tree->access< std::vector<std::string> >(tx_rf_fe_root(chan) / "los" / name / "source" / "options").get();
+ } else {
+ throw uhd::runtime_error("Could not find LO stage " + name);
+ }
+ }
+ } else {
+ // If the daughterboard doesn't expose its LO(s) then it can only
+ // be internal
+ return std::vector<std::string>(1, "internal");
+ }
+ }
+
+ void set_tx_lo_export_enabled(
+ const bool enabled,
+ const std::string &name = ALL_LOS,
+ const size_t chan=0
+ ) {
+ if (_tree->exists(tx_rf_fe_root(chan) / "los")) {
+ if (name == ALL_LOS) {
+ if (_tree->exists(tx_rf_fe_root(chan) / "los" / ALL_LOS)) {
+ //Special value ALL_LOS support atomically sets the source for all LOs
+ _tree->access<bool>(tx_rf_fe_root(chan) / "los" / ALL_LOS / "export").set(enabled);
+ } else {
+ for(const std::string &n: _tree->list(tx_rf_fe_root(chan) / "los")) {
+ this->set_tx_lo_export_enabled(enabled, n, chan);
+ }
+ }
+ } else {
+ if (_tree->exists(tx_rf_fe_root(chan) / "los")) {
+ _tree->access<bool>(tx_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_tx_lo_export_enabled(
+ const std::string &name = ALL_LOS,
+ const size_t chan = 0
+ ) {
+ if (_tree->exists(tx_rf_fe_root(chan) / "los")) {
+ if (_tree->exists(tx_rf_fe_root(chan) / "los")) {
+ return _tree->access<bool>(
+ tx_rf_fe_root(chan) / "los" / name / "export"
+ ).get();
+ } else {
+ throw uhd::runtime_error("Could not find LO stage " + name);
+ }
+ } else {
+ // If the daughterboard doesn't expose its LO(s), assume it cannot
+ // export
+ return false;
+ }
+ }
+
+ double set_tx_lo_freq(
+ const double freq,
+ const std::string &name = ALL_LOS,
+ const size_t chan = 0
+ ) {
+ if (_tree->exists(tx_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(tx_rf_fe_root(chan) / "los")) {
+ return _tree->access<double>(
+ tx_rf_fe_root(chan) / "los" / name / "freq" / "value"
+ ).set(freq).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_tx_lo_freq(
+ const std::string &name = ALL_LOS,
+ const size_t chan = 0
+ ) {
+ if (_tree->exists(tx_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(tx_rf_fe_root(chan) / "los")) {
+ return _tree->access<double>(tx_rf_fe_root(chan) / "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
+ // its LO(s)
+ return _tree->access<double>(
+ tx_rf_fe_root(chan) / "freq" /" value"
+ ).get();
+ }
+ }
+
+ freq_range_t get_tx_lo_freq_range(
+ const std::string &name = ALL_LOS,
+ const size_t chan = 0
+ ) {
+ if (_tree->exists(tx_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(tx_rf_fe_root(chan) / "los")) {
+ return _tree->access<freq_range_t>(
+ tx_rf_fe_root(chan) / "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
+ // its LO(s)
+ return _tree->access<meta_range_t>(
+ tx_rf_fe_root(chan) / "freq" / "range"
+ ).get();
+ }
+ }
+
+ /**************************************************************************
+ * Gain control
+ *************************************************************************/
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) {