Skip to content

Commit 7c79971

Browse files
committed
ch_estimator: make cfo compensation optional
In some cases (e.g., PUCCH Format 1), the CFO estimation is not good enough and compensation is likely to be detrimental. This commit makes CFO compensation optional.
1 parent 478119c commit 7c79971

File tree

4 files changed

+32
-14
lines changed

4 files changed

+32
-14
lines changed

include/srsran/phy/upper/signal_processors/signal_processor_factories.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,8 @@ class port_channel_estimator_factory
9494
virtual ~port_channel_estimator_factory() = default;
9595
virtual std::unique_ptr<port_channel_estimator>
9696
create(port_channel_estimator_fd_smoothing_strategy fd_smoothing_strategy =
97-
port_channel_estimator_fd_smoothing_strategy::filter) = 0;
97+
port_channel_estimator_fd_smoothing_strategy::filter,
98+
bool complensate_cfo = true) = 0;
9899
};
99100

100101
std::shared_ptr<port_channel_estimator_factory>

lib/phy/upper/signal_processors/port_channel_estimator_average_impl.cpp

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,7 @@ static unsigned extract_layer_hop_rx_pilots(dmrs_symbol_list&
156156
/// \param[in] dmrs_mask Boolean mask identifying the OFDM symbols carrying DM-RS within the slot.
157157
/// \param[in] scs Subcarrier spacing.
158158
/// \param[in] cp_cum_duration Cumulative duration of all CPs in the slot.
159+
/// \param[in] compensate_cfo Boolean flag to activate the CFO compensation.
159160
/// \param[in] first_hop_symbol Index of the first OFDM symbol of the current hop, within the slot.
160161
/// \param[in] last_hop_symbol Index of the last OFDM symbol of the current hop (not included), within the slot.
161162
/// \param[in] hop_offset Number of OFDM symbols carrying DM-RS in the previous hop.
@@ -169,6 +170,7 @@ static std::pair<float, optional<float>> preprocess_pilots_and_cfo(span<cf_t>
169170
const bounded_bitset<MAX_NSYMB_PER_SLOT>& dmrs_mask,
170171
const subcarrier_spacing& scs,
171172
span<const float> cp_cum_duration,
173+
bool compensate_cfo,
172174
unsigned first_hop_symbol,
173175
unsigned last_hop_symbol,
174176
unsigned hop_offset,
@@ -183,6 +185,7 @@ static std::pair<float, optional<float>> preprocess_pilots_and_cfo(span<cf_t>
183185
/// \param[in] scs Subcarrier spacing.
184186
/// \param[in] cfo Carrier frequency offset.
185187
/// \param[in] cp_cum_duration Cumulative duration of all CPs in the slot.
188+
/// \param[in] compensate_cfo Boolean flag to activate the CFO compensation.
186189
/// \param[in] first_hop_symbol Index of the first OFDM symbol of the current hop, within the slot.
187190
/// \param[in] last_hop_symbol Index of the last OFDM symbol of the current hop (not included), within the slot.
188191
/// \param[in] hop_symbols Number of OFDM symbols containing DM-RS pilots in the current hop.
@@ -198,6 +201,7 @@ static float estimate_noise(const dmrs_symbol_list& pilots,
198201
const subcarrier_spacing& scs,
199202
optional<float> cfo,
200203
span<const float> cp_cum_duration,
204+
bool compensate_cfo,
201205
unsigned first_hop_symbol,
202206
unsigned last_hop_symbol,
203207
unsigned hop_symbols,
@@ -261,7 +265,7 @@ void port_channel_estimator_average_impl::compute(channel_estimate& es
261265
time_alignment_s /= 2.0F;
262266
}
263267

264-
if (cfo_normalized.has_value()) {
268+
if (compensate_cfo && cfo_normalized.has_value()) {
265269
// Apply CFO to the estimated channel.
266270
float cfo = cfo_normalized.value();
267271
for (unsigned i_symbol = cfg.first_symbol, last_symbol = cfg.first_symbol + cfg.nof_symbols;
@@ -344,6 +348,7 @@ void port_channel_estimator_average_impl::compute_layer_hop(srsran::channel_esti
344348
pattern.symbols,
345349
cfg.scs,
346350
cp_cum_duration,
351+
compensate_cfo,
347352
first_symbol,
348353
last_symbol,
349354
hop_offset,
@@ -393,6 +398,7 @@ void port_channel_estimator_average_impl::compute_layer_hop(srsran::channel_esti
393398
cfg.scs,
394399
cfo_hop,
395400
cp_cum_duration,
401+
compensate_cfo,
396402
first_symbol,
397403
last_symbol,
398404
nof_dmrs_symbols,
@@ -480,6 +486,7 @@ static std::pair<float, optional<float>> preprocess_pilots_and_cfo(span<cf_t>
480486
const bounded_bitset<MAX_NSYMB_PER_SLOT>& dmrs_mask,
481487
const subcarrier_spacing& scs,
482488
span<const float> cp_cum_duration,
489+
bool compensate_cfo,
483490
unsigned first_hop_symbol,
484491
unsigned last_hop_symbol,
485492
unsigned hop_offset,
@@ -510,9 +517,11 @@ static std::pair<float, optional<float>> preprocess_pilots_and_cfo(span<cf_t>
510517
std::arg(noisy_phase) / TWOPI / (i_dmrs_1 - i_dmrs_0 + cp_cum_duration[i_dmrs_1] - cp_cum_duration[i_dmrs_0]);
511518

512519
// Compensate the CFO in the first two DM-RS symbols and combine them.
513-
srsvec::sc_prod(pilots_lse, std::polar(1.0f, -TWOPI * (i_dmrs_0 + cp_cum_duration[i_dmrs_0]) * cfo), pilots_lse);
514-
srsvec::sc_prod(
515-
pilot_products, std::polar(1.0f, -TWOPI * (i_dmrs_1 + cp_cum_duration[i_dmrs_1]) * cfo), pilot_products);
520+
if (compensate_cfo) {
521+
srsvec::sc_prod(pilots_lse, std::polar(1.0f, -TWOPI * (i_dmrs_0 + cp_cum_duration[i_dmrs_0]) * cfo), pilots_lse);
522+
srsvec::sc_prod(
523+
pilot_products, std::polar(1.0f, -TWOPI * (i_dmrs_1 + cp_cum_duration[i_dmrs_1]) * cfo), pilot_products);
524+
}
516525
srsvec::add(pilots_lse, pilot_products, pilots_lse);
517526

518527
// If there are other DM-RS symbols in the hop, match them with the corresponding transmitted symbols, compensate the
@@ -521,8 +530,10 @@ static std::pair<float, optional<float>> preprocess_pilots_and_cfo(span<cf_t>
521530
auto combine_pilots = [&, i_dmrs = 2](size_t i_symbol) mutable {
522531
srsvec::prod_conj(
523532
rx_pilots.get_symbol(i_dmrs, i_layer), pilots.get_symbol(hop_offset + i_dmrs, i_layer), pilot_products);
524-
srsvec::sc_prod(
525-
pilot_products, std::polar(1.0f, -TWOPI * (i_symbol + cp_cum_duration[i_symbol]) * cfo), pilot_products);
533+
if (compensate_cfo) {
534+
srsvec::sc_prod(
535+
pilot_products, std::polar(1.0f, -TWOPI * (i_symbol + cp_cum_duration[i_symbol]) * cfo), pilot_products);
536+
}
526537
srsvec::add(pilots_lse, pilot_products, pilots_lse);
527538
epre += std::real(srsvec::dot_prod(rx_pilots.get_symbol(i_dmrs, i_layer), rx_pilots.get_symbol(i_dmrs, i_layer)));
528539
++i_dmrs;
@@ -542,6 +553,7 @@ static float estimate_noise(const dmrs_symbol_list& pilots,
542553
const subcarrier_spacing& scs,
543554
optional<float> cfo,
544555
span<const float> cp_cum_duration,
556+
bool compensate_cfo,
545557
unsigned first_hop_symbol,
546558
unsigned last_hop_symbol,
547559
unsigned hop_symbols,
@@ -558,7 +570,7 @@ static float estimate_noise(const dmrs_symbol_list& pilots,
558570
span<cf_t> predicted_obs = span<cf_t>(predicted_obs_buffer).first(estimates.size());
559571
float noise_energy = 0.0F;
560572

561-
if (cfo.has_value()) {
573+
if (compensate_cfo && cfo.has_value()) {
562574
auto noise_cfo = [&, i_dmrs = 0](size_t i_symbol) mutable {
563575
span<const cf_t> symbol_pilots = pilots.get_symbol(hop_offset + i_dmrs, i_layer);
564576
span<const cf_t> symbol_rx_pilots = rx_pilots.get_symbol(i_dmrs, i_layer);

lib/phy/upper/signal_processors/port_channel_estimator_average_impl.h

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,8 +39,10 @@ class port_channel_estimator_average_impl : public port_channel_estimator
3939
/// Constructor - Sets the internal interpolator and inverse DFT processor of size \c DFT_SIZE.
4040
port_channel_estimator_average_impl(std::unique_ptr<interpolator> interp,
4141
std::unique_ptr<time_alignment_estimator> ta_estimator_,
42-
port_channel_estimator_fd_smoothing_strategy fd_smoothing_strategy_) :
42+
port_channel_estimator_fd_smoothing_strategy fd_smoothing_strategy_,
43+
bool compensate_cfo_ = true) :
4344
fd_smoothing_strategy(fd_smoothing_strategy_),
45+
compensate_cfo(compensate_cfo_),
4446
freq_interpolator(std::move(interp)),
4547
ta_estimator(std::move(ta_estimator_))
4648
{
@@ -72,6 +74,9 @@ class port_channel_estimator_average_impl : public port_channel_estimator
7274
/// Frequency domain smoothing strategy.
7375
port_channel_estimator_fd_smoothing_strategy fd_smoothing_strategy;
7476

77+
/// Boolean flag for activating CFO compensation (active when true).
78+
bool compensate_cfo;
79+
7580
/// \brief Interpolator.
7681
///
7782
/// When DM-RS pilots do not occupy all REs in an OFDM symbol, the interpolator is used to estimate the channel of the

lib/phy/upper/signal_processors/signal_processor_factories.cpp

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@ class dmrs_pucch_estimator_sw_factory : public dmrs_pucch_estimator_factory
111111
return std::make_unique<dmrs_pucch_processor_format1_impl>(
112112
prg_factory->create(),
113113
lpc_factory->create(m, delta, alphas),
114-
ch_estimator_factory->create(port_channel_estimator_fd_smoothing_strategy::mean));
114+
ch_estimator_factory->create(port_channel_estimator_fd_smoothing_strategy::mean, /*compensate_cfo =*/false));
115115
}
116116

117117
std::unique_ptr<dmrs_pucch_processor> create_format2() override
@@ -230,13 +230,13 @@ class port_channel_estimator_factory_sw : public port_channel_estimator_factory
230230
srsran_assert(ta_estimator_factory, "Invalid TA estimator factory.");
231231
}
232232

233-
std::unique_ptr<port_channel_estimator>
234-
create(port_channel_estimator_fd_smoothing_strategy fd_smoothing_strategy) override
233+
std::unique_ptr<port_channel_estimator> create(port_channel_estimator_fd_smoothing_strategy fd_smoothing_strategy,
234+
bool compensate_cfo) override
235235
{
236236
std::unique_ptr<interpolator> interp = create_interpolator();
237237

238238
return std::make_unique<port_channel_estimator_average_impl>(
239-
std::move(interp), ta_estimator_factory->create(), fd_smoothing_strategy);
239+
std::move(interp), ta_estimator_factory->create(), fd_smoothing_strategy, compensate_cfo);
240240
}
241241

242242
private:
@@ -366,4 +366,4 @@ class logging_nzp_csi_rs_generator_decorator : public nzp_csi_rs_generator
366366
std::unique_ptr<nzp_csi_rs_generator> nzp_csi_rs_generator_factory::create(srslog::basic_logger& logger)
367367
{
368368
return std::make_unique<logging_nzp_csi_rs_generator_decorator>(logger, create());
369-
}
369+
}

0 commit comments

Comments
 (0)