From 79489496042816268c2e8623a0865b8c15030977 Mon Sep 17 00:00:00 2001 From: Sakthivel Velumani Date: Mon, 10 May 2021 00:09:18 +0200 Subject: [PATCH] Smoothing the frequency response --- .../NR_ESTIMATION/nr_ul_channel_estimation.c | 285 +++++++++++++++++- openair1/PHY/NR_UE_ESTIMATION/filt16a_32.c | 21 ++ openair1/PHY/NR_UE_ESTIMATION/filt16a_32.h | 15 +- .../nr_dl_channel_estimation.c | 280 ++++++++++++++++- 4 files changed, 572 insertions(+), 29 deletions(-) diff --git a/openair1/PHY/NR_ESTIMATION/nr_ul_channel_estimation.c b/openair1/PHY/NR_ESTIMATION/nr_ul_channel_estimation.c index fe945bfba6..682570bf67 100644 --- a/openair1/PHY/NR_ESTIMATION/nr_ul_channel_estimation.c +++ b/openair1/PHY/NR_ESTIMATION/nr_ul_channel_estimation.c @@ -518,9 +518,72 @@ int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB, } else if (pusch_pdu->dmrs_config_type == pusch_dmrs_type1) {// this is case without frequency-domain linear interpolation, just take average of LS channel estimates of 6 DMRS REs and use a common value for the whole PRB + int32_t ch_0, ch_1; + // First PRB + ch_0 = ((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15; + ch_1 = ((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15; - for (pilot_cnt=0; pilot_cnt<6*nb_rb_pusch; pilot_cnt += 6) { - int32_t ch_0, ch_1; + pil += 2; + re_offset = (re_offset+2) % gNB->frame_parms.ofdm_symbol_size; + rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; + + ch_0 += ((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15; + ch_1 += ((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15; + + pil += 2; + re_offset = (re_offset+2) % gNB->frame_parms.ofdm_symbol_size; + rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; + + ch_0 += ((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15; + ch_1 += ((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15; + + pil += 2; + re_offset = (re_offset+2) % gNB->frame_parms.ofdm_symbol_size; + rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; + + ch_0 += ((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15; + ch_1 += ((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15; + + pil += 2; + re_offset = (re_offset+2) % gNB->frame_parms.ofdm_symbol_size; + rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; + + ch_0 += ((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15; + ch_1 += ((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15; + + pil += 2; + re_offset = (re_offset+2) % gNB->frame_parms.ofdm_symbol_size; + rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; + + ch_0 += ((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15; + ch_1 += ((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15; + + pil += 2; + re_offset = (re_offset+2) % gNB->frame_parms.ofdm_symbol_size; + rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; + + ch[0] = ch_0 / 6; + ch[1] = ch_1 / 6; + + multadd_real_vector_complex_scalar(filt8_avlip0, + ch, + ul_ch, + 8); + + ul_ch += 16; + multadd_real_vector_complex_scalar(filt8_avlip1, + ch, + ul_ch, + 8); + + ul_ch += 16; + multadd_real_vector_complex_scalar(filt8_avlip2, + ch, + ul_ch, + 8); + ul_ch -= 24; + + for (pilot_cnt=6; pilot_cnt<6*(nb_rb_pusch-1); pilot_cnt += 6) { ch_0 = ((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15; ch_1 = ((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15; @@ -566,51 +629,243 @@ int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB, ch[0] = ch_0 / 6; ch[1] = ch_1 / 6; - ((__m128i*)ul_ch)[0]=_mm_set1_epi32(*(int32_t*)ch); - ((__m128i*)ul_ch)[1]=((__m128i*)ul_ch)[0]; - ((__m128i*)ul_ch)[2]=((__m128i*)ul_ch)[0]; - ul_ch += 24; + + ul_ch[6] += (ch[0] * 1365)>>15; // 1/12*16384 + ul_ch[7] += (ch[1] * 1365)>>15; // 1/12*16384 + + ul_ch += 8; + multadd_real_vector_complex_scalar(filt8_avlip3, + ch, + ul_ch, + 8); + + ul_ch += 16; + multadd_real_vector_complex_scalar(filt8_avlip4, + ch, + ul_ch, + 8); + + ul_ch += 16; + multadd_real_vector_complex_scalar(filt8_avlip5, + ch, + ul_ch, + 8); + ul_ch -= 16; } + // Last PRB + ch_0 = ((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15; + ch_1 = ((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15; + + pil += 2; + re_offset = (re_offset+2) % gNB->frame_parms.ofdm_symbol_size; + rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; + + ch_0 += ((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15; + ch_1 += ((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15; + + pil += 2; + re_offset = (re_offset+2) % gNB->frame_parms.ofdm_symbol_size; + rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; + + ch_0 += ((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15; + ch_1 += ((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15; + + pil += 2; + re_offset = (re_offset+2) % gNB->frame_parms.ofdm_symbol_size; + rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; + + ch_0 += ((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15; + ch_1 += ((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15; + + pil += 2; + re_offset = (re_offset+2) % gNB->frame_parms.ofdm_symbol_size; + rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; + + ch_0 += ((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15; + ch_1 += ((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15; + + pil += 2; + re_offset = (re_offset+2) % gNB->frame_parms.ofdm_symbol_size; + rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; + + ch_0 += ((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15; + ch_1 += ((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15; + + pil += 2; + re_offset = (re_offset+2) % gNB->frame_parms.ofdm_symbol_size; + rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; + + ch[0] = ch_0 / 6; + ch[1] = ch_1 / 6; + + ul_ch[6] += (ch[0] * 1365)>>15; // 1/12*16384 + ul_ch[7] += (ch[1] * 1365)>>15; // 1/12*16384 + + ul_ch += 8; + multadd_real_vector_complex_scalar(filt8_avlip3, + ch, + ul_ch, + 8); + + ul_ch += 16; + multadd_real_vector_complex_scalar(filt8_avlip6, + ch, + ul_ch, + 8); } else { // this is case without frequency-domain linear interpolation, just take average of LS channel estimates of 4 DMRS REs and use a common value for the whole PRB + int32_t ch_0, ch_1; + //First PRB + ch_0 = ((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15; + ch_1 = ((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15; + + pil += 2; + re_offset = (re_offset+1) % gNB->frame_parms.ofdm_symbol_size; + rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; + + ch_0 += ((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15; + ch_1 += ((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15; + + pil += 2; + re_offset = (re_offset+5) % gNB->frame_parms.ofdm_symbol_size; + rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; + + ch_0 += ((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15; + ch_1 += ((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15; + + pil += 2; + re_offset = (re_offset+1) % gNB->frame_parms.ofdm_symbol_size; + rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; + + ch_0 += ((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15; + ch_1 += ((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15; + + pil += 2; + re_offset = (re_offset+5) % gNB->frame_parms.ofdm_symbol_size; + rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; + + ch[0] = ch_0 / 4; + ch[1] = ch_1 / 4; + + multadd_real_vector_complex_scalar(filt8_avlip0, + ch, + ul_ch, + 8); + + ul_ch += 16; + multadd_real_vector_complex_scalar(filt8_avlip1, + ch, + ul_ch, + 8); + + ul_ch += 16; + multadd_real_vector_complex_scalar(filt8_avlip2, + ch, + ul_ch, + 8); + ul_ch -= 24; + for (pilot_cnt=0; pilot_cnt<4*nb_rb_pusch; pilot_cnt += 4) { - int32_t ch_0, ch_1; ch_0 = ((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15; ch_1 = ((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15; pil += 2; - re_offset = (re_offset+2) % gNB->frame_parms.ofdm_symbol_size; + re_offset = (re_offset+1) % gNB->frame_parms.ofdm_symbol_size; rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; ch_0 += ((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15; ch_1 += ((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15; pil += 2; - re_offset = (re_offset+2) % gNB->frame_parms.ofdm_symbol_size; + re_offset = (re_offset+5) % gNB->frame_parms.ofdm_symbol_size; rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; ch_0 += ((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15; ch_1 += ((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15; pil += 2; - re_offset = (re_offset+2) % gNB->frame_parms.ofdm_symbol_size; + re_offset = (re_offset+1) % gNB->frame_parms.ofdm_symbol_size; rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; ch_0 += ((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15; ch_1 += ((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15; pil += 2; - re_offset = (re_offset+2) % gNB->frame_parms.ofdm_symbol_size; + re_offset = (re_offset+5) % gNB->frame_parms.ofdm_symbol_size; rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; ch[0] = ch_0 / 4; ch[1] = ch_1 / 4; - ((__m128i*)ul_ch)[0]=_mm_set1_epi32(*(int32_t*)ch); - ((__m128i*)ul_ch)[1]=((__m128i*)ul_ch)[0]; - ((__m128i*)ul_ch)[2]=((__m128i*)ul_ch)[0]; - ul_ch += 24; + + ul_ch[6] += (ch[0] * 1365)>>15; // 1/12*16384 + ul_ch[7] += (ch[1] * 1365)>>15; // 1/12*16384 + + ul_ch += 8; + multadd_real_vector_complex_scalar(filt8_avlip3, + ch, + ul_ch, + 8); + + ul_ch += 16; + multadd_real_vector_complex_scalar(filt8_avlip4, + ch, + ul_ch, + 8); + + ul_ch += 16; + multadd_real_vector_complex_scalar(filt8_avlip5, + ch, + ul_ch, + 8); + ul_ch -= 16; } + // Last PRB + ch_0 = ((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15; + ch_1 = ((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15; + + pil += 2; + re_offset = (re_offset+1) % gNB->frame_parms.ofdm_symbol_size; + rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; + + ch_0 += ((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15; + ch_1 += ((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15; + + pil += 2; + re_offset = (re_offset+5) % gNB->frame_parms.ofdm_symbol_size; + rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; + + ch_0 += ((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15; + ch_1 += ((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15; + + pil += 2; + re_offset = (re_offset+1) % gNB->frame_parms.ofdm_symbol_size; + rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; + + ch_0 += ((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15; + ch_1 += ((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15; + + pil += 2; + re_offset = (re_offset+5) % gNB->frame_parms.ofdm_symbol_size; + rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; + + ch[0] = ch_0 / 4; + ch[1] = ch_1 / 4; + + ul_ch[6] += (ch[0] * 1365)>>15; // 1/12*16384 + ul_ch[7] += (ch[1] * 1365)>>15; // 1/12*16384 + + ul_ch += 8; + multadd_real_vector_complex_scalar(filt8_avlip3, + ch, + ul_ch, + 8); + + ul_ch += 16; + multadd_real_vector_complex_scalar(filt8_avlip6, + ch, + ul_ch, + 8); } #ifdef DEBUG_PUSCH ul_ch = (int16_t *)&ul_ch_estimates[p*gNB->frame_parms.nb_antennas_rx+aarx][ch_offset]; diff --git a/openair1/PHY/NR_UE_ESTIMATION/filt16a_32.c b/openair1/PHY/NR_UE_ESTIMATION/filt16a_32.c index 990f3101fd..65ae288252 100644 --- a/openair1/PHY/NR_UE_ESTIMATION/filt16a_32.c +++ b/openair1/PHY/NR_UE_ESTIMATION/filt16a_32.c @@ -239,3 +239,24 @@ short filt8_dcll2[8] = { short filt8_dclh2[8] = { 0,0,0,0,1489,2979,4468,5958}; + +short filt8_avlip0[8] = { +16384,16384,16384,16384,16384,16384,16384,15019}; + +short filt8_avlip1[8] = { +13653,12288,10923,9557,8192,6827,5461,4096}; + +short filt8_avlip2[8] = { +2731,1365,0,0,0,0,0,0}; + +short filt8_avlip3[8] = { +2731,4096,5461,6827,8192,9557,10923,12288}; + +short filt8_avlip4[8] = { +13653,15019,16384,15019,13653,12288,10923,9557}; + +short filt8_avlip5[8] = { +8192,6827,5461,4096,2731,1365,0,0}; + +short filt8_avlip6[8] = { +13653,15019,16384,16384,16384,16384,16384,16384}; diff --git a/openair1/PHY/NR_UE_ESTIMATION/filt16a_32.h b/openair1/PHY/NR_UE_ESTIMATION/filt16a_32.h index ef6137a07f..e28736b51d 100644 --- a/openair1/PHY/NR_UE_ESTIMATION/filt16a_32.h +++ b/openair1/PHY/NR_UE_ESTIMATION/filt16a_32.h @@ -169,4 +169,17 @@ extern short filt8_dcll2[8]; extern short filt8_dclh2[8]; -#endif \ No newline at end of file +extern short filt8_avlip0[8]; + +extern short filt8_avlip1[8]; + +extern short filt8_avlip2[8]; + +extern short filt8_avlip3[8]; + +extern short filt8_avlip4[8]; + +extern short filt8_avlip5[8]; + +extern short filt8_avlip6[8]; +#endif diff --git a/openair1/PHY/NR_UE_ESTIMATION/nr_dl_channel_estimation.c b/openair1/PHY/NR_UE_ESTIMATION/nr_dl_channel_estimation.c index ab9a42c60d..56eafba87e 100644 --- a/openair1/PHY/NR_UE_ESTIMATION/nr_dl_channel_estimation.c +++ b/openair1/PHY/NR_UE_ESTIMATION/nr_dl_channel_estimation.c @@ -1198,9 +1198,72 @@ int nr_pdsch_channel_estimation(PHY_VARS_NR_UE *ue, } } else if (config_type == pdsch_dmrs_type1) { // this is case without frequency-domain linear interpolation, just take average of LS channel estimates of 6 DMRS REs and use a common value for the whole PRB + int32_t ch_0, ch_1; + ch_0 = ((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15; + ch_1 = ((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15; + + pil += 2; + re_offset = (re_offset+2) % ue->frame_parms.ofdm_symbol_size; + rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; + + ch_0 += ((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15; + ch_1 += ((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15; + + pil += 2; + re_offset = (re_offset+2) % ue->frame_parms.ofdm_symbol_size; + rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; + + ch_0 += ((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15; + ch_1 += ((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15; + + pil += 2; + re_offset = (re_offset+2) % ue->frame_parms.ofdm_symbol_size; + rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; + + ch_0 += ((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15; + ch_1 += ((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15; + + pil += 2; + re_offset = (re_offset+2) % ue->frame_parms.ofdm_symbol_size; + rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; + + ch_0 += ((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15; + ch_1 += ((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15; + + pil += 2; + re_offset = (re_offset+2) % ue->frame_parms.ofdm_symbol_size; + rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; + + ch_0 += ((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15; + ch_1 += ((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15; + + pil += 2; + re_offset = (re_offset+2) % ue->frame_parms.ofdm_symbol_size; + rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; + + ch[0] = ch_0 / 6; + ch[1] = ch_1 / 6; + + multadd_real_vector_complex_scalar(filt8_avlip0, + ch, + dl_ch, + 8); + + dl_ch += 16; + multadd_real_vector_complex_scalar(filt8_avlip1, + ch, + dl_ch, + 8); + + dl_ch += 16; + multadd_real_vector_complex_scalar(filt8_avlip2, + ch, + dl_ch, + 8); + dl_ch -= 24; + for (pilot_cnt=0; pilot_cnt<6*nb_rb_pdsch; pilot_cnt += 6) { - int32_t ch_0, ch_1; ch_0 = ((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15; ch_1 = ((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15; @@ -1246,13 +1309,140 @@ int nr_pdsch_channel_estimation(PHY_VARS_NR_UE *ue, ch[0] = ch_0 / 6; ch[1] = ch_1 / 6; - ((__m128i*)dl_ch)[0]=_mm_set1_epi32(*(int32_t*)ch); - ((__m128i*)dl_ch)[1]=((__m128i*)dl_ch)[0]; - ((__m128i*)dl_ch)[2]=((__m128i*)dl_ch)[0]; - dl_ch += 24; + dl_ch[6] += (ch[0] * 1365)>>15; // 1/12*16384 + dl_ch[7] += (ch[1] * 1365)>>15; // 1/12*16384 + + dl_ch += 8; + multadd_real_vector_complex_scalar(filt8_avlip3, + ch, + dl_ch, + 8); + + dl_ch += 16; + multadd_real_vector_complex_scalar(filt8_avlip4, + ch, + dl_ch, + 8); + + dl_ch += 16; + multadd_real_vector_complex_scalar(filt8_avlip5, + ch, + dl_ch, + 8); + dl_ch -= 16; } + ch_0 = ((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15; + ch_1 = ((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15; + + pil += 2; + re_offset = (re_offset+2) % ue->frame_parms.ofdm_symbol_size; + rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; + + ch_0 += ((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15; + ch_1 += ((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15; + + pil += 2; + re_offset = (re_offset+2) % ue->frame_parms.ofdm_symbol_size; + rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; + + ch_0 += ((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15; + ch_1 += ((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15; + + pil += 2; + re_offset = (re_offset+2) % ue->frame_parms.ofdm_symbol_size; + rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; + + ch_0 += ((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15; + ch_1 += ((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15; + + pil += 2; + re_offset = (re_offset+2) % ue->frame_parms.ofdm_symbol_size; + rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; + + ch_0 += ((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15; + ch_1 += ((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15; + + pil += 2; + re_offset = (re_offset+2) % ue->frame_parms.ofdm_symbol_size; + rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; + + ch_0 += ((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15; + ch_1 += ((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15; + + pil += 2; + re_offset = (re_offset+2) % ue->frame_parms.ofdm_symbol_size; + rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; + + ch[0] = ch_0 / 6; + ch[1] = ch_1 / 6; + + dl_ch[6] += (ch[0] * 1365)>>15; // 1/12*16384 + dl_ch[7] += (ch[1] * 1365)>>15; // 1/12*16384 + + dl_ch += 8; + multadd_real_vector_complex_scalar(filt8_avlip3, + ch, + dl_ch, + 8); + + dl_ch += 16; + multadd_real_vector_complex_scalar(filt8_avlip6, + ch, + dl_ch, + 8); } else { // this is case without frequency-domain linear interpolation, just take average of LS channel estimates of 4 DMRS REs and use a common value for the whole PRB + int32_t ch_0, ch_1; + + ch_0 = ((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15; + ch_1 = ((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15; + + pil += 2; + re_offset = (re_offset+1) % ue->frame_parms.ofdm_symbol_size; + rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; + + ch_0 += ((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15; + ch_1 += ((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15; + + pil += 2; + re_offset = (re_offset+5) % ue->frame_parms.ofdm_symbol_size; + rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; + + ch_0 += ((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15; + ch_1 += ((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15; + + pil += 2; + re_offset = (re_offset+1) % ue->frame_parms.ofdm_symbol_size; + rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; + + ch_0 += ((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15; + ch_1 += ((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15; + + pil += 2; + re_offset = (re_offset+5) % ue->frame_parms.ofdm_symbol_size; + rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; + + ch[0] = ch_0 / 4; + ch[1] = ch_1 / 4; + + multadd_real_vector_complex_scalar(filt8_avlip0, + ch, + dl_ch, + 8); + + dl_ch += 16; + multadd_real_vector_complex_scalar(filt8_avlip1, + ch, + dl_ch, + 8); + + dl_ch += 16; + multadd_real_vector_complex_scalar(filt8_avlip2, + ch, + dl_ch, + 8); + dl_ch -= 24; + for (pilot_cnt=0; pilot_cnt<4*nb_rb_pdsch; pilot_cnt += 4) { int32_t ch_0, ch_1; @@ -1260,37 +1450,101 @@ int nr_pdsch_channel_estimation(PHY_VARS_NR_UE *ue, ch_1 = ((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15; pil += 2; - re_offset = (re_offset+2) % ue->frame_parms.ofdm_symbol_size; + re_offset = (re_offset+1) % ue->frame_parms.ofdm_symbol_size; rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; ch_0 += ((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15; ch_1 += ((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15; pil += 2; - re_offset = (re_offset+2) % ue->frame_parms.ofdm_symbol_size; + re_offset = (re_offset+5) % ue->frame_parms.ofdm_symbol_size; rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; ch_0 += ((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15; ch_1 += ((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15; pil += 2; - re_offset = (re_offset+2) % ue->frame_parms.ofdm_symbol_size; + re_offset = (re_offset+1) % ue->frame_parms.ofdm_symbol_size; rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; ch_0 += ((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15; ch_1 += ((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15; pil += 2; - re_offset = (re_offset+2) % ue->frame_parms.ofdm_symbol_size; + re_offset = (re_offset+5) % ue->frame_parms.ofdm_symbol_size; rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; ch[0] = ch_0 / 4; ch[1] = ch_1 / 4; - ((__m128i*)dl_ch)[0]=_mm_set1_epi32(*(int32_t*)ch); - ((__m128i*)dl_ch)[1]=((__m128i*)dl_ch)[0]; - ((__m128i*)dl_ch)[2]=((__m128i*)dl_ch)[0]; - dl_ch += 24; + + dl_ch[6] += (ch[0] * 1365)>>15; // 1/12*16384 + dl_ch[7] += (ch[1] * 1365)>>15; // 1/12*16384 + + dl_ch += 8; + multadd_real_vector_complex_scalar(filt8_avlip3, + ch, + dl_ch, + 8); + + dl_ch += 16; + multadd_real_vector_complex_scalar(filt8_avlip4, + ch, + dl_ch, + 8); + + dl_ch += 16; + multadd_real_vector_complex_scalar(filt8_avlip5, + ch, + dl_ch, + 8); + dl_ch -= 16; } + + ch_0 = ((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15; + ch_1 = ((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15; + + pil += 2; + re_offset = (re_offset+1) % ue->frame_parms.ofdm_symbol_size; + rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; + + ch_0 += ((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15; + ch_1 += ((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15; + + pil += 2; + re_offset = (re_offset+5) % ue->frame_parms.ofdm_symbol_size; + rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; + + ch_0 += ((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15; + ch_1 += ((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15; + + pil += 2; + re_offset = (re_offset+1) % ue->frame_parms.ofdm_symbol_size; + rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; + + ch_0 += ((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15; + ch_1 += ((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15; + + pil += 2; + re_offset = (re_offset+5) % ue->frame_parms.ofdm_symbol_size; + rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+nushift+re_offset)]; + + ch[0] = ch_0 / 4; + ch[1] = ch_1 / 4; + + dl_ch[6] += (ch[0] * 1365)>>15; // 1/12*16384 + dl_ch[7] += (ch[1] * 1365)>>15; // 1/12*16384 + + dl_ch += 8; + multadd_real_vector_complex_scalar(filt8_avlip3, + ch, + dl_ch, + 8); + + dl_ch += 16; + multadd_real_vector_complex_scalar(filt8_avlip6, + ch, + dl_ch, + 8); } #ifdef DEBUG_PDSCH dl_ch = (int16_t *)&dl_ch_estimates[p*ue->frame_parms.nb_antennas_rx+aarx][ch_offset];