Compare commits

...

4 Commits

Author SHA1 Message Date
rakesh mundlamuri
be84e19e52 fix rsrp and snr computations 2025-08-29 13:20:35 +05:30
rakesh mundlamuri
9916d28944 fix for PRS channel estimation with multiple antennas 2025-08-26 17:26:58 +05:30
rakesh mundlamuri
fe43323739 harmonize IQ samples in prs channel estimation to use c16_t 2025-08-26 12:59:50 +05:30
rakesh mundlamuri
e113d0537e PRS bug fix in channel estimation while copying memory 2025-08-22 15:46:42 +05:30
3 changed files with 203 additions and 144 deletions

View File

@@ -1336,6 +1336,10 @@ ID = UE_PHY_INPUT_SIGNAL
DESC = UE received signal in the time domain for a duration of 1ms
GROUP = ALL:PHY:GRAPHIC:HEAVY:UE
FORMAT = int,eNB_ID : int,frame : int,subframe : int,antenna : buffer,rxdata
ID = UE_PHY_PRS_RX_SIGNAL
DESC = UE PRS received signal in the frequency domain for every OFDM symbol
GROUP = ALL:PHY:GRAPHIC:HEAVY:UE
FORMAT = int,eNB_ID : int,frame : int,subframe : int,antenna : buffer,rxdata
ID = UE_PHY_DL_CHANNEL_ESTIMATE
DESC = UE channel estimation in the time domain
GROUP = ALL:PHY:GRAPHIC:HEAVY:UE

View File

