diff --git a/openair1/PHY/INIT/nr_init.c b/openair1/PHY/INIT/nr_init.c index 1c29d631818ea9d6ae0ee28fd5c2ed45f85cf70f..298c69118f43fcbb83236a4d98606a09507d018b 100644 --- a/openair1/PHY/INIT/nr_init.c +++ b/openair1/PHY/INIT/nr_init.c @@ -67,6 +67,17 @@ int l1_north_init_gNB() { return(0); } +void init_ul_delay_table(NR_DL_FRAME_PARMS *fp) +{ + for (int delay = -MAX_UL_DELAY_COMP; delay <= MAX_UL_DELAY_COMP; delay++) { + for (int k = 0; k < fp->ofdm_symbol_size; k++) { + double complex delay_cexp = cexp(I * (2.0 * M_PI * k * delay / fp->ofdm_symbol_size)); + fp->ul_delay_table[MAX_UL_DELAY_COMP + delay][k].r = (int16_t)round(256 * creal(delay_cexp)); + fp->ul_delay_table[MAX_UL_DELAY_COMP + delay][k].i = (int16_t)round(256 * cimag(delay_cexp)); + } + } +} + int init_codebook_gNB(PHY_VARS_gNB *gNB) { if(gNB->frame_parms.nb_antennas_tx>1){ @@ -501,6 +512,7 @@ int phy_init_nr_gNB(PHY_VARS_gNB *gNB) load_nrLDPClib_offload(); init_codebook_gNB(gNB); + init_ul_delay_table(fp); // PBCH DMRS gold sequences generation nr_init_pbch_dmrs(gNB); diff --git a/openair1/PHY/NR_ESTIMATION/nr_ul_channel_estimation.c b/openair1/PHY/NR_ESTIMATION/nr_ul_channel_estimation.c index 7827d69b7e35fa09864a88ce26785a563b21d8d8..aabdd15f4e9b96fa3485cc17ef5ee6e94ec42c47 100644 --- a/openair1/PHY/NR_ESTIMATION/nr_ul_channel_estimation.c +++ b/openair1/PHY/NR_ESTIMATION/nr_ul_channel_estimation.c @@ -100,6 +100,17 @@ __attribute__((always_inline)) inline c16_t c32x16cumulVectVectWithSteps(c16_t * return c16x32div(cumul, N); } +int get_delay_idx(int delay) { + int delay_idx = MAX_UL_DELAY_COMP + delay; + if (delay_idx < 0) { + delay_idx = 0; + } + if (delay_idx > MAX_UL_DELAY_COMP<<1) { + delay_idx = MAX_UL_DELAY_COMP<<1; + } + return delay_idx; +} + int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB, unsigned char Ns, unsigned short p, @@ -209,9 +220,9 @@ int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB, 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; + for (int k = pilot_cnt << 1; k < (pilot_cnt << 1) + 4; k++) { + ul_ls_est[k] = ch16; + } pilot_cnt += 2; } @@ -221,6 +232,8 @@ int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB, 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; + int delay_idx = get_delay_idx(delay); + c16_t *ul_delay_table = gNB->frame_parms.ul_delay_table[delay_idx]; #ifdef DEBUG_PUSCH printf("Estimated delay = %i\n", delay >> 1); @@ -231,21 +244,25 @@ int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB, // Channel interpolation for (int k_line = 0; k_line <= 1; k_line++) { + + // Apply delay + int k = pilot_cnt << 1; + c16_t ch16 = c16mulShift(ul_ls_est[k], ul_delay_table[k], 8); + #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, ul_ls_est[pilot_cnt << 1].r, ul_ls_est[pilot_cnt << 1].i); + printf("ch -> (%4d,%4d), ch_delay_comp -> (%4d,%4d)\n", ul_ls_est[k].r, ul_ls_est[k].i, ch16.r, ch16.i); #endif if (pilot_cnt == 0) { - c16multaddVectRealComplex(filt16_ul_p0, &ul_ls_est[pilot_cnt << 1], ul_ch, 16); + c16multaddVectRealComplex(filt16_ul_p0, &ch16, ul_ch, 16); } else if (pilot_cnt == 1 || pilot_cnt == 2) { - c16multaddVectRealComplex(filt16_ul_p1p2, &ul_ls_est[pilot_cnt << 1], ul_ch, 16); + c16multaddVectRealComplex(filt16_ul_p1p2, &ch16, ul_ch, 16); } else if (pilot_cnt == (6 * nb_rb_pusch - 1)) { - c16multaddVectRealComplex(filt16_ul_last, &ul_ls_est[pilot_cnt << 1], ul_ch, 16); + c16multaddVectRealComplex(filt16_ul_last, &ch16, ul_ch, 16); } else { - c16multaddVectRealComplex(filt16_ul_middle, &ul_ls_est[pilot_cnt << 1], ul_ch, 16); + c16multaddVectRealComplex(filt16_ul_middle, &ch16, ul_ch, 16); if (pilot_cnt % 2 == 0) { ul_ch += 4; } @@ -255,19 +272,24 @@ int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB, } } + // Revert delay + pilot_cnt = 0; + ul_ch = &ul_ch_estimates[p * gNB->frame_parms.nb_antennas_rx + aarx][ch_offset]; + int inv_delay_idx = get_delay_idx(-delay); + c16_t *ul_inv_delay_table = gNB->frame_parms.ul_delay_table[inv_delay_idx]; + for (int n = 0; n < 3 * nb_rb_pusch; n++) { + for (int k_line = 0; k_line <= 1; k_line++) { + int k = pilot_cnt << 1; + ul_ch[k] = c16mulShift(ul_ch[k], ul_inv_delay_table[k], 8); + ul_ch[k + 1] = c16mulShift(ul_ch[k + 1], ul_inv_delay_table[k + 1], 8); #ifdef DEBUG_PUSCH - ul_ch = &ul_ch_estimates[p*gNB->frame_parms.nb_antennas_rx+aarx][ch_offset]; - - for(uint16_t idxP=0; idxP<ceil((float)nb_rb_pusch*12/8); idxP++) { - printf("(%3d)\t",idxP); - - for(uint8_t idxI=0; idxI<8; idxI++) { - printf("%d\t%d\t",ul_ch[idxP*8+idxI].r,ul_ch[idxP*8+idxI].i); + re_offset = (k0 + (n << 2) + (k_line << 1)) % symbolSize; + c16_t *rxF = &rxdataF[soffset + re_offset]; + printf("ch -> (%4d,%4d), ch_inter -> (%4d,%4d)\n", ul_ls_est[k].r, ul_ls_est[k].i, ul_ch[k].r, ul_ch[k].i); +#endif + pilot_cnt++; } - - printf("\n"); } -#endif } else if (pusch_pdu->dmrs_config_type == pusch_dmrs_type2 && chest_freq == 0) { //pusch_dmrs_type2 |p_r,p_l,d,d,d,d,p_r,p_l,d,d,d,d| LOG_D(PHY,"PUSCH estimation DMRS type 2, Freq-domain interpolation"); @@ -500,16 +522,15 @@ int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB, } #ifdef DEBUG_PUSCH - ul_ch = &ul_ch_estimates[p*gNB->frame_parms.nb_antennas_rx+aarx][ch_offset]; - - for(int idxP=0; idxP<ceil((float)nb_rb_pusch*12/8); idxP++) { - for(int idxI=0; idxI<8; idxI++) { - printf("%d\t%d\t",ul_ch[idxP*8+idxI].r,ul_ch[idxP*8+idxI].i); + ul_ch = &ul_ch_estimates[p * gNB->frame_parms.nb_antennas_rx + aarx][ch_offset]; + for (int idxP = 0; idxP < ceil((float)nb_rb_pusch * 12 / 8); idxP++) { + for (int idxI = 0; idxI < 8; idxI++) { + printf("%d\t%d\t", ul_ch[idxP * 8 + idxI].r, ul_ch[idxP * 8 + idxI].i); } - - printf("%d\n",idxP); + printf("%d\n", idxP); } #endif + } #ifdef DEBUG_CH diff --git a/openair1/PHY/defs_nr_common.h b/openair1/PHY/defs_nr_common.h index c99e07fe7d15412830fa52ac4a79369125af671c..b5d7bb784906fc288221b65cc6422e67322d7caa 100644 --- a/openair1/PHY/defs_nr_common.h +++ b/openair1/PHY/defs_nr_common.h @@ -107,6 +107,8 @@ #define NR_NB_NSCID 2 +#define MAX_UL_DELAY_COMP 20 + extern const uint8_t nr_rv_round_map[4]; static inline @@ -303,6 +305,8 @@ struct NR_DL_FRAME_PARMS { /// sequence used to compensate the phase rotation due to timeshifted OFDM symbols /// First dimenstion is for different CP lengths c16_t timeshift_symbol_rotation[4096*2] __attribute__ ((aligned (16))); + /// Table used to apply the delay compensation in UL + c16_t ul_delay_table[2 * MAX_UL_DELAY_COMP + 1][NR_MAX_OFDM_SYMBOL_SIZE * 2]; /// shift of pilot position in one RB uint8_t nushift; /// SRS configuration from TS 38.331 RRC