From 18469302d879688a0889706dbce0a57ac7befd8b Mon Sep 17 00:00:00 2001 From: Thomas Schlichter Date: Tue, 14 Jan 2025 13:29:29 +0100 Subject: [PATCH] NR UE: add PI controller to continuous frequency offset compensation --- doc/RUNMODEM.md | 2 ++ executables/nr-uesoftmodem.h | 6 ++++++ openair1/PHY/defs_nr_UE.h | 1 + openair1/SCHED_NR_UE/phy_procedures_nr_ue.c | 8 ++++++-- 4 files changed, 15 insertions(+), 2 deletions(-) diff --git a/doc/RUNMODEM.md b/doc/RUNMODEM.md index fc35146e45..eb47a8f753 100644 --- a/doc/RUNMODEM.md +++ b/doc/RUNMODEM.md @@ -139,6 +139,8 @@ Here are some useful command line options for the NR UE: | `--ue-fo-compensation` | Enables the initial frequency offset compensation at the UE. Useful when running over the air and/or without an external clock/time source. | | `--cont-fo-comp` | Enables the continuous frequency offset (FO) estimation and compensation. Parameter value `1` specifies that the main FO contribution comes from the local oscillator's (LO) accuracy. Parameter value `2` specifies that the main FO contribution comes from Doppler shift. | | `--initial-fo` | Sets the known initial frequency offset. Useful especially with large Doppler frequency, e.g. LEO satellite. | +| `--freq-sync-P` | Sets the coefficient for the Proportional part of the PI-controller for the continuous frequency offset compensation. Default value 0.01. | +| `--freq-sync-I` | Sets the coefficient for the Integrating part of the PI-controller for the continuous frequency offset compensation. Default value 0.001. | | `--usrp-args` | Equivalent to the `sdr_addrs` field in the gNB config file. Used to identify the USRP and set some basic parameters (like the clock source). | | `--clock-source` | Sets the clock source (internal or external). | | `--time-source` | Sets the time source (internal or external). | diff --git a/executables/nr-uesoftmodem.h b/executables/nr-uesoftmodem.h index cc134eaecd..2b2387915a 100644 --- a/executables/nr-uesoftmodem.h +++ b/executables/nr-uesoftmodem.h @@ -15,6 +15,8 @@ #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_FREQ_SYNC_P "coefficient for Proportional part of continuous frequency offset compensation PI controller\n" +#define CONFIG_HLP_FREQ_SYNC_I "coefficient for Integrating part of continuous frequency offset compensation PI controller\n" #define CONFIG_HLP_CONT_FO_COMP "Enable continuous frequency offset (FO) estimation and compensation and specify main FO source (1 = local oscillator, 2 = Doppler shift)\n" #define CONFIG_HLP_AGC "Rx Gain control used for UE\n" @@ -68,6 +70,8 @@ {"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}, \ + {"freq-sync-P", CONFIG_HLP_FREQ_SYNC_P, 0, .dblptr=&(nrUE_params.freq_sync_P), .defdblval=0.01, TYPE_DOUBLE, 0}, \ + {"freq-sync-I", CONFIG_HLP_FREQ_SYNC_I, 0, .dblptr=&(nrUE_params.freq_sync_I), .defdblval=0.001, TYPE_DOUBLE, 0}, \ {"cont-fo-comp", CONFIG_HLP_CONT_FO_COMP, 0, .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}, \ } @@ -94,6 +98,8 @@ typedef struct { double ntn_init_time_drift; int autonomous_ta; double initial_fo; + double freq_sync_P; + double freq_sync_I; int cont_fo_comp; int agc; char *usrp_args; diff --git a/openair1/PHY/defs_nr_UE.h b/openair1/PHY/defs_nr_UE.h index 1b0bfe9f89..b1f75e8bb4 100644 --- a/openair1/PHY/defs_nr_UE.h +++ b/openair1/PHY/defs_nr_UE.h @@ -463,6 +463,7 @@ typedef struct PHY_VARS_NR_UE_s { 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 + double freq_off_acc; /// accumulated frequency error (for PI controller) /// Timing Advance updates variables /// Timing advance update computed from the TA command signalled from gNB diff --git a/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c b/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c index c7bfbb0f3b..936adb6d6c 100644 --- a/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c +++ b/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c @@ -932,9 +932,13 @@ int pbch_pdcch_processing(PHY_VARS_NR_UE *ue, const UE_nr_rxtx_proc_t *proc, nr_ if (get_nrUE_params()->cont_fo_comp && pbchSuccess == 0) { double freq_offset = nr_ue_pbch_freq_offset(fp, estimateSz, dl_ch_estimates); - LOG_D(PHY,"compensated frequency offset = %.3f Hz, detected residual frequency offset = %.3f Hz\n", ue->freq_offset, freq_offset); + LOG_D(PHY,"compensated frequency offset = %.3f Hz, detected residual frequency offset = %.3f Hz, accumulated frequency offset = %.3f Hz\n", ue->freq_offset, freq_offset, ue->freq_off_acc); - ue->freq_offset += freq_offset; + // PI controller + const double PID_P = get_nrUE_params()->freq_sync_P; + const double PID_I = get_nrUE_params()->freq_sync_I; + ue->freq_offset += freq_offset * PID_P + ue->freq_off_acc * PID_I; + ue->freq_off_acc += freq_offset; } } LOG_D(PHY, "Doing N0 measurements in %s\n", __FUNCTION__);