From b66f3701a7c3c34b08f3e977c385f8343fa2c852 Mon Sep 17 00:00:00 2001 From: Martin Braun Date: Mon, 30 Jul 2018 16:52:54 -0700 Subject: multi_usrp: Add sync_source API The sync_source API is an atomic setter for all sync-related settings. If supported by the underlying USRP, it can be faster to call set_sync_source() rather than sequentially calling set_clock_source() and set_time_source(). If the underlying device does not support the sync_source API, it will fall back to the set_clock_source() and set_time_source() APIs, making this change backward-compatiple. --- host/lib/usrp/multi_usrp.cpp | 166 +++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 160 insertions(+), 6 deletions(-) (limited to 'host/lib/usrp') diff --git a/host/lib/usrp/multi_usrp.cpp b/host/lib/usrp/multi_usrp.cpp index 4fb76cafa..019502ee7 100644 --- a/host/lib/usrp/multi_usrp.cpp +++ b/host/lib/usrp/multi_usrp.cpp @@ -722,7 +722,20 @@ public: void set_time_source(const std::string &source, const size_t mboard){ if (mboard != ALL_MBOARDS){ - _tree->access(mb_root(mboard) / "time_source" / "value").set(source); + const auto time_source_path = + mb_root(mboard) / "time_source/value"; + const auto sync_source_path = + mb_root(mboard) / "sync_source/value"; + if (_tree->exists(time_source_path)) { + _tree->access(time_source_path).set(source); + } else if (_tree->exists(sync_source_path)) { + auto sync_source = + _tree->access(sync_source_path).get(); + sync_source["time_source"] = source; + _tree->access(sync_source_path).set(sync_source); + } else { + throw uhd::runtime_error("Can't set time source on this device."); + } return; } for (size_t m = 0; m < get_num_mboards(); m++){ @@ -731,16 +744,53 @@ public: } std::string get_time_source(const size_t mboard){ - return _tree->access(mb_root(mboard) / "time_source" / "value").get(); + const auto time_source_path = mb_root(mboard) / "time_source/value"; + if (_tree->exists(time_source_path)) { + return _tree->access(time_source_path).get(); + } else if (_tree->exists(mb_root(mboard) / "sync_source/value")) { + auto sync_source = _tree->access( + mb_root(mboard) / "sync_source" / "value").get(); + if (sync_source.has_key("time_source")) { + return sync_source.get("time_source"); + } + } + throw uhd::runtime_error("Cannot query time_source on this device!"); } std::vector get_time_sources(const size_t mboard){ - return _tree->access >(mb_root(mboard) / "time_source" / "options").get(); + const auto time_source_path = mb_root(mboard) / "time_source/options"; + if (_tree->exists(time_source_path)) { + return _tree->access>(time_source_path) + .get(); + } else if (_tree->exists(mb_root(mboard) / "sync_source/options")) { + const auto sync_sources = get_sync_sources(mboard); + std::vector time_sources; + for (const auto& sync_source : sync_sources) { + if (sync_source.has_key("time_source")) { + time_sources.push_back(sync_source.get("time_source")); + } + } + } + throw uhd::runtime_error("Cannot query time_source on this device!"); } 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); + const auto clock_source_path = + mb_root(mboard) / "clock_source/value"; + const auto sync_source_path = + mb_root(mboard) / "sync_source/value"; + if (_tree->exists(clock_source_path)) { + _tree->access(clock_source_path).set(source); + } else if (_tree->exists(sync_source_path)) { + auto sync_source = + _tree->access(sync_source_path).get(); + sync_source["clock_source"] = source; + _tree->access(sync_source_path).set(sync_source); + } else { + throw uhd::runtime_error( + "Can't set clock source on this device."); + } return; } for (size_t m = 0; m < get_num_mboards(); m++){ @@ -749,11 +799,115 @@ public: } std::string get_clock_source(const size_t mboard){ - return _tree->access(mb_root(mboard) / "clock_source" / "value").get(); + const auto clock_source_path = mb_root(mboard) / "clock_source/value"; + if (_tree->exists(clock_source_path)) { + return _tree->access( + mb_root(mboard) / "clock_source" / "value").get(); + } else if (_tree->exists(mb_root(mboard) / "sync_source/value")) { + auto sync_source = _tree->access( + mb_root(mboard) / "sync_source" / "value").get(); + if (sync_source.has_key("clock_source")) { + return sync_source.get("clock_source"); + } + } + throw uhd::runtime_error("Cannot query clock_source on this device!"); + } + + void set_sync_source( + const std::string &clock_source, + const std::string &time_source, + const size_t mboard + ) { + device_addr_t sync_args; + sync_args["clock_source"] = clock_source; + sync_args["time_source"] = time_source; + set_sync_source(sync_args, mboard); + } + + void set_sync_source( + const device_addr_t& sync_source, + const size_t mboard + ) { + if (mboard != ALL_MBOARDS) { + const auto sync_source_path = + mb_root(mboard) / "sync_source/value"; + if (_tree->exists(sync_source_path)) { + _tree->access(sync_source_path) + .set(sync_source); + } else if (_tree->exists(mb_root(mboard) / "clock_source/value") + and _tree->exists(mb_root(mboard) / "time_source/value") + and sync_source.has_key("clock_source") + and sync_source.has_key("time_source")) { + const std::string clock_source = sync_source["clock_source"]; + const std::string time_source = sync_source["time_source"]; + set_clock_source(clock_source, mboard); + set_time_source(time_source, mboard); + } else { + throw uhd::runtime_error( + "Can't set sync source on this device."); + } + return; + } + for (size_t m = 0; m < get_num_mboards(); m++){ + this->set_sync_source(sync_source, m); + } + + } + + device_addr_t get_sync_source(const size_t mboard) + { + const auto sync_source_path = mb_root(mboard) / "sync_source/value"; + if (_tree->exists(sync_source_path)) { + return _tree->access(sync_source_path).get(); + } + // If this path is not there, we fall back to the oldschool method and + // convert to a new-fangled sync source dictionary + const std::string clock_source = get_clock_source(mboard); + const std::string time_source = get_time_source(mboard); + device_addr_t sync_source; + sync_source["clock_source"] = clock_source; + sync_source["time_source"] = time_source; + return sync_source; + } + + std::vector get_sync_sources(const size_t mboard) + { + const auto sync_source_path = mb_root(mboard) / "sync_source/options"; + if (_tree->exists(sync_source_path)) { + return _tree->access>(sync_source_path).get(); + } + // If this path is not there, we fall back to the oldschool method and + // convert to a new-fangled sync source dictionary + const auto clock_sources = get_clock_sources(mboard); + const auto time_sources = get_time_sources(mboard); + std::vector sync_sources; + for (const auto& clock_source : clock_sources) { + for (const auto& time_source : time_sources) { + device_addr_t sync_source; + sync_source["clock_source"] = clock_source; + sync_source["time_source"] = time_source; + sync_sources.push_back(sync_source); + } + } + + return sync_sources; } std::vector get_clock_sources(const size_t mboard){ - return _tree->access >(mb_root(mboard) / "clock_source" / "options").get(); + const auto clock_source_path = mb_root(mboard) / "clock_source/options"; + if (_tree->exists(clock_source_path)) { + return _tree->access>(clock_source_path) + .get(); + } else if (_tree->exists(mb_root(mboard) / "sync_source/options")) { + const auto sync_sources = get_sync_sources(mboard); + std::vector clock_sources; + for (const auto& sync_source : sync_sources) { + if (sync_source.has_key("clock_source")) { + clock_sources.push_back(sync_source.get("clock_source")); + } + } + } + throw uhd::runtime_error("Cannot query clock_source on this device!"); } void set_clock_source_out(const bool enb, const size_t mboard) -- cgit v1.2.3