From 386881c382a5e52710f98d1fc7791877c3a96403 Mon Sep 17 00:00:00 2001 From: Sagar Parsawar Date: Mon, 12 Dec 2022 14:16:25 +0100 Subject: [PATCH] Fixed PRS IDFT 16x oversampling buffer issue --- .../nr_dl_channel_estimation.c | 86 +++++++++++-------- openair1/PHY/defs_nr_common.h | 6 +- 2 files changed, 55 insertions(+), 37 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 6684fdf222..b4115f53ca 100644 --- a/openair1/PHY/NR_UE_ESTIMATION/nr_dl_channel_estimation.c +++ b/openair1/PHY/NR_UE_ESTIMATION/nr_dl_channel_estimation.c @@ -97,8 +97,8 @@ int nr_prs_channel_estimation(uint8_t gNB_id, int16_t *rxF, *pil, mod_prs[NR_MAX_PRS_LENGTH << 1]; const int16_t *fl, *fm, *fmm, *fml, *fmr, *fr; int16_t ch[2] = {0}; - int16_t k_prime = 0, k = 0, re_offset = 0, first_half = 0, second_half = 0; - int32_t ch_pwr = 0, snr = 0, noiseFig[2] = {0}, mean_val = 0; + int16_t k_prime = 0, k = 0; + int32_t ch_pwr = 0, snr = 0, noiseFig[2] = {0}, rsrp = 0, mean_val = 0, prs_toa = 0; double ch_pwr_dbm = 0.0f; #ifdef DEBUG_PRS_CHEST char filename[64] = {0}, varname[64] = {0}; @@ -106,7 +106,10 @@ int nr_prs_channel_estimation(uint8_t gNB_id, int16_t *ch_tmp = (int16_t *)ch_tmp_buf; int16_t scale_factor = (1.0f/(float)(prs_cfg->NumPRSSymbols))*(1<<15); int16_t num_pilots = (12/prs_cfg->CombSize)*prs_cfg->NumRB; - int16_t start_offset = (NR_PRS_IDFT_OVERSAMP_FACTOR-1)*frame_params->ofdm_symbol_size>>1; + int16_t first_half = frame_params->ofdm_symbol_size - frame_params->first_carrier_offset; + int16_t second_half = (prs_cfg->NumRB*12) - first_half; + int16_t start_offset = NR_PRS_IDFT_OVERSAMP_FACTOR*frame_params->ofdm_symbol_size - first_half; + LOG_D(PHY, "start_offset %d, first_half %d, second_half %d\n", start_offset, first_half, second_half); int16_t k_prime_table[K_PRIME_TABLE_ROW_SIZE][K_PRIME_TABLE_COL_SIZE] = PRS_K_PRIME_TABLE; for(int l = prs_cfg->SymbolStart; l < prs_cfg->SymbolStart+prs_cfg->NumPRSSymbols; l++) @@ -138,10 +141,11 @@ int nr_prs_channel_estimation(uint8_t gNB_id, for (rxAnt=0; rxAnt < frame_params->nb_antennas_rx; rxAnt++) { - snr = 0; + // reset variables + snr = 0; rsrp = 0; // calculate RE offset - k = re_offset = (prs_cfg->REOffset+k_prime) % prs_cfg->CombSize + prs_cfg->RBOffset*12 + frame_params->first_carrier_offset; + k = (prs_cfg->REOffset+k_prime) % prs_cfg->CombSize + prs_cfg->RBOffset*12 + frame_params->first_carrier_offset; // Channel estimation and interpolation pil = (int16_t *)&mod_prs[0]; @@ -183,7 +187,8 @@ int nr_prs_channel_estimation(uint8_t gNB_id, ch_tmp, 8); - //SNR estimation + //SNR & RSRP estimation + rsrp += squaredMod(*((c16_t*)rxF); noiseFig[0] = rxF[0] - (int16_t)(((int32_t)ch[0]*pil[0] - (int32_t)ch[1]*pil[1])>>15); noiseFig[1] = rxF[1] - (int16_t)(((int32_t)ch[1]*pil[0] + (int32_t)ch[0]*pil[1])>>15); snr += 10*log10(squaredMod(*(c16_t*)rxF) - squaredMod(*(c16_t*)noiseFig)) - 10*log10(squaredMod(*(c16_t*)noiseFig)); @@ -214,7 +219,8 @@ int nr_prs_channel_estimation(uint8_t gNB_id, 8); } - //SNR estimation + //SNR & RSRP estimation + rsrp += squaredMod(*((c16_t*)rxF); noiseFig[0] = rxF[0] - (int16_t)(((int32_t)ch[0]*pil[0] - (int32_t)ch[1]*pil[1])>>15); noiseFig[1] = rxF[1] - (int16_t)(((int32_t)ch[1]*pil[0] + (int32_t)ch[0]*pil[1])>>15); snr += 10*log10(squaredMod(*(c16_t*)rxF) - squaredMod(*(c16_t*)noiseFig)) - 10*log10(squaredMod(*(c16_t*)noiseFig)); @@ -242,7 +248,8 @@ int nr_prs_channel_estimation(uint8_t gNB_id, 8); } - //SNR estimation + //SNR & RSRP estimation + rsrp += squaredMod(*((c16_t*)rxF); noiseFig[0] = rxF[0] - (int16_t)(((int32_t)ch[0]*pil[0] - (int32_t)ch[1]*pil[1])>>15); noiseFig[1] = rxF[1] - (int16_t)(((int32_t)ch[1]*pil[0] + (int32_t)ch[0]*pil[1])>>15); snr += 10*log10(squaredMod(*((c16_t*)rxF)) - squaredMod(*((c16_t*)noiseFig))) - 10*log10(squaredMod(*((c16_t*)noiseFig))); @@ -263,16 +270,14 @@ int nr_prs_channel_estimation(uint8_t gNB_id, ch_tmp, 8); - //SNR estimation - noiseFig[0] = rxF[0] - (int16_t)(((int32_t)ch[0]*pil[0] - (int32_t)ch[1]*pil[1])>>15); - noiseFig[1] = rxF[1] - (int16_t)(((int32_t)ch[1]*pil[0] + (int32_t)ch[0]*pil[1])>>15); - snr += 10*log10(squaredMod(*((c16_t*)rxF)) - squaredMod(*((c16_t*)noiseFig))) - 10*log10(squaredMod(*((c16_t*)noiseFig))); + //SNR & RSRP estimation + rsrp += squaredMod(*((c16_t*)rxF); + noiseFig[0] = rxF[0] - (int16_t)(((int32_t)ch[0]*pil[0] - (int32_t)ch[1]*pil[1])>>15); + noiseFig[1] = rxF[1] - (int16_t)(((int32_t)ch[1]*pil[0] + (int32_t)ch[0]*pil[1])>>15); + snr += 10*log10(squaredMod(*((c16_t*)rxF)) - squaredMod(*((c16_t*)noiseFig))) - 10*log10(squaredMod(*((c16_t*)noiseFig))); #ifdef DEBUG_PRS_PRINTS - printf("[Rx %d] pilot %3d, SNR %+2d dB: rxF - > (%+3d, %+3d) addr %p ch -> (%+3d, %+3d), pil -> (%+d, %+d) \n", rxAnt, num_pilots-1, snr/num_pilots, rxF[0],rxF[1],&rxF[0],ch[0],ch[1],pil[0],pil[1]); + printf("[Rx %d] pilot %3d, SNR %+2d dB: rxF - > (%+3d, %+3d) addr %p ch -> (%+3d, %+3d), pil -> (%+d, %+d) \n", rxAnt, num_pilots-1, snr/num_pilots, rxF[0],rxF[1],&rxF[0],ch[0],ch[1],pil[0],pil[1]); #endif - // average out the SNR computed - snr = snr/num_pilots; - prs_meas[rxAnt]->snr = snr; } else if(prs_cfg->CombSize == 4) { @@ -328,7 +333,8 @@ int nr_prs_channel_estimation(uint8_t gNB_id, ch_tmp, 16); - //SNR estimation + //SNR & RSRP estimation + rsrp += squaredMod(*((c16_t*)rxF); noiseFig[0] = rxF[0] - (int16_t)(((int32_t)ch[0]*pil[0] - (int32_t)ch[1]*pil[1])>>15); noiseFig[1] = rxF[1] - (int16_t)(((int32_t)ch[1]*pil[0] + (int32_t)ch[0]*pil[1])>>15); snr += 10*log10(squaredMod(*((c16_t*)rxF)) - squaredMod(*((c16_t*)noiseFig))) - 10*log10(squaredMod(*((c16_t*)noiseFig))); @@ -346,7 +352,8 @@ int nr_prs_channel_estimation(uint8_t gNB_id, ch_tmp, 16); - //SNR estimation + //SNR & RSRP estimation + rsrp += squaredMod(*((c16_t*)rxF); noiseFig[0] = rxF[0] - (int16_t)(((int32_t)ch[0]*pil[0] - (int32_t)ch[1]*pil[1])>>15); noiseFig[1] = rxF[1] - (int16_t)(((int32_t)ch[1]*pil[0] + (int32_t)ch[0]*pil[1])>>15); snr += 10*log10(squaredMod(*((c16_t*)rxF)) - squaredMod(*((c16_t*)noiseFig))) - 10*log10(squaredMod(*((c16_t*)noiseFig))); @@ -368,7 +375,8 @@ int nr_prs_channel_estimation(uint8_t gNB_id, ch_tmp, 16); - //SNR estimation + //SNR & RSRP estimation + rsrp += squaredMod(*((c16_t*)rxF); noiseFig[0] = rxF[0] - (int16_t)(((int32_t)ch[0]*pil[0] - (int32_t)ch[1]*pil[1])>>15); noiseFig[1] = rxF[1] - (int16_t)(((int32_t)ch[1]*pil[0] + (int32_t)ch[0]*pil[1])>>15); snr += 10*log10(squaredMod(*((c16_t*)rxF)) - squaredMod(*((c16_t*)noiseFig))) - 10*log10(squaredMod(*((c16_t*)noiseFig))); @@ -389,7 +397,8 @@ int nr_prs_channel_estimation(uint8_t gNB_id, ch_tmp, 16); - //SNR estimation + //SNR & RSRP estimation + rsrp += squaredMod(*((c16_t*)rxF); noiseFig[0] = rxF[0] - (int16_t)(((int32_t)ch[0]*pil[0] - (int32_t)ch[1]*pil[1])>>15); noiseFig[1] = rxF[1] - (int16_t)(((int32_t)ch[1]*pil[0] + (int32_t)ch[0]*pil[1])>>15); snr += 10*log10(squaredMod(*((c16_t*)rxF)) - squaredMod(*((c16_t*)noiseFig))) - 10*log10(squaredMod(*((c16_t*)noiseFig))); @@ -407,21 +416,23 @@ int nr_prs_channel_estimation(uint8_t gNB_id, ch_tmp, 16); - //SNR estimation + //SNR & RSRP estimation + rsrp += squaredMod(*((c16_t*)rxF); noiseFig[0] = rxF[0] - (int16_t)(((int32_t)ch[0]*pil[0] - (int32_t)ch[1]*pil[1])>>15); noiseFig[1] = rxF[1] - (int16_t)(((int32_t)ch[1]*pil[0] + (int32_t)ch[0]*pil[1])>>15); snr += 10*log10(squaredMod(*((c16_t*)rxF)) - squaredMod(*((c16_t*)noiseFig))) - 10*log10(squaredMod(*((c16_t*)noiseFig))); #ifdef DEBUG_PRS_PRINTS printf("[Rx %d] pilot %3d, SNR %+2d dB: rxF - > (%+3d, %+3d) addr %p ch -> (%+3d, %+3d), pil -> (%+d, +%d) \n", rxAnt, num_pilots-1, snr/num_pilots, rxF[0],rxF[1],&rxF[0],ch[0],ch[1],pil[0],pil[1]); #endif - // average out the SNR computed - snr = snr/num_pilots; - prs_meas[rxAnt]->snr = snr; } else { AssertFatal((prs_cfg->CombSize == 2)||(prs_cfg->CombSize == 4), "[%s] DL PRS CombSize other than 2 and 4 are NOT supported currently. Exiting!!!", __FUNCTION__); } + + // average out the SNR and RSRP computed + prs_meas[rxAnt]->snr = snr/(float)num_pilots; + prs_meas[rxAnt]->rsrp = rsrp/(float)num_pilots; //reset channel pointer ch_tmp = (int16_t*)ch_tmp_buf; @@ -451,12 +462,10 @@ int nr_prs_channel_estimation(uint8_t gNB_id, #endif // Place PRS channel estimates in FFT shifted format - first_half = frame_params->ofdm_symbol_size - re_offset; - second_half = (prs_cfg->NumRB*12) - first_half; if(first_half > 0) - memcpy((int16_t *)&chF_interpol[rxAnt][start_offset+re_offset], &ch_tmp[0], first_half*sizeof(int32_t)); + memcpy((int16_t *)&chF_interpol[rxAnt][start_offset], &ch_tmp[0], first_half*sizeof(int32_t)); if(second_half > 0) - memcpy((int16_t *)&chF_interpol[rxAnt][start_offset], &ch_tmp[(first_half<<1)], second_half*sizeof(int32_t)); + memcpy((int16_t *)&chF_interpol[rxAnt][0], &ch_tmp[first_half<<1], second_half*sizeof(int32_t)); // Time domain IMPULSE response idft_size_idx_t idftsizeidx; @@ -541,9 +550,9 @@ int nr_prs_channel_estimation(uint8_t gNB_id, // peak estimator mean_val = abs32((int32_t)ch_tmp[(prs_cfg->NumRB*12)]); - peak_estimator(&chT_interpol[rxAnt][start_offset], - frame_params->ofdm_symbol_size, - &prs_meas[rxAnt]->dl_toa, + peak_estimator(&chT_interpol[rxAnt][0], + NR_PRS_IDFT_OVERSAMP_FACTOR*frame_params->ofdm_symbol_size, + &prs_toa, &ch_pwr, mean_val); @@ -551,14 +560,21 @@ int nr_prs_channel_estimation(uint8_t gNB_id, ch_pwr_dbm = 10*log10(ch_pwr)+30 - 10*log10(pow(2,30)) - ((int)openair0_cfg[0].rx_gain[0] - (int)openair0_cfg[0].rx_gain_offset[0]) - dB_fixed(frame_params->ofdm_symbol_size); - + + prs_meas[rxAnt]->rsrp_dBm = 10*log10(prs_meas[rxAnt]->rsrp) + 30 + - 10*log10(pow(2,30)) - ((int)openair0_cfg[0].rx_gain[0] + - (int)openair0_cfg[0].rx_gain_offset[0]) - dB_fixed(ue->frame_parms.ofdm_symbol_size); + //prs measurements prs_meas[rxAnt]->gNB_id = gNB_id; prs_meas[rxAnt]->sfn = proc->frame_rx; prs_meas[rxAnt]->slot = proc->nr_slot_rx; prs_meas[rxAnt]->rxAnt_idx = rxAnt; prs_meas[rxAnt]->dl_aoa = rsc_id; - LOG_I(PHY, "[gNB %d][rsc %d][Rx %d][sfn %d][slot %d] DL PRS ToA ==> %d / %d samples, peak channel power %.1f dBm, SNR %+2d dB\n", gNB_id, rsc_id, rxAnt, proc->frame_rx, proc->nr_slot_rx, prs_meas[rxAnt]->dl_toa, frame_params->ofdm_symbol_size, ch_pwr_dbm, prs_meas[rxAnt]->snr); + prs_meas[rxAnt]->dl_toa = prs_toa/(float)NR_PRS_IDFT_OVERSAMP_FACTOR; + if ((frame_params->ofdm_symbol_size - prs_meas[rxAnt]->dl_toa) < frame_params->ofdm_symbol_size/2) + prs_meas[rxAnt]->dl_toa -= (frame_params->ofdm_symbol_size); + LOG_I(PHY, "[gNB %d][rsc %d][Rx %d][sfn %d][slot %d] DL PRS ToA ==> %.1f / %d samples, peak channel power %.1f dBm, SNR %+.1f dB, rsrp %+.1f dBm\n", gNB_id, rsc_id, rxAnt, proc->frame_rx, proc->nr_slot_rx, prs_meas[rxAnt]->dl_toa, frame_params->ofdm_symbol_size, ch_pwr_dbm, prs_meas[rxAnt]->snr, prs_meas[rxAnt]->rsrp_dBm); #ifdef DEBUG_PRS_CHEST sprintf(filename, "%s%i%s", "PRSpilot_", rxAnt, ".m"); @@ -581,11 +597,11 @@ int nr_prs_channel_estimation(uint8_t gNB_id, T(T_UE_PHY_DL_CHANNEL_ESTIMATE_FREQ, T_INT(gNB_id), T_INT(rsc_id), T_INT(proc->frame_rx), T_INT(proc->nr_slot_rx), - T_INT(rxAnt), T_BUFFER(&chF_interpol[rxAnt][start_offset], frame_params->ofdm_symbol_size*sizeof(int32_t))); + T_INT(rxAnt), T_BUFFER(&chF_interpol[rxAnt][0], NR_PRS_IDFT_OVERSAMP_FACTOR*frame_params->ofdm_symbol_size*sizeof(int32_t))); T(T_UE_PHY_DL_CHANNEL_ESTIMATE, T_INT(gNB_id), T_INT(rsc_id), T_INT(proc->frame_rx), T_INT(proc->nr_slot_rx), - T_INT(rxAnt), T_BUFFER(&chT_interpol[rxAnt][start_offset], frame_params->ofdm_symbol_size*sizeof(int32_t))); + T_INT(rxAnt), T_BUFFER(&chT_interpol[rxAnt][0], NR_PRS_IDFT_OVERSAMP_FACTOR*frame_params->ofdm_symbol_size*sizeof(int32_t))); } return(0); diff --git a/openair1/PHY/defs_nr_common.h b/openair1/PHY/defs_nr_common.h index 13a75aaf44..a7b22cc211 100644 --- a/openair1/PHY/defs_nr_common.h +++ b/openair1/PHY/defs_nr_common.h @@ -289,9 +289,11 @@ typedef struct { int32_t sfn; int8_t slot; int8_t rxAnt_idx; - int32_t dl_toa; + float dl_toa; int32_t dl_aoa; - int32_t snr; + float snr; + float rsrp; + float rsrp_dBm; int32_t reserved; } prs_meas_t;