rfnoc: Add Tune Request in RFNoC blocks

Implementing tune requests in rfnoc blocks using Action API.
Created new tune request action which contains the
tune_request, tune_result and ranges required for tuning.
The tune request can be issued using issue_tune_request() API from
RX/TX Streamers. The tune request action propagates through the
blocks in the rfnoc graph and does necessary frequency settings.
The output tune frequency can also be obtained from the RX/TX
streamers using get_rx_tune_frequency() or get_tx_tune_frequency()
respectively.

Co-authored-by: Riya Alias <riya.alias@ni.com>
This commit is contained in:
Martin Anderseck 2024-10-02 10:44:14 +02:00 committed by joergho
parent 786e819ba6
commit 7833aa71c3
19 changed files with 606 additions and 2 deletions

View File

@ -9,7 +9,11 @@
#include <uhd/config.hpp>
#include <uhd/types/device_addr.hpp>
#include <uhd/types/metadata.hpp>
#include <uhd/types/ranges.hpp>
#include <uhd/types/stream_cmd.hpp>
#include <uhd/types/time_spec.hpp>
#include <uhd/types/tune_request.hpp>
#include <uhd/types/tune_result.hpp>
#include <boost/optional.hpp>
#include <cstddef>
#include <cstdint>
@ -103,4 +107,23 @@ protected:
const boost::optional<uint64_t>& tsf);
};
//! Action object for graph-based tuning
struct UHD_API tune_request_action_info : public action_info
{
public:
using sptr = std::shared_ptr<tune_request_action_info>;
uhd::tune_request_t tune_request;
uhd::time_spec_t time_spec;
uhd::tune_result_t tune_result;
uhd::freq_range_t dsp_range;
uhd::freq_range_t rf_range;
uhd::freq_range_t overall_freq_range;
//! Factory function
static sptr make(const uhd::tune_request_t tune_request);
private:
tune_request_action_info(const uhd::tune_request_t tune_request);
};
}} /* namespace uhd::rfnoc */

View File

@ -38,6 +38,7 @@ static const std::string ACTION_KEY_STREAM_CMD("stream_cmd");
static const std::string ACTION_KEY_RX_EVENT("rx_event");
static const std::string ACTION_KEY_RX_RESTART_REQ("restart_request");
static const std::string ACTION_KEY_TX_EVENT("tx_event");
static const std::string ACTION_KEY_TUNE_REQUEST("tune_request");
//! If the block name can't be automatically detected, this name is used
static const std::string DEFAULT_BLOCK_NAME = "Block";

View File

@ -463,6 +463,26 @@ public:
*/
virtual void issue_stream_cmd(
const uhd::stream_cmd_t& stream_cmd, const size_t port = 0) = 0;
/*! Issue an action from the replay block
*
* Post an action to the input of replay block.
*
* \param action The action pointer to post
* \param port Which input port of the replay block to use
*/
virtual void post_input_action(
const std::shared_ptr<uhd::rfnoc::action_info>& action, const size_t port) = 0;
/*! Issue an action from the replay block
*
* Post an action to the output of replay block.
*
* \param action The action pointer to post
* \param port Which output port of the replay block to use
*/
virtual void post_output_action(
const std::shared_ptr<uhd::rfnoc::action_info>& action, const size_t port) = 0;
};
}} /* namespace uhd::rfnoc */

View File

@ -8,6 +8,7 @@
#pragma once
#include <uhd/config.hpp>
#include <uhd/rfnoc/actions.hpp>
#include <uhd/types/device_addr.hpp>
#include <uhd/types/ref_vector.hpp>
#include <uhd/types/stream_cmd.hpp>
@ -256,6 +257,14 @@ public:
* \param stream_cmd the stream command to issue
*/
virtual void issue_stream_cmd(const stream_cmd_t& stream_cmd) = 0;
/*!
* Post an action to the input edge of the Streamer.
* \param action shared pointer to the corresponding action_info request
* \param port the port to which to post the action
*/
virtual void post_input_action(
const std::shared_ptr<uhd::rfnoc::action_info>& action, const size_t port) = 0;
};
/*!
@ -320,6 +329,14 @@ public:
*/
virtual bool recv_async_msg(
async_metadata_t& async_metadata, double timeout = 0.1) = 0;
/*!
* Post an action to the output edge of the Streamer.
* \param action shared pointer to the corresponding action_info request
* \param port the port to which to post the action
*/
virtual void post_output_action(
const std::shared_ptr<uhd::rfnoc::action_info>& action, const size_t port) = 0;
};
} // namespace uhd

