aboutsummaryrefslogtreecommitdiffstats
path: root/host
diff options
context:
space:
mode:
Diffstat (limited to 'host')
-rw-r--r--host/include/uhd/rfnoc/duc_block_control.hpp7
-rw-r--r--host/lib/rfnoc/ddc_block_control.cpp3
-rw-r--r--host/lib/rfnoc/duc_block_control.cpp7
-rw-r--r--host/tests/rfnoc_block_tests/duc_block_test.cpp28
4 files changed, 32 insertions, 13 deletions
diff --git a/host/include/uhd/rfnoc/duc_block_control.hpp b/host/include/uhd/rfnoc/duc_block_control.hpp
index cf9d3a5d7..7e398454d 100644
--- a/host/include/uhd/rfnoc/duc_block_control.hpp
+++ b/host/include/uhd/rfnoc/duc_block_control.hpp
@@ -78,6 +78,13 @@ public:
/*! Return the range of frequencies that \p chan can be set to.
*
+ * The frequency shifter is the last component in the DUC, and thus can
+ * shift frequencies (digitally) between -get_output_rate()/2
+ * and +get_output_rate()/2.
+ *
+ * The returned values are in Hz (not normalized frequencies) and are valid
+ * inputs for set_freq().
+ *
* \return The range of frequencies that the DUC can shift the input by
*/
virtual uhd::freq_range_t get_frequency_range(const size_t chan) const = 0;
diff --git a/host/lib/rfnoc/ddc_block_control.cpp b/host/lib/rfnoc/ddc_block_control.cpp
index 3326d4e46..dbcb1b763 100644
--- a/host/lib/rfnoc/ddc_block_control.cpp
+++ b/host/lib/rfnoc/ddc_block_control.cpp
@@ -126,8 +126,7 @@ public:
uhd::freq_range_t get_frequency_range(const size_t chan) const override
{
- const double input_rate =
- _samp_rate_in.at(chan).is_valid() ? _samp_rate_in.at(chan).get() : 1.0;
+ const double input_rate = get_input_rate(chan);
// TODO add steps
return uhd::freq_range_t(-input_rate / 2, input_rate / 2);
}
diff --git a/host/lib/rfnoc/duc_block_control.cpp b/host/lib/rfnoc/duc_block_control.cpp
index 12937ac21..674e9d309 100644
--- a/host/lib/rfnoc/duc_block_control.cpp
+++ b/host/lib/rfnoc/duc_block_control.cpp
@@ -123,10 +123,9 @@ public:
uhd::freq_range_t get_frequency_range(const size_t chan) const override
{
- const double input_rate =
- _samp_rate_in.at(chan).is_valid() ? _samp_rate_in.at(chan).get() : 1.0;
+ const double output_rate = get_output_rate(chan);
// TODO add steps
- return uhd::freq_range_t(-input_rate / 2, input_rate / 2);
+ return uhd::freq_range_t(-output_rate / 2, output_rate / 2);
}
double get_input_rate(const size_t chan) const override
@@ -241,7 +240,7 @@ private:
* Add resolvers
*********************************************************************/
// Resolver for _interp: this gets executed when the user directly
- // modifies interp. the desired behaviour is to coerce it first, then
+ // modifies 'interp'. The desired behaviour is to coerce it first, then
// keep the output rate constant, and re-calculate the input rate.
add_property_resolver({interp, scaling_in},
{interp, samp_rate_out, samp_rate_in, scaling_in},
diff --git a/host/tests/rfnoc_block_tests/duc_block_test.cpp b/host/tests/rfnoc_block_tests/duc_block_test.cpp
index 78e988713..6c92c9d91 100644
--- a/host/tests/rfnoc_block_tests/duc_block_test.cpp
+++ b/host/tests/rfnoc_block_tests/duc_block_test.cpp
@@ -34,6 +34,7 @@ BOOST_AUTO_TEST_CASE(test_duc_block)
constexpr size_t num_chans = 4;
constexpr noc_id_t noc_id = DUC_BLOCK;
constexpr int TEST_INTERP = 20; // 2 halfbands, CIC==5
+ constexpr double DEFAULT_RATE = 200e6; // Matches typical MCR of X310
auto block_container = get_mock_block(noc_id, num_chans, num_chans);
auto& duc_reg_iface = block_container.reg_iface;
@@ -70,14 +71,21 @@ BOOST_AUTO_TEST_CASE(test_duc_block)
mock_source_term.set_edge_property<double>(
"scaling", 1.0, {res_source_info::OUTPUT_EDGE, 0});
mock_source_term.set_edge_property<double>(
- "samp_rate", 1.0, {res_source_info::OUTPUT_EDGE, 0});
+ "samp_rate", DEFAULT_RATE / TEST_INTERP, {res_source_info::OUTPUT_EDGE, 0});
UHD_LOG_INFO("TEST", "Priming mock sink node props");
mock_sink_term.set_edge_property<std::string>(
"type", "sc16", {res_source_info::INPUT_EDGE, 0});
mock_sink_term.set_edge_property<double>(
"scaling", 1.0, {res_source_info::INPUT_EDGE, 0});
mock_sink_term.set_edge_property<double>(
- "samp_rate", 1.0, {res_source_info::INPUT_EDGE, 0});
+ "samp_rate", DEFAULT_RATE, {res_source_info::INPUT_EDGE, 0});
+
+#define CHECK_OUTPUT_RATE(req_rate) \
+ BOOST_REQUIRE_CLOSE(mock_sink_term.get_edge_property<double>( \
+ "samp_rate", {res_source_info::INPUT_EDGE, 0}), \
+ req_rate, \
+ 1e-6);
+
UHD_LOG_INFO("TEST", "Creating graph...");
graph.connect(&mock_source_term, test_duc.get(), edge_info);
@@ -85,6 +93,7 @@ BOOST_AUTO_TEST_CASE(test_duc_block)
UHD_LOG_INFO("TEST", "Committing graph...");
graph.commit();
UHD_LOG_INFO("TEST", "Commit complete.");
+ CHECK_OUTPUT_RATE(DEFAULT_RATE);
// We need to set the interpation again, because the rates will screw it
// change it w.r.t. to the previous setting
test_duc->set_property<int>("interp", TEST_INTERP, 0);
@@ -94,6 +103,8 @@ BOOST_AUTO_TEST_CASE(test_duc_block)
* TEST_INTERP
== mock_sink_term.get_edge_property<double>(
"samp_rate", {res_source_info::INPUT_EDGE, 0}));
+ // Output rate should remain unchanged
+ CHECK_OUTPUT_RATE(DEFAULT_RATE);
const double initial_input_scaling = mock_source_term.get_edge_property<double>(
"scaling", {res_source_info::OUTPUT_EDGE, 0});
const double initial_output_scaling = mock_sink_term.get_edge_property<double>(
@@ -122,25 +133,28 @@ BOOST_AUTO_TEST_CASE(test_duc_block)
"scaling", {res_source_info::OUTPUT_EDGE, 0});
BOOST_CHECK_EQUAL(doubled_input_scaling, 2 * initial_input_scaling);
- UHD_LOG_INFO("TEST", "Setting freq to 1/8 of input rate");
- constexpr double TEST_FREQ = 1.0 / 8;
+ BOOST_CHECK_CLOSE(test_duc->get_frequency_range(0).start(), -DEFAULT_RATE / 2, 1e-6);
+ BOOST_CHECK_CLOSE(test_duc->get_frequency_range(0).stop(), DEFAULT_RATE / 2, 1e-6);
+ UHD_LOG_INFO("TEST",
+ "Setting freq to 1/8 of input rate (to " << (DEFAULT_RATE / 8) / 1e6 << " MHz)");
+ constexpr double TEST_FREQ = DEFAULT_RATE / 8;
test_duc->set_property<double>("freq", TEST_FREQ, 0);
const uint32_t freq_word_1 =
duc_reg_iface->write_memory.at(duc_block_control::SR_FREQ_ADDR);
BOOST_REQUIRE(freq_word_1 != 0);
- UHD_LOG_INFO("TEST", "Doubling input rate (to 2.0)");
+ UHD_LOG_INFO(
+ "TEST", "Doubling input rate (to " << (DEFAULT_RATE / 4) / 1e6 << " MHz)");
// Now this should change the freq word, but not the absolute frequency
mock_sink_term.set_edge_property<double>("samp_rate",
2
* mock_sink_term.get_edge_property<double>(
- "samp_rate", {res_source_info::INPUT_EDGE, 0}),
+ "samp_rate", {res_source_info::INPUT_EDGE, 0}),
{res_source_info::INPUT_EDGE, 0});
const double freq_word_2 =
duc_reg_iface->write_memory.at(duc_block_control::SR_FREQ_ADDR);
// The frequency word is the phase increment, which will halve. We skirt
// around fixpoint/floating point accuracy issues by using CLOSE.
BOOST_CHECK_CLOSE(double(freq_word_1) / double(freq_word_2), 2.0, 1e-6);
-
// Reset the interpolation
test_duc->set_property<int>("interp", TEST_INTERP, 0);
BOOST_REQUIRE_EQUAL(test_duc->get_property<int>("interp", 0), TEST_INTERP);