From 0b05fce71bd328fb479f36b817699fd154e15ccb Mon Sep 17 00:00:00 2001 From: Roberto Louro Magueta Date: Fri, 27 Jan 2023 02:13:37 +0000 Subject: [PATCH] Time shift estimation based on DMRS-PUSCH --- .../PHY/NR_ESTIMATION/nr_measurements_gNB.c | 26 ++++------ .../NR_ESTIMATION/nr_ul_channel_estimation.c | 47 ++++++++++++------- openair1/PHY/NR_ESTIMATION/nr_ul_estimation.h | 2 +- openair1/PHY/defs_gNB.h | 10 ++++ openair1/SCHED_NR/phy_procedures_nr_gNB.c | 4 +- openair1/SIMULATION/NR_PHY/ulsim.c | 21 +++++++-- 6 files changed, 72 insertions(+), 38 deletions(-) diff --git a/openair1/PHY/NR_ESTIMATION/nr_measurements_gNB.c b/openair1/PHY/NR_ESTIMATION/nr_measurements_gNB.c index 0c73d3cd1d..c443fabb3c 100644 --- a/openair1/PHY/NR_ESTIMATION/nr_measurements_gNB.c +++ b/openair1/PHY/NR_ESTIMATION/nr_measurements_gNB.c @@ -38,34 +38,28 @@ extern openair0_config_t openair0_cfg[MAX_CARDS]; -int nr_est_timing_advance_pusch(PHY_VARS_gNB* gNB, int UE_id) +void nr_est_timing_advance_pusch(const NR_DL_FRAME_PARMS *frame_parms, const int32_t *ul_ch_estimates_time, struct delay_s *delay) { - int max_pos = 0, max_val = 0; - - NR_DL_FRAME_PARMS *frame_parms = &gNB->frame_parms; - NR_gNB_PUSCH *gNB_pusch_vars = gNB->pusch_vars[UE_id]; - int32_t **ul_ch_estimates_time = gNB_pusch_vars->ul_ch_estimates_time; - + int max_pos = delay->pusch_delay_max_pos; + int max_val = delay->pusch_delay_max_val; const int sync_pos = 0; for (int i = 0; i < frame_parms->ofdm_symbol_size; i++) { - int temp = 0; - - for (int aa = 0; aa < frame_parms->nb_antennas_rx; aa++) { - int Re = ((int16_t*)ul_ch_estimates_time[aa])[(i<<1)]; - int Im = ((int16_t*)ul_ch_estimates_time[aa])[1+(i<<1)]; - temp += (Re*Re/2) + (Im*Im/2); - } + int Re = ((int16_t *)ul_ch_estimates_time)[(i << 1)]; + int Im = ((int16_t *)ul_ch_estimates_time)[1 + (i << 1)]; + int temp = (Re * Re / 2) + (Im * Im / 2); if (temp > max_val) { max_pos = i; max_val = temp; } } - if (max_pos > frame_parms->ofdm_symbol_size/2) + if (max_pos > frame_parms->ofdm_symbol_size / 2) max_pos = max_pos - frame_parms->ofdm_symbol_size; - return max_pos - sync_pos; + delay->pusch_delay_max_pos = max_pos; + delay->pusch_delay_max_val = max_val; + delay->pusch_est_delay = max_pos - sync_pos; } int nr_est_timing_advance_srs(const NR_DL_FRAME_PARMS *frame_parms, diff --git a/openair1/PHY/NR_ESTIMATION/nr_ul_channel_estimation.c b/openair1/PHY/NR_ESTIMATION/nr_ul_channel_estimation.c index ebc225d82b..6dd2c85dfa 100644 --- a/openair1/PHY/NR_ESTIMATION/nr_ul_channel_estimation.c +++ b/openair1/PHY/NR_ESTIMATION/nr_ul_channel_estimation.c @@ -172,6 +172,10 @@ int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB, #endif + c16_t ul_ls_est[symbolSize]; + memset(ul_ls_est, 0, sizeof(c16_t) * symbolSize); + memset(&gNB->measurements.delay[ul_id], 0, sizeof(gNB->measurements.delay[ul_id])); + for (int aarx=0; aarxframe_parms.nb_antennas_rx; aarx++) { c16_t *rxdataF = (c16_t *)&gNB->common_vars.rxdataF[aarx][symbol_offset]; c16_t *ul_ch = &ul_ch_estimates[p*gNB->frame_parms.nb_antennas_rx+aarx][ch_offset]; @@ -193,39 +197,55 @@ int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB, int pilot_cnt = 0; int delta = nr_pusch_dmrs_delta(pusch_dmrs_type1, p); - for (int n = 0; n < 3*nb_rb_pusch; n++) { + for (int n = 0; n < 3 * nb_rb_pusch; n++) { // LS estimation c32_t ch = {0}; for (int k_line = 0; k_line <= 1; k_line++) { re_offset = (k0 + (n << 2) + (k_line << 1) + delta) % symbolSize; - ch=c32x16maddShift(*pil, - rxdataF[soffset + re_offset], - ch, - 16); + ch = c32x16maddShift(*pil, rxdataF[soffset + re_offset], ch, 16); pil++; } - c16_t ch16= {.r=(int16_t)ch.r, .i=(int16_t)ch.i}; + c16_t ch16 = {.r = (int16_t)ch.r, .i = (int16_t)ch.i}; *max_ch = max(*max_ch, max(abs(ch.r), abs(ch.i))); + ul_ls_est[pilot_cnt << 1] = ch16; + ul_ls_est[(pilot_cnt + 1) << 1] = ch16; + pilot_cnt += 2; + } + + freq2time(symbolSize, + (int16_t *) ul_ls_est, + (int16_t *) gNB->pusch_vars[ul_id]->ul_ch_estimates_time[aarx]); + + nr_est_timing_advance_pusch(&gNB->frame_parms, gNB->pusch_vars[ul_id]->ul_ch_estimates_time[aarx], &gNB->measurements.delay[ul_id]); + int delay = gNB->measurements.delay[ul_id].pusch_est_delay; + +#ifdef DEBUG_PUSCH + printf("Estimated delay = %i\n", delay >> 1); +#endif + + pilot_cnt = 0; + for (int n = 0; n < 3*nb_rb_pusch; n++) { + // Channel interpolation for (int k_line = 0; k_line <= 1; k_line++) { #ifdef DEBUG_PUSCH re_offset = (k0 + (n << 2) + (k_line << 1)) % symbolSize; c16_t *rxF = &rxdataF[soffset + re_offset]; printf("pilot %4u: pil -> (%6d,%6d), rxF -> (%4d,%4d), ch -> (%4d,%4d)\n", - pilot_cnt, pil->r, pil->i, rxF->r, rxF->i, ch.r, ch.i); + pilot_cnt, pil->r, pil->i, rxF->r, rxF->i, ul_ls_est[pilot_cnt << 1].r, ul_ls_est[pilot_cnt << 1].i); #endif if (pilot_cnt == 0) { - c16multaddVectRealComplex(filt16_ul_p0, &ch16, ul_ch, 16); + c16multaddVectRealComplex(filt16_ul_p0, &ul_ls_est[pilot_cnt << 1], ul_ch, 16); } else if (pilot_cnt == 1 || pilot_cnt == 2) { - c16multaddVectRealComplex(filt16_ul_p1p2, &ch16, ul_ch, 16); + c16multaddVectRealComplex(filt16_ul_p1p2, &ul_ls_est[pilot_cnt << 1], ul_ch, 16); } else if (pilot_cnt == (6 * nb_rb_pusch - 1)) { - c16multaddVectRealComplex(filt16_ul_last, &ch16, ul_ch, 16); + c16multaddVectRealComplex(filt16_ul_last, &ul_ls_est[pilot_cnt << 1], ul_ch, 16); } else { - c16multaddVectRealComplex(filt16_ul_middle, &ch16, ul_ch, 16); + c16multaddVectRealComplex(filt16_ul_middle, &ul_ls_est[pilot_cnt << 1], ul_ch, 16); if (pilot_cnt % 2 == 0) { ul_ch += 4; } @@ -442,11 +462,6 @@ int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB, printf("%d\n",idxP); } #endif - - // Convert to time domain - freq2time(symbolSize, - (int16_t *) &ul_ch_estimates[aarx][symbol_offset], - (int16_t *) gNB->pusch_vars[ul_id]->ul_ch_estimates_time[aarx]); } #ifdef DEBUG_CH diff --git a/openair1/PHY/NR_ESTIMATION/nr_ul_estimation.h b/openair1/PHY/NR_ESTIMATION/nr_ul_estimation.h index 9801e72e87..fb43e83827 100644 --- a/openair1/PHY/NR_ESTIMATION/nr_ul_estimation.h +++ b/openair1/PHY/NR_ESTIMATION/nr_ul_estimation.h @@ -55,7 +55,7 @@ void gNB_I0_measurements(PHY_VARS_gNB *gNB,int slot,int first_symb,int num_symb) void nr_gnb_measurements(PHY_VARS_gNB *gNB, uint8_t ulsch_id, unsigned char harq_pid, unsigned char symbol, uint8_t nrOfLayers); -int nr_est_timing_advance_pusch(PHY_VARS_gNB* phy_vars_gNB, int UE_id); +void nr_est_timing_advance_pusch(const NR_DL_FRAME_PARMS *frame_parms, const int32_t *ul_ch_estimates_time, struct delay_s *delay); int nr_est_timing_advance_srs(const NR_DL_FRAME_PARMS *frame_parms, const int32_t srs_estimated_channel_time[][frame_parms->ofdm_symbol_size]); diff --git a/openair1/PHY/defs_gNB.h b/openair1/PHY/defs_gNB.h index 60bf49796b..9c338b5d3f 100644 --- a/openair1/PHY/defs_gNB.h +++ b/openair1/PHY/defs_gNB.h @@ -545,6 +545,16 @@ typedef struct { int subband_cqi_tot_dB[NUMBER_OF_NR_ULSCH_MAX][275]; /// PRACH background noise level int prach_I0; + + struct delay_s { + /// Time shift in number of samples estimated based on DMRS-PUSCH + int pusch_est_delay; + /// Max position in OFDM symbol related to time shift estimation based on DMRS-PUSCH + int pusch_delay_max_pos; + /// Max value related to time shift estimation based on DMRS-PUSCH + int pusch_delay_max_val; + } delay[NUMBER_OF_NR_ULSCH_MAX]; + } PHY_MEASUREMENTS_gNB; diff --git a/openair1/SCHED_NR/phy_procedures_nr_gNB.c b/openair1/SCHED_NR/phy_procedures_nr_gNB.c index 6a1a8f7b36..110fe68ed4 100644 --- a/openair1/SCHED_NR/phy_procedures_nr_gNB.c +++ b/openair1/SCHED_NR/phy_procedures_nr_gNB.c @@ -401,8 +401,8 @@ void nr_fill_indication(PHY_VARS_gNB *gNB, int frame, int slot_rx, int ULSCH_id, nfapi_nr_pusch_pdu_t *pusch_pdu = &harq_process->ulsch_pdu; - // pdu->data = gNB->ulsch[ULSCH_id+1]->harq_processes[harq_pid]->b; - int sync_pos = nr_est_timing_advance_pusch(gNB, ULSCH_id); // estimate timing advance for MAC + // Get estimated timing advance for MAC + int sync_pos = gNB->measurements.delay[ULSCH_id].pusch_est_delay; // scale the 16 factor in N_TA calculation in 38.213 section 4.2 according to the used FFT size uint16_t bw_scaling = 16 * gNB->frame_parms.ofdm_symbol_size / 2048; diff --git a/openair1/SIMULATION/NR_PHY/ulsim.c b/openair1/SIMULATION/NR_PHY/ulsim.c index 8685626284..a2c5a40561 100644 --- a/openair1/SIMULATION/NR_PHY/ulsim.c +++ b/openair1/SIMULATION/NR_PHY/ulsim.c @@ -1040,6 +1040,12 @@ int main(int argc, char **argv) double berStats[16] = {0}; clear_pusch_stats(gNB); + + uint64_t sum_pusch_delay = 0; + int min_pusch_delay = INT_MAX; + int max_pusch_delay = INT_MIN; + int delay_pusch_est_count = 0; + for (trial = 0; trial < n_trials; trial++) { uint8_t round = 0; @@ -1552,6 +1558,12 @@ int main(int argc, char **argv) roundStats += ((float)round); if (!crc_status) effRate += ((double)TBS) / (double)round; + + sum_pusch_delay += gNB->measurements.delay[UE_id].pusch_est_delay; + min_pusch_delay = gNB->measurements.delay[UE_id].pusch_est_delay < min_pusch_delay ? gNB->measurements.delay[UE_id].pusch_est_delay : min_pusch_delay; + max_pusch_delay = gNB->measurements.delay[UE_id].pusch_est_delay > max_pusch_delay ? gNB->measurements.delay[UE_id].pusch_est_delay : max_pusch_delay; + delay_pusch_est_count++; + } // trial loop roundStats/=((float)n_trials); @@ -1581,6 +1593,12 @@ int main(int argc, char **argv) printf(",%e", berStats[r]); printf(") Avg round %.2f, Eff Rate %.4f bits/slot, Eff Throughput %.2f, TBS %u bits/slot\n", roundStats,effRate,effTP,TBS); + printf("DMRS-PUSCH delay estimation: min %i, max %i, average %f\n", + min_pusch_delay >> 1, max_pusch_delay >> 1, (double)sum_pusch_delay / (2 * delay_pusch_est_count)); + + printf("*****************************************\n"); + printf("\n"); + FILE *fd=fopen("nr_ulsim.log","w"); if (fd == NULL) { printf("Problem with filename %s\n", "nr_ulsim.log"); @@ -1589,9 +1607,6 @@ int main(int argc, char **argv) dump_pusch_stats(fd,gNB); fclose(fd); - printf("*****************************************\n"); - printf("\n"); - if (print_perf==1) { printDistribution(&gNB->phy_proc_rx,table_rx,"Total PHY proc rx"); printStatIndent(&gNB->rx_pusch_stats,"RX PUSCH time");