View File

@ -71,6 +71,16 @@ struct UHD_API tune_result_t
* \return the printable string
*/
std::string to_pp_string(void) const;
tune_result_t()
: clipped_rf_freq(0.0)
, target_rf_freq(0.0)
, actual_rf_freq(0.0)
, target_dsp_freq(0.0)
, actual_dsp_freq(0.0)
{
/* NOP */
}
};
} // namespace uhd

View File

@ -50,6 +50,12 @@ public:
void enable_rx_timestamps(const bool enable, const size_t chan) override;
/**************************************************************************
* Tune related API calls
*************************************************************************/
void _tune_request_action_handler(
tune_request_action_info::sptr tune_request_action, const res_source_info& src);
/**************************************************************************
* Rate-Related API Calls
*************************************************************************/
@ -363,6 +369,18 @@ private:
// required for CHDR headers!)
int get_max_spp(const size_t bytes);
//! Calculates and apply the RF tune frequencies
//
// Calculates the target frequency based on the incoming tune request.
// Sets the RF frequency and updates the tune request action info.
//
// \param tune_request_action shared pointer to tune_request_action_info
// \param set_rf_freq Lambda function to set the frequency
// \param get_rf_freq Lambda function to get the current frequency
void apply_and_update_tune_request(tune_request_action_info::sptr tune_request_action,
std::function<void(double)> set_rf_freq,
std::function<double()> get_rf_freq);
//! FPGA compat number
const uint32_t _fpga_compat;

View File

@ -68,6 +68,14 @@ public:
*/
void issue_stream_cmd(const stream_cmd_t& stream_cmd) override;
/*! Implementation of a generic action request
*
* \param action shared pointer to the corresponding action_info request
* \param port the port to which to post action
*/
void post_input_action(const std::shared_ptr<uhd::rfnoc::action_info>& action,
const size_t port) override;
/*! Returns stream args provided at creation
*
* \return stream args provided when streamer is created

View File

@ -68,6 +68,14 @@ public:
*/
const uhd::stream_args_t& get_stream_args() const;
/*! Implementation of a generic action request
*
* \param action shared pointer to the corresponding action_info request
* \param port the port to which to post action
*/
void post_output_action(const std::shared_ptr<uhd::rfnoc::action_info>& action,
const size_t port) override;
/*! Check that all streamer ports are connected to blocks
*
* Overrides node_t to ensure there are no unconnected ports.

View File

@ -94,3 +94,17 @@ tx_event_action_info::sptr tx_event_action_info::make(
};
return std::make_shared<tx_event_action_info_make_shared>(event_code, tsf);
}
/*** Tune Request Metadata Action Info *************************************************/
tune_request_action_info::tune_request_action_info(
const uhd::tune_request_t tune_request_)
: action_info(ACTION_KEY_TUNE_REQUEST), tune_request(tune_request_)
{
// nop
}
tune_request_action_info::sptr tune_request_action_info::make(
const uhd::tune_request_t tune_request)
{
return sptr(new tune_request_action_info(tune_request));
}

View File

