From 4f31a4eb89fb491f23bfe6d0fdb500c79f6d6397 Mon Sep 17 00:00:00 2001 From: rmagueta Date: Wed, 14 Jan 2026 14:41:41 +0000 Subject: [PATCH] The nr_srs_channel_estimation function is split into the nr_srs_ls_channel_estimation and nr_srs_channel_interpolation functions to allow the use of a common delay Define CIRCULAR_INC --- common/utils/T/tracer/gnb.c | 2 +- common/utils/nr/nr_common.h | 4 + .../NR_ESTIMATION/nr_ul_channel_estimation.c | 259 +++++++++--------- openair1/PHY/NR_ESTIMATION/nr_ul_estimation.h | 54 ++-- openair1/SCHED_NR/phy_procedures_nr_gNB.c | 84 ++++-- 5 files changed, 231 insertions(+), 172 deletions(-) diff --git a/common/utils/T/tracer/gnb.c b/common/utils/T/tracer/gnb.c index d47f627341..ebed555ae6 100644 --- a/common/utils/T/tracer/gnb.c +++ b/common/utils/T/tracer/gnb.c @@ -195,7 +195,7 @@ static void gnb_main_gui(gnb_gui *e, gui *g, event_handler *h, void *database, g e->ul_freq_estimate_ue_xy_plot = w; widget_add_child(g, line, w, -1); xy_plot_set_range(g, w, 0, 2048, -10, 80); - l = new_framelog(h, database, "GNB_PHY_UL_FREQ_CHANNEL_ESTIMATE", "subframe", "chest_t"); + l = new_framelog(h, database, "GNB_PHY_UL_FREQ_CHANNEL_ESTIMATE", "subframe", "chest_f"); framelog_set_update_only_at_sf9(l, 0); v = new_view_xy(2048, 10, g, w, new_color(g, "#0c0c72"), XY_LOOP_MODE); logger_add_view(l, v); diff --git a/common/utils/nr/nr_common.h b/common/utils/nr/nr_common.h index 2197fe91a7..0b54bd233f 100644 --- a/common/utils/nr/nr_common.h +++ b/common/utils/nr/nr_common.h @@ -366,6 +366,10 @@ void nr_deconstruct_5g_s_tmsi(const uint64_t fiveg_s_tmsi, uint16_t *amf_set_id, #define ROUNDIDIV(a,b) (((a<<1)+b)/(b<<1)) #define BOUNDED_EVAL(a, b, c) (min(c, max(a, b))) +/* Macro used to perform a circular increment. This implementation is computationally more efficient than using the remainder of the + * integer division, and improves code readability when compared to repetitive if... else statements. */ +#define CIRCULAR_INC(val, inc, size) (((val) + (inc) >= (size)) ? ((val) + (inc) - (size)) : ((val) + (inc))) + static const char *const duplex_mode_txt[] = {"FDD", "TDD"}; #ifdef __cplusplus diff --git a/openair1/PHY/NR_ESTIMATION/nr_ul_channel_estimation.c b/openair1/PHY/NR_ESTIMATION/nr_ul_channel_estimation.c index 7c5accdb68..d51eb1919c 100644 --- a/openair1/PHY/NR_ESTIMATION/nr_ul_channel_estimation.c +++ b/openair1/PHY/NR_ESTIMATION/nr_ul_channel_estimation.c @@ -765,30 +765,23 @@ void nr_pusch_ptrs_processing(PHY_VARS_gNB *gNB, } // Antenna loop } -int nr_srs_channel_estimation(int ant, - int p_index, - uint16_t ofdm_symbol_size, - uint16_t first_carrier_offset, - uint8_t N_symb_SRS, - const nfapi_nr_srs_pdu_t *srs_pdu, - const nr_srs_info_t *nr_srs_info, - const c16_t *srs_generated_signal, - c16_t srs_received_signal[ofdm_symbol_size * N_symb_SRS], - c16_t srs_received_noise[ofdm_symbol_size * N_symb_SRS], - c16_t srs_estimated_channel_freq[ofdm_symbol_size * N_symb_SRS], - c16_t srs_estimated_channel_time[NR_SRS_IDFT_OVERSAMP_FACTOR * ofdm_symbol_size], - 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, - c16_t delay_table[2 * MAX_DELAY_COMP + 1][NR_MAX_OFDM_SYMBOL_SIZE]) +int nr_srs_ls_channel_estimation(int ant, + int p_index, + uint16_t ofdm_symbol_size, + uint16_t first_carrier_offset, + uint8_t N_symb_SRS, + const nfapi_nr_srs_pdu_t *srs_pdu, + const nr_srs_info_t *nr_srs_info, + const c16_t *srs_generated_signal, + c16_t srs_received_signal[ofdm_symbol_size * N_symb_SRS], + c16_t srs_ls_estimated_channel[ofdm_symbol_size * N_symb_SRS], + delay_t *delay) { #ifdef SRS_DEBUG LOG_I(NR_PHY, "Calling %s function\n", __FUNCTION__); #endif const uint64_t subcarrier_offset = first_carrier_offset + srs_pdu->bwp_start * NR_NB_SC_PER_RB; - const uint64_t first_subcarrier = (first_carrier_offset - (ofdm_symbol_size >> 1)) + srs_pdu->bwp_start * NR_NB_SC_PER_RB; const uint8_t N_ap = 1 << srs_pdu->num_ant_ports; const uint8_t K_TC = 2 << srs_pdu->comb_size; @@ -799,11 +792,7 @@ int nr_srs_channel_estimation(int ant, fd_cdm = 2; } - 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; @@ -813,12 +802,7 @@ int nr_srs_channel_estimation(int ant, LOG_I(NR_PHY, "============================== SRS symbol index %d ===========================\n", srs_symb); #endif - // 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 = CIRCULAR_INC(subcarrier_offset + nr_srs_info->k_0_p[p_index][srs_symb], 0, ofdm_symbol_size); c16_t ls_estimated = {0}; for (int k = 0; k < M_sc_b_SRS; k++) { @@ -835,10 +819,7 @@ int nr_srs_channel_estimation(int ant, ls_estimated = c16maddConjShift(generated_srs, received_srs, ls_estimated, nr_srs_info->srs_generated_signal_bits); // Subcarrier increment - subcarrier_cdm += K_TC; - if (subcarrier_cdm >= ofdm_symbol_size) { - subcarrier_cdm = subcarrier_cdm - ofdm_symbol_size; - } + subcarrier_cdm = CIRCULAR_INC(subcarrier_cdm, K_TC, ofdm_symbol_size); } } @@ -867,17 +848,116 @@ int nr_srs_channel_estimation(int ant, #endif // Subcarrier increment - subcarrier += K_TC; - if (subcarrier >= ofdm_symbol_size) { - subcarrier -= ofdm_symbol_size; - } + subcarrier = CIRCULAR_INC(subcarrier, K_TC, 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); + if (srs_symb == 0) { + 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); + } + } // for (int srs_symb = 0; srs_symb < N_symb_SRS; srs_symb++) - // Interpolation of LS estimates + return 0; +} + +void nr_srs_noise_power_estimation(uint16_t ofdm_symbol_size, + uint16_t first_carrier_offset, + uint8_t N_symb_SRS, + const nfapi_nr_srs_pdu_t *srs_pdu, + const nr_srs_info_t *nr_srs_info, + uint32_t signal_power, + const c16_t srs_received_noise[ofdm_symbol_size * N_symb_SRS], + uint32_t *noise_power, + int16_t *noise_power_per_rb) +{ + const uint64_t subcarrier_offset = first_carrier_offset + srs_pdu->bwp_start * NR_NB_SC_PER_RB; + const uint16_t m_SRS_b = get_m_srs(srs_pdu->config_index, srs_pdu->bandwidth_index); + int tot_subcarriers = m_SRS_b * NR_NB_SC_PER_RB; + + uint16_t subcarrier = CIRCULAR_INC(subcarrier_offset + nr_srs_info->k_0_p[0][0], 0, ofdm_symbol_size); + + if (subcarrier + tot_subcarriers < ofdm_symbol_size) { + *noise_power = signal_energy_nodc(&srs_received_noise[subcarrier], tot_subcarriers) / tot_subcarriers; + } else { + int size1 = ofdm_symbol_size - subcarrier; + int size2 = tot_subcarriers - size1; + uint64_t noise_power_p1 = signal_energy_nodc(&srs_received_noise[subcarrier], size1) * size1; + uint64_t noise_power_p2 = signal_energy_nodc(&srs_received_noise[0], size2) * size2; + *noise_power = (noise_power_p1 + noise_power_p2) / tot_subcarriers; + } + + // Compute SNR per RB on symbol 0 + subcarrier = CIRCULAR_INC(subcarrier_offset + nr_srs_info->k_0_p[0][0], 0, ofdm_symbol_size); + for (int rb = 0; rb < m_SRS_b; rb++) { + if (subcarrier + NR_NB_SC_PER_RB < ofdm_symbol_size) { + noise_power_per_rb[rb] += signal_energy_nodc(&srs_received_noise[subcarrier], NR_NB_SC_PER_RB); + } else { + int size1 = ofdm_symbol_size - subcarrier; + int size2 = NR_NB_SC_PER_RB - size1; + uint32_t noise_power_per_rb1 = signal_energy_nodc(&srs_received_noise[subcarrier], size1) * size1; + uint32_t noise_power_per_rb2 = signal_energy_nodc(&srs_received_noise[0], size2) * size2; + noise_power_per_rb[rb] += (noise_power_per_rb1 + noise_power_per_rb2) / NR_NB_SC_PER_RB; + } + noise_power_per_rb[rb] = max(noise_power_per_rb[rb], 1); + subcarrier = CIRCULAR_INC(subcarrier, NR_NB_SC_PER_RB, ofdm_symbol_size); + +#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[rb], + dB_fixed(signal_power) - dB_fixed(noise_power_per_rb[rb])); +#endif + } + +#ifdef SRS_DEBUG + 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 +} + +int nr_srs_channel_interpolation(int ant, + int p_index, + uint16_t ofdm_symbol_size, + uint16_t first_carrier_offset, + uint8_t N_symb_SRS, + const nfapi_nr_srs_pdu_t *srs_pdu, + const nr_srs_info_t *nr_srs_info, + const c16_t srs_ls_estimated_channel[ofdm_symbol_size * N_symb_SRS], + int est_delay, + c16_t srs_received_noise[ofdm_symbol_size * N_symb_SRS], + c16_t srs_estimated_channel_freq[ofdm_symbol_size * N_symb_SRS], + c16_t srs_estimated_channel_time[NR_SRS_IDFT_OVERSAMP_FACTOR * ofdm_symbol_size], + c16_t srs_estimated_channel_time_shifted[NR_SRS_IDFT_OVERSAMP_FACTOR * ofdm_symbol_size], + uint32_t *signal_power, + 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__); +#endif + + const uint64_t subcarrier_offset = first_carrier_offset + srs_pdu->bwp_start * NR_NB_SC_PER_RB; + const uint64_t first_subcarrier = (first_carrier_offset - (ofdm_symbol_size >> 1)) + srs_pdu->bwp_start * NR_NB_SC_PER_RB; + const uint8_t K_TC = 2 << srs_pdu->comb_size; + const uint16_t m_SRS_b = get_m_srs(srs_pdu->config_index, srs_pdu->bandwidth_index); + const uint16_t M_sc_b_SRS = m_SRS_b * NR_NB_SC_PER_RB / K_TC; + + c16_t srs_estimated_channel_freq_avg[ofdm_symbol_size]; + 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; + +#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 // Additional 4 in the array size is needed to maintain 16 byte memory alignment required for AVX2 instructions in channel // interpolation @@ -891,18 +971,15 @@ int nr_srs_channel_estimation(int ant, 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; - } + uint16_t subcarrier = CIRCULAR_INC(subcarrier_offset + nr_srs_info->k_0_p[p_index][srs_symb], 0, ofdm_symbol_size); - int delay_idx = get_delay_idx(delay.est_delay, MAX_DELAY_COMP); + int delay_idx = get_delay_idx(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); + c16_t ls_estimated = c16mulShift(srs_ls_estimated_channel[srs_symbol_offset + subcarrier], srs_delay_table[subcarrier], 8); // Channel interpolation if (srs_pdu->comb_size == 0) { @@ -935,34 +1012,21 @@ int nr_srs_channel_estimation(int ant, } // Subcarrier increment - subcarrier += K_TC; - if (subcarrier >= ofdm_symbol_size) { - subcarrier -= ofdm_symbol_size; - } - + subcarrier = CIRCULAR_INC(subcarrier, K_TC, ofdm_symbol_size); subcarrier_abs += K_TC; - } // 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); + int inv_delay_idx = get_delay_idx(-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; - } + subcarrier_abs = mem_offset + first_subcarrier + nr_srs_info->k_0_p[p_index][srs_symb]; + subcarrier = CIRCULAR_INC(subcarrier_offset + nr_srs_info->k_0_p[p_index][0], 0, 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 = CIRCULAR_INC(subcarrier, 1, 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)); @@ -975,11 +1039,7 @@ int nr_srs_channel_estimation(int ant, ofdm_symbol_size); #ifdef SRS_DEBUG - subcarrier = subcarrier_offset + nr_srs_info->k_0_p[p_index][srs_symb]; - if (subcarrier >= ofdm_symbol_size) { - subcarrier -= ofdm_symbol_size; - } - + subcarrier = CIRCULAR_INC(subcarrier_offset + nr_srs_info->k_0_p[p_index][srs_symb], 0, ofdm_symbol_size); subcarrier_abs = first_subcarrier + nr_srs_info->k_0_p[p_index][srs_symb]; for (int k = 0; k < K_TC * M_sc_b_SRS; k++) { @@ -1007,10 +1067,7 @@ int nr_srs_channel_estimation(int ant, srs_received_noise[srs_symbol_offset + subcarrier].i); // Subcarrier increment - subcarrier++; - if (subcarrier >= ofdm_symbol_size) { - subcarrier -= ofdm_symbol_size; - } + subcarrier = CIRCULAR_INC(subcarrier, 1, ofdm_symbol_size); subcarrier_abs++; } #endif @@ -1047,61 +1104,5 @@ int nr_srs_channel_estimation(int ant, return -1; } - uint16_t subcarrier = subcarrier_offset + nr_srs_info->k_0_p[p_index][0]; - if (subcarrier >= ofdm_symbol_size) { - subcarrier -= ofdm_symbol_size; - } - - if (p_index == 0) { - if (subcarrier + tot_subcarriers < ofdm_symbol_size) { - *noise_power = signal_energy_nodc(&srs_received_noise[subcarrier], tot_subcarriers) / tot_subcarriers; - } else { - int size1 = ofdm_symbol_size - subcarrier; - int size2 = tot_subcarriers - size1; - uint64_t noise_power_p1 = signal_energy_nodc(&srs_received_noise[subcarrier], size1) * size1; - uint64_t noise_power_p2 = signal_energy_nodc(&srs_received_noise[0], size2) * size2; - *noise_power = (noise_power_p1 + noise_power_p2) / tot_subcarriers; - } - } - - // Compute SNR per RB for port 0 and symbol 0 - if (p_index == 0) { - subcarrier = subcarrier_offset + nr_srs_info->k_0_p[p_index][0]; - for (int rb = 0; rb < m_SRS_b; rb++) { - if (subcarrier >= ofdm_symbol_size) { - subcarrier -= ofdm_symbol_size; - } - if (subcarrier + NR_NB_SC_PER_RB < ofdm_symbol_size) { - noise_power_per_rb[rb] += signal_energy_nodc(&srs_received_noise[subcarrier], NR_NB_SC_PER_RB); - } else { - int size1 = ofdm_symbol_size - subcarrier; - int size2 = NR_NB_SC_PER_RB - size1; - uint32_t noise_power_per_rb1 = signal_energy_nodc(&srs_received_noise[subcarrier], size1) * size1; - uint32_t noise_power_per_rb2 = signal_energy_nodc(&srs_received_noise[0], size2) * size2; - noise_power_per_rb[rb] += (noise_power_per_rb1 + noise_power_per_rb2) / NR_NB_SC_PER_RB; - } - noise_power_per_rb[rb] = max(noise_power_per_rb[rb], 1); - subcarrier += NR_NB_SC_PER_RB; - -#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[rb], - dB_fixed(*signal_power) - dB_fixed(noise_power_per_rb[rb])); -#endif - } - } - -#ifdef SRS_DEBUG - 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 - return 0; } diff --git a/openair1/PHY/NR_ESTIMATION/nr_ul_estimation.h b/openair1/PHY/NR_ESTIMATION/nr_ul_estimation.h index 4530493d53..533c755241 100644 --- a/openair1/PHY/NR_ESTIMATION/nr_ul_estimation.h +++ b/openair1/PHY/NR_ESTIMATION/nr_ul_estimation.h @@ -75,23 +75,43 @@ void nr_pusch_ptrs_processing(PHY_VARS_gNB *gNB, unsigned char symbol, uint32_t nb_re_pusch); -int nr_srs_channel_estimation(int ant, - int p_index, - uint16_t ofdm_symbol_size, - uint16_t first_carrier_offset, - uint8_t N_symb_SRS, - const nfapi_nr_srs_pdu_t *srs_pdu, - const nr_srs_info_t *nr_srs_info, - const c16_t *srs_generated_signal, - c16_t srs_received_signal[ofdm_symbol_size * N_symb_SRS], - c16_t srs_received_noise[ofdm_symbol_size * N_symb_SRS], - c16_t srs_estimated_channel_freq[ofdm_symbol_size * N_symb_SRS], - c16_t srs_estimated_channel_time[NR_SRS_IDFT_OVERSAMP_FACTOR * ofdm_symbol_size], - 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, - c16_t delay_table[2 * MAX_DELAY_COMP + 1][NR_MAX_OFDM_SYMBOL_SIZE]); +int nr_srs_ls_channel_estimation(int ant, + int p_index, + uint16_t ofdm_symbol_size, + uint16_t first_carrier_offset, + uint8_t N_symb_SRS, + const nfapi_nr_srs_pdu_t *srs_pdu, + const nr_srs_info_t *nr_srs_info, + const c16_t *srs_generated_signal, + c16_t srs_received_signal[ofdm_symbol_size * N_symb_SRS], + c16_t srs_ls_estimated_channel[ofdm_symbol_size * N_symb_SRS], + delay_t *delay); + +int nr_srs_channel_interpolation(int ant, + int p_index, + uint16_t ofdm_symbol_size, + uint16_t first_carrier_offset, + uint8_t N_symb_SRS, + const nfapi_nr_srs_pdu_t *srs_pdu, + const nr_srs_info_t *nr_srs_info, + const c16_t srs_ls_estimated_channel[ofdm_symbol_size * N_symb_SRS], + int est_delay, + c16_t srs_received_noise[ofdm_symbol_size * N_symb_SRS], + c16_t srs_estimated_channel_freq[ofdm_symbol_size * N_symb_SRS], + c16_t srs_estimated_channel_time[NR_SRS_IDFT_OVERSAMP_FACTOR * ofdm_symbol_size], + c16_t srs_estimated_channel_time_shifted[NR_SRS_IDFT_OVERSAMP_FACTOR * ofdm_symbol_size], + uint32_t *signal_power, + c16_t delay_table[2 * MAX_DELAY_COMP + 1][NR_MAX_OFDM_SYMBOL_SIZE]); + +void nr_srs_noise_power_estimation(uint16_t ofdm_symbol_size, + uint16_t first_carrier_offset, + uint8_t N_symb_SRS, + const nfapi_nr_srs_pdu_t *srs_pdu, + const nr_srs_info_t *nr_srs_info, + uint32_t signal_power, + const c16_t srs_received_noise[ofdm_symbol_size * N_symb_SRS], + uint32_t *noise_power, + int16_t *noise_power_per_rb); void nr_freq_equalization(NR_DL_FRAME_PARMS *frame_parms, c16_t *rxdataF_comp, diff --git a/openair1/SCHED_NR/phy_procedures_nr_gNB.c b/openair1/SCHED_NR/phy_procedures_nr_gNB.c index 4dea08ea0f..b6b29f20d3 100644 --- a/openair1/SCHED_NR/phy_procedures_nr_gNB.c +++ b/openair1/SCHED_NR/phy_procedures_nr_gNB.c @@ -880,33 +880,49 @@ void nr_srs_rx_procedures(PHY_VARS_gNB *gNB, stop_meas(&gNB->get_srs_signal_stats); uint32_t signal_power_avg = 0; - uint32_t noise_power_avg = 0; - int16_t noise_power_per_rb[srs_pdu->bwp_size]; - memset(noise_power_per_rb, 0, srs_pdu->bwp_size * sizeof(int16_t)); + c16_t srs_ls_estimated_channel[nb_antennas_rx][N_ap][ofdm_symbol_size * N_symb_SRS]; if (*srs_est >= 0) { start_meas(&gNB->srs_channel_estimation_stats); + + delay_t delay = {0}; + for (int ant_rx_ind = 0; ant_rx_ind < nb_antennas_rx; ant_rx_ind++) { + for (int p_ind = 0; p_ind < N_ap; p_ind++) { + delay_t delay_aux = {0}; + nr_srs_ls_channel_estimation(ant_rx_ind, + p_ind, + ofdm_symbol_size, + frame_parms->first_carrier_offset, + N_symb_SRS, + srs_pdu, + nr_srs_info, + nr_srs_info->srs_generated_signal[p_ind], + srs_received_signal[ant_rx_ind], + srs_ls_estimated_channel[ant_rx_ind][p_ind], + &delay_aux); + if (delay_aux.delay_max_val > delay.delay_max_val) + delay = delay_aux; + } + } + for (int ant_rx_ind = 0; ant_rx_ind < nb_antennas_rx; ant_rx_ind++) { - uint32_t noise_power = 0; for (int p_ind = 0; p_ind < N_ap; p_ind++) { uint32_t signal_power = 0; - nr_srs_channel_estimation(ant_rx_ind, - p_ind, - ofdm_symbol_size, - frame_parms->first_carrier_offset, - N_symb_SRS, - srs_pdu, - nr_srs_info, - nr_srs_info->srs_generated_signal[p_ind], - srs_received_signal[ant_rx_ind], - srs_received_noise[ant_rx_ind], - srs_estimated_channel_freq[ant_rx_ind][p_ind], - srs_estimated_channel_time[ant_rx_ind][p_ind], - srs_estimated_channel_time_shifted[ant_rx_ind][p_ind], - &signal_power, - &noise_power, - noise_power_per_rb, - frame_parms->delay_table); + nr_srs_channel_interpolation(ant_rx_ind, + p_ind, + ofdm_symbol_size, + frame_parms->first_carrier_offset, + N_symb_SRS, + srs_pdu, + nr_srs_info, + srs_ls_estimated_channel[ant_rx_ind][p_ind], + delay.est_delay, + srs_received_noise[ant_rx_ind], + srs_estimated_channel_freq[ant_rx_ind][p_ind], + srs_estimated_channel_time[ant_rx_ind][p_ind], + srs_estimated_channel_time_shifted[ant_rx_ind][p_ind], + &signal_power, + frame_parms->delay_table); signal_power_avg += signal_power; @@ -914,7 +930,7 @@ void nr_srs_rx_procedures(PHY_VARS_gNB *gNB, T_INT(gNB->Mod_id), T_INT(srs_pdu->rnti), T_INT(frame_rx), - T_INT(slot_rx), + T_INT(0), T_INT(ant_rx_ind), T_INT(p_ind), T_BUFFER(srs_estimated_channel_freq[ant_rx_ind][p_ind], N_symb_SRS * ofdm_symbol_size * sizeof(c16_t))); @@ -923,17 +939,35 @@ void nr_srs_rx_procedures(PHY_VARS_gNB *gNB, T_INT(gNB->Mod_id), T_INT(srs_pdu->rnti), T_INT(frame_rx), - T_INT(slot_rx), + T_INT(0), T_INT(ant_rx_ind), T_INT(p_ind), T_BUFFER(srs_estimated_channel_time_shifted[ant_rx_ind][p_ind], NR_SRS_IDFT_OVERSAMP_FACTOR * ofdm_symbol_size * sizeof(c16_t))); } - noise_power_avg += noise_power; } + signal_power_avg /= (nb_antennas_rx * N_ap); - noise_power_avg /= nb_antennas_rx; signal_power_avg = max(signal_power_avg, 1); + + uint32_t noise_power_avg = 0; + int16_t noise_power_per_rb[srs_pdu->bwp_size]; + memset(noise_power_per_rb, 0, srs_pdu->bwp_size * sizeof(int16_t)); + for (int ant_rx_ind = 0; ant_rx_ind < nb_antennas_rx; ant_rx_ind++) { + uint32_t noise_power_per_ant = 0; + nr_srs_noise_power_estimation(ofdm_symbol_size, + frame_parms->first_carrier_offset, + N_symb_SRS, + srs_pdu, + nr_srs_info, + signal_power_avg, + srs_received_noise[ant_rx_ind], + &noise_power_per_ant, + noise_power_per_rb); + noise_power_avg += noise_power_per_ant; + } + + noise_power_avg /= nb_antennas_rx; gNB->srs->snr = dB_fixed(signal_power_avg) - dB_fixed(max(noise_power_avg, 1)); const uint16_t m_SRS_b = get_m_srs(srs_pdu->config_index, srs_pdu->bandwidth_index);