mirror of
https://github.com/EttusResearch/uhd.git
synced 2026-10-25 17:36:10 +00:00
fbx: Add guided mode for X440
Since X440 is special in terms of operation in different Nyquist zones users may stumble upon unexpected RF performance compared to other devices if frequencies are chosen close to a Nyquist boundary. The guided mode provides more information about the Nyquist zone in which the chosen frequency is located in the info log. For disabling the guided mode, `guided_mode=false` can be added to the UHD config file in the "Global" section.
This commit is contained in:
parent
479f65d9d6
commit
7f6e8e3276
@ -235,122 +235,15 @@ public:
|
||||
* \tparam argN_t Data type of the Nth argument to the constructor
|
||||
*
|
||||
* \param container A shared pointer to the container to add the node to
|
||||
* \param arg1 First arg to ctor
|
||||
* \param args arguments to the ctor
|
||||
* \param ...
|
||||
*
|
||||
*/
|
||||
template <typename worker_t, typename arg1_t>
|
||||
template <typename worker_t, typename... Args>
|
||||
inline static void add_worker_node(
|
||||
expert_container::sptr container, arg1_t const& arg1)
|
||||
expert_container::sptr container, Args const&... args)
|
||||
{
|
||||
container->add_worker(new worker_t(arg1));
|
||||
}
|
||||
|
||||
template <typename worker_t, typename arg1_t, typename arg2_t>
|
||||
inline static void add_worker_node(
|
||||
expert_container::sptr container, arg1_t const& arg1, arg2_t const& arg2)
|
||||
{
|
||||
container->add_worker(new worker_t(arg1, arg2));
|
||||
}
|
||||
|
||||
template <typename worker_t, typename arg1_t, typename arg2_t, typename arg3_t>
|
||||
inline static void add_worker_node(expert_container::sptr container,
|
||||
arg1_t const& arg1,
|
||||
arg2_t const& arg2,
|
||||
arg3_t const& arg3)
|
||||
{
|
||||
container->add_worker(new worker_t(arg1, arg2, arg3));
|
||||
}
|
||||
|
||||
template <typename worker_t,
|
||||
typename arg1_t,
|
||||
typename arg2_t,
|
||||
typename arg3_t,
|
||||
typename arg4_t>
|
||||
inline static void add_worker_node(expert_container::sptr container,
|
||||
arg1_t const& arg1,
|
||||
arg2_t const& arg2,
|
||||
arg3_t const& arg3,
|
||||
arg4_t const& arg4)
|
||||
{
|
||||
container->add_worker(new worker_t(arg1, arg2, arg3, arg4));
|
||||
}
|
||||
|
||||
template <typename worker_t,
|
||||
typename arg1_t,
|
||||
typename arg2_t,
|
||||
typename arg3_t,
|
||||
typename arg4_t,
|
||||
typename arg5_t>
|
||||
inline static void add_worker_node(expert_container::sptr container,
|
||||
arg1_t const& arg1,
|
||||
arg2_t const& arg2,
|
||||
arg3_t const& arg3,
|
||||
arg4_t const& arg4,
|
||||
arg5_t const& arg5)
|
||||
{
|
||||
container->add_worker(new worker_t(arg1, arg2, arg3, arg4, arg5));
|
||||
}
|
||||
|
||||
template <typename worker_t,
|
||||
typename arg1_t,
|
||||
typename arg2_t,
|
||||
typename arg3_t,
|
||||
typename arg4_t,
|
||||
typename arg5_t,
|
||||
typename arg6_t>
|
||||
inline static void add_worker_node(expert_container::sptr container,
|
||||
arg1_t const& arg1,
|
||||
arg2_t const& arg2,
|
||||
arg3_t const& arg3,
|
||||
arg4_t const& arg4,
|
||||
arg5_t const& arg5,
|
||||
arg6_t const& arg6)
|
||||
{
|
||||
container->add_worker(new worker_t(arg1, arg2, arg3, arg4, arg5, arg6));
|
||||
}
|
||||
|
||||
template <typename worker_t,
|
||||
typename arg1_t,
|
||||
typename arg2_t,
|
||||
typename arg3_t,
|
||||
typename arg4_t,
|
||||
typename arg5_t,
|
||||
typename arg6_t,
|
||||
typename arg7_t>
|
||||
inline static void add_worker_node(expert_container::sptr container,
|
||||
arg1_t const& arg1,
|
||||
arg2_t const& arg2,
|
||||
arg3_t const& arg3,
|
||||
arg4_t const& arg4,
|
||||
arg5_t const& arg5,
|
||||
arg6_t const& arg6,
|
||||
arg7_t const& arg7)
|
||||
{
|
||||
container->add_worker(new worker_t(arg1, arg2, arg3, arg4, arg5, arg6, arg7));
|
||||
}
|
||||
|
||||
template <typename worker_t,
|
||||
typename arg1_t,
|
||||
typename arg2_t,
|
||||
typename arg3_t,
|
||||
typename arg4_t,
|
||||
typename arg5_t,
|
||||
typename arg6_t,
|
||||
typename arg7_t,
|
||||
typename arg8_t>
|
||||
inline static void add_worker_node(expert_container::sptr container,
|
||||
arg1_t const& arg1,
|
||||
arg2_t const& arg2,
|
||||
arg3_t const& arg3,
|
||||
arg4_t const& arg4,
|
||||
arg5_t const& arg5,
|
||||
arg6_t const& arg6,
|
||||
arg7_t const& arg7,
|
||||
arg7_t const& arg8)
|
||||
{
|
||||
container->add_worker(
|
||||
new worker_t(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8));
|
||||
container->add_worker(new worker_t(args...));
|
||||
}
|
||||
};
|
||||
}} // namespace uhd::experts
|
||||
|
||||
@ -77,4 +77,7 @@ UHD_API int from_str(const std::string& val);
|
||||
template <>
|
||||
UHD_API std::string from_str(const std::string& val);
|
||||
|
||||
//! Create an ordinal string from a number.
|
||||
UHD_API std::string to_ordinal_string(int val);
|
||||
|
||||
}} // namespace uhd::cast
|
||||
|
||||
@ -164,7 +164,7 @@ struct UHD_API logging_info
|
||||
/*! Set the global log level
|
||||
*
|
||||
* The global log level gets applied before the specific log level.
|
||||
* So, if the global log level is 'info', no logger can can print
|
||||
* So, if the global log level is 'info', no logger can print
|
||||
* messages at level 'debug' or below.
|
||||
*/
|
||||
UHD_API void set_log_level(uhd::log::severity_level level);
|
||||
|
||||
@ -209,6 +209,7 @@ public:
|
||||
const uhd::fs_path fe_path,
|
||||
const uhd::direction_t trx,
|
||||
const size_t chan,
|
||||
const double rfdc_rate,
|
||||
const std::string rpc_prefix,
|
||||
int db_idx,
|
||||
uhd::usrp::x400_rpc_iface::sptr rpcc)
|
||||
@ -224,6 +225,7 @@ public:
|
||||
, _db_idx(db_idx)
|
||||
, _rpcc(rpcc)
|
||||
, _trx(trx)
|
||||
, _rfdc_rate(rfdc_rate)
|
||||
, _chan(chan)
|
||||
{
|
||||
bind_accessor(_rfdc_freq_desired);
|
||||
@ -255,6 +257,7 @@ private:
|
||||
const size_t _db_idx;
|
||||
uhd::usrp::x400_rpc_iface::sptr _rpcc;
|
||||
const uhd::direction_t _trx;
|
||||
const double _rfdc_rate;
|
||||
const size_t _chan;
|
||||
};
|
||||
|
||||
|
||||
20
host/lib/include/uhdlib/utils/log.hpp
Normal file
20
host/lib/include/uhdlib/utils/log.hpp
Normal file
@ -0,0 +1,20 @@
|
||||
//
|
||||
// Copyright 2018 Ettus Research, a National Instruments Company
|
||||
//
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <uhd/utils/log.hpp>
|
||||
#include <uhdlib/utils/prefs.hpp>
|
||||
|
||||
#define UHD_LOG_GUIDE(message) \
|
||||
if (uhd::prefs::is_guided_mode()) { \
|
||||
UHD_LOG_INFO("Guide", message); \
|
||||
}
|
||||
|
||||
#define UHD_LOG_IF_GUIDED(statement) \
|
||||
if (uhd::prefs::is_guided_mode()) { \
|
||||
statement; \
|
||||
}
|
||||
@ -12,6 +12,11 @@
|
||||
|
||||
namespace uhd { namespace prefs {
|
||||
|
||||
/*! For general configuration items not targeted to a specific device we have the
|
||||
* "General" section.
|
||||
*/
|
||||
constexpr char GLOBAL_SECTION[] = "Global";
|
||||
|
||||
/*! Return a reference to an object representing the UHD config file
|
||||
* state.
|
||||
*
|
||||
@ -19,6 +24,18 @@ namespace uhd { namespace prefs {
|
||||
*/
|
||||
config_parser& get_uhd_config();
|
||||
|
||||
/*! Guided mode helps the user by providing additional information about current settings
|
||||
* via info level log messages. In case this is too much it can be turned off in the
|
||||
* config file. This is the check if guided mode is enabled.
|
||||
*/
|
||||
bool is_guided_mode();
|
||||
|
||||
/*! Sets the `guided_mode_suspended` flag in the config to true. */
|
||||
void suspend_guided_mode();
|
||||
|
||||
/*! Sets the `guided_mode_suspended` flag in the config to false. */
|
||||
void resume_guided_mode();
|
||||
|
||||
/*! Convenience function to update device args with settings from
|
||||
* config files.
|
||||
*
|
||||
|
||||
@ -154,6 +154,7 @@ void fbx_dboard_impl::_init_experts(expert_container::sptr expert,
|
||||
fe_path,
|
||||
trx,
|
||||
chan_idx,
|
||||
_rfdc_rate,
|
||||
_rpc_prefix,
|
||||
_db_idx,
|
||||
_mb_rpcc);
|
||||
|
||||
@ -6,10 +6,12 @@
|
||||
|
||||
#include <uhd/types/direction.hpp>
|
||||
#include <uhd/utils/assert_has.hpp>
|
||||
#include <uhd/utils/cast.hpp>
|
||||
#include <uhd/utils/log.hpp>
|
||||
#include <uhd/utils/math.hpp>
|
||||
#include <uhdlib/usrp/dboard/fbx/fbx_expert.hpp>
|
||||
#include <uhdlib/utils/interpolation.hpp>
|
||||
#include <uhdlib/utils/log.hpp>
|
||||
#include <algorithm>
|
||||
#include <array>
|
||||
|
||||
@ -127,6 +129,44 @@ void fbx_rfdc_freq_expert::resolve()
|
||||
_get_trx_string(_trx), _db_idx, _chan, desired_rfdc_freq);
|
||||
_if_frequency_coerced = _rfdc_freq_coerced;
|
||||
_coerced_frequency = _if_frequency_coerced;
|
||||
|
||||
// Both are dirty during the session start and we don't want to spam the user with
|
||||
// logs there.
|
||||
if (!(_rfdc_freq_desired.is_dirty() && _frequency_desired.is_dirty())) {
|
||||
UHD_LOG_IF_GUIDED(
|
||||
auto nyquist_boundary = _rfdc_rate / 2;
|
||||
uint32_t nyquist_zone =
|
||||
std::floor(_if_frequency_coerced / nyquist_boundary) + 1;
|
||||
// Provide more information about implications of chosen frequency.
|
||||
UHD_LOG_GUIDE(_get_trx_string(_trx)
|
||||
<< " frequency " << (_if_frequency_coerced / 1e6)
|
||||
<< " MHz on DB " << _db_idx << ", channel " << _chan
|
||||
<< " is in the " << uhd::cast::to_ordinal_string(nyquist_zone)
|
||||
<< " Nyquist zone.");
|
||||
// warnings according to
|
||||
// https://kb.ettus.com/About_Sampling_Rates_and_Master_Clock_Rates_for_the_USRP_X440#Aliases_and_Nyquist_Zones
|
||||
if ((nyquist_zone > 2 && _trx == TX_DIRECTION)
|
||||
|| (nyquist_zone > 3 && _trx == RX_DIRECTION)) {
|
||||
UHD_LOG_GUIDE(
|
||||
_get_trx_string(_trx)
|
||||
<< " operation in this Nyquist zone will result in decreased RF "
|
||||
"performance.");
|
||||
} auto passband_freq = static_cast<int>(std::round(_if_frequency_coerced))
|
||||
% static_cast<int>(nyquist_boundary);
|
||||
if (passband_freq < 0.1 * nyquist_boundary
|
||||
|| passband_freq > 0.9 * nyquist_boundary) {
|
||||
auto pass_low_mhz =
|
||||
(nyquist_zone * nyquist_boundary - 0.9 * nyquist_boundary) / 1e6;
|
||||
auto pass_high_mhz =
|
||||
(nyquist_zone * nyquist_boundary - 0.1 * nyquist_boundary) / 1e6;
|
||||
UHD_LOG_GUIDE(_get_trx_string(_trx)
|
||||
<< " frequency " << (_if_frequency_coerced / 1e6)
|
||||
<< " MHz is outside the 80% Nyquist passband ("
|
||||
<< pass_low_mhz << " MHz to " << pass_high_mhz
|
||||
<< " MHz for this Nyquist zone). This "
|
||||
<< "may result in aliasing and undesired effects.");
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
void fbx_sync_expert::resolve()
|
||||
|
||||
@ -18,6 +18,7 @@
|
||||
#include <uhdlib/usrp/dboard/fbx/fbx_dboard.hpp>
|
||||
#include <uhdlib/usrp/dboard/null_dboard.hpp>
|
||||
#include <uhdlib/usrp/dboard/zbx/zbx_dboard.hpp>
|
||||
#include <uhdlib/utils/prefs.hpp>
|
||||
|
||||
namespace uhd { namespace rfnoc {
|
||||
|
||||
@ -247,6 +248,13 @@ x400_radio_control_impl::x400_radio_control_impl(make_args_ptr make_args)
|
||||
auto& self_cal =
|
||||
get_feature<uhd::features::adc_self_calibration_iface>();
|
||||
const size_t num_channels = get_num_output_ports();
|
||||
// Get current setting for guided mode and disable it for the duration
|
||||
// of the calibration
|
||||
|
||||
uhd::prefs::suspend_guided_mode();
|
||||
auto resume_guided_mode = uhd::utils::scope_exit::make(
|
||||
[&]() { uhd::prefs::resume_guided_mode(); });
|
||||
|
||||
for (size_t i = 0; i < num_channels; i++) {
|
||||
auto abs_ch = get_block_id().get_block_count() * num_channels + i;
|
||||
if (ch_list.size() == 0
|
||||
|
||||
@ -60,3 +60,12 @@ std::string cast::from_str(const std::string& val)
|
||||
{
|
||||
return val;
|
||||
}
|
||||
|
||||
std::string cast::to_ordinal_string(int val)
|
||||
{
|
||||
const std::string ordinals = "thstndrd";
|
||||
std::string result = std::to_string(val);
|
||||
int index = (val % 10) * (val % 10 < 4 && !(10 < val % 100 && val % 100 < 14));
|
||||
result += ordinals.substr(2 * index, 2);
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -4,6 +4,7 @@
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
//
|
||||
|
||||
#include <uhd/utils/cast.hpp>
|
||||
#include <uhd/utils/log.hpp>
|
||||
#include <uhd/utils/paths.hpp>
|
||||
#include <uhdlib/utils/paths.hpp>
|
||||
@ -116,6 +117,28 @@ config_parser& uhd::prefs::get_uhd_config()
|
||||
return _conf_files;
|
||||
}
|
||||
|
||||
bool uhd::prefs::is_guided_mode()
|
||||
{
|
||||
const std::string guided_mode = uhd::prefs::get_uhd_config().get<std::string>(
|
||||
uhd::prefs::GLOBAL_SECTION, "guided_mode", "true");
|
||||
const std::string guided_mode_suspended =
|
||||
uhd::prefs::get_uhd_config().get<std::string>(
|
||||
uhd::prefs::GLOBAL_SECTION, "guided_mode_suspended", "false");
|
||||
return cast::from_str<bool>(guided_mode)
|
||||
&& !cast::from_str<bool>(guided_mode_suspended);
|
||||
}
|
||||
|
||||
void uhd::prefs::suspend_guided_mode()
|
||||
{
|
||||
uhd::prefs::get_uhd_config().set<std::string>(
|
||||
uhd::prefs::GLOBAL_SECTION, "guided_mode_suspended", "true");
|
||||
}
|
||||
|
||||
void uhd::prefs::resume_guided_mode()
|
||||
{
|
||||
uhd::prefs::get_uhd_config().set<std::string>(
|
||||
uhd::prefs::GLOBAL_SECTION, "guided_mode_suspended", "false");
|
||||
}
|
||||
|
||||
device_addr_t uhd::prefs::get_usrp_args(const uhd::device_addr_t& user_args)
|
||||
{
|
||||
|
||||
@ -417,6 +417,10 @@ IF(ENABLE_X400)
|
||||
${UHD_SOURCE_DIR}/lib/usrp/cores/gpio_atr_3000.cpp
|
||||
${UHD_SOURCE_DIR}/lib/usrp/cores/spi_core_4000.cpp
|
||||
${UHD_SOURCE_DIR}/lib/usrp/x400/x400_internal_sync.cpp
|
||||
${UHD_SOURCE_DIR}/lib/utils/prefs.cpp
|
||||
${UHD_SOURCE_DIR}/lib/utils/pathslib.cpp
|
||||
${UHD_SOURCE_DIR}/lib/utils/paths.cpp
|
||||
${UHD_SOURCE_DIR}/lib/utils/config_parser.cpp
|
||||
$<TARGET_OBJECTS:uhd_rpclib>
|
||||
INCLUDE_DIRS ${UHD_SOURCE_DIR}/lib/deps/rpclib/include
|
||||
INCLUDE_DIRS ${UHD_SOURCE_DIR}/lib/deps/flatbuffers/include
|
||||
@ -448,6 +452,10 @@ IF(ENABLE_X400)
|
||||
${UHD_SOURCE_DIR}/lib/usrp/cores/gpio_atr_3000.cpp
|
||||
${UHD_SOURCE_DIR}/lib/usrp/cores/spi_core_4000.cpp
|
||||
${UHD_SOURCE_DIR}/lib/usrp/x400/x400_internal_sync.cpp
|
||||
${UHD_SOURCE_DIR}/lib/utils/prefs.cpp
|
||||
${UHD_SOURCE_DIR}/lib/utils/pathslib.cpp
|
||||
${UHD_SOURCE_DIR}/lib/utils/paths.cpp
|
||||
${UHD_SOURCE_DIR}/lib/utils/config_parser.cpp
|
||||
$<TARGET_OBJECTS:uhd_rpclib>
|
||||
INCLUDE_DIRS ${UHD_SOURCE_DIR}/lib/deps/rpclib/include
|
||||
INCLUDE_DIRS ${UHD_SOURCE_DIR}/lib/deps/flatbuffers/include
|
||||
|
||||
Loading…
Reference in New Issue
Block a user