@@ -46,12 +46,12 @@
#define NO_INTERP 1
/* Generic function to find the peak of channel estimation buffer */
void peak_estimator(int32_t *buffer, int32_t buf_len, int32_t *peak_idx, int32_t *peak_val, int32_t mean_val)
void peak_estimator(c16_t *buffer, int32_t buf_len, int32_t *peak_idx, int32_t *peak_val, int32_t mean_val)
{
int32_t max_val = 0, max_idx = 0, abs_val = 0;
for(int k = 0; k < buf_len; k++)
{
abs_val = squaredMod(((c16_t*)buffer)[k]);
abs_val = squaredMod(buffer[k]);
if(abs_val > max_val)
{
max_val = abs_val;
@@ -78,13 +78,11 @@ int nr_prs_channel_estimation(uint8_t gNB_id,
NR_DL_FRAME_PARMS *frame_params,
c16_t rxdataF[][ue->frame_parms.samples_per_slot_wCP])
{
uint8_t rxAnt = 0, idx = 0;
prs_config_t *prs_cfg = &ue->prs_vars[gNB_id]->prs_resource[rsc_id].prs_cfg;
prs_meas_t **prs_meas = ue->prs_vars[gNB_id]->prs_resource[rsc_id].prs_meas;
c16_t ch_tmp_buf[ ue->frame_parms.ofdm_symbol_size] __attribute__((aligned(32)));
int32_t chF_interpol[frame_params->nb_antennas_rx][NR_PRS_IDFT_OVERSAMP_FACTOR*ue->frame_parms.ofdm_symbol_size] __attribute__((aligned(32)));
int32_t chT_interpol[frame_params->nb_antennas_rx][NR_PRS_IDFT_OVERSAMP_FACTOR*ue->frame_parms.ofdm_symbol_size] __attribute__((aligned(32)));
memset(ch_tmp_buf,0,sizeof(ch_tmp_buf));
c16_t chF_interpol[frame_params->nb_antennas_rx][NR_PRS_IDFT_OVERSAMP_FACTOR*ue->frame_parms.ofdm_symbol_size] __attribute__((aligned(32)));
c16_t chT_interpol[frame_params->nb_antennas_rx][NR_PRS_IDFT_OVERSAMP_FACTOR*ue->frame_parms.ofdm_symbol_size] __attribute__((aligned(32)));
memset(chF_interpol,0,sizeof(chF_interpol));
memset(chT_interpol,0,sizeof(chF_interpol));
@@ -94,13 +92,16 @@ int nr_prs_channel_estimation(uint8_t gNB_id,
c16_t mod_prs[NR_MAX_PRS_LENGTH];
const int16_t *fl, *fm, *fmm, *fml, *fmr, *fr;
int16_t k_prime = 0, k = 0;
int32_t ch_pwr = 0, snr = 0, rsrp = 0, mean_val = 0, prs_toa = 0;
int32_t ch_pwr = 0, mean_val = 0, prs_toa = 0;
double rsrp = 0.0, noise_power = 0.0;
uint8_t idx = 0;
double ch_pwr_dbm = 0.0f;
#ifdef DEBUG_PRS_CHEST
char filename[64] = {0}, varname[64] = {0};
#endif
c16_t *ch_tmp = ch_tmp_buf;
int16_t scale_factor = (1.0f/(float)(prs_cfg->NumPRSSymbols))*(1<<15);
int16_t num_symbols = prs_cfg->NumPRSSymbols;
int16_t scale_factor = (1.0f / (float)(num_symbols)) * (1 << 15);
int16_t num_pilots = (12/prs_cfg->CombSize)*prs_cfg->NumRB;
int16_t first_half = frame_params->ofdm_symbol_size - frame_params->first_carrier_offset;
int16_t second_half = (prs_cfg->NumRB * 12) - first_half;
@@ -108,40 +109,35 @@ int nr_prs_channel_estimation(uint8_t gNB_id,
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++)
{
uint32_t *gold_prs = nr_gold_prs(ue->prs_vars[gNB_id]->prs_resource[rsc_id].prs_cfg.NPRSID, slot_prs, l);
int symInd = l-prs_cfg->SymbolStart;
if (prs_cfg->CombSize == 2) {
k_prime = k_prime_table[0][symInd];
}
else if (prs_cfg->CombSize == 4){
k_prime = k_prime_table[1][symInd];
}
else if (prs_cfg->CombSize == 6){
k_prime = k_prime_table[2][symInd];
}
else if (prs_cfg->CombSize == 12){
k_prime = k_prime_table[3][symInd];
}
for (uint8_t rxAnt = 0; rxAnt < frame_params->nb_antennas_rx; rxAnt++) {
// reset variables
rsrp = 0.0;
noise_power = 0.0;
memset(ch_tmp_buf, 0, sizeof(ch_tmp_buf));
for (int l = prs_cfg->SymbolStart; l < prs_cfg->SymbolStart + num_symbols; l++) {
uint32_t *gold_prs = nr_gold_prs(ue->prs_vars[gNB_id]->prs_resource[rsc_id].prs_cfg.NPRSID, slot_prs, l);
int symInd = l - prs_cfg->SymbolStart;
if (prs_cfg->CombSize == 2) {
k_prime = k_prime_table[0][symInd];
} else if (prs_cfg->CombSize == 4) {
k_prime = k_prime_table[1][symInd];
} else if (prs_cfg->CombSize == 6) {
k_prime = k_prime_table[2][symInd];
} else if (prs_cfg->CombSize == 12) {
k_prime = k_prime_table[3][symInd];
}
#ifdef DEBUG_PRS_PRINTS
printf("[gNB %d][rsc %d] PRS config l %d k_prime %d:\nprs_cfg->SymbolStart %d\nprs_cfg->NumPRSSymbols %d\nprs_cfg->NumRB %d\nprs_cfg->CombSize %d\n", gNB_id, rsc_id, l, k_prime, prs_cfg->SymbolStart, prs_cfg->NumPRSSymbols, prs_cfg->NumRB, prs_cfg->CombSize);
#endif
// Pilots generation and modulation
AssertFatal(num_pilots > 0, "num_pilots needs to be gt 0 or mod_prs[0] UB");
for (int m = 0; m < num_pilots; m++)
{
idx = (((gold_prs[(m << 1) >> 5]) >> ((m << 1) & 0x1f)) & 3);
mod_prs[m] = nr_qpsk_mod_table[idx];
}
for (rxAnt=0; rxAnt < frame_params->nb_antennas_rx; rxAnt++)
{
// reset variables
snr = 0;
rsrp = 0;
// Pilots generation and modulation
AssertFatal(num_pilots > 0, "num_pilots needs to be gt 0 or mod_prs[0] UB");
for (int m = 0; m < num_pilots; m++) {
idx = (((gold_prs[(m << 1) >> 5]) >> ((m << 1) & 0x1f)) & 3);
mod_prs[m] = nr_qpsk_mod_table[idx];
}
// calculate RE offset
k = (prs_cfg->REOffset + k_prime) % prs_cfg->CombSize + prs_cfg->RBOffset * 12 + frame_params->first_carrier_offset;
@@ -182,12 +178,19 @@ int nr_prs_channel_estimation(uint8_t gNB_id,
c16_t ch = c16MulConjShift(*pil, *rxF, 15);
multadd_real_vector_complex_scalar(fl, ch, ch_tmp, 8);
// SNR & RSRP estimation
// RSRP estimation
rsrp += squaredMod(*rxF);
c16_t noiseFig = c16sub(*rxF, c16mulShift(ch, *pil, 15));
snr += 10 * log10(squaredMod(*rxF) - squaredMod(noiseFig)) - 10 * log10(squaredMod(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, 0, snr, rxF[0],rxF[1],&rxF[0],ch[0],ch[1],pil[0],pil[1]);
printf("[Rx %d] pilot %3d: rxF - > (%+3d, %+3d) addr %p ch -> (%+3d, %+3d), pil -> (%+d, %+d) \n",
rxAnt,
0,
rxF->r,
rxF->i,
rxF,
ch.r,
ch.i,
pil->r,
pil->i);
#endif
pil++;
k = (k+prs_cfg->CombSize) % frame_params->ofdm_symbol_size;
@@ -198,22 +201,19 @@ int nr_prs_channel_estimation(uint8_t gNB_id,
c16_t ch = c16MulConjShift(*pil, *rxF, 15);
multadd_real_vector_complex_scalar(pIdx == 1 ? fml : fm, ch, ch_tmp, 8);
// SNR & RSRP estimation
// RSRP estimation
rsrp += squaredMod(*rxF);
c16_t noiseFig = c16sub(*rxF, c16mulShift(ch, *pil, 15));
snr += 10 * log10(squaredMod(*rxF) - squaredMod(noiseFig)) - 10 * log10(squaredMod(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",
printf("[Rx %d] pilot %3d: rxF - > (%+3d, %+3d) addr %p ch -> (%+3d, %+3d), pil -> (%+d, %+d) \n",
rxAnt,
pIdx,
snr / (pIdx + 1),
rxF[0],
rxF[1],
&rxF[0],
ch[0],
ch[1],
pil[0],
pil[1]);
rxF->r,
rxF->i,
rxF,
ch.r,
ch.i,
pil->r,
pil->i);
#endif
pil++;
k = (k + prs_cfg->CombSize) % frame_params->ofdm_symbol_size;
@@ -221,22 +221,19 @@ int nr_prs_channel_estimation(uint8_t gNB_id,
ch = c16MulConjShift(*pil, *rxF, 15);
multadd_real_vector_complex_scalar(pIdx == (num_pilots - 3) ? fmr : fmm, ch, ch_tmp, 8);
// SNR & RSRP estimation
// RSRP estimation
rsrp += squaredMod(*rxF);
noiseFig = c16sub(*rxF, c16mulShift(ch, *pil, 15));
snr += 10 * log10(squaredMod(*rxF) - squaredMod(noiseFig)) - 10 * log10(squaredMod(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",
printf("[Rx %d] pilot %3d: rxF - > (%+3d, %+3d) addr %p ch -> (%+3d, %+3d), pil -> (%+d, %+d) \n",
rxAnt,
pIdx + 1,
snr / (pIdx + 2),
rxF[0],
rxF[1],
&rxF[0],
ch[0],
ch[1],
pil[0],
pil[1]);
rxF->r,
rxF->i,
rxF,
ch.r,
ch.i,
pil->r,
pil->i);
#endif
pil++;
k = (k + prs_cfg->CombSize) % frame_params->ofdm_symbol_size;
@@ -248,22 +245,19 @@ int nr_prs_channel_estimation(uint8_t gNB_id,
ch = c16MulConjShift(*pil, *rxF, 15);
multadd_real_vector_complex_scalar(fr, ch, ch_tmp, 8);
// SNR & RSRP estimation
// RSRP estimation
rsrp += squaredMod(*rxF);
noiseFig = c16sub(*rxF, c16mulShift(ch, *pil, 15));
snr += 10 * log10(squaredMod(*rxF) - squaredMod(noiseFig)) - 10 * log10(squaredMod(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",
printf("[Rx %d] pilot %3d: 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]);
rxF->r,
rxF->i,
rxF,
ch.r,
ch.i,
pil->r,
pil->i);
#endif
}
else if(prs_cfg->CombSize == 4)
@@ -314,33 +308,41 @@ int nr_prs_channel_estimation(uint8_t gNB_id,
//Start pilot
c16_t ch = c16MulConjShift(*pil, *rxF, 15);
multadd_real_vector_complex_scalar(fl,
ch,
ch_tmp,
16);
multadd_real_vector_complex_scalar(fl, ch, ch_tmp, 16);
// SNR & RSRP estimation
// RSRP estimation
rsrp += squaredMod(*rxF);
c16_t noiseFig = c16sub(*rxF, c16mulShift(ch, *pil, 15));
snr += 10 * log10(squaredMod(*rxF) - squaredMod(noiseFig)) - 10 * log10(squaredMod(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, 0, snr, rxF[0],rxF[1],&rxF[0],ch[0],ch[1],pil[0],pil[1]);
printf("[Rx %d] pilot %3d: rxF - > (%+3d, %+3d) addr %p ch -> (%+3d, %+3d), pil -> (%+d, %+d) \n",
rxAnt,
0,
rxF->r,
rxF->i,
rxF,
ch.r,
ch.i,
pil->r,
pil->i);
#endif
pil++;
k = (k+prs_cfg->CombSize) % frame_params->ofdm_symbol_size;
rxF = &rxdataF[rxAnt][l * frame_params->ofdm_symbol_size + k];
ch = c16MulConjShift(*pil, *rxF, 15);
multadd_real_vector_complex_scalar(fml,
ch,
ch_tmp,
16);
multadd_real_vector_complex_scalar(fml, ch, ch_tmp, 16);
// SNR & RSRP estimation
// RSRP estimation
rsrp += squaredMod(*rxF);
noiseFig = c16sub(*rxF, c16mulShift(ch, *pil, 15));
snr += 10 * log10(squaredMod(*rxF) - squaredMod(noiseFig)) - 10 * log10(squaredMod(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, 1, snr/2, rxF[0],rxF[1],&rxF[0],ch[0],ch[1],pil[0],pil[1]);
printf("[Rx %d] pilot %3d: rxF - > (%+3d, %+3d) addr %p ch -> (%+3d, %+3d), pil -> (%+d, %+d) \n",
rxAnt,
1,
rxF->r,
rxF->i,
rxF,
ch.r,
ch.i,
pil->r,
pil->i);
#endif
pil++;
k = (k+prs_cfg->CombSize) % frame_params->ofdm_symbol_size;
@@ -351,17 +353,21 @@ int nr_prs_channel_estimation(uint8_t gNB_id,
for(int pIdx = 2; pIdx < num_pilots-2; pIdx++)
{
c16_t ch = c16MulConjShift(*pil, *rxF, 15);
multadd_real_vector_complex_scalar(fmm,
ch,
ch_tmp,
16);
multadd_real_vector_complex_scalar(fmm, ch, ch_tmp, 16);
// SNR & RSRP estimation
// RSRP estimation
rsrp += squaredMod(*rxF);
c16_t noiseFig = c16sub(*rxF, c16mulShift(ch, *pil, 15));
snr += 10 * log10(squaredMod(*rxF) - squaredMod(noiseFig)) - 10 * log10(squaredMod(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, pIdx, snr/(pIdx+1), rxF[0],rxF[1],&rxF[0],ch[0],ch[1],pil[0],pil[1]);
printf("[Rx %d] pilot %3d: rxF - > (%+3d, %+3d) addr %p ch -> (%+3d, %+3d), pil -> (%+d, %+d) \n",
rxAnt,
pIdx,
rxF->r,
rxF->i,
rxF,
ch.r,
ch.i,
pil->r,
pil->i);
#endif
pil++;
k = (k+prs_cfg->CombSize) % frame_params->ofdm_symbol_size;
@@ -371,33 +377,41 @@ int nr_prs_channel_estimation(uint8_t gNB_id,
//End pilot
ch = c16MulConjShift(*pil, *rxF, 15);
multadd_real_vector_complex_scalar(fmr,
ch,
ch_tmp,
16);
multadd_real_vector_complex_scalar(fmr, ch, ch_tmp, 16);
// SNR & RSRP estimation
// RSRP estimation
rsrp += squaredMod(*rxF);
noiseFig = c16sub(*rxF, c16mulShift(ch, *pil, 15));
snr += 10 * log10(squaredMod(*rxF) - squaredMod(noiseFig)) - 10 * log10(squaredMod(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-2, snr/(num_pilots-1), rxF[0],rxF[1],&rxF[0],ch[0],ch[1],pil[0],pil[1]);
printf("[Rx %d] pilot %3d: rxF - > (%+3d, %+3d) addr %p ch -> (%+3d, %+3d), pil -> (%+d, %+d) \n",
rxAnt,
num_pilots - 2,
rxF->r,
rxF->i,
rxF,
ch.r,
ch.i,
pil->r,
pil->i);
#endif
pil++;
k = (k+prs_cfg->CombSize) % frame_params->ofdm_symbol_size;
rxF = &rxdataF[rxAnt][l * frame_params->ofdm_symbol_size + k];
ch = c16MulConjShift(*pil, *rxF, 15);
multadd_real_vector_complex_scalar(fr,
ch,
ch_tmp,
16);
multadd_real_vector_complex_scalar(fr, ch, ch_tmp, 16);
// SNR & RSRP estimation
// RSRP estimation
rsrp += squaredMod(*rxF);
noiseFig = c16sub(*rxF, c16mulShift(ch, *pil, 15));
snr += 10 * log10(squaredMod(*rxF) - squaredMod(noiseFig)) - 10 * log10(squaredMod(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: rxF - > (%+3d, %+3d) addr %p ch -> (%+3d, %+3d), pil -> (%+d, +%d) \n",
rxAnt,
num_pilots - 1,
rxF->r,
rxF->i,
rxF,
ch.r,
ch.i,
pil->r,
pil->i);
#endif
}
else
@@ -405,38 +419,81 @@ int nr_prs_channel_estimation(uint8_t gNB_id,
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 = (c16_t *)ch_tmp_buf;
} // for rxAnt
} //for l
for (rxAnt=0; rxAnt < frame_params->nb_antennas_rx; rxAnt++)
{
// T tracer dump
T(T_UE_PHY_PRS_RX_SIGNAL,
T_INT(gNB_id),
T_INT(proc->frame_rx),
T_INT(proc->nr_slot_rx),
T_INT(rxAnt),
T_BUFFER(&rxdataF[rxAnt][l * frame_params->ofdm_symbol_size], frame_params->ofdm_symbol_size * sizeof(c16_t)));
// estimate the noise power in the guard carriers (2 PRBs) on the either side of the band
for (int noise_idx = frame_params->first_carrier_offset - 2 * NR_NB_SC_PER_RB; noise_idx < frame_params->first_carrier_offset;
noise_idx++) {
noise_power += squaredMod(rxdataF[rxAnt][l * frame_params->ofdm_symbol_size + noise_idx]);
}
for (int noise_idx = (frame_params->N_RB_DL >> 1) * NR_NB_SC_PER_RB;
noise_idx < (frame_params->N_RB_DL >> 1) * NR_NB_SC_PER_RB + 2 * NR_NB_SC_PER_RB;
noise_idx++) {
noise_power += squaredMod(rxdataF[rxAnt][l * frame_params->ofdm_symbol_size + noise_idx]);
}
} // for l
// scale by averaging factor 1/NumPrsSymbols
mult_complex_vector_real_scalar(ch_tmp, scale_factor, ch_tmp, frame_params->ofdm_symbol_size);
rsrp = rsrp / (double)(num_pilots * num_symbols); // average rsrp
prs_meas[rxAnt]->rsrp = rsrp;
noise_power = noise_power / (double)(4 * NR_NB_SC_PER_RB * num_symbols); // average noise power
prs_meas[rxAnt]->snr = 10 * log10(rsrp - noise_power) - 10 * log10(noise_power);
#ifdef DEBUG_PRS_PRINTS
for (int rb = 0; rb < prs_cfg->NumRB; rb++)
{
printf("================================================================\n");
printf("\t\t\t[gNB %d][Rx %d][RB %d]\n", gNB_id, rxAnt, rb);
printf("================================================================\n");
idx = (12*rb)<<1;
printf("%4d %4d %4d %4d %4d %4d %4d %4d %4d %4d %4d %4d\n", ch_tmp[idx], ch_tmp[idx+1], ch_tmp[idx+2], ch_tmp[idx+3], ch_tmp[idx+4], ch_tmp[idx+5], ch_tmp[idx+6], ch_tmp[idx+7], ch_tmp[idx+8], ch_tmp[idx+9], ch_tmp[idx+10], ch_tmp[idx+11]);
printf("%4d %4d %4d %4d %4d %4d %4d %4d %4d %4d %4d %4d\n", ch_tmp[idx+12], ch_tmp[idx+13], ch_tmp[idx+14], ch_tmp[idx+15], ch_tmp[idx+16], ch_tmp[idx+17], ch_tmp[idx+18], ch_tmp[idx+19], ch_tmp[idx+20], ch_tmp[idx+21], ch_tmp[idx+22], ch_tmp[idx+23]);
idx = (12 * rb);
printf("%4d %4d %4d %4d %4d %4d %4d %4d %4d %4d %4d %4d\n",
ch_tmp[idx].r,
ch_tmp[idx].i,
ch_tmp[idx + 1].r,
ch_tmp[idx + 1].i,
ch_tmp[idx + 2].r,
ch_tmp[idx + 2].i,
ch_tmp[idx + 3].r,
ch_tmp[idx + 3].i,
ch_tmp[idx + 4].r,
ch_tmp[idx + 4].i,
ch_tmp[idx + 5].r,
ch_tmp[idx + 5].i);
printf("%4d %4d %4d %4d %4d %4d %4d %4d %4d %4d %4d %4d\n",
ch_tmp[idx + 6].r,
ch_tmp[idx + 6].i,
ch_tmp[idx + 7].r,
ch_tmp[idx + 7].i,
ch_tmp[idx + 8].r,
ch_tmp[idx + 8].i,
ch_tmp[idx + 9].r,
ch_tmp[idx + 9].i,
ch_tmp[idx + 10].r,
ch_tmp[idx + 10].i,
ch_tmp[idx + 11].r,
ch_tmp[idx + 11].i);
printf("\n");
}
#endif
// Place PRS channel estimates in FFT shifted format
if(first_half > 0)
memcpy((int16_t *)&chF_interpol[rxAnt][start_offset], &ch_tmp[0], first_half * sizeof(int32_t));
memcpy(&chF_interpol[rxAnt][start_offset], &ch_tmp[0], first_half * sizeof(c16_t));
if(second_half > 0)
memcpy((int16_t *)&chF_interpol[rxAnt][0], &ch_tmp[first_half << 1], second_half * sizeof(int32_t));
memcpy(&chF_interpol[rxAnt][0], &ch_tmp[first_half], second_half * sizeof(c16_t));
// Convert to time domain
freq2time(NR_PRS_IDFT_OVERSAMP_FACTOR * frame_params->ofdm_symbol_size,
@@ -448,10 +505,11 @@ int nr_prs_channel_estimation(uint8_t gNB_id,
peak_estimator(&chT_interpol[rxAnt][0], NR_PRS_IDFT_OVERSAMP_FACTOR * frame_params->ofdm_symbol_size, &prs_toa, &ch_pwr, mean_val);
// adjusting the rx_gains for channel peak power
ch_pwr_dbm = 10 * log10(ch_pwr) + 30 - SQ15_SQUARED_NORM_FACTOR_DB - ((int)openair0_cfg[0].rx_gain[0] - (int)openair0_cfg[0].rx_gain_offset[0]) - dB_fixed(frame_params->ofdm_symbol_size);
ch_pwr_dbm = 10 * log10(ch_pwr) + 30 - SQ15_SQUARED_NORM_FACTOR_DB
- ((int)openair0_cfg[0].rx_gain[0] - (int)openair0_cfg[0].rx_gain_offset[0]);
prs_meas[rxAnt]->rsrp_dBm =
10 * log10(prs_meas[rxAnt]->rsrp) + 30 - SQ15_SQUARED_NORM_FACTOR_DB - ((int)openair0_cfg[0].rx_gain[0] - (int)openair0_cfg[0].rx_gain_offset[0]) - dB_fixed(ue->frame_parms.ofdm_symbol_size);
prs_meas[rxAnt]->rsrp_dBm = 10 * log10(prs_meas[rxAnt]->rsrp) + 30 - SQ15_SQUARED_NORM_FACTOR_DB
- ((int)openair0_cfg[0].rx_gain[0] - (int)openair0_cfg[0].rx_gain_offset[0]);
//prs measurements
prs_meas[rxAnt]->gNB_id = gNB_id;
@@ -460,6 +518,7 @@ int nr_prs_channel_estimation(uint8_t gNB_id,
prs_meas[rxAnt]->rxAnt_idx = rxAnt;
prs_meas[rxAnt]->dl_aoa = rsc_id;
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,
@@ -480,7 +539,7 @@ int nr_prs_channel_estimation(uint8_t gNB_id,
LOG_M(filename, "prs_loc", mod_prs, num_pilots, 1, 1);
sprintf(filename, "%s%i%s", "rxSigF_", rxAnt, ".m");
sprintf(varname, "%s%i", "rxF_", rxAnt);
LOG_M(filename, varname, &rxdataF[rxAnt][0], prs_cfg->NumPRSSymbols*frame_params->ofdm_symbol_size,1,1);
LOG_M(filename, varname, &rxdataF[rxAnt][0], num_symbols * frame_params->ofdm_symbol_size, 1, 1);
sprintf(filename, "%s%i%s", "prsChestF_", rxAnt, ".m");
sprintf(varname, "%s%i", "prsChF_", rxAnt);
LOG_M(filename, varname, &chF_interpol[rxAnt][start_offset], frame_params->ofdm_symbol_size,1,1);
@@ -490,17 +549,13 @@ int nr_prs_channel_estimation(uint8_t gNB_id,
#endif
// T tracer dump
T(T_UE_PHY_INPUT_SIGNAL, T_INT(gNB_id),
T_INT(proc->frame_rx), T_INT(proc->nr_slot_rx),
T_INT(rxAnt), T_BUFFER(&rxdataF[rxAnt][0], frame_params->samples_per_slot_wCP*sizeof(int32_t)));
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][0], NR_PRS_IDFT_OVERSAMP_FACTOR * frame_params->ofdm_symbol_size * sizeof(int32_t)));
T_BUFFER(&chF_interpol[rxAnt][0], NR_PRS_IDFT_OVERSAMP_FACTOR * frame_params->ofdm_symbol_size * sizeof(c16_t)));
T(T_UE_PHY_DL_CHANNEL_ESTIMATE,
T_INT(gNB_id),
@@ -508,8 +563,8 @@ int nr_prs_channel_estimation(uint8_t gNB_id,
T_INT(proc->frame_rx),
T_INT(proc->nr_slot_rx),
T_INT(rxAnt),
T_BUFFER(&chT_interpol[rxAnt][0], NR_PRS_IDFT_OVERSAMP_FACTOR * frame_params->ofdm_symbol_size * sizeof(int32_t)));
}
T_BUFFER(&chT_interpol[rxAnt][0], NR_PRS_IDFT_OVERSAMP_FACTOR * frame_params->ofdm_symbol_size * sizeof(c16_t)));
} // for rxAnt
return(0);
}

View File

@@ -39,7 +39,7 @@ int nr_prs_channel_estimation(uint8_t gNB_id,
c16_t rxdataF[][ue->frame_parms.samples_per_slot_wCP]);
/* Generic function to find the peak of channel estimation buffer */
void peak_estimator(int32_t *buffer, int32_t buf_len, int32_t *peak_idx, int32_t *peak_val, int32_t mean_val);
void peak_estimator(c16_t *buffer, int32_t buf_len, int32_t *peak_idx, int32_t *peak_val, int32_t mean_val);
/*!
\brief This function performs channel estimation including frequency and temporal interpolation