@ -77,6 +77,7 @@ public:
// This line is not strictly necessary, as ONE_TO_ONE is the default.
// We set it make it explicit how this block works.
set_mtu_forwarding_policy(forwarding_policy_t::ONE_TO_ONE);
// Load list of valid decimation values
std::set<size_t> decims{1}; // 1 is always a valid decimation
for (size_t hb = 0; hb < _num_halfbands; hb++) {
@ -104,6 +105,7 @@ public:
_register_props(chan);
}
register_issue_stream_cmd();
register_issue_tune_request();
}
double set_freq(const double freq,
@ -453,6 +455,115 @@ private:
post_action(dst_edge, new_action);
}
void register_issue_tune_request()
{
register_action_handler(ACTION_KEY_TUNE_REQUEST,
[this](const res_source_info& src, action_info::sptr action) {
tune_request_action_info::sptr tune_request_action =
std::dynamic_pointer_cast<tune_request_action_info>(action);
if (!tune_request_action) {
throw uhd::runtime_error(
"Received tune_request of invalid action type!");
}
issue_tune_request_action_handler(src, tune_request_action);
});
}
void issue_tune_request_action_handler(
const res_source_info& src, tune_request_action_info::sptr tune_request_action)
{
RFNOC_LOG_TRACE("DDC issue_tune_request_action_handler");
res_source_info dst_edge{res_source_info::invert_edge(src.type), src.instance};
const size_t chan = src.instance;
uhd::tune_request_t tune_request = tune_request_action->tune_request;
RFNOC_LOG_TRACE("Received tune_request to "
<< src.to_string() << ", id==" << tune_request_action->id);
uhd::freq_range_t dsp_range = get_frequency_range(chan);
uhd::freq_range_t tune_range = tune_request_action->overall_freq_range;
tune_request_action->dsp_range = dsp_range;
if (tune_range.empty()) {
tune_range = dsp_range;
}
if (src.type == res_source_info::INPUT_EDGE) {
auto set_dsp_freq = [this, chan](
double freq) { set_freq(freq, chan, boost::none); };
double clipped_requested_freq = tune_range.clip(tune_request.target_freq);
tune_request_action->tune_result.target_dsp_freq = abs(
tune_request_action->tune_result.actual_rf_freq - clipped_requested_freq);
//------------------------------------------------------------------
//-- Set the DSP frequency depending upon the DSP frequency policy.
//------------------------------------------------------------------
double target_dsp_freq = 0.0;
switch (tune_request.dsp_freq_policy) {
case uhd::tune_request_t::POLICY_AUTO:
/* If we are using the AUTO tuning policy, then we prevent the
* CORDIC from spinning us outside of the range of the baseband
* filter, regardless of what the user requested. This could happen
* if the user requested a center frequency so far outside of the
* tunable range of the FE that the CORDIC would spin outside the
* filtered baseband. */
target_dsp_freq = tune_request_action->tune_result.target_dsp_freq
- tune_request_action->tune_result.actual_dsp_freq;
break;
case uhd::tune_request_t::POLICY_MANUAL:
/* If the user has specified a manual tune policy, we will allow
* tuning outside of the baseband filter, but will still clip the
* target DSP frequency to within the bounds of the CORDIC to
* prevent undefined behavior (likely an overflow). */
target_dsp_freq = dsp_range.clip(tune_request.dsp_freq);
break;
case uhd::tune_request_t::POLICY_NONE:
break; // does not set
}
RFNOC_LOG_TRACE(
str(boost::format("Target DSP Freq: %.6fMHz") % (target_dsp_freq / 1e6)));
//------------------------------------------------------------------
//-- Tune the DSP
//------------------------------------------------------------------
if (tune_request.dsp_freq_policy != uhd::tune_request_t::POLICY_NONE) {
set_dsp_freq(target_dsp_freq);
}
const double actual_dsp_freq = get_freq(chan);
RFNOC_LOG_TRACE(
str(boost::format("Actual DSP Freq: %.6fMHz") % (actual_dsp_freq / 1e6)));
tune_request_action->tune_result.actual_dsp_freq += actual_dsp_freq;
RFNOC_LOG_TRACE(
"Tune_result details DDC : target_rf_frq = "
<< tune_request_action->tune_result.target_rf_freq
<< " target dsp freq = "
<< tune_request_action->tune_result.target_dsp_freq << " clipped rf_freq "
<< tune_request_action->tune_result.clipped_rf_freq
<< " actual_rf_freq = " << tune_request_action->tune_result.actual_rf_freq
<< " actual dsp_freq= "
<< tune_request_action->tune_result.actual_dsp_freq);
auto new_action = tune_request_action_info::make(tune_request);
new_action->tune_request = tune_request_action->tune_request;
new_action->tune_result = tune_request_action->tune_result;
new_action->dsp_range = tune_request_action->dsp_range;
new_action->overall_freq_range = tune_request_action->overall_freq_range;
post_action(dst_edge, new_action);
} else {
auto new_action = tune_request_action_info::make(tune_request);
new_action->tune_request = tune_request_action->tune_request;
new_action->tune_result = tune_request_action->tune_result;
new_action->dsp_range = tune_request_action->dsp_range;
new_action->overall_freq_range = tune_request_action->overall_freq_range;
post_action(dst_edge, new_action);
}
}
/**************************************************************************
* FPGA communication (register IO)
*************************************************************************/

