aboutsummaryrefslogtreecommitdiffstats
path: root/host/lib
diff options
context:
space:
mode:
Diffstat (limited to 'host/lib')
-rw-r--r--host/lib/experts/expert_container.cpp13
-rw-r--r--host/lib/rfnoc/legacy_compat.cpp49
-rw-r--r--host/lib/usrp/dboard/db_twinrx.cpp6
-rw-r--r--host/lib/usrp/dboard/db_xcvr2450.cpp2
-rw-r--r--host/lib/usrp/dboard/twinrx/twinrx_experts.cpp32
-rw-r--r--host/lib/usrp/dboard/twinrx/twinrx_experts.hpp39
-rw-r--r--host/lib/usrp/x300/x300_radio_ctrl_impl.cpp39
-rw-r--r--host/lib/usrp/x300/x300_radio_ctrl_impl.hpp2
8 files changed, 158 insertions, 24 deletions
diff --git a/host/lib/experts/expert_container.cpp b/host/lib/experts/expert_container.cpp
index edfc2ebe3..78c783790 100644
--- a/host/lib/experts/expert_container.cpp
+++ b/host/lib/experts/expert_container.cpp
@@ -92,23 +92,28 @@ public:
boost::lock_guard<boost::recursive_mutex> resolve_lock(_resolve_mutex);
boost::lock_guard<boost::mutex> lock(_mutex);
EX_LOG(0, str(boost::format("resolve_all(%s)") % (force?"force":"")));
+ // Do a full resolve of the graph
_resolve_helper("", "", force);
}
- void resolve_from(const std::string& node_name)
+ void resolve_from(const std::string&)
{
boost::lock_guard<boost::recursive_mutex> resolve_lock(_resolve_mutex);
boost::lock_guard<boost::mutex> lock(_mutex);
EX_LOG(0, str(boost::format("resolve_from(%s)") % node_name));
- _resolve_helper(node_name, "", false);
+ // Do a full resolve of the graph
+ // Not optimizing the traversal using node_name to reduce experts complexity
+ _resolve_helper("", "", false);
}
- void resolve_to(const std::string& node_name)
+ void resolve_to(const std::string&)
{
boost::lock_guard<boost::recursive_mutex> resolve_lock(_resolve_mutex);
boost::lock_guard<boost::mutex> lock(_mutex);
EX_LOG(0, str(boost::format("resolve_to(%s)") % node_name));
- _resolve_helper("", node_name, false);
+ // Do a full resolve of the graph
+ // Not optimizing the traversal using node_name to reduce experts complexity
+ _resolve_helper("", "", false);
}
dag_vertex_t& retrieve(const std::string& name) const
diff --git a/host/lib/rfnoc/legacy_compat.cpp b/host/lib/rfnoc/legacy_compat.cpp
index 2c8e10c4a..20553062f 100644
--- a/host/lib/rfnoc/legacy_compat.cpp
+++ b/host/lib/rfnoc/legacy_compat.cpp
@@ -16,6 +16,7 @@
//
#include "legacy_compat.hpp"
+#include "../usrp/device3/device3_impl.hpp"
#include <uhd/property_tree.hpp>
#include <uhd/rfnoc/radio_ctrl.hpp>
#include <uhd/rfnoc/ddc_block_ctrl.hpp>
@@ -171,6 +172,13 @@ public:
/************************************************************************
* API Calls
***********************************************************************/
+ inline uhd::fs_path rx_dsp_root(const size_t mboard_idx, const size_t dsp_index, const size_t port_index)
+ {
+ return mb_root(mboard_idx) / "xbar" /
+ str(boost::format("%s_%d") % DDC_BLOCK_NAME % dsp_index) /
+ "legacy_api" / port_index;
+ }
+
uhd::fs_path rx_dsp_root(const size_t mboard_idx, const size_t chan)
{
// The DSP index is the same as the radio index
@@ -181,8 +189,13 @@ public:
return mb_root(mboard_idx) / "rx_dsps" / dsp_index / port_index;
}
+ return rx_dsp_root(mboard_idx, dsp_index, port_index);
+ }
+
+ inline uhd::fs_path tx_dsp_root(const size_t mboard_idx, const size_t dsp_index, const size_t port_index)
+ {
return mb_root(mboard_idx) / "xbar" /
- str(boost::format("%s_%d") % DDC_BLOCK_NAME % dsp_index) /
+ str(boost::format("%s_%d") % DUC_BLOCK_NAME % dsp_index) /
"legacy_api" / port_index;
}
@@ -196,9 +209,7 @@ public:
return mb_root(mboard_idx) / "tx_dsps" / dsp_index / port_index;
}
- return mb_root(mboard_idx) / "xbar" /
- str(boost::format("%s_%d") % DUC_BLOCK_NAME % dsp_index) /
- "legacy_api" / port_index;
+ return tx_dsp_root(mboard_idx, dsp_index, port_index);
}
uhd::fs_path rx_fe_root(const size_t mboard_idx, const size_t chan)
@@ -511,6 +522,20 @@ private: // methods
;
}
}
+ } else {
+ for (size_t dsp_idx = 0; dsp_idx < _num_radios_per_board; dsp_idx++) {
+ for (size_t chan = 0; chan < _num_rx_chans_per_radio; chan++) {
+ _tree->access<double>(rx_dsp_root(mboard_idx, dsp_idx, chan) / "rate/value")
+ .add_coerced_subscriber(
+ boost::bind(
+ &uhd::usrp::device3_impl::update_rx_streamers,
+ boost::dynamic_pointer_cast<uhd::usrp::device3_impl>(_device),
+ _1
+ )
+ )
+ ;
+ }
+ }
}
if (not _has_ducs) {
for (size_t radio_idx = 0; radio_idx < _num_radios_per_board; radio_idx++) {
@@ -544,7 +569,21 @@ private: // methods
;
}
}
- }
+ } else {
+ for (size_t dsp_idx = 0; dsp_idx < _num_radios_per_board; dsp_idx++) {
+ for (size_t chan = 0; chan < _num_tx_chans_per_radio; chan++) {
+ _tree->access<double>(tx_dsp_root(mboard_idx, dsp_idx, chan) / "rate/value")
+ .add_coerced_subscriber(
+ boost::bind(
+ &uhd::usrp::device3_impl::update_tx_streamers,
+ boost::dynamic_pointer_cast<uhd::usrp::device3_impl>(_device),
+ _1
+ )
+ )
+ ;
+ }
+ }
+ } /* if not _has_ducs */
}
}
diff --git a/host/lib/usrp/dboard/db_twinrx.cpp b/host/lib/usrp/dboard/db_twinrx.cpp
index e960f134f..477412de0 100644
--- a/host/lib/usrp/dboard/db_twinrx.cpp
+++ b/host/lib/usrp/dboard/db_twinrx.cpp
@@ -75,6 +75,11 @@ public:
get_rx_subtree()->create<meta_range_t>("bandwidth/range")
.set(freq_range_t(BW, BW));
+ // Command Time
+ expert_factory::add_data_node<time_spec_t>(_expert, prepend_ch("time/rx_frontend", _ch_name), time_spec_t(0.0));
+ expert_factory::add_prop_node<time_spec_t>(_expert, get_rx_subtree(),
+ "time/cmd", prepend_ch("time/cmd", _ch_name), time_spec_t(0.0));
+
//Frequency Specific
get_rx_subtree()->create<meta_range_t>("freq/range")
.set(freq_range_t(10e6, 6.0e9));
@@ -263,6 +268,7 @@ public:
expert_factory::add_worker_node<twinrx_freq_path_expert>(_expert, _expert->node_retriever(), fe);
expert_factory::add_worker_node<twinrx_freq_coercion_expert>(_expert, _expert->node_retriever(), fe);
expert_factory::add_worker_node<twinrx_chan_gain_expert>(_expert, _expert->node_retriever(), fe);
+ expert_factory::add_worker_node<twinrx_scheduling_expert>(_expert, _expert->node_retriever(), fe);
expert_factory::add_worker_node<twinrx_nyquist_expert>(_expert, _expert->node_retriever(), fe, _db_iface);
}
diff --git a/host/lib/usrp/dboard/db_xcvr2450.cpp b/host/lib/usrp/dboard/db_xcvr2450.cpp
index aa0bae8b8..0f839b03e 100644
--- a/host/lib/usrp/dboard/db_xcvr2450.cpp
+++ b/host/lib/usrp/dboard/db_xcvr2450.cpp
@@ -372,7 +372,7 @@ double xcvr2450::set_lo_freq_core(double target_freq){
//variables used in the calculation below
double scaler = xcvr2450::is_highband(target_freq)? (4.0/5.0) : (4.0/3.0);
double ref_freq = this->get_iface()->get_clock_rate(dboard_iface::UNIT_TX);
- int R, intdiv, fracdiv;
+ int R, intdiv = 131, fracdiv = 0;
//loop through values until we get a match
for(_ad9515div = 2; _ad9515div <= 3; _ad9515div++){
diff --git a/host/lib/usrp/dboard/twinrx/twinrx_experts.cpp b/host/lib/usrp/dboard/twinrx/twinrx_experts.cpp
index ddaa4211e..3b41972da 100644
--- a/host/lib/usrp/dboard/twinrx/twinrx_experts.cpp
+++ b/host/lib/usrp/dboard/twinrx/twinrx_experts.cpp
@@ -30,6 +30,17 @@ using namespace uhd::math;
using namespace uhd::usrp::dboard::twinrx;
/*!---------------------------------------------------------
+ * twinrx_scheduling_expert::resolve
+ * ---------------------------------------------------------
+ */
+void twinrx_scheduling_expert::resolve()
+{
+ // Currently a straight pass-through. To be expanded as needed
+ // when more advanced scheduling is needed
+ _rx_frontend_time = _command_time;
+}
+
+/*!---------------------------------------------------------
* twinrx_freq_path_expert::resolve
* ---------------------------------------------------------
*/
@@ -222,6 +233,19 @@ void twinrx_freq_coercion_expert::resolve()
*/
void twinrx_nyquist_expert::resolve()
{
+ // Do not execute when clear_command_time is called.
+ // This is a transition of the command time from non-zero to zero.
+ if (_rx_frontend_time == time_spec_t(0.0) and _cached_cmd_time != time_spec_t(0.0)) {
+ _cached_cmd_time = _rx_frontend_time;
+ return;
+ }
+
+ // Do not execute twice for the same command time unless untimed
+ if (_rx_frontend_time == _cached_cmd_time and _rx_frontend_time != time_spec_t(0.0)) {
+ return;
+ }
+ _cached_cmd_time = _rx_frontend_time;
+
double if_freq_sign = 1.0;
if (_lo1_inj_side == INJ_HIGH_SIDE) if_freq_sign *= -1.0;
if (_lo2_inj_side == INJ_HIGH_SIDE) if_freq_sign *= -1.0;
@@ -570,10 +594,6 @@ void twinrx_settings_expert::_resolve_lox_freq(
ch0_freq_c = _set_lox_synth_freq(lo_stage, twinrx_ctrl::CH2, ch0_freq_d);
} else if (synth0_mapping == MAPPING_SHARED or synth1_mapping == MAPPING_SHARED) {
// If any synthesizer is being shared then we are not in hopping mode
- if (rf_freq_ppm_t(ch0_freq_d) != ch1_freq_d) {
- UHD_MSG(warning) <<
- "Incompatible RF/LO frequencies for LO sharing. Using Ch0 settings for both channels.";
- }
twinrx_ctrl::channel_t ch = (synth0_mapping == MAPPING_SHARED) ? twinrx_ctrl::CH1 : twinrx_ctrl::CH2;
ch0_freq_c = _set_lox_synth_freq(lo_stage, ch, ch0_freq_d);
ch1_freq_c = ch0_freq_c;
@@ -597,10 +617,6 @@ void twinrx_settings_expert::_resolve_lox_freq(
ch1_freq_c = _set_lox_synth_freq(lo_stage, twinrx_ctrl::CH2, ch1_freq_d);
} else if (synth0_mapping == MAPPING_SHARED or synth1_mapping == MAPPING_SHARED) {
// If any synthesizer is being shared then we are not in hopping mode
- if (rf_freq_ppm_t(ch0_freq_d) != ch1_freq_d) {
- UHD_MSG(warning) <<
- "Incompatible RF/LO frequencies for LO sharing. Using Ch0 settings for both channels.";
- }
twinrx_ctrl::channel_t ch = (synth0_mapping == MAPPING_SHARED) ? twinrx_ctrl::CH1 : twinrx_ctrl::CH2;
ch0_freq_c = _set_lox_synth_freq(lo_stage, ch, ch0_freq_d);
ch1_freq_c = ch0_freq_c;
diff --git a/host/lib/usrp/dboard/twinrx/twinrx_experts.hpp b/host/lib/usrp/dboard/twinrx/twinrx_experts.hpp
index 1617c9c80..9c83dbfa8 100644
--- a/host/lib/usrp/dboard/twinrx/twinrx_experts.hpp
+++ b/host/lib/usrp/dboard/twinrx/twinrx_experts.hpp
@@ -52,6 +52,38 @@ static const std::string lo_stage_str(lo_stage_t stage, bool lower = false) {
return prefix + ((stage == STAGE_LO1) ? "1" : "2");
}
+
+/*!---------------------------------------------------------
+ * twinrx_scheduling_expert
+ *
+ * This expert is responsible for scheduling time sensitive actions
+ * in other experts. It responds to changes in the command time and
+ * selectively causes experts to run in order to ensure a synchronized
+ * system.
+ *
+ * ---------------------------------------------------------
+ */
+class twinrx_scheduling_expert : public experts::worker_node_t {
+public:
+ twinrx_scheduling_expert(const experts::node_retriever_t& db, std::string ch)
+ : experts::worker_node_t(prepend_ch("twinrx_scheduling_expert", ch)),
+ _command_time (db, prepend_ch("time/cmd", ch)),
+ _rx_frontend_time (db, prepend_ch("time/rx_frontend", ch))
+ {
+ bind_accessor(_command_time);
+ bind_accessor(_rx_frontend_time);
+ }
+
+private:
+ virtual void resolve();
+
+ //Inputs
+ experts::data_reader_t<time_spec_t> _command_time;
+
+ //Outputs
+ experts::data_writer_t<time_spec_t> _rx_frontend_time;
+};
+
/*!---------------------------------------------------------
* twinrx_freq_path_expert
*
@@ -271,6 +303,7 @@ public:
_if_freq_d (db, prepend_ch("if_freq/desired", ch)),
_lo1_inj_side (db, prepend_ch("ch/LO1/inj_side", ch)),
_lo2_inj_side (db, prepend_ch("ch/LO2/inj_side", ch)),
+ _rx_frontend_time (db, prepend_ch("time/rx_frontend", ch)),
_if_freq_c (db, prepend_ch("if_freq/coerced", ch)),
_db_iface (db_iface)
{
@@ -280,6 +313,7 @@ public:
bind_accessor(_lo1_inj_side);
bind_accessor(_lo2_inj_side);
bind_accessor(_if_freq_c);
+ bind_accessor(_rx_frontend_time);
}
private:
@@ -293,9 +327,14 @@ private:
experts::data_reader_t<double> _if_freq_d;
experts::data_reader_t<lo_inj_side_t> _lo1_inj_side;
experts::data_reader_t<lo_inj_side_t> _lo2_inj_side;
+ experts::data_reader_t<time_spec_t> _rx_frontend_time;
+
//Outputs
experts::data_writer_t<double> _if_freq_c;
dboard_iface::sptr _db_iface;
+
+ //Misc
+ time_spec_t _cached_cmd_time;
};
/*!---------------------------------------------------------
diff --git a/host/lib/usrp/x300/x300_radio_ctrl_impl.cpp b/host/lib/usrp/x300/x300_radio_ctrl_impl.cpp
index f14ea3fd9..991b97696 100644
--- a/host/lib/usrp/x300/x300_radio_ctrl_impl.cpp
+++ b/host/lib/usrp/x300/x300_radio_ctrl_impl.cpp
@@ -120,6 +120,15 @@ UHD_RFNOC_RADIO_BLOCK_CONSTRUCTOR(x300_radio_ctrl)
_tx_fe_map[i].core->set_dc_offset(tx_frontend_core_200::DEFAULT_DC_OFFSET_VALUE);
_tx_fe_map[i].core->set_iq_balance(tx_frontend_core_200::DEFAULT_IQ_BALANCE_VALUE);
_tx_fe_map[i].core->populate_subtree(_tree->subtree(_root_path / "tx_fe_corrections" / i));
+
+ ////////////////////////////////////////////////////////////////
+ // Bind the daughterboard command time to the motherboard level property
+ ////////////////////////////////////////////////////////////////
+
+ if (_tree->exists(fs_path("time") / "cmd")) {
+ _tree->access<time_spec_t>(fs_path("time") / "cmd")
+ .add_coerced_subscriber(boost::bind(&x300_radio_ctrl_impl::set_fe_cmd_time, this, _1, i));
+ }
}
////////////////////////////////////////////////////////////////
@@ -163,6 +172,13 @@ double x300_radio_ctrl_impl::set_rate(double /* rate */)
return get_rate();
}
+time_spec_t x300_radio_ctrl_impl::set_fe_cmd_time(const time_spec_t &time, const size_t chan)
+{
+ return _tree->access<time_spec_t>(
+ fs_path("dboards" / _radio_slot / "rx_frontends" / _rx_fe_map.at(chan).db_fe_name / "time" / "cmd")
+ ).set(time).get();
+}
+
void x300_radio_ctrl_impl::set_tx_antenna(const std::string &ant, const size_t chan)
{
_tree->access<std::string>(
@@ -399,14 +415,25 @@ void x300_radio_ctrl_impl::setup_radio(
//bind frontend corrections to the dboard freq props
const fs_path db_tx_fe_path = db_path / "tx_frontends";
- BOOST_FOREACH(const std::string &name, _tree->list(db_tx_fe_path)) {
- _tree->access<double>(db_tx_fe_path / name / "freq" / "value")
- .add_coerced_subscriber(boost::bind(&x300_radio_ctrl_impl::set_tx_fe_corrections, this, db_path, _root_path / "tx_fe_corrections" / name, _1));
+ if (not _tx_fe_map.empty()) {
+ for (size_t i = 0; i < _get_num_radios(); i++) {
+ if (_tree->exists(db_tx_fe_path / _tx_fe_map[i].db_fe_name / "freq" / "value")) {
+ _tree->access<double>(db_tx_fe_path / _tx_fe_map[i].db_fe_name / "freq" / "value")
+ .add_coerced_subscriber(boost::bind(&x300_radio_ctrl_impl::set_tx_fe_corrections, this, db_path,
+ _root_path / "tx_fe_corrections" / _tx_fe_map[i].db_fe_name, _1));
+ }
+ }
}
const fs_path db_rx_fe_path = db_path / "rx_frontends";
- BOOST_FOREACH(const std::string &name, _tree->list(db_rx_fe_path)) {
- _tree->access<double>(db_rx_fe_path / name / "freq" / "value")
- .add_coerced_subscriber(boost::bind(&x300_radio_ctrl_impl::set_rx_fe_corrections, this, db_path, _root_path / "rx_fe_corrections" / name,_1));
+ if (not _rx_fe_map.empty()) {
+ for (size_t i = 0; i < _get_num_radios(); i++) {
+ if (_tree->exists(db_rx_fe_path / _tx_fe_map[i].db_fe_name / "freq" / "value")) {
+ _tree->access<double>(db_rx_fe_path / _tx_fe_map[i].db_fe_name / "freq" / "value")
+ .add_coerced_subscriber(boost::bind(&x300_radio_ctrl_impl::set_rx_fe_corrections, this, db_path,
+ _root_path / "rx_fe_corrections" / _tx_fe_map[i].db_fe_name,
+ _1));
+ }
+ }
}
////////////////////////////////////////////////////////////////
diff --git a/host/lib/usrp/x300/x300_radio_ctrl_impl.hpp b/host/lib/usrp/x300/x300_radio_ctrl_impl.hpp
index 65d4443eb..5b9d47841 100644
--- a/host/lib/usrp/x300/x300_radio_ctrl_impl.hpp
+++ b/host/lib/usrp/x300/x300_radio_ctrl_impl.hpp
@@ -161,6 +161,8 @@ private:
void set_rx_fe_corrections(const uhd::fs_path &db_path, const uhd::fs_path &rx_fe_corr_path, const double lo_freq);
void set_tx_fe_corrections(const uhd::fs_path &db_path, const uhd::fs_path &tx_fe_corr_path, const double lo_freq);
+ time_spec_t set_fe_cmd_time(const time_spec_t &time, const size_t chan);
+
private: // members
enum radio_connection_t { PRIMARY, SECONDARY };