multi_usrp: set_master_clock_rate function now sets duc/ddc rates

RFNoC's `multi_usrp` did not fully propagate `set_master_clock_rate()`
to the DUC/DDC chain.

Before this change, `set_master_clock_rate()` updated only the radio
rate. If a channel had a DUC or DDC, the adjacent converter rate was
left stale:
- TX: the DUC output rate was not updated to the new radio rate
- RX: the DDC input rate was not updated to the new radio rate

That caused follow-up `set_tx_rate()` / `set_rx_rate()` calls on the
same `multi_usrp` object to operate on outdated DUC/DDC state. In
practice, after changing the master clock, setting the channel sample
rate could be coerced unexpectedly because interpolation/decimation was
derived from the old converter-side rate.

This change updates `multi_usrp_rfnoc` so that `set_master_clock_rate()`:
- propagates the new radio rate to the attached DUC/DDC
- reapplies the previously requested per-channel TX/RX rate so the
  DUC/DDC continues to follow the user-requested sample rate

Note that property propagation by itself is insufficient here, because
multi_usrp_rfnoc caches RX and TX rates, and these caches require
manual updating.

Co-authored-by: Martin Braun <martin.braun@ettus.com>
This commit is contained in:
TalFel 2026-03-11 13:24:22 +02:00 committed by mkoop-ni
parent a48ccdb0a0
commit 2feedf3338

View File

@ -747,18 +747,41 @@ public:
******************************************************************/
void set_master_clock_rate(double rate, size_t mboard) override
{
std::lock_guard<std::recursive_mutex> l(_graph_mutex);
for (auto& chain : _rx_chans) {
auto radio = chain.second.radio;
auto& rx_chain = chain.second;
auto radio = rx_chain.radio;
if (radio->get_block_id().get_device_no() == mboard
|| mboard == ALL_MBOARDS) {
radio->set_rate(rate);
const double actual_radio_rate = radio->set_rate(rate);
auto rx_rate_it = _rx_rates.find(chain.first);
if (rx_chain.ddc) {
rx_chain.ddc->set_input_rate(actual_radio_rate, rx_chain.block_chan);
if (rx_rate_it != _rx_rates.end()) {
rx_rate_it->second = rx_chain.ddc->set_output_rate(
rx_rate_it->second, rx_chain.block_chan);
}
} else if (rx_rate_it != _rx_rates.end()) {
rx_rate_it->second = actual_radio_rate;
}
}
}
for (auto& chain : _tx_chans) {
auto radio = chain.second.radio;
auto& tx_chain = chain.second;
auto radio = tx_chain.radio;
if (radio->get_block_id().get_device_no() == mboard
|| mboard == ALL_MBOARDS) {
radio->set_rate(rate);
const double actual_radio_rate = radio->set_rate(rate);
auto tx_rate_it = _tx_rates.find(chain.first);
if (tx_chain.duc) {
tx_chain.duc->set_output_rate(actual_radio_rate, tx_chain.block_chan);
if (tx_rate_it != _tx_rates.end()) {
tx_rate_it->second = tx_chain.duc->set_input_rate(
tx_rate_it->second, tx_chain.block_chan);
}
} else if (tx_rate_it != _tx_rates.end()) {
tx_rate_it->second = actual_radio_rate;
}
}
}
}