NR UE: add support for continuous DL frequency offset compensation (--cont-fo-comp)

This commit is contained in:
Thomas Schlichter
2025-04-10 13:54:59 +00:00
parent 616568a79d
commit aac4642910
9 changed files with 42 additions and 6 deletions
+9 -4
View File
@@ -436,9 +436,13 @@ static void UE_synch(void *arg) {
((ret.rx_offset << 1) / fp->samples_per_subframe * fp->slots_per_subframe)
+ round((float)((ret.rx_offset << 1) % fp->samples_per_subframe) / fp->samples_per_slot0);
// rerun with new cell parameters and frequency-offset
// todo: the freq_offset computed on DL shall be scaled before being applied to UL
nr_rf_card_config_freq(cfg0, ul_carrier, dl_carrier, freq_offset);
if (get_nrUE_params()->cont_fo_comp) {
UE->freq_offset = freq_offset;
} else {
// rerun with new cell parameters and frequency-offset
nr_rf_card_config_freq(cfg0, ul_carrier, dl_carrier, freq_offset);
UE->rfdevice.trx_set_freq_func(&UE->rfdevice, cfg0);
}
if (get_nrUE_params()->agc) {
nr_ue_adjust_rx_gain(UE, cfg0, UE->adjust_rxgain);
@@ -452,7 +456,6 @@ static void UE_synch(void *arg) {
cfg0->rx_freq[0],
cfg0->tx_freq[0]);
UE->rfdevice.trx_set_freq_func(&UE->rfdevice, cfg0);
UE->is_synchronized = 1;
} else {
int gain_change = 0;
@@ -913,6 +916,8 @@ void *UE_thread(void *arg)
if (usrp_tx_thread == 1)
UE->rfdevice.trx_write_init(&UE->rfdevice);
InitSinLUT();
notifiedFIFO_t nf;
initNotifiedFIFO(&nf);
+1
View File
@@ -225,6 +225,7 @@ void set_options(int CC_id, PHY_VARS_NR_UE *UE){
UE->chest_time = nrUE_params.chest_time;
UE->no_timing_correction = nrUE_params.no_timing_correction;
UE->initial_fo = nrUE_params.initial_fo;
UE->cont_fo_comp = nrUE_params.cont_fo_comp;
LOG_I(PHY,"Set UE_fo_compensation %d, UE_scan_carrier %d, UE_no_timing_correction %d \n, chest-freq %d, chest-time %d\n",
UE->UE_fo_compensation, UE->UE_scan_carrier, UE->no_timing_correction, UE->chest_freq, UE->chest_time);
+3
View File
@@ -15,6 +15,7 @@
#define CONFIG_HLP_NTN_INIT_TIME_DRIFT "Initial NTN DL time drift (feeder link and service link), given in µs/s\n"
#define CONFIG_HLP_AUTONOMOUS_TA "Autonomously update TA based on DL drift (useful if main contribution to DL drift is movement, e.g. LEO satellite)\n"
#define CONFIG_HLP_INITIAL_FO "Initially compensated DL frequency offset (e.g. known Doppler shift in NTN LEO scenario)\n"
#define CONFIG_HLP_CONT_FO_COMP "Enable continuous frequency offset estimation and compensation\n"
#define CONFIG_HLP_AGC "Rx Gain control used for UE\n"
/***************************************************************************************************************************************/
@@ -67,6 +68,7 @@
{"ntn-initial-time-drift", CONFIG_HLP_NTN_INIT_TIME_DRIFT, 0, .dblptr=&(nrUE_params.ntn_init_time_drift), .defdblval=0.0, TYPE_DOUBLE, 0}, \
{"autonomous-ta", CONFIG_HLP_AUTONOMOUS_TA, PARAMFLAG_BOOL, .iptr=&(nrUE_params.autonomous_ta), .defintval=0, TYPE_INT, 0}, \
{"initial-fo", CONFIG_HLP_INITIAL_FO, 0, .dblptr=&(nrUE_params.initial_fo), .defdblval=0.0, TYPE_DOUBLE, 0}, \
{"cont-fo-comp", CONFIG_HLP_CONT_FO_COMP, PARAMFLAG_BOOL, .iptr=&(nrUE_params.cont_fo_comp), .defintval=0, TYPE_INT, 0}, \
{"agc", CONFIG_HLP_AGC, PARAMFLAG_BOOL, .iptr=&(nrUE_params.agc), .defintval=0, TYPE_INT, 0}, \
}
// clang-format on
@@ -92,6 +94,7 @@ typedef struct {
double ntn_init_time_drift;
int autonomous_ta;
double initial_fo;
int cont_fo_comp;
int agc;
char *usrp_args;
char *tx_subdev;
+7
View File
@@ -25,6 +25,7 @@
#include "nr_modulation.h"
#include "PHY/LTE_ESTIMATION/lte_estimation.h"
#include "PHY/NR_UE_ESTIMATION/nr_estimation.h"
#include "PHY/nr_phy_common/inc/nr_phy_common.h"
#include <common/utils/LOG/log.h>
//#define DEBUG_FEP
@@ -108,6 +109,12 @@ int nr_slot_fep(PHY_VARS_NR_UE *ue,
rxdata_ptr = (int16_t *)tmp_dft_in;
}
if (ue && ue->cont_fo_comp) {
start_meas_nr_ue_phy(ue, RX_FO_COMPENSATION_STATS);
nr_fo_compensation(ue->freq_offset, frame_parms->samples_per_subframe, rx_offset, (c16_t *)rxdata_ptr, frame_parms->ofdm_symbol_size);
stop_meas_nr_ue_phy(ue, RX_FO_COMPENSATION_STATS);
}
if (ue)
start_meas_nr_ue_phy(ue, RX_DFT_STATS);
+2
View File
@@ -461,6 +461,8 @@ typedef struct PHY_VARS_NR_UE_s {
int max_pos_acc; /// Timing offset accumuluated error for PI filter
double initial_fo; /// initial frequency offset provided by the user
int cont_fo_comp; /// flag enabling the continuous frequency offset estimation and compensation
double freq_offset; /// currently compensated frequency offset
/// Timing Advance updates variables
/// Timing advance update computed from the TA command signalled from gNB
@@ -80,4 +80,6 @@ void nr_256qam_llr(int32_t *rxdataF_comp, int32_t *ch_mag, int32_t *ch_mag2, int
void freq2time(uint16_t ofdm_symbol_size, int16_t *freq_signal, int16_t *time_signal);
void nr_est_delay(int ofdm_symbol_size, const c16_t *ls_est, c16_t *ch_estimates_time, delay_t *delay);
unsigned int nr_get_tx_amp(int power_dBm, int power_max_dBm, int total_nb_rb, int nb_rb);
void nr_fo_compensation(double fo_Hz, int samples_per_ms, int sample_offset, c16_t *rxdata_ptr, int size);
#endif
@@ -28,6 +28,7 @@
#define FOREACH_NR_PHY_CPU_MEAS(FN) \
FN(RX_PDSCH_STATS),\
FN(DLSCH_RX_PDCCH_STATS),\
FN(RX_FO_COMPENSATION_STATS),\
FN(RX_DFT_STATS),\
FN(DLSCH_CHANNEL_ESTIMATION_STATS),\
FN(DLSCH_DECODING_STATS),\
@@ -453,3 +453,16 @@ unsigned int nr_get_tx_amp(int power_dBm, int power_max_dBm, int total_nb_rb, in
}
return (0);
}
void nr_fo_compensation(double fo_Hz, int samples_per_ms, int sample_offset, c16_t *rxdata_ptr, int size)
{
const double phase_inc = -fo_Hz / (samples_per_ms * 1000);
double phase = sample_offset * phase_inc;
phase -= (int)phase;
for (int i = 0; i < size; i++) {
c16_t rot = get_sin_cos(phase);
*rxdata_ptr = c16mulShift(*rxdata_ptr, rot, 14);
rxdata_ptr++;
phase += phase_inc;
}
}
+4 -2
View File
@@ -930,9 +930,11 @@ int pbch_pdcch_processing(PHY_VARS_NR_UE *ue, const UE_nr_rxtx_proc_t *proc, nr_
nr_adjust_synch_ue(fp, ue, gNB_id, fp->ofdm_symbol_size, dl_ch_estimates_time, frame_rx, nr_slot_rx, 16384);
}
if (/*ue->continuous_freq_correction &&*/ pbchSuccess == 0) {
if (get_nrUE_params()->cont_fo_comp && pbchSuccess == 0) {
double freq_offset = nr_ue_pbch_freq_offset(fp, estimateSz, dl_ch_estimates);
LOG_I(PHY,"detected frequency offset = %.3f Hz\n", freq_offset);
LOG_D(PHY,"compensated frequency offset = %.3f Hz, detected residual frequency offset = %.3f Hz\n", ue->freq_offset, freq_offset);
ue->freq_offset += freq_offset;
}
}
LOG_D(PHY, "Doing N0 measurements in %s\n", __FUNCTION__);