View File

@ -26,6 +26,7 @@ constexpr double DEFAULT_SCALING = 1.0;
constexpr int DEFAULT_INTERP = 1;
constexpr double DEFAULT_FREQ = 0.0;
const uhd::rfnoc::io_type_t DEFAULT_TYPE = uhd::rfnoc::IO_TYPE_SC16;
constexpr double TX_SIGN = -1.0;
//! Space (in bytes) between register banks per channel
constexpr uint32_t REG_CHAN_OFFSET = 2048;
@ -103,6 +104,7 @@ public:
_register_props(chan);
}
register_issue_stream_cmd();
register_issue_tune_request();
}
double set_freq(const double freq,
@ -443,6 +445,121 @@ private:
post_action(dst_edge, new_action);
}
void register_issue_tune_request()
{
RFNOC_LOG_TRACE("DUC register_isssue_tune_request");
register_action_handler(ACTION_KEY_TUNE_REQUEST,
[this](const res_source_info& src, action_info::sptr action) {
tune_request_action_info::sptr tune_request_action =
std::dynamic_pointer_cast<tune_request_action_info>(action);
if (!tune_request_action) {
throw uhd::runtime_error(
"Received tune_request of invalid action type!");
}
issue_tune_request_action_handler(src, tune_request_action);
});
}
void issue_tune_request_action_handler(
const res_source_info& src, tune_request_action_info::sptr tune_request_action)
{
RFNOC_LOG_TRACE("DUC isssue_tune_request_action_handler");
res_source_info dst_edge{res_source_info::invert_edge(src.type), src.instance};
const size_t chan = src.instance;
uhd::tune_request_t tune_request = tune_request_action->tune_request;
RFNOC_LOG_TRACE("Received tune_request to "
<< src.to_string() << ", id==" << tune_request_action->id);
uhd::freq_range_t dsp_range = get_frequency_range(chan);
uhd::freq_range_t tune_range = tune_request_action->overall_freq_range;
tune_request_action->dsp_range = dsp_range;
if (tune_range.empty()) {
tune_range = dsp_range;
}
if (src.type == res_source_info::OUTPUT_EDGE) {
auto set_dsp_freq = [this, chan](
double freq) { set_freq(freq, chan, boost::none); };
double clipped_requested_freq = tune_range.clip(tune_request.target_freq);
tune_request_action->tune_result.target_dsp_freq = abs(
tune_request_action->tune_result.actual_rf_freq - clipped_requested_freq);
//------------------------------------------------------------------
//-- Set the DSP frequency depending upon the DSP frequency policy.
//------------------------------------------------------------------
double target_dsp_freq = 0.0;
switch (tune_request.dsp_freq_policy) {
case uhd::tune_request_t::POLICY_AUTO:
// invert the sign on the dsp freq for transmit (spinning up vs down)
tune_request_action->tune_result.target_dsp_freq *= TX_SIGN;
/* If we are using the AUTO tuning policy, then we prevent the
* CORDIC from spinning us outside of the range of the baseband
* filter, regardless of what the user requested. This could happen
* if the user requested a center frequency so far outside of the
* tunable range of the FE that the CORDIC would spin outside the
* filtered baseband. */
target_dsp_freq = tune_request_action->tune_result.target_dsp_freq
- tune_request_action->tune_result.actual_dsp_freq;
break;
case uhd::tune_request_t::POLICY_MANUAL:
/* If the user has specified a manual tune policy, we will allow
* tuning outside of the baseband filter, but will still clip the
* target DSP frequency to within the bounds of the CORDIC to
* prevent undefined behavior (likely an overflow). */
target_dsp_freq = dsp_range.clip(tune_request.dsp_freq);
break;
case uhd::tune_request_t::POLICY_NONE:
break; // does not set
}
RFNOC_LOG_TRACE(
str(boost::format("Target DSP Freq: %.6fMHz") % (target_dsp_freq / 1e6)));
//------------------------------------------------------------------
//-- Tune the DSP
//------------------------------------------------------------------
if (tune_request.dsp_freq_policy != uhd::tune_request_t::POLICY_NONE) {
set_dsp_freq(target_dsp_freq);
}
const double actual_dsp_freq = get_freq(chan);
RFNOC_LOG_TRACE(
str(boost::format("Actual DSP Freq: %.6fMHz") % (actual_dsp_freq / 1e6)));
tune_request_action->tune_result.target_dsp_freq = target_dsp_freq;
tune_request_action->tune_result.actual_dsp_freq += actual_dsp_freq;
RFNOC_LOG_TRACE(
"Tune_result details DUC : target_rf_frq = "
<< tune_request_action->tune_result.target_rf_freq
<< " target dsp freq = "
<< tune_request_action->tune_result.target_dsp_freq << " clipped rf_freq "
<< tune_request_action->tune_result.clipped_rf_freq
<< " actual_rf_freq = " << tune_request_action->tune_result.actual_rf_freq
<< " actual dsp_freq= "
<< tune_request_action->tune_result.actual_dsp_freq);
auto new_action = tune_request_action_info::make(tune_request);
new_action->tune_request = tune_request_action->tune_request;
new_action->tune_result = tune_request_action->tune_result;
new_action->dsp_range = tune_request_action->dsp_range;
new_action->overall_freq_range = tune_request_action->overall_freq_range;
post_action(dst_edge, new_action);
} else {
auto new_action = tune_request_action_info::make(tune_request);
new_action->tune_request = tune_request_action->tune_request;
new_action->tune_result = tune_request_action->tune_result;
new_action->dsp_range = tune_request_action->dsp_range;
new_action->overall_freq_range = tune_request_action->overall_freq_range;
post_action(dst_edge, new_action);
}
}
/**************************************************************************
* FPGA communication (register IO)
*************************************************************************/

