From 8b4d21d911be508adc079b5887c694914020345d Mon Sep 17 00:00:00 2001 From: Sagar Parsawar Date: Mon, 24 Jan 2022 12:57:13 +0100 Subject: [PATCH] OAI UE: CombSize 2 support for PRS channel estimation and interpolation --- .../nr_dl_channel_estimation.c | 364 +++++++++++++----- 1 file changed, 260 insertions(+), 104 deletions(-) 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 af1bd95e9d..262dcada2d 100644 --- a/openair1/PHY/NR_UE_ESTIMATION/nr_dl_channel_estimation.c +++ b/openair1/PHY/NR_UE_ESTIMATION/nr_dl_channel_estimation.c @@ -52,7 +52,7 @@ int nr_prs_channel_estimation(PHY_VARS_NR_UE *ue, uint32_t **nr_gold_prs = ue->nr_gold_prs[proc->nr_slot_rx]; prs_data_t *prs_cfg = &ue->prs_cfg; - int16_t *prs_chest, ch[2] = {0}, *rxF, *pil, *fl,*fm, *fmm, *fml, *fr, mod_prs[NR_MAX_PRS_LENGTH<<1]; + int16_t *prs_chest, ch[2] = {0}, *rxF, *pil, *fl,*fm, *fmm, *fml, *fmr, *fr, mod_prs[NR_MAX_PRS_LENGTH<<1]; int16_t k_prime = 0, k = 0; uint8_t idx = prs_cfg->NPRSID; uint8_t rxAnt = 0; // ant 0 rxdataF for now @@ -76,46 +76,6 @@ int nr_prs_channel_estimation(PHY_VARS_NR_UE *ue, printf("PRS config l %d k_prime %d:\nprs_cfg->SymbolStart %d\nprs_cfg->NumPRSSymbols %d\nprs_cfg->NumRB %d\nprs_cfg->CombSize %d\n", l, k_prime, prs_cfg->SymbolStart, prs_cfg->NumPRSSymbols, prs_cfg->NumRB, prs_cfg->CombSize); - //TODO currently supported only comb_size 2 and 4 - switch (k_prime) { - case 0: - fl = filt16a_l0; - fmm = filt16a_mm0; - fml = filt16a_mm0; - fm = filt16a_m0; - fr = filt16a_r0; - break; - - case 1: - fl = filt16a_l1; - fmm = filt16a_mm1; - fml = filt16a_ml1; - fm = filt16a_m1; - fr = filt16a_r1; - break; - - case 2: - fl = filt16a_l2; - fmm = filt16a_mm2; - fml = filt16a_ml2; - fm = filt16a_m2; - fr = filt16a_r2; - break; - - case 3: - fl = filt16a_l3; - fmm = filt16a_mm3; - fml = filt16a_ml3; - fm = filt16a_m3; - fr = filt16a_r3; - break; - - default: - printf("nr=prs channel_estimation: k_prime=%d -> ERROR\n",k_prime); - return(-1); - break; - } - //re_offset k = (prs_cfg->REOffset+k_prime) % prs_cfg->CombSize + frame_params->first_carrier_offset; @@ -126,91 +86,287 @@ int nr_prs_channel_estimation(PHY_VARS_NR_UE *ue, mod_prs[m<<1] = nr_qpsk_mod_table[idx<<1]; mod_prs[(m<<1)+1] = nr_qpsk_mod_table[(idx<<1) + 1]; } - + // Channel estimation and interpolation pil = (int16_t *)&mod_prs[0]; rxF = (int16_t *)&rxdataF[rxAnt][l*frame_params->ofdm_symbol_size + k]; prs_chest = (int16_t *)&ue->prs_ch_estimates[rxAnt][l*frame_params->ofdm_symbol_size]; memset(prs_chest,0,4*(ue->frame_parms.ofdm_symbol_size)); - - //Start pilot - ch[0] = (int16_t)(((int32_t)rxF[0]*pil[0] + (int32_t)rxF[1]*pil[1])>>15); - ch[1] = (int16_t)(((int32_t)rxF[1]*pil[0] - (int32_t)rxF[0]*pil[1])>>15); -#ifdef DEBUG_PRS_CHEST - printf("pilIdx %d at k %d of l %d reIdx %d rxF %p %d %d ch[0] %d ch[1] %d\n", 0, k, l, (l*frame_params->ofdm_symbol_size + k), rxF, rxF[0], rxF[1], ch[0], ch[1]); -#endif - - multadd_real_vector_complex_scalar(fl, - ch, - prs_chest, - 16); - pil +=2; - k = (k+prs_cfg->CombSize) % frame_params->ofdm_symbol_size; - rxF = (int16_t *)&rxdataF[rxAnt][l*frame_params->ofdm_symbol_size + k]; - - ch[0] = (int16_t)(((int32_t)rxF[0]*pil[0] + (int32_t)rxF[1]*pil[1])>>15); - ch[1] = (int16_t)(((int32_t)rxF[1]*pil[0] - (int32_t)rxF[0]*pil[1])>>15); -#ifdef DEBUG_PRS_CHEST - printf("pilIdx %d at k %d of l %d reIdx %d rxF %p %d %d ch[0] %d ch[1] %d\n", 1, k, l, (l*frame_params->ofdm_symbol_size + k), rxF, rxF[0], rxF[1], ch[0], ch[1]); -#endif - - multadd_real_vector_complex_scalar(fml, - ch, - prs_chest, - 16); - - pil +=2; - k = (k+prs_cfg->CombSize) % frame_params->ofdm_symbol_size; - rxF = (int16_t *)&rxdataF[rxAnt][l*frame_params->ofdm_symbol_size + k]; - prs_chest +=8; - - //Middle pilots - for(int pIdx = 2; pIdx < prs_cfg->NumRB*(12/prs_cfg->CombSize)-2; pIdx++) + if(prs_cfg->CombSize == 2) { + // Choose the interpolation filters + switch (k_prime) { + case 0: + fl = filt8_l0; + fml = filt8_m0; + fmm = filt8_mm0; + fmr = filt8_mr0; + fm = filt8_m0; + fr = filt8_r0; + break; + + case 1: + fl = filt8_l1; + fmm = filt8_mm1; + fml = filt8_ml1; + fmr = fmm; + fm = filt8_m1; + fr = filt8_r1; + break; + default: + printf("nr=prs channel_estimation: k_prime=%d -> ERROR\n",k_prime); + return(-1); + break; + } + + //Start pilot ch[0] = (int16_t)(((int32_t)rxF[0]*pil[0] + (int32_t)rxF[1]*pil[1])>>15); ch[1] = (int16_t)(((int32_t)rxF[1]*pil[0] - (int32_t)rxF[0]*pil[1])>>15); #ifdef DEBUG_PRS_CHEST - printf("pilIdx %d at k %d of l %d reIdx %d rxF %p %d %d ch[0] %d ch[1] %d\n", pIdx, k, l, (l*frame_params->ofdm_symbol_size + k), rxF, rxF[0], rxF[1], ch[0], ch[1]); + printf("pilIdx %d at k %d of l %d reIdx %d rxF %p %d %d ch[0] %d ch[1] %d\n", 0, k, l, (l*frame_params->ofdm_symbol_size + k), rxF, rxF[0], rxF[1], ch[0], ch[1]); +#endif + + multadd_real_vector_complex_scalar(fl, + ch, + prs_chest, + 8); + + pil +=2; + k = (k+prs_cfg->CombSize) % frame_params->ofdm_symbol_size; + rxF = (int16_t *)&rxdataF[rxAnt][l*frame_params->ofdm_symbol_size + k]; + + ch[0] = (int16_t)(((int32_t)rxF[0]*pil[0] + (int32_t)rxF[1]*pil[1])>>15); + ch[1] = (int16_t)(((int32_t)rxF[1]*pil[0] - (int32_t)rxF[0]*pil[1])>>15); +#ifdef DEBUG_PRS_CHEST + printf("pilIdx %d at k %d of l %d reIdx %d rxF %p %d %d ch[0] %d ch[1] %d\n", 1, k, l, (l*frame_params->ofdm_symbol_size + k), rxF, rxF[0], rxF[1], ch[0], ch[1]); +#endif + + multadd_real_vector_complex_scalar(fml, + ch, + prs_chest, + 8); + + pil +=2; + k = (k+prs_cfg->CombSize) % frame_params->ofdm_symbol_size; + rxF = (int16_t *)&rxdataF[rxAnt][l*frame_params->ofdm_symbol_size + k]; + + ch[0] = (int16_t)(((int32_t)rxF[0]*pil[0] + (int32_t)rxF[1]*pil[1])>>15); + ch[1] = (int16_t)(((int32_t)rxF[1]*pil[0] - (int32_t)rxF[0]*pil[1])>>15); +#ifdef DEBUG_PRS_CHEST + printf("pilIdx %d at k %d of l %d reIdx %d rxF %p %d %d ch[0] %d ch[1] %d\n", 2, k, l, (l*frame_params->ofdm_symbol_size + k), rxF, rxF[0], rxF[1], ch[0], ch[1]); #endif multadd_real_vector_complex_scalar(fmm, - ch, - prs_chest, - 16); + ch, + prs_chest, + 8); pil +=2; k = (k+prs_cfg->CombSize) % frame_params->ofdm_symbol_size; rxF = (int16_t *)&rxdataF[rxAnt][l*frame_params->ofdm_symbol_size + k]; prs_chest +=8; - } - - //End pilot - ch[0] = (int16_t)(((int32_t)rxF[0]*pil[0] + (int32_t)rxF[1]*pil[1])>>15); - ch[1] = (int16_t)(((int32_t)rxF[1]*pil[0] - (int32_t)rxF[0]*pil[1])>>15); + + //Middle pilots + for(int pIdx = 3; pIdx < prs_cfg->NumRB*(12/prs_cfg->CombSize)-3; pIdx+=2) + { + ch[0] = (int16_t)(((int32_t)rxF[0]*pil[0] + (int32_t)rxF[1]*pil[1])>>15); + ch[1] = (int16_t)(((int32_t)rxF[1]*pil[0] - (int32_t)rxF[0]*pil[1])>>15); #ifdef DEBUG_PRS_CHEST - printf("pilIdx %d at k %d of l %d reIdx %d rxF %p %d %d ch[0] %d ch[1] %d\n", 0, k, l, (l*frame_params->ofdm_symbol_size + k), rxF, rxF[0], rxF[1], ch[0], ch[1]); + printf("pilIdx %d at k %d of l %d reIdx %d rxF %p %d %d ch[0] %d ch[1] %d\n", pIdx, k, l, (l*frame_params->ofdm_symbol_size + k), rxF, rxF[0], rxF[1], ch[0], ch[1]); #endif - - multadd_real_vector_complex_scalar(fm, - ch, - prs_chest, - 16); - - pil +=2; - k = (k+prs_cfg->CombSize) % frame_params->ofdm_symbol_size; - rxF = (int16_t *)&rxdataF[rxAnt][l*frame_params->ofdm_symbol_size + k]; - - ch[0] = (int16_t)(((int32_t)rxF[0]*pil[0] + (int32_t)rxF[1]*pil[1])>>15); - ch[1] = (int16_t)(((int32_t)rxF[1]*pil[0] - (int32_t)rxF[0]*pil[1])>>15); + + multadd_real_vector_complex_scalar(fm, + ch, + prs_chest, + 8); + + pil +=2; + k = (k+prs_cfg->CombSize) % frame_params->ofdm_symbol_size; + rxF = (int16_t *)&rxdataF[rxAnt][l*frame_params->ofdm_symbol_size + k]; + + ch[0] = (int16_t)(((int32_t)rxF[0]*pil[0] + (int32_t)rxF[1]*pil[1])>>15); + ch[1] = (int16_t)(((int32_t)rxF[1]*pil[0] - (int32_t)rxF[0]*pil[1])>>15); #ifdef DEBUG_PRS_CHEST - printf("pilIdx %d at k %d of l %d reIdx %d rxF %p %d %d ch[0] %d ch[1] %d\n", 1, k, l, (l*frame_params->ofdm_symbol_size + k), rxF, rxF[0], rxF[1], ch[0], ch[1]); + printf("pilIdx %d at k %d of l %d reIdx %d rxF %p %d %d ch[0] %d ch[1] %d\n", pIdx+1, k, l, (l*frame_params->ofdm_symbol_size + k), rxF, rxF[0], rxF[1], ch[0], ch[1]); +#endif + + multadd_real_vector_complex_scalar(fmm, + ch, + prs_chest, + 8); + + pil +=2; + k = (k+prs_cfg->CombSize) % frame_params->ofdm_symbol_size; + rxF = (int16_t *)&rxdataF[rxAnt][l*frame_params->ofdm_symbol_size + k]; + prs_chest +=8; + } + + //End pilot + ch[0] = (int16_t)(((int32_t)rxF[0]*pil[0] + (int32_t)rxF[1]*pil[1])>>15); + ch[1] = (int16_t)(((int32_t)rxF[1]*pil[0] - (int32_t)rxF[0]*pil[1])>>15); +#ifdef DEBUG_PRS_CHEST + printf("pilIdx %d at k %d of l %d reIdx %d rxF %p %d %d ch[0] %d ch[1] %d\n", 1, k, l, (l*frame_params->ofdm_symbol_size + k), rxF, rxF[0], rxF[1], ch[0], ch[1]); +#endif + + multadd_real_vector_complex_scalar(fm, + ch, + prs_chest, + 8); + + pil +=2; + k = (k+prs_cfg->CombSize) % frame_params->ofdm_symbol_size; + rxF = (int16_t *)&rxdataF[rxAnt][l*frame_params->ofdm_symbol_size + k]; + + ch[0] = (int16_t)(((int32_t)rxF[0]*pil[0] + (int32_t)rxF[1]*pil[1])>>15); + ch[1] = (int16_t)(((int32_t)rxF[1]*pil[0] - (int32_t)rxF[0]*pil[1])>>15); +#ifdef DEBUG_PRS_CHEST + printf("pilIdx %d at k %d of l %d reIdx %d rxF %p %d %d ch[0] %d ch[1] %d\n", prs_cfg->NumRB*(12/prs_cfg->CombSize)-2, k, l, (l*frame_params->ofdm_symbol_size + k), rxF, rxF[0], rxF[1], ch[0], ch[1]); +#endif + + multadd_real_vector_complex_scalar(fmr, + ch, + prs_chest, + 8); + + pil +=2; + k = (k+prs_cfg->CombSize) % frame_params->ofdm_symbol_size; + rxF = (int16_t *)&rxdataF[rxAnt][l*frame_params->ofdm_symbol_size + k]; + prs_chest +=8; + + ch[0] = (int16_t)(((int32_t)rxF[0]*pil[0] + (int32_t)rxF[1]*pil[1])>>15); + ch[1] = (int16_t)(((int32_t)rxF[1]*pil[0] - (int32_t)rxF[0]*pil[1])>>15); +#ifdef DEBUG_PRS_CHEST + printf("pilIdx %d at k %d of l %d reIdx %d rxF %p %d %d ch[0] %d ch[1] %d\n", prs_cfg->NumRB*(12/prs_cfg->CombSize)-1, k, l, (l*frame_params->ofdm_symbol_size + k), rxF, rxF[0], rxF[1], ch[0], ch[1]); #endif - multadd_real_vector_complex_scalar(fr, - ch, - prs_chest, - 16); + multadd_real_vector_complex_scalar(fr, + ch, + prs_chest, + 8); + + } + else if(prs_cfg->CombSize == 4) + { + // Choose the interpolation filters + switch (k_prime) { + case 0: + fl = filt16a_l0; + fmm = filt16a_mm0; + fml = filt16a_mm0; + fm = filt16a_m0; + fr = filt16a_r0; + break; + + case 1: + fl = filt16a_l1; + fmm = filt16a_mm1; + fml = filt16a_ml1; + fm = filt16a_m1; + fr = filt16a_r1; + break; + + case 2: + fl = filt16a_l2; + fmm = filt16a_mm2; + fml = filt16a_ml2; + fm = filt16a_m2; + fr = filt16a_r2; + break; + + case 3: + fl = filt16a_l3; + fmm = filt16a_mm3; + fml = filt16a_ml3; + fm = filt16a_m3; + fr = filt16a_r3; + break; + + default: + printf("nr=prs channel_estimation: k_prime=%d -> ERROR\n",k_prime); + return(-1); + break; + } + + //Start pilot + ch[0] = (int16_t)(((int32_t)rxF[0]*pil[0] + (int32_t)rxF[1]*pil[1])>>15); + ch[1] = (int16_t)(((int32_t)rxF[1]*pil[0] - (int32_t)rxF[0]*pil[1])>>15); +#ifdef DEBUG_PRS_CHEST + printf("pilIdx %d at k %d of l %d reIdx %d rxF %p %d %d ch[0] %d ch[1] %d\n", 0, k, l, (l*frame_params->ofdm_symbol_size + k), rxF, rxF[0], rxF[1], ch[0], ch[1]); +#endif + + multadd_real_vector_complex_scalar(fl, + ch, + prs_chest, + 16); + + pil +=2; + k = (k+prs_cfg->CombSize) % frame_params->ofdm_symbol_size; + rxF = (int16_t *)&rxdataF[rxAnt][l*frame_params->ofdm_symbol_size + k]; + + ch[0] = (int16_t)(((int32_t)rxF[0]*pil[0] + (int32_t)rxF[1]*pil[1])>>15); + ch[1] = (int16_t)(((int32_t)rxF[1]*pil[0] - (int32_t)rxF[0]*pil[1])>>15); +#ifdef DEBUG_PRS_CHEST + printf("pilIdx %d at k %d of l %d reIdx %d rxF %p %d %d ch[0] %d ch[1] %d\n", 1, k, l, (l*frame_params->ofdm_symbol_size + k), rxF, rxF[0], rxF[1], ch[0], ch[1]); +#endif + + multadd_real_vector_complex_scalar(fml, + ch, + prs_chest, + 16); + + pil +=2; + k = (k+prs_cfg->CombSize) % frame_params->ofdm_symbol_size; + rxF = (int16_t *)&rxdataF[rxAnt][l*frame_params->ofdm_symbol_size + k]; + prs_chest +=8; + + //Middle pilots + for(int pIdx = 2; pIdx < prs_cfg->NumRB*(12/prs_cfg->CombSize)-2; pIdx++) + { + ch[0] = (int16_t)(((int32_t)rxF[0]*pil[0] + (int32_t)rxF[1]*pil[1])>>15); + ch[1] = (int16_t)(((int32_t)rxF[1]*pil[0] - (int32_t)rxF[0]*pil[1])>>15); +#ifdef DEBUG_PRS_CHEST + printf("pilIdx %d at k %d of l %d reIdx %d rxF %p %d %d ch[0] %d ch[1] %d\n", pIdx, k, l, (l*frame_params->ofdm_symbol_size + k), rxF, rxF[0], rxF[1], ch[0], ch[1]); +#endif + + multadd_real_vector_complex_scalar(fmm, + ch, + prs_chest, + 16); + + pil +=2; + k = (k+prs_cfg->CombSize) % frame_params->ofdm_symbol_size; + rxF = (int16_t *)&rxdataF[rxAnt][l*frame_params->ofdm_symbol_size + k]; + prs_chest +=8; + } + + //End pilot + ch[0] = (int16_t)(((int32_t)rxF[0]*pil[0] + (int32_t)rxF[1]*pil[1])>>15); + ch[1] = (int16_t)(((int32_t)rxF[1]*pil[0] - (int32_t)rxF[0]*pil[1])>>15); +#ifdef DEBUG_PRS_CHEST + printf("pilIdx %d at k %d of l %d reIdx %d rxF %p %d %d ch[0] %d ch[1] %d\n", prs_cfg->NumRB*(12/prs_cfg->CombSize)-2, k, l, (l*frame_params->ofdm_symbol_size + k), rxF, rxF[0], rxF[1], ch[0], ch[1]); +#endif + + multadd_real_vector_complex_scalar(fm, + ch, + prs_chest, + 16); + + pil +=2; + k = (k+prs_cfg->CombSize) % frame_params->ofdm_symbol_size; + rxF = (int16_t *)&rxdataF[rxAnt][l*frame_params->ofdm_symbol_size + k]; + + ch[0] = (int16_t)(((int32_t)rxF[0]*pil[0] + (int32_t)rxF[1]*pil[1])>>15); + ch[1] = (int16_t)(((int32_t)rxF[1]*pil[0] - (int32_t)rxF[0]*pil[1])>>15); +#ifdef DEBUG_PRS_CHEST + printf("pilIdx %d at k %d of l %d reIdx %d rxF %p %d %d ch[0] %d ch[1] %d\n", prs_cfg->NumRB*(12/prs_cfg->CombSize)-1, k, l, (l*frame_params->ofdm_symbol_size + k), rxF, rxF[0], rxF[1], ch[0], ch[1]); +#endif + + multadd_real_vector_complex_scalar(fr, + ch, + prs_chest, + 16); + } prs_chest = (int16_t *)&ue->prs_ch_estimates[rxAnt][l*frame_params->ofdm_symbol_size]; for (int re = 0; re < prs_cfg->NumRB*12; re++) @@ -218,7 +374,7 @@ int nr_prs_channel_estimation(PHY_VARS_NR_UE *ue, } //for l - LOG_M("prsEst.m","prs_chest",&ue->prs_ch_estimates[rxAnt][prs_cfg->SymbolStart*frame_params->ofdm_symbol_size], prs_cfg->NumRB*12,1,1); + LOG_M("prsEst.m","prs_chest",&ue->prs_ch_estimates[rxAnt][prs_cfg->SymbolStart*frame_params->ofdm_symbol_size], prs_cfg->NumPRSSymbols*prs_cfg->NumRB*12,1,1); return(0); }