aboutsummaryrefslogtreecommitdiffstats
path: root/host/lib/rfnoc/ddc_block_ctrl_impl.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'host/lib/rfnoc/ddc_block_ctrl_impl.cpp')
-rw-r--r--host/lib/rfnoc/ddc_block_ctrl_impl.cpp226
1 files changed, 113 insertions, 113 deletions
diff --git a/host/lib/rfnoc/ddc_block_ctrl_impl.cpp b/host/lib/rfnoc/ddc_block_ctrl_impl.cpp
index 7ea81e255..f115a876b 100644
--- a/host/lib/rfnoc/ddc_block_ctrl_impl.cpp
+++ b/host/lib/rfnoc/ddc_block_ctrl_impl.cpp
@@ -4,14 +4,14 @@
// SPDX-License-Identifier: GPL-3.0-or-later
//
-#include <uhd/rfnoc/ddc_block_ctrl.hpp>
-#include <uhd/utils/log.hpp>
#include <uhd/convert.hpp>
+#include <uhd/rfnoc/ddc_block_ctrl.hpp>
#include <uhd/types/ranges.hpp>
+#include <uhd/utils/log.hpp>
+#include <uhdlib/usrp/cores/dsp_core_utils.hpp>
+#include <uhdlib/utils/compat_check.hpp>
#include <uhdlib/utils/math.hpp>
#include <uhdlib/utils/narrow.hpp>
-#include <uhdlib/utils/compat_check.hpp>
-#include <uhdlib/usrp/cores/dsp_core_utils.hpp>
#include <boost/math/special_functions/round.hpp>
#include <cmath>
@@ -21,20 +21,20 @@ class ddc_block_ctrl_impl : public ddc_block_ctrl
{
public:
UHD_RFNOC_BLOCK_CONSTRUCTOR(ddc_block_ctrl)
- , _fpga_compat(user_reg_read64(RB_REG_COMPAT_NUM))
- , _num_halfbands(uhd::narrow_cast<size_t>(
- user_reg_read64(RB_REG_NUM_HALFBANDS)))
- , _cic_max_decim(uhd::narrow_cast<size_t>(
- user_reg_read64(RB_REG_CIC_MAX_DECIM)))
+ , _fpga_compat(user_reg_read64(RB_REG_COMPAT_NUM)),
+ _num_halfbands(uhd::narrow_cast<size_t>(user_reg_read64(RB_REG_NUM_HALFBANDS))),
+ _cic_max_decim(uhd::narrow_cast<size_t>(user_reg_read64(RB_REG_CIC_MAX_DECIM)))
{
UHD_LOG_DEBUG(unique_id(),
- "Loading DDC with " << get_num_halfbands() << " halfbands and "
- "max CIC decimation " << get_cic_max_decim()
- );
- uhd::assert_fpga_compat(
- MAJOR_COMP, MINOR_COMP,
+ "Loading DDC with " << get_num_halfbands()
+ << " halfbands and "
+ "max CIC decimation "
+ << get_cic_max_decim());
+ uhd::assert_fpga_compat(MAJOR_COMP,
+ MINOR_COMP,
_fpga_compat,
- "DDC", "DDC",
+ "DDC",
+ "DDC",
false /* Let it slide if minors mismatch */
);
@@ -42,76 +42,64 @@ public:
for (size_t chan = 0; chan < get_input_ports().size(); chan++) {
const double default_freq = get_arg<double>("freq", chan);
_tree->access<double>(get_arg_path("freq/value", chan))
- .set_coercer([this, chan](const double value){
+ .set_coercer([this, chan](const double value) {
return this->set_freq(value, chan);
})
.set(default_freq);
;
- const double default_output_rate =
- get_arg<double>("output_rate", chan);
+ const double default_output_rate = get_arg<double>("output_rate", chan);
_tree->access<double>(get_arg_path("output_rate/value", chan))
- .set_coercer([this, chan](const double value){
+ .set_coercer([this, chan](const double value) {
return this->set_output_rate(value, chan);
})
- .set(default_output_rate)
- ;
+ .set(default_output_rate);
_tree->access<double>(get_arg_path("input_rate/value", chan))
- .add_coerced_subscriber([this, chan](const double rate){
+ .add_coerced_subscriber([this, chan](const double rate) {
this->set_input_rate(rate, chan);
- })
- ;
+ });
// Legacy properties (for backward compat w/ multi_usrp)
const uhd::fs_path dsp_base_path = _root_path / "legacy_api" / chan;
// Legacy properties simply forward to the block args properties
_tree->create<double>(dsp_base_path / "rate/value")
- .set_coercer([this, chan](const double value){
- return this->_tree->access<double>(
- this->get_arg_path("output_rate/value", chan)
- ).set(value).get();
+ .set_coercer([this, chan](const double value) {
+ return this->_tree
+ ->access<double>(this->get_arg_path("output_rate/value", chan))
+ .set(value)
+ .get();
})
- .set_publisher([this, chan](){
- return this->_tree->access<double>(
- this->get_arg_path("output_rate/value", chan)
- ).get();
- })
- ;
+ .set_publisher([this, chan]() {
+ return this->_tree
+ ->access<double>(this->get_arg_path("output_rate/value", chan))
+ .get();
+ });
_tree->create<uhd::meta_range_t>(dsp_base_path / "rate/range")
- .set_publisher([this](){
- return get_output_rates();
- })
- ;
+ .set_publisher([this]() { return get_output_rates(); });
_tree->create<double>(dsp_base_path / "freq/value")
- .set_coercer([this, chan](const double value){
- return this->_tree->access<double>(
- this->get_arg_path("freq/value", chan)
- ).set(value).get();
- })
- .set_publisher([this, chan](){
- return this->_tree->access<double>(
- this->get_arg_path("freq/value", chan)
- ).get();
+ .set_coercer([this, chan](const double value) {
+ return this->_tree
+ ->access<double>(this->get_arg_path("freq/value", chan))
+ .set(value)
+ .get();
})
- ;
+ .set_publisher([this, chan]() {
+ return this->_tree
+ ->access<double>(this->get_arg_path("freq/value", chan))
+ .get();
+ });
_tree->create<uhd::meta_range_t>(dsp_base_path / "freq/range")
- .set_publisher([this](){
- return get_freq_range();
- })
- ;
+ .set_publisher([this]() { return get_freq_range(); });
_tree->access<uhd::time_spec_t>("time/cmd")
- .add_coerced_subscriber([this, chan](const uhd::time_spec_t time_spec){
+ .add_coerced_subscriber([this, chan](const uhd::time_spec_t time_spec) {
this->set_command_time(time_spec, chan);
- })
- ;
+ });
if (_tree->exists("tick_rate")) {
- const double tick_rate =
- _tree->access<double>("tick_rate").get();
+ const double tick_rate = _tree->access<double>("tick_rate").get();
set_command_tick_rate(tick_rate, chan);
_tree->access<double>("tick_rate")
- .add_coerced_subscriber([this, chan](const double rate){
+ .add_coerced_subscriber([this, chan](const double rate) {
this->set_command_tick_rate(rate, chan);
- })
- ;
+ });
}
// Rate 1:1 by default
@@ -123,25 +111,25 @@ public:
virtual ~ddc_block_ctrl_impl() {}
- double get_output_scale_factor(size_t port=ANY_PORT)
+ double get_output_scale_factor(size_t port = ANY_PORT)
{
port = port == ANY_PORT ? 0 : port;
- if (not (_rx_streamer_active.count(port) and _rx_streamer_active.at(port))) {
+ if (not(_rx_streamer_active.count(port) and _rx_streamer_active.at(port))) {
return SCALE_UNDEFINED;
}
return get_arg<double>("scalar_correction", port);
}
- double get_input_samp_rate(size_t port=ANY_PORT)
+ double get_input_samp_rate(size_t port = ANY_PORT)
{
port = port == ANY_PORT ? 0 : port;
- if (not (_tx_streamer_active.count(port) and _tx_streamer_active.at(port))) {
+ if (not(_tx_streamer_active.count(port) and _tx_streamer_active.at(port))) {
return RATE_UNDEFINED;
}
return get_arg<double>("input_rate", port);
}
- double get_output_samp_rate(size_t port=ANY_PORT)
+ double get_output_samp_rate(size_t port = ANY_PORT)
{
if (port == ANY_PORT) {
port = 0;
@@ -161,28 +149,28 @@ public:
set_command_tick_rate(tick_rate, port);
}
- if (not (_rx_streamer_active.count(port) and _rx_streamer_active.at(port))) {
+ if (not(_rx_streamer_active.count(port) and _rx_streamer_active.at(port))) {
return RATE_UNDEFINED;
}
return get_arg<double>("output_rate", port);
}
- void issue_stream_cmd(
- const uhd::stream_cmd_t &stream_cmd_,
- const size_t chan
- ) {
- UHD_RFNOC_BLOCK_TRACE() << "ddc_block_ctrl_base::issue_stream_cmd()" ;
+ void issue_stream_cmd(const uhd::stream_cmd_t& stream_cmd_, const size_t chan)
+ {
+ UHD_RFNOC_BLOCK_TRACE() << "ddc_block_ctrl_base::issue_stream_cmd()";
if (list_upstream_nodes().count(chan) == 0) {
- UHD_LOGGER_INFO("RFNOC") << "No upstream blocks." ;
+ UHD_LOGGER_INFO("RFNOC") << "No upstream blocks.";
return;
}
uhd::stream_cmd_t stream_cmd = stream_cmd_;
- if (stream_cmd.stream_mode == uhd::stream_cmd_t::STREAM_MODE_NUM_SAMPS_AND_DONE or
- stream_cmd.stream_mode == uhd::stream_cmd_t::STREAM_MODE_NUM_SAMPS_AND_MORE) {
- size_t decimation = get_arg<double>("input_rate", chan) / get_arg<double>("output_rate", chan);
+ if (stream_cmd.stream_mode == uhd::stream_cmd_t::STREAM_MODE_NUM_SAMPS_AND_DONE
+ or stream_cmd.stream_mode
+ == uhd::stream_cmd_t::STREAM_MODE_NUM_SAMPS_AND_MORE) {
+ size_t decimation = get_arg<double>("input_rate", chan)
+ / get_arg<double>("output_rate", chan);
stream_cmd.num_samps *= decimation;
}
@@ -190,9 +178,9 @@ public:
}
private:
- static constexpr size_t MAJOR_COMP = 2;
- static constexpr size_t MINOR_COMP = 0;
- static constexpr size_t RB_REG_COMPAT_NUM = 0;
+ static constexpr size_t MAJOR_COMP = 2;
+ static constexpr size_t MINOR_COMP = 0;
+ static constexpr size_t RB_REG_COMPAT_NUM = 0;
static constexpr size_t RB_REG_NUM_HALFBANDS = 1;
static constexpr size_t RB_REG_CIC_MAX_DECIM = 2;
@@ -216,10 +204,7 @@ private:
{
const double input_rate = get_arg<double>("input_rate");
return uhd::meta_range_t(
- -input_rate/2,
- +input_rate/2,
- input_rate/std::pow(2.0, 32)
- );
+ -input_rate / 2, +input_rate / 2, input_rate / std::pow(2.0, 32));
}
uhd::meta_range_t get_output_rates(void)
@@ -227,11 +212,11 @@ private:
uhd::meta_range_t range;
const double input_rate = get_arg<double>("input_rate");
for (int hb = _num_halfbands; hb >= 0; hb--) {
- const size_t decim_offset = _cic_max_decim<<(hb-1);
- for(size_t decim = _cic_max_decim; decim > 0; decim--) {
- const size_t hb_cic_decim = decim*(1<<hb);
- if(hb == 0 || hb_cic_decim > decim_offset) {
- range.push_back(uhd::range_t(input_rate/hb_cic_decim));
+ const size_t decim_offset = _cic_max_decim << (hb - 1);
+ for (size_t decim = _cic_max_decim; decim > 0; decim--) {
+ const size_t hb_cic_decim = decim * (1 << hb);
+ if (hb == 0 || hb_cic_decim > decim_offset) {
+ range.push_back(uhd::range_t(input_rate / hb_cic_decim));
}
}
}
@@ -241,8 +226,8 @@ private:
double set_output_rate(const double requested_rate, const size_t chan)
{
const double input_rate = get_arg<double>("input_rate");
- const size_t decim_rate =
- boost::math::iround(input_rate/this->get_output_rates().clip(requested_rate, true));
+ const size_t decim_rate = boost::math::iround(
+ input_rate / this->get_output_rates().clip(requested_rate, true));
size_t decim = decim_rate;
// The FPGA knows which halfbands to enable for any given value of hb_enable.
uint32_t hb_enable = 0;
@@ -268,54 +253,69 @@ private:
}
if (decim > 1 and hb_enable == 0) {
- UHD_LOGGER_WARNING("RFNOC") << boost::format(
- "The requested decimation is odd; the user should expect passband CIC rolloff.\n"
- "Select an even decimation to ensure that a halfband filter is enabled.\n"
- "Decimations factorable by 4 will enable 2 halfbands, those factorable by 8 will enable 3 halfbands.\n"
- "decimation = dsp_rate/samp_rate -> %d = (%f MHz)/(%f MHz)\n"
- ) % decim_rate % (input_rate/1e6) % (requested_rate/1e6);
+ UHD_LOGGER_WARNING("RFNOC")
+ << boost::format(
+ "The requested decimation is odd; the user should expect passband "
+ "CIC rolloff.\n"
+ "Select an even decimation to ensure that a halfband filter is "
+ "enabled.\n"
+ "Decimations factorable by 4 will enable 2 halfbands, those "
+ "factorable by 8 will enable 3 halfbands.\n"
+ "decimation = dsp_rate/samp_rate -> %d = (%f MHz)/(%f MHz)\n")
+ % decim_rate % (input_rate / 1e6) % (requested_rate / 1e6);
}
// Calculate algorithmic gain of CIC for a given decimation.
// For Ettus CIC R=decim, M=1, N=4. Gain = (R * M) ^ N
const double rate_pow = std::pow(double(decim & 0xff), 4);
- // Calculate compensation gain values for algorithmic gain of DDS and CIC taking into account
- // gain compensation blocks already hardcoded in place in DDC (that provide simple 1/2^n gain compensation).
+ // Calculate compensation gain values for algorithmic gain of DDS and CIC taking
+ // into account gain compensation blocks already hardcoded in place in DDC (that
+ // provide simple 1/2^n gain compensation).
static const double DDS_GAIN = 2.0;
//
- // The polar rotation of [I,Q] = [1,1] by Pi/8 also yields max magnitude of SQRT(2) (~1.4142) however
- // input to the DDS thats outside the unit circle can only be sourced from a saturated RF frontend.
- // To provide additional dynamic range head room accordingly using scale factor applied at egress from DDC would
- // cost us small signal performance, thus we do no provide compensation gain for a saturated front end and allow
- // the signal to clip in the H/W as needed. If we wished to avoid the signal clipping in these circumstances then adjust code to read:
+ // The polar rotation of [I,Q] = [1,1] by Pi/8 also yields max magnitude of
+ // SQRT(2) (~1.4142) however input to the DDS thats outside the unit circle can
+ // only be sourced from a saturated RF frontend. To provide additional dynamic
+ // range head room accordingly using scale factor applied at egress from DDC would
+ // cost us small signal performance, thus we do no provide compensation gain for a
+ // saturated front end and allow the signal to clip in the H/W as needed. If we
+ // wished to avoid the signal clipping in these circumstances then adjust code to
+ // read:
const double scaling_adjustment =
- std::pow(2, uhd::math::ceil_log2(rate_pow))/(DDS_GAIN*rate_pow);
+ std::pow(2, uhd::math::ceil_log2(rate_pow)) / (DDS_GAIN * rate_pow);
update_scalar(scaling_adjustment, chan);
- return input_rate/decim_rate;
+ return input_rate / decim_rate;
}
//! Set frequency and decimation again
void set_input_rate(const double /* rate */, const size_t chan)
{
- const double desired_freq = _tree->access<double>(get_arg_path("freq", chan) / "value").get_desired();
+ const double desired_freq =
+ _tree->access<double>(get_arg_path("freq", chan) / "value").get_desired();
set_arg<double>("freq", desired_freq, chan);
- const double desired_output_rate = _tree->access<double>(get_arg_path("output_rate", chan) / "value").get_desired();
+ const double desired_output_rate =
+ _tree->access<double>(get_arg_path("output_rate", chan) / "value")
+ .get_desired();
set_arg<double>("output_rate", desired_output_rate, chan);
}
- // Calculate compensation gain values for algorithmic gain of DDS and CIC taking into account
- // gain compensation blocks already hardcoded in place in DDC (that provide simple 1/2^n gain compensation).
- // Further more factor in OTW format which adds further gain factor to weight output samples correctly.
+ // Calculate compensation gain values for algorithmic gain of DDS and CIC taking into
+ // account gain compensation blocks already hardcoded in place in DDC (that provide
+ // simple 1/2^n gain compensation). Further more factor in OTW format which adds
+ // further gain factor to weight output samples correctly.
void update_scalar(const double scalar, const size_t chan)
{
- const double target_scalar = (1 << 15) * scalar;
+ const double target_scalar = (1 << 15) * scalar;
const int32_t actual_scalar = boost::math::iround(target_scalar);
- // Calculate the error introduced by using integer representation for the scalar, can be corrected in host later.
+ // Calculate the error introduced by using integer representation for the scalar,
+ // can be corrected in host later.
const double scalar_correction =
- target_scalar / actual_scalar / double(1 << 15) // Rounding error, normalized to 1.0
+ target_scalar / actual_scalar
+ / double(1 << 15) // Rounding error, normalized to 1.0
* get_arg<double>("fullscale"); // Scaling requested by host
set_arg<double>("scalar_correction", scalar_correction, chan);
- // Write DDC with scaling correction for CIC and DDS that maximizes dynamic range in 32/16/12/8bits.
+ // Write DDC with scaling correction for CIC and DDS that maximizes dynamic range
+ // in 32/16/12/8bits.
sr_write("SCALE_IQ", actual_scalar, chan);
}