View File

@ -103,6 +103,24 @@ radio_control_impl::radio_control_impl(make_args_ptr make_args)
}
post_action({res_source_info::OUTPUT_EDGE, port}, stream_cmd_action);
});
register_action_handler(ACTION_KEY_TUNE_REQUEST,
[this](const res_source_info& src, action_info::sptr action) {
tune_request_action_info::sptr tune_request_action =
std::dynamic_pointer_cast<tune_request_action_info>(action);
if (!tune_request_action) {
RFNOC_LOG_WARNING("Received invalid Tune request command!");
return;
}
const size_t port = src.instance;
if (port >= get_num_output_ports()) {
RFNOC_LOG_WARNING("Received tune_request to invalid output port!");
return;
}
_tune_request_action_handler(tune_request_action, src);
});
// Register spp properties and resolvers
_spp_prop.reserve(get_num_output_ports());
_atomic_item_size_in.reserve(get_num_input_ports());
@ -714,6 +732,86 @@ uhd::meta_range_t radio_control_impl::get_tx_power_range(const size_t chan)
return _tx_pwr_mgr.at(chan)->get_power_range();
}
static uhd::meta_range_t make_overall_tune_range(const uhd::meta_range_t& fe_range,
const uhd::meta_range_t& dsp_range,
const double bw)
{
uhd::meta_range_t range;
for (const uhd::range_t& sub_range : fe_range) {
range.push_back(uhd::range_t(
std::max(0.0, sub_range.start() + std::max(dsp_range.start(), -bw / 2)),
sub_range.stop() + std::min(dsp_range.stop(), bw / 2),
dsp_range.step()));
}
return range;
}
void radio_control_impl::apply_and_update_tune_request(
tune_request_action_info::sptr tune_request_action,
std::function<void(double)> set_rf_freq,
std::function<double()> get_rf_freq)
{
uhd::tune_request_t tune_request = tune_request_action->tune_request;
const double clipped_requested_freq =
tune_request_action->overall_freq_range.clip(tune_request.target_freq);
RFNOC_LOG_TRACE(str(boost::format("Frequency Range %.3fMHz->%.3fMHz")
% (tune_request_action->overall_freq_range.start() / 1e6)
% (tune_request_action->overall_freq_range.stop() / 1e6)));
RFNOC_LOG_TRACE(str(boost::format("Clipped frequency requested: %.3fMHz")
% (clipped_requested_freq / 1e6)));
//------------------------------------------------------------------
//-- set the RF frequency depending upon the policy
//------------------------------------------------------------------
double target_rf_freq = 0.0;
switch (tune_request.rf_freq_policy) {
case uhd::tune_request_t::POLICY_AUTO:
target_rf_freq = clipped_requested_freq;
break;
case uhd::tune_request_t::POLICY_MANUAL:
if ((tune_request.dsp_freq_policy == uhd::tune_request_t::POLICY_AUTO)
&& (tune_request_action->dsp_range.size() == 1)
&& tune_request_action->dsp_range.stop() == 0) {
/* Hardware does not incl. DSP chain
* (dsp_freq_range only has single item, with value 0),
* requested dsp frequency will be combined with rf frequency.
* The case to handle uses MANUAL rf_freq_policy and
* AUTOMATIC dsp_freq_policy */
RFNOC_LOG_DEBUG(
str(boost::format("No DSP capabilities detected. Combining offset "
"into target frequency of %.3fMHz")
% (clipped_requested_freq / 1e6)));
target_rf_freq = clipped_requested_freq;
} else {
/* Normal manual mode observing individual tune requests*/
target_rf_freq = tune_request_action->rf_range.clip(tune_request.rf_freq);
}
case uhd::tune_request_t::POLICY_NONE:
break;
}
RFNOC_LOG_TRACE(
str(boost::format("Target RF Freq: %.3fMHz") % (target_rf_freq / 1e6)));
//------------------------------------------------------------------
//-- Tune the RF frontend
//------------------------------------------------------------------
if (tune_request.rf_freq_policy != uhd::tune_request_t::POLICY_NONE) {
set_rf_freq(target_rf_freq);
}
const double actual_rf_freq = get_rf_freq();
RFNOC_LOG_TRACE(
str(boost::format("RADIO Actual RF Freq: %.3fMHz") % (actual_rf_freq / 1e6)));
tune_request_action->tune_result.clipped_rf_freq = clipped_requested_freq;
tune_request_action->tune_result.target_rf_freq = target_rf_freq;
tune_request_action->tune_result.actual_rf_freq = actual_rf_freq;
}
/******************************************************************************
* LO Default API
@ -993,6 +1091,67 @@ void radio_control_impl::enable_rx_timestamps(const bool enable, const size_t ch
_radio_reg_iface.poke32(regmap::REG_RX_HAS_TIME, enable ? 0x1 : 0x0, chan);
}
/****************************************************************************
* Tune Request API
***************************************************************************/
void radio_control_impl::_tune_request_action_handler(
tune_request_action_info::sptr tune_request_action, const res_source_info& src)
{
RFNOC_LOG_TRACE("Received tune request on " << src.to_string());
res_source_info dst_edge{res_source_info::invert_edge(src.type), src.instance};
const size_t chan = src.instance;
freq_range_t tune_range_nonmono;
uhd::tune_request_t tune_request = tune_request_action->tune_request;
if (src.type == res_source_info::OUTPUT_EDGE) {
set_rx_tune_args(tune_request.args, chan);
tune_range_nonmono = (tune_request_action->dsp_range.empty())
? get_rx_frequency_range(chan)
: make_overall_tune_range(get_rx_frequency_range(chan),
tune_request_action->dsp_range,
get_rx_bandwidth(chan));
tune_request_action->overall_freq_range = tune_range_nonmono.as_monotonic();
tune_request_action->rf_range = get_rx_frequency_range(chan);
auto set_rf_freq = [this, chan](double freq) { set_rx_frequency(freq, chan); };
auto get_rf_freq = [this, chan]() { return get_rx_frequency(chan); };
apply_and_update_tune_request(tune_request_action, set_rf_freq, get_rf_freq);
} else if (src.type == res_source_info::INPUT_EDGE) {
set_tx_tune_args(tune_request.args, chan);
tune_range_nonmono = (tune_request_action->dsp_range.empty())
? get_tx_frequency_range(chan)
: make_overall_tune_range(get_tx_frequency_range(chan),
tune_request_action->dsp_range,
get_tx_bandwidth(chan));
tune_request_action->overall_freq_range = tune_range_nonmono.as_monotonic();
tune_request_action->rf_range = get_tx_frequency_range(chan);
auto set_rf_freq = [this, chan](double freq) { set_tx_frequency(freq, chan); };
auto get_rf_freq = [this, chan]() { return get_tx_frequency(chan); };
apply_and_update_tune_request(tune_request_action, set_rf_freq, get_rf_freq);
}
RFNOC_LOG_TRACE(
"Tune_result details radio_control.cpp : target_rf_frq = "
<< tune_request_action->tune_result.target_rf_freq
<< " target dsp freq = " << tune_request_action->tune_result.target_dsp_freq
<< " clipped rf_freq " << tune_request_action->tune_result.clipped_rf_freq
<< " actual_rf_freq = " << tune_request_action->tune_result.actual_rf_freq
<< " actual dsp_freq= " << tune_request_action->tune_result.actual_dsp_freq);
RFNOC_LOG_TRACE("Sending tune_request to " << src.to_string()
<< ", id==" << tune_request_action->id);
post_action(src, tune_request_action);
}
/******************************************************************************
* Private methods
*****************************************************************************/

