mirror of
https://github.com/EttusResearch/uhd.git
synced 2026-10-25 17:36:10 +00:00
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:
parent
786e819ba6
commit
7833aa71c3
@ -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 */
|
||||
|
||||
@ -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";
|
||||
|
||||
@ -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 */
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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;
|
||||
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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.
|
||||
|
||||
@ -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));
|
||||
}
|
||||
|
||||
@ -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)
|
||||
*************************************************************************/
|
||||
|
||||
@ -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)
|
||||
*************************************************************************/
|
||||
|
||||
@ -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
|
||||
*****************************************************************************/
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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;
|
||||
};
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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>
|
||||
|
||||
Loading…
Reference in New Issue
Block a user