Implementing delay compensation during SRS-based channel estimation
This commit is contained in:
@@ -780,7 +780,8 @@ int nr_srs_channel_estimation(int ant,
|
||||
c16_t srs_estimated_channel_time_shifted[NR_SRS_IDFT_OVERSAMP_FACTOR * ofdm_symbol_size],
|
||||
uint32_t *signal_power,
|
||||
uint32_t *noise_power,
|
||||
int16_t *noise_power_per_rb)
|
||||
int16_t *noise_power_per_rb,
|
||||
c16_t delay_table[2 * MAX_DELAY_COMP + 1][NR_MAX_OFDM_SYMBOL_SIZE])
|
||||
{
|
||||
#ifdef SRS_DEBUG
|
||||
LOG_I(NR_PHY, "Calling %s function\n", __FUNCTION__);
|
||||
@@ -797,40 +798,29 @@ 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))) {
|
||||
fd_cdm = 2;
|
||||
}
|
||||
uint16_t subcarrier;
|
||||
|
||||
c16_t srs_ls_estimated_channel[ofdm_symbol_size * N_symb_SRS];
|
||||
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));
|
||||
delay_t delay = {0};
|
||||
|
||||
for (int srs_symb = 0; srs_symb < N_symb_SRS; srs_symb++) {
|
||||
uint16_t srs_symbol_offset = srs_symb * ofdm_symbol_size;
|
||||
|
||||
// Additional 4 in the array size is needed to maintain 16 byte memory alignment required for AVX2 instructions in channel
|
||||
// interpolation
|
||||
c16_t srs_est[ofdm_symbol_size + 4] __attribute__((aligned(32)));
|
||||
memset(srs_est, 0, (ofdm_symbol_size + 4) * sizeof(c16_t));
|
||||
|
||||
// Estimate 16 byte memory alignment offset for the first SRS subcarrier to use AVX2 instructions in channel interpolation
|
||||
uint8_t mem_offset = (16 - (((intptr_t)&srs_est[first_subcarrier + nr_srs_info->k_0_p[p_index][srs_symb]]) & 0xF))
|
||||
>> 2; // >> 2 <=> /sizeof(int32_t)
|
||||
|
||||
c16_t ls_estimated = {0};
|
||||
|
||||
#ifdef SRS_DEBUG
|
||||
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
|
||||
|
||||
subcarrier = subcarrier_offset + nr_srs_info->k_0_p[p_index][srs_symb];
|
||||
// Channel estimation based on least square method
|
||||
|
||||
uint16_t subcarrier = subcarrier_offset + nr_srs_info->k_0_p[p_index][srs_symb];
|
||||
if (subcarrier >= ofdm_symbol_size) {
|
||||
subcarrier -= ofdm_symbol_size;
|
||||
}
|
||||
|
||||
uint16_t subcarrier_abs = mem_offset + first_subcarrier + nr_srs_info->k_0_p[p_index][srs_symb];
|
||||
c16_t *srs_estimated_channel16 = &srs_est[subcarrier_abs];
|
||||
|
||||
c16_t ls_estimated = {0};
|
||||
for (int k = 0; k < M_sc_b_SRS; k++) {
|
||||
if (k % fd_cdm == 0) {
|
||||
ls_estimated = (c16_t){0, 0};
|
||||
@@ -852,7 +842,9 @@ int nr_srs_channel_estimation(int ant,
|
||||
}
|
||||
}
|
||||
|
||||
srs_ls_estimated_channel[srs_symbol_offset + subcarrier] = ls_estimated;
|
||||
for (int ktc = 0; ktc < K_TC && srs_symbol_offset + subcarrier + ktc < ofdm_symbol_size * N_symb_SRS; ktc++) {
|
||||
srs_ls_estimated_channel[srs_symbol_offset + subcarrier + ktc] = ls_estimated;
|
||||
}
|
||||
|
||||
#ifdef SRS_DEBUG
|
||||
int subcarrier_log = subcarrier - subcarrier_offset;
|
||||
@@ -874,6 +866,44 @@ int nr_srs_channel_estimation(int ant,
|
||||
ls_estimated.i);
|
||||
#endif
|
||||
|
||||
// Subcarrier increment
|
||||
subcarrier += K_TC;
|
||||
if (subcarrier >= ofdm_symbol_size) {
|
||||
subcarrier -= ofdm_symbol_size;
|
||||
}
|
||||
} // for (int k = 0; k < M_sc_b_SRS; k++)
|
||||
|
||||
// Delay estimation
|
||||
c16_t ch_estimates_time[ofdm_symbol_size] __attribute__((aligned(32)));
|
||||
nr_est_delay(ofdm_symbol_size, srs_ls_estimated_channel, ch_estimates_time, &delay);
|
||||
|
||||
// Interpolation of LS estimates
|
||||
|
||||
// Additional 4 in the array size is needed to maintain 16 byte memory alignment required for AVX2 instructions in channel
|
||||
// interpolation
|
||||
c16_t srs_est[ofdm_symbol_size + 4] __attribute__((aligned(32)));
|
||||
memset(srs_est, 0, (ofdm_symbol_size + 4) * sizeof(c16_t));
|
||||
|
||||
// Estimate 16 byte memory alignment offset for the first SRS subcarrier to use AVX2 instructions in channel interpolation
|
||||
uint8_t mem_offset =
|
||||
(16 - (((intptr_t)&srs_est[first_subcarrier + nr_srs_info->k_0_p[p_index][srs_symb]]) & 0xF)) / sizeof(c16_t);
|
||||
|
||||
uint16_t subcarrier_abs = mem_offset + first_subcarrier + nr_srs_info->k_0_p[p_index][srs_symb];
|
||||
c16_t *srs_estimated_channel16 = &srs_est[subcarrier_abs];
|
||||
|
||||
subcarrier = subcarrier_offset + nr_srs_info->k_0_p[p_index][srs_symb];
|
||||
if (subcarrier >= ofdm_symbol_size) {
|
||||
subcarrier -= ofdm_symbol_size;
|
||||
}
|
||||
|
||||
int delay_idx = get_delay_idx(delay.est_delay, MAX_DELAY_COMP);
|
||||
const c16_t *srs_delay_table = delay_table[delay_idx];
|
||||
|
||||
for (int k = 0; k < M_sc_b_SRS; k++) {
|
||||
|
||||
// Apply delay
|
||||
ls_estimated = c16mulShift(srs_ls_estimated_channel[srs_symbol_offset + subcarrier], srs_delay_table[subcarrier], 8);
|
||||
|
||||
// Channel interpolation
|
||||
if (srs_pdu->comb_size == 0) {
|
||||
if (k == 0) { // First subcarrier case
|
||||
@@ -914,6 +944,27 @@ int nr_srs_channel_estimation(int ant,
|
||||
|
||||
} // for (int k = 0; k < M_sc_b_SRS; k++)
|
||||
|
||||
// Revert delay
|
||||
int inv_delay_idx = get_delay_idx(-delay.est_delay, MAX_DELAY_COMP);
|
||||
const c16_t *srs_inv_delay_table = delay_table[inv_delay_idx];
|
||||
subcarrier_abs = mem_offset + first_subcarrier + nr_srs_info->k_0_p[p_index][srs_symb];
|
||||
subcarrier = subcarrier_offset + nr_srs_info->k_0_p[p_index][0];
|
||||
if (subcarrier >= ofdm_symbol_size) {
|
||||
subcarrier -= ofdm_symbol_size;
|
||||
}
|
||||
for (int k = 0; k < K_TC * M_sc_b_SRS; k++) {
|
||||
srs_est[subcarrier_abs] = c16mulShift(srs_est[subcarrier_abs], srs_inv_delay_table[subcarrier], 8);
|
||||
// Subcarrier increment
|
||||
subcarrier++;
|
||||
if (subcarrier >= ofdm_symbol_size) {
|
||||
subcarrier -= ofdm_symbol_size;
|
||||
}
|
||||
subcarrier_abs++;
|
||||
if (subcarrier_abs >= ofdm_symbol_size) {
|
||||
subcarrier_abs -= ofdm_symbol_size;
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
@@ -996,7 +1047,7 @@ int nr_srs_channel_estimation(int ant,
|
||||
return -1;
|
||||
}
|
||||
|
||||
subcarrier = subcarrier_offset + nr_srs_info->k_0_p[p_index][0];
|
||||
uint16_t subcarrier = subcarrier_offset + nr_srs_info->k_0_p[p_index][0];
|
||||
if (subcarrier >= ofdm_symbol_size) {
|
||||
subcarrier -= ofdm_symbol_size;
|
||||
}
|
||||
|
||||
@@ -90,7 +90,8 @@ int nr_srs_channel_estimation(int ant,
|
||||
c16_t srs_estimated_channel_time_shifted[NR_SRS_IDFT_OVERSAMP_FACTOR * ofdm_symbol_size],
|
||||
uint32_t *signal_power,
|
||||
uint32_t *noise_power,
|
||||
int16_t *noise_power_per_rb);
|
||||
int16_t *noise_power_per_rb,
|
||||
c16_t delay_table[2 * MAX_DELAY_COMP + 1][NR_MAX_OFDM_SYMBOL_SIZE]);
|
||||
|
||||
void nr_freq_equalization(NR_DL_FRAME_PARMS *frame_parms,
|
||||
c16_t *rxdataF_comp,
|
||||
|
||||
@@ -905,7 +905,8 @@ void nr_srs_rx_procedures(PHY_VARS_gNB *gNB,
|
||||
srs_estimated_channel_time_shifted[ant_rx_ind][p_ind],
|
||||
&signal_power,
|
||||
&noise_power,
|
||||
noise_power_per_rb);
|
||||
noise_power_per_rb,
|
||||
frame_parms->delay_table);
|
||||
|
||||
signal_power_avg += signal_power;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user