View File

@ -161,6 +161,16 @@ public:
}
_handle_tx_event_action(src, tx_event_action);
});
register_action_handler(ACTION_KEY_TUNE_REQUEST,
[this](const res_source_info& src, action_info::sptr action) {
tune_request_action_info::sptr tune_request_action =
std::dynamic_pointer_cast<tune_request_action_info>(action);
if (!tune_request_action) {
RFNOC_LOG_WARNING("Received invalid tune request action!");
return;
}
RFNOC_LOG_DEBUG("Received tune request on " << src.to_string());
});
// Initialize record properties
_record_type.reserve(_num_input_ports);
@ -462,6 +472,26 @@ public:
}
}
void post_input_action(const std::shared_ptr<uhd::rfnoc::action_info>& action,
const size_t port) override
{
if (port > get_num_input_ports()) {
throw uhd::runtime_error("Invalid port. Please provide a valid port");
}
const uhd::rfnoc::res_source_info info(res_source_info::INPUT_EDGE, port);
post_action(info, action);
}
void post_output_action(const std::shared_ptr<uhd::rfnoc::action_info>& action,
const size_t port) override
{
if (port > get_num_output_ports()) {
throw uhd::runtime_error("Invalid port. Please provide a valid port");
}
const uhd::rfnoc::res_source_info info(res_source_info::OUTPUT_EDGE, port);
post_action(info, action);
}
protected:
// Block-specific register interface
multichan_register_iface _replay_reg_iface;

