Commit 4039473a authored by Thomas Schlichter's avatar Thomas Schlichter

NR_UE: add PI controller to time sync

this allows to compensate larger continuous time drift in DL (e.g. large Doppler from LEO satellite)
parent 8ab7f1dd
...@@ -947,7 +947,7 @@ void *UE_thread(void *arg) ...@@ -947,7 +947,7 @@ void *UE_thread(void *arg)
if (slot_nr == nb_slot_frame - 1) { if (slot_nr == nb_slot_frame - 1) {
// we shift of half of measured drift, at each beginning of frame for both rx and tx // we shift of half of measured drift, at each beginning of frame for both rx and tx
iq_shift_to_apply = shiftForNextFrame; iq_shift_to_apply = shiftForNextFrame;
shiftForNextFrame = 0; // We will get a new measured offset if we decode PBCH shiftForNextFrame = -round(UE->max_pos_acc * get_nrUE_params()->time_sync_I);
} }
const int readBlockSize = get_readBlockSize(slot_nr, fp) - iq_shift_to_apply; const int readBlockSize = get_readBlockSize(slot_nr, fp) - iq_shift_to_apply;
......
...@@ -9,6 +9,8 @@ ...@@ -9,6 +9,8 @@
#define CONFIG_HLP_DLSCH_PARA "number of threads for dlsch processing 0 for no parallelization\n" #define CONFIG_HLP_DLSCH_PARA "number of threads for dlsch processing 0 for no parallelization\n"
#define CONFIG_HLP_OFFSET_DIV "Divisor for computing OFDM symbol offset in Rx chain (num samples in CP/<the value>). Default value is 8. To set the sample offset to 0, set this value ~ 10e6\n" #define CONFIG_HLP_OFFSET_DIV "Divisor for computing OFDM symbol offset in Rx chain (num samples in CP/<the value>). Default value is 8. To set the sample offset to 0, set this value ~ 10e6\n"
#define CONFIG_HLP_MAX_LDPC_ITERATIONS "Maximum LDPC decoder iterations\n" #define CONFIG_HLP_MAX_LDPC_ITERATIONS "Maximum LDPC decoder iterations\n"
#define CONFIG_HLP_TIME_SYNC_P "coefficient for Proportional part of time sync PI controller\n"
#define CONFIG_HLP_TIME_SYNC_I "coefficient for Integrating part of time sync PI controller\n"
#define CONFIG_HLP_NTN_KOFFSET "NTN cellSpecificKoffset-r17 (number of slots for a given subcarrier spacing of 15 kHz)\n" #define CONFIG_HLP_NTN_KOFFSET "NTN cellSpecificKoffset-r17 (number of slots for a given subcarrier spacing of 15 kHz)\n"
#define CONFIG_HLP_NTN_TA_COMMON "NTN ta-Common, but given in ms\n" #define CONFIG_HLP_NTN_TA_COMMON "NTN ta-Common, but given in ms\n"
...@@ -59,6 +61,8 @@ ...@@ -59,6 +61,8 @@
{"ue-timing-correction-disable", CONFIG_HLP_DISABLETIMECORR, PARAMFLAG_BOOL, .iptr=&(nrUE_params.no_timing_correction), .defintval=0, TYPE_INT, 0}, \ {"ue-timing-correction-disable", CONFIG_HLP_DISABLETIMECORR, PARAMFLAG_BOOL, .iptr=&(nrUE_params.no_timing_correction), .defintval=0, TYPE_INT, 0}, \
{"SLC", CONFIG_HLP_SLF, 0, .u64ptr=&(sidelink_frequency[0][0]), .defuintval=2600000000,TYPE_UINT64,0}, \ {"SLC", CONFIG_HLP_SLF, 0, .u64ptr=&(sidelink_frequency[0][0]), .defuintval=2600000000,TYPE_UINT64,0}, \
{"num-ues", NULL, 0, .iptr=&(NB_UE_INST), .defuintval=1, TYPE_INT, 0}, \ {"num-ues", NULL, 0, .iptr=&(NB_UE_INST), .defuintval=1, TYPE_INT, 0}, \
{"time-sync-P", CONFIG_HLP_TIME_SYNC_P, 0, .dblptr=&(nrUE_params.time_sync_P), .defdblval=0.5, TYPE_DOUBLE, 0}, \
{"time-sync-I", CONFIG_HLP_TIME_SYNC_I, 0, .dblptr=&(nrUE_params.time_sync_I), .defdblval=0.2, TYPE_DOUBLE, 0}, \
{"ntn-koffset", CONFIG_HLP_NTN_KOFFSET, 0, .uptr=&(nrUE_params.ntn_koffset), .defuintval=0, TYPE_UINT, 0}, \ {"ntn-koffset", CONFIG_HLP_NTN_KOFFSET, 0, .uptr=&(nrUE_params.ntn_koffset), .defuintval=0, TYPE_UINT, 0}, \
{"ntn-ta-common", CONFIG_HLP_NTN_TA_COMMON, 0, .dblptr=&(nrUE_params.ntn_ta_common), .defdblval=0.0, TYPE_DOUBLE, 0}, \ {"ntn-ta-common", CONFIG_HLP_NTN_TA_COMMON, 0, .dblptr=&(nrUE_params.ntn_ta_common), .defdblval=0.0, TYPE_DOUBLE, 0}, \
{"agc", CONFIG_HLP_AGC, PARAMFLAG_BOOL, .iptr=&(nrUE_params.agc), .defintval=0, TYPE_INT, 0}, \ {"agc", CONFIG_HLP_AGC, PARAMFLAG_BOOL, .iptr=&(nrUE_params.agc), .defintval=0, TYPE_INT, 0}, \
...@@ -82,6 +86,8 @@ typedef struct { ...@@ -82,6 +86,8 @@ typedef struct {
int N_RB_DL; int N_RB_DL;
int ssb_start_subcarrier; int ssb_start_subcarrier;
int ldpc_offload_flag; int ldpc_offload_flag;
double time_sync_P;
double time_sync_I;
unsigned int ntn_koffset; unsigned int ntn_koffset;
double ntn_ta_common; double ntn_ta_common;
int agc; int agc;
......
...@@ -24,7 +24,7 @@ ...@@ -24,7 +24,7 @@
#include "PHY/NR_UE_ESTIMATION/nr_estimation.h" #include "PHY/NR_UE_ESTIMATION/nr_estimation.h"
#include "PHY/impl_defs_top.h" #include "PHY/impl_defs_top.h"
#include "executables/softmodem-common.h" #include "executables/nr-uesoftmodem.h"
#include "common/utils/LOG/vcd_signal_dumper.h" #include "common/utils/LOG/vcd_signal_dumper.h"
//#define DEBUG_PHY //#define DEBUG_PHY
...@@ -43,12 +43,9 @@ int nr_adjust_synch_ue(NR_DL_FRAME_PARMS *frame_parms, ...@@ -43,12 +43,9 @@ int nr_adjust_synch_ue(NR_DL_FRAME_PARMS *frame_parms,
short coef) short coef)
{ {
int max_val = 0, max_pos = 0; int max_val = 0, max_pos = 0;
uint8_t sync_offset = 0;
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_ADJUST_SYNCH, VCD_FUNCTION_IN); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_ADJUST_SYNCH, VCD_FUNCTION_IN);
short ncoef = 32767 - coef;
// search for maximum position within the cyclic prefix // search for maximum position within the cyclic prefix
for (int i = -frame_parms->nb_prefix_samples/2; i < frame_parms->nb_prefix_samples/2; i++) { for (int i = -frame_parms->nb_prefix_samples/2; i < frame_parms->nb_prefix_samples/2; i++) {
int temp = 0; int temp = 0;
...@@ -67,32 +64,37 @@ int nr_adjust_synch_ue(NR_DL_FRAME_PARMS *frame_parms, ...@@ -67,32 +64,37 @@ int nr_adjust_synch_ue(NR_DL_FRAME_PARMS *frame_parms,
} }
// filter position to reduce jitter // filter position to reduce jitter
ue->max_pos_avg = ((ue->max_pos_avg * coef) >> 15) + (max_pos * ncoef); const int ncoef = 32767 - coef;
ue->max_pos_iir = ((ue->max_pos_iir * coef) >> 15) + (max_pos * ncoef);
int diff = ue->max_pos_avg >> 15; const int diff = (ue->max_pos_iir + 16384) >> 15;
// FIXME: Do we really need this hysteresis for FR2?
int sampleShift = diff;
if (frame_parms->freq_range == FR2) if (frame_parms->freq_range == FR2)
sync_offset = 2; if (abs(diff) <= 2)
else sampleShift = 0;
sync_offset = 0;
int sampleShift = 0; // PI controller
if (abs(diff) > (NR_SYNCH_HYST + sync_offset)) const double PID_P = get_nrUE_params()->time_sync_P;
sampleShift = diff; const double PID_I = get_nrUE_params()->time_sync_I;
int sample_shift = -round(sampleShift * PID_P + ue->max_pos_acc * PID_I);
const int sample_shift = -(sampleShift / 2);
// reset IIR filter for next offset calculation
ue->max_pos_avg += sample_shift * 32768;
LOG_D(PHY, LOG_D(PHY,
"Slot %d: diff = %i, rx_offset (final) = %i : max_pos = %d, max_pos filtered = %ld, max_power = %d\n", "Frame %d, Slot %d: max_pos = %d, max_pos filtered = %f, diff = %i, sampleShift = %i, max_pos_acc = %d, sample_shift (final) = %d, max_power = %d\n",
frame,
slot, slot,
max_pos,
ue->max_pos_iir / 32768.0,
diff, diff,
sampleShift, sampleShift,
max_pos, ue->max_pos_acc,
ue->max_pos_avg, sample_shift,
max_val); max_val);
// reset IIR filter for next offset calculation
ue->max_pos_iir += -round(sampleShift * PID_P) * 32768;
ue->max_pos_acc += max_pos;
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_ADJUST_SYNCH, VCD_FUNCTION_OUT); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_ADJUST_SYNCH, VCD_FUNCTION_OUT);
return sample_shift; return sample_shift;
} }
...@@ -29,9 +29,6 @@ ...@@ -29,9 +29,6 @@
* @{ * @{
*/ */
/*!\brief Timing drift hysterisis in samples*/
#define NR_SYNCH_HYST 1
/* A function to perform the channel estimation of DL PRS signal */ /* A function to perform the channel estimation of DL PRS signal */
int nr_prs_channel_estimation(uint8_t gNB_id, int nr_prs_channel_estimation(uint8_t gNB_id,
uint8_t rsc_id, uint8_t rsc_id,
......
...@@ -456,7 +456,8 @@ typedef struct PHY_VARS_NR_UE_s { ...@@ -456,7 +456,8 @@ typedef struct PHY_VARS_NR_UE_s {
/// temporary offset during cell search prior to MIB decoding /// temporary offset during cell search prior to MIB decoding
int ssb_offset; int ssb_offset;
uint16_t symbol_offset; /// offset in terms of symbols for detected ssb in sync uint16_t symbol_offset; /// offset in terms of symbols for detected ssb in sync
int64_t max_pos_avg; /// Timing offset IIR filter int64_t max_pos_iir; /// Timing offset IIR filter
int max_pos_acc; /// Timing offset accumuluated error for PI filter
/// Timing Advance updates variables /// Timing Advance updates variables
/// Timing advance update computed from the TA command signalled from gNB /// Timing advance update computed from the TA command signalled from gNB
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment