|
|
@@ -800,26 +800,37 @@ int nr_srs_channel_estimation(int ant,
|
|
|
|
if (N_ap == 4 && ((K_TC == 2 && srs_pdu->cyclic_shift >= 4) || (K_TC == 4 && srs_pdu->cyclic_shift >= 6))) {
|
|
|
|
if (N_ap == 4 && ((K_TC == 2 && srs_pdu->cyclic_shift >= 4) || (K_TC == 4 && srs_pdu->cyclic_shift >= 6))) {
|
|
|
|
fd_cdm = 2;
|
|
|
|
fd_cdm = 2;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
uint16_t subcarrier;
|
|
|
|
|
|
|
|
|
|
|
|
c16_t srs_ls_estimated_channel[ofdm_symbol_size * N_symb_SRS];
|
|
|
|
c16_t srs_ls_estimated_channel[ofdm_symbol_size * N_symb_SRS];
|
|
|
|
uint8_t mem_offset = ((16 - ((intptr_t)&srs_estimated_channel_freq[subcarrier_offset + nr_srs_info->k_0_p[p_index][0]])) & 0xF)
|
|
|
|
c16_t srs_estimated_channel_freq_avg[ofdm_symbol_size];
|
|
|
|
|
|
|
|
memset(srs_ls_estimated_channel, 0, ofdm_symbol_size * N_symb_SRS * sizeof(c16_t));
|
|
|
|
|
|
|
|
memset(srs_estimated_channel_freq_avg, 0, ofdm_symbol_size * sizeof(c16_t));
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for (int srs_symb = 0; srs_symb < N_symb_SRS; srs_symb++) {
|
|
|
|
|
|
|
|
uint16_t srs_symbol_offset = srs_symb * ofdm_symbol_size;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
uint8_t mem_offset =
|
|
|
|
|
|
|
|
((16
|
|
|
|
|
|
|
|
- ((intptr_t)&srs_estimated_channel_freq[srs_symbol_offset + subcarrier_offset + nr_srs_info->k_0_p[p_index][srs_symb]]))
|
|
|
|
|
|
|
|
& 0xF)
|
|
|
|
>> 2; // >> 2 <=> /sizeof(int32_t)
|
|
|
|
>> 2; // >> 2 <=> /sizeof(int32_t)
|
|
|
|
|
|
|
|
|
|
|
|
// filt16_end is {4096,8192,8192,8192,12288,16384,16384,16384,0,0,0,0,0,0,0,0}
|
|
|
|
// filt16_end is {4096,8192,8192,8192,12288,16384,16384,16384,0,0,0,0,0,0,0,0}
|
|
|
|
// The End of OFDM symbol corresponds to the position of last 16384 in the filter
|
|
|
|
// The End of OFDM symbol corresponds to the position of last 16384 in the filter
|
|
|
|
// The c16multaddVectRealComplex applies the remaining 8 zeros of filter, therefore, to avoid a buffer overflow,
|
|
|
|
// The c16multaddVectRealComplex applies the remaining 8 zeros of filter, therefore, to avoid a buffer overflow,
|
|
|
|
// we added 8 in the array size
|
|
|
|
// we added 8 in the array size
|
|
|
|
c16_t srs_est[ofdm_symbol_size * N_symb_SRS + mem_offset + 8] __attribute__((aligned(32)));
|
|
|
|
c16_t srs_est[ofdm_symbol_size + mem_offset + 8] __attribute__((aligned(32)));
|
|
|
|
c16_t ls_estimated = {0};
|
|
|
|
c16_t ls_estimated = {0};
|
|
|
|
|
|
|
|
|
|
|
|
memset(srs_ls_estimated_channel, 0, ofdm_symbol_size * N_symb_SRS * sizeof(c16_t));
|
|
|
|
memset(srs_est, 0, (ofdm_symbol_size + mem_offset + 8) * sizeof(c16_t));
|
|
|
|
memset(srs_est, 0, (ofdm_symbol_size * N_symb_SRS + mem_offset) * sizeof(c16_t));
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#ifdef SRS_DEBUG
|
|
|
|
#ifdef SRS_DEBUG
|
|
|
|
LOG_I(NR_PHY, "====================== UE port %d --> gNB Rx antenna %i ======================\n", p_index, ant);
|
|
|
|
LOG_I(NR_PHY, "====================== UE port %d --> gNB Rx antenna %i ======================\n", p_index, ant);
|
|
|
|
|
|
|
|
LOG_I(NR_PHY, "============================== SRS symbol index %d ===========================\n", srs_symb);
|
|
|
|
#endif
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
uint16_t subcarrier = subcarrier_offset + nr_srs_info->k_0_p[p_index][0];
|
|
|
|
subcarrier = subcarrier_offset + nr_srs_info->k_0_p[p_index][srs_symb];
|
|
|
|
if (subcarrier >= ofdm_symbol_size) {
|
|
|
|
if (subcarrier >= ofdm_symbol_size) {
|
|
|
|
subcarrier -= ofdm_symbol_size;
|
|
|
|
subcarrier -= ofdm_symbol_size;
|
|
|
|
}
|
|
|
|
}
|
|
|
@@ -832,8 +843,8 @@ int nr_srs_channel_estimation(int ant,
|
|
|
|
uint16_t subcarrier_cdm = subcarrier;
|
|
|
|
uint16_t subcarrier_cdm = subcarrier;
|
|
|
|
|
|
|
|
|
|
|
|
for (int cdm_idx = 0; cdm_idx < fd_cdm; cdm_idx++) {
|
|
|
|
for (int cdm_idx = 0; cdm_idx < fd_cdm; cdm_idx++) {
|
|
|
|
c16_t generated_srs = srs_generated_signal[subcarrier_cdm];
|
|
|
|
c16_t generated_srs = srs_generated_signal[srs_symbol_offset + subcarrier_cdm];
|
|
|
|
c16_t received_srs = srs_received_signal[subcarrier_cdm];
|
|
|
|
c16_t received_srs = srs_received_signal[srs_symbol_offset + subcarrier_cdm];
|
|
|
|
// We know that nr_srs_info->srs_generated_signal_bits bits are enough to represent the real and imaginary parts of
|
|
|
|
// We know that nr_srs_info->srs_generated_signal_bits bits are enough to represent the real and imaginary parts of
|
|
|
|
// generated_srs. So we only need a nr_srs_info->srs_generated_signal_bits shift to ensure that the result fits into 16
|
|
|
|
// generated_srs. So we only need a nr_srs_info->srs_generated_signal_bits shift to ensure that the result fits into 16
|
|
|
|
// bits.
|
|
|
|
// bits.
|
|
|
@@ -847,7 +858,7 @@ int nr_srs_channel_estimation(int ant,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
srs_ls_estimated_channel[subcarrier] = ls_estimated;
|
|
|
|
srs_ls_estimated_channel[srs_symbol_offset + subcarrier] = ls_estimated;
|
|
|
|
|
|
|
|
|
|
|
|
#ifdef SRS_DEBUG
|
|
|
|
#ifdef SRS_DEBUG
|
|
|
|
int subcarrier_log = subcarrier - subcarrier_offset;
|
|
|
|
int subcarrier_log = subcarrier - subcarrier_offset;
|
|
|
@@ -861,10 +872,10 @@ int nr_srs_channel_estimation(int ant,
|
|
|
|
LOG_I(NR_PHY,
|
|
|
|
LOG_I(NR_PHY,
|
|
|
|
"(%4i) %6i\t%6i | %6i\t%6i | %6i\t%6i\n",
|
|
|
|
"(%4i) %6i\t%6i | %6i\t%6i | %6i\t%6i\n",
|
|
|
|
subcarrier_log,
|
|
|
|
subcarrier_log,
|
|
|
|
srs_generated_signal[subcarrier].r,
|
|
|
|
srs_generated_signal[srs_symbol_offset + subcarrier].r,
|
|
|
|
srs_generated_signal[subcarrier].i,
|
|
|
|
srs_generated_signal[srs_symbol_offset + subcarrier].i,
|
|
|
|
srs_received_signal[subcarrier].r,
|
|
|
|
srs_received_signal[srs_symbol_offset + subcarrier].r,
|
|
|
|
srs_received_signal[subcarrier].i,
|
|
|
|
srs_received_signal[srs_symbol_offset + subcarrier].i,
|
|
|
|
ls_estimated.r,
|
|
|
|
ls_estimated.r,
|
|
|
|
ls_estimated.i);
|
|
|
|
ls_estimated.i);
|
|
|
|
#endif
|
|
|
|
#endif
|
|
|
@@ -921,10 +932,17 @@ int nr_srs_channel_estimation(int ant,
|
|
|
|
|
|
|
|
|
|
|
|
} // for (int k = 0; k < M_sc_b_SRS; k++)
|
|
|
|
} // for (int k = 0; k < M_sc_b_SRS; k++)
|
|
|
|
|
|
|
|
|
|
|
|
memcpy(srs_estimated_channel_freq, &srs_est[mem_offset], (ofdm_symbol_size * N_symb_SRS) * sizeof(c16_t));
|
|
|
|
memcpy(&srs_estimated_channel_freq[srs_symbol_offset], &srs_est[mem_offset], ofdm_symbol_size * sizeof(c16_t));
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Average srs channel estimates over multiple symbols
|
|
|
|
|
|
|
|
int16_t scale_factor = (1 << 15) / N_symb_SRS;
|
|
|
|
|
|
|
|
multadd_complex_vector_real_scalar(&srs_estimated_channel_freq[srs_symbol_offset],
|
|
|
|
|
|
|
|
scale_factor,
|
|
|
|
|
|
|
|
srs_estimated_channel_freq_avg,
|
|
|
|
|
|
|
|
ofdm_symbol_size);
|
|
|
|
|
|
|
|
|
|
|
|
#ifdef SRS_DEBUG
|
|
|
|
#ifdef SRS_DEBUG
|
|
|
|
subcarrier = subcarrier_offset + nr_srs_info->k_0_p[p_index][0];
|
|
|
|
subcarrier = subcarrier_offset + nr_srs_info->k_0_p[p_index][srs_symb];
|
|
|
|
if (subcarrier >= ofdm_symbol_size) {
|
|
|
|
if (subcarrier >= ofdm_symbol_size) {
|
|
|
|
subcarrier -= ofdm_symbol_size;
|
|
|
|
subcarrier -= ofdm_symbol_size;
|
|
|
|
}
|
|
|
|
}
|
|
|
@@ -936,19 +954,22 @@ int nr_srs_channel_estimation(int ant,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (subcarrier_log % 12 == 0) {
|
|
|
|
if (subcarrier_log % 12 == 0) {
|
|
|
|
LOG_I(NR_PHY, "------------------------------------- %d -------------------------------------\n", subcarrier_log / 12);
|
|
|
|
LOG_I(NR_PHY,
|
|
|
|
|
|
|
|
"---------------------------- PRB %d, symbol %d -------------------------------\n",
|
|
|
|
|
|
|
|
subcarrier_log / 12,
|
|
|
|
|
|
|
|
srs_symb);
|
|
|
|
LOG_I(NR_PHY, "\t __lsRe__________lsIm__|____intRe_______intIm__|____noiRe_______noiIm__\n");
|
|
|
|
LOG_I(NR_PHY, "\t __lsRe__________lsIm__|____intRe_______intIm__|____noiRe_______noiIm__\n");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
LOG_I(NR_PHY,
|
|
|
|
LOG_I(NR_PHY,
|
|
|
|
"(%4i) %6i\t%6i | %6i\t%6i | %6i\t%6i\n",
|
|
|
|
"(%4i) %6i\t%6i | %6i\t%6i | %6i\t%6i\n",
|
|
|
|
subcarrier_log,
|
|
|
|
subcarrier_log,
|
|
|
|
srs_ls_estimated_channel[subcarrier].r,
|
|
|
|
srs_ls_estimated_channel[srs_symbol_offset + subcarrier].r,
|
|
|
|
srs_ls_estimated_channel[subcarrier].i,
|
|
|
|
srs_ls_estimated_channel[srs_symbol_offset + subcarrier].i,
|
|
|
|
srs_estimated_channel_freq[subcarrier].r,
|
|
|
|
srs_estimated_channel_freq[srs_symbol_offset + subcarrier].r,
|
|
|
|
srs_estimated_channel_freq[subcarrier].i,
|
|
|
|
srs_estimated_channel_freq[srs_symbol_offset + subcarrier].i,
|
|
|
|
srs_received_noise[subcarrier].r,
|
|
|
|
srs_received_noise[srs_symbol_offset + subcarrier].r,
|
|
|
|
srs_received_noise[subcarrier].i);
|
|
|
|
srs_received_noise[srs_symbol_offset + subcarrier].i);
|
|
|
|
|
|
|
|
|
|
|
|
// Subcarrier increment
|
|
|
|
// Subcarrier increment
|
|
|
|
subcarrier++;
|
|
|
|
subcarrier++;
|
|
|
@@ -957,6 +978,7 @@ int nr_srs_channel_estimation(int ant,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
#endif
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Convert to time domain
|
|
|
|
// Convert to time domain
|
|
|
|
int16_t ofdm_symbol_size_half = ofdm_symbol_size >> 1;
|
|
|
|
int16_t ofdm_symbol_size_half = ofdm_symbol_size >> 1;
|
|
|
@@ -968,9 +990,9 @@ int nr_srs_channel_estimation(int ant,
|
|
|
|
memset(chF_interpol, 0, sizeof(chF_interpol));
|
|
|
|
memset(chF_interpol, 0, sizeof(chF_interpol));
|
|
|
|
|
|
|
|
|
|
|
|
// Place SRS channel estimates in FFT shifted format for oversampling
|
|
|
|
// Place SRS channel estimates in FFT shifted format for oversampling
|
|
|
|
memcpy(&chF_interpol[0], &srs_estimated_channel_freq[0], ofdm_symbol_size_half * sizeof(c16_t));
|
|
|
|
memcpy(&chF_interpol[0], &srs_estimated_channel_freq_avg[0], ofdm_symbol_size_half * sizeof(c16_t));
|
|
|
|
memcpy(&chF_interpol[start_offset],
|
|
|
|
memcpy(&chF_interpol[start_offset],
|
|
|
|
&srs_estimated_channel_freq[ofdm_symbol_size_half],
|
|
|
|
&srs_estimated_channel_freq_avg[ofdm_symbol_size_half],
|
|
|
|
ofdm_symbol_size_half * sizeof(c16_t));
|
|
|
|
ofdm_symbol_size_half * sizeof(c16_t));
|
|
|
|
|
|
|
|
|
|
|
|
// Convert to time domain oversampled
|
|
|
|
// Convert to time domain oversampled
|
|
|
@@ -981,7 +1003,7 @@ int nr_srs_channel_estimation(int ant,
|
|
|
|
|
|
|
|
|
|
|
|
memcpy(&srs_estimated_channel_time_shifted[ofdm_os_size_half], srs_estimated_channel_time, ofdm_os_size_half * sizeof(c16_t));
|
|
|
|
memcpy(&srs_estimated_channel_time_shifted[ofdm_os_size_half], srs_estimated_channel_time, ofdm_os_size_half * sizeof(c16_t));
|
|
|
|
|
|
|
|
|
|
|
|
// Compute wideband SNR
|
|
|
|
// Compute wideband SNR on the symbol 0
|
|
|
|
int tot_subcarriers = m_SRS_b * NR_NB_SC_PER_RB;
|
|
|
|
int tot_subcarriers = m_SRS_b * NR_NB_SC_PER_RB;
|
|
|
|
subcarrier = subcarrier_offset + nr_srs_info->k_0_p[p_index][0];
|
|
|
|
subcarrier = subcarrier_offset + nr_srs_info->k_0_p[p_index][0];
|
|
|
|
if (subcarrier >= ofdm_symbol_size) {
|
|
|
|
if (subcarrier >= ofdm_symbol_size) {
|
|
|
@@ -1011,7 +1033,7 @@ int nr_srs_channel_estimation(int ant,
|
|
|
|
return -1;
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Compute SNR per RB for port 0
|
|
|
|
// Compute SNR per RB for port 0 and symbol 0
|
|
|
|
if (p_index == 0) {
|
|
|
|
if (p_index == 0) {
|
|
|
|
subcarrier = subcarrier_offset + nr_srs_info->k_0_p[p_index][0];
|
|
|
|
subcarrier = subcarrier_offset + nr_srs_info->k_0_p[p_index][0];
|
|
|
|
for (int rb = 0; rb < m_SRS_b; rb++) {
|
|
|
|
for (int rb = 0; rb < m_SRS_b; rb++) {
|
|
|
@@ -1031,13 +1053,23 @@ int nr_srs_channel_estimation(int ant,
|
|
|
|
subcarrier += NR_NB_SC_PER_RB;
|
|
|
|
subcarrier += NR_NB_SC_PER_RB;
|
|
|
|
|
|
|
|
|
|
|
|
#ifdef SRS_DEBUG
|
|
|
|
#ifdef SRS_DEBUG
|
|
|
|
LOG_I(NR_PHY, "[RB %3i] noise_power_per_rb = %i, snr_per_rb = %i dB\n", rb, noise_power_per_rb, snr_per_rb[rb]);
|
|
|
|
LOG_I(NR_PHY,
|
|
|
|
|
|
|
|
"[RB %3i] noise_power_per_rb = %i, SNR_per_rb = %i dB\n",
|
|
|
|
|
|
|
|
rb,
|
|
|
|
|
|
|
|
noise_power_per_rb[rb],
|
|
|
|
|
|
|
|
dB_fixed(*signal_power) - dB_fixed(noise_power_per_rb[rb]));
|
|
|
|
#endif
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#ifdef SRS_DEBUG
|
|
|
|
#ifdef SRS_DEBUG
|
|
|
|
LOG_I(NR_PHY, "signal_power = %i dB, noise_power = %i dB, SNR = %i dB\n", dB_fixed(signal_power), dB_fixed(noise_power), *snr);
|
|
|
|
int32_t signal_power_dB = dB_fixed(*signal_power);
|
|
|
|
|
|
|
|
int32_t noise_power_dB = dB_fixed(*noise_power);
|
|
|
|
|
|
|
|
LOG_I(NR_PHY,
|
|
|
|
|
|
|
|
"signal_power = %i dB, noise_power = %i dB, SNR = %i dB\n",
|
|
|
|
|
|
|
|
signal_power_dB,
|
|
|
|
|
|
|
|
noise_power_dB,
|
|
|
|
|
|
|
|
signal_power_dB - noise_power_dB);
|
|
|
|
#endif
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
return 0;
|
|
|
|