View File

@ -53,6 +53,16 @@ rfnoc_rx_streamer::rfnoc_rx_streamer(const size_t num_chans,
}
_handle_stream_cmd_action(src, stream_cmd_action);
});
register_action_handler(ACTION_KEY_TUNE_REQUEST,
[this](const res_source_info& src, action_info::sptr action) {
tune_request_action_info::sptr tune_request_action =
std::dynamic_pointer_cast<tune_request_action_info>(action);
if (!tune_request_action) {
RFNOC_LOG_WARNING("Received invalid tune request action!");
return;
}
RFNOC_LOG_DEBUG("Received tune request on " << src.to_string());
});
// Initialize properties
_scaling_in.reserve(num_chans);
@ -139,6 +149,16 @@ void rfnoc_rx_streamer::issue_stream_cmd(const stream_cmd_t& stream_cmd)
}
}
void rfnoc_rx_streamer::post_input_action(
const std::shared_ptr<uhd::rfnoc::action_info>& action, const size_t port)
{
if (port > get_num_channels()) {
throw uhd::runtime_error("Invalid channel. Please provide a valid channel");
}
const uhd::rfnoc::res_source_info info(res_source_info::INPUT_EDGE, port);
post_action(info, action);
}
const uhd::stream_args_t& rfnoc_rx_streamer::get_stream_args() const
{
return _stream_args;
@ -169,7 +189,6 @@ void rfnoc_rx_streamer::connect_channel(
const size_t channel, chdr_rx_data_xport::uptr xport)
{
UHD_ASSERT_THROW(channel < _mtu_in.size());
// Stash away the MTU before we lose access to xports
const size_t mtu = xport->get_mtu();
@ -305,7 +324,7 @@ void rfnoc_rx_streamer::_handle_rx_event_action(
void rfnoc_rx_streamer::_handle_stream_cmd_action(
const res_source_info& src, stream_cmd_action_info::sptr stream_cmd_action)
{
RFNOC_LOG_TRACE("Received stream command on " << src.to_string());
RFNOC_LOG_DEBUG("Received stream command on " << src.to_string());
UHD_ASSERT_THROW(src.type == res_source_info::INPUT_EDGE);
auto start_action =
stream_cmd_action_info::make(stream_cmd_action->stream_cmd.stream_mode);

View File

@ -42,6 +42,17 @@ rfnoc_tx_streamer::rfnoc_tx_streamer(const size_t num_chans,
_handle_tx_event_action(src, tx_event_action);
});
register_action_handler(ACTION_KEY_TUNE_REQUEST,
[this](const res_source_info& src, action_info::sptr action) {
tune_request_action_info::sptr tune_request_action =
std::dynamic_pointer_cast<tune_request_action_info>(action);
if (!tune_request_action) {
RFNOC_LOG_WARNING("Received invalid tune request action!");
return;
}
RFNOC_LOG_DEBUG("Received tune request on " << src.to_string());
});
// Initialize properties
_scaling_out.reserve(num_chans);
_samp_rate_out.reserve(num_chans);
@ -106,6 +117,16 @@ size_t rfnoc_tx_streamer::get_num_output_ports() const
return get_num_channels();
}
void rfnoc_tx_streamer::post_output_action(
const std::shared_ptr<uhd::rfnoc::action_info>& action, const size_t port)
{
if (port > get_num_channels()) {
throw uhd::runtime_error("Invalid channel. Please provide a valid channel");
}
const uhd::rfnoc::res_source_info info(res_source_info::OUTPUT_EDGE, port);
post_action(info, action);
}
const uhd::stream_args_t& rfnoc_tx_streamer::get_stream_args() const
{
return _stream_args;

View File

@ -832,6 +832,13 @@ public:
return recv_packet_handler::issue_stream_cmd(stream_cmd);
}
// Post an action to the input edge.
void post_input_action(
const std::shared_ptr<uhd::rfnoc::action_info>&, const size_t) override
{
throw uhd::not_implemented_error("post_input_action is not implemented here!");
}
private:
size_t _max_num_samps;
};

View File

@ -418,6 +418,12 @@ public:
{
return send_packet_handler::recv_async_msg(async_metadata, timeout);
}
// Post an action to the output edge
void post_output_action(
const std::shared_ptr<uhd::rfnoc::action_info>&, const size_t) override
{
throw uhd::not_implemented_error("post_output_action is not implemented here!");
}
private:
size_t _max_num_samps;

View File

@ -368,6 +368,13 @@ public:
_stc->issue_stream_cmd(stream_cmd);
}
void post_input_action(
const std::shared_ptr<uhd::rfnoc::action_info>&, const size_t) override
{
throw uhd::not_implemented_error(
"post_input_action is currently not implemented here!");
}
private:
size_t _max_num_samps;
soft_time_ctrl::sptr _stc;
@ -431,6 +438,13 @@ public:
return _stc->get_async_queue().pop_with_timed_wait(async_metadata, timeout);
}
void post_output_action(
const std::shared_ptr<uhd::rfnoc::action_info>&, const size_t) override
{
throw uhd::not_implemented_error(
"post_output_action is currently not implemented here!");
}
private:
size_t _max_num_samps;
soft_time_ctrl::sptr _stc;

View File

@ -12,6 +12,7 @@
#include <uhd/types/metadata.hpp>
#include <uhd/types/stream_cmd.hpp>
#include <uhd/types/time_spec.hpp>
#include <uhd/types/tune_request.hpp>
#include <uhd/utils/noncopyable.hpp>
#include <functional>
#include <memory>