SRS-based noise calculation using holes

This commit is contained in:
rmagueta
2025-10-02 11:43:07 +01:00
parent 55a56002de
commit 799934024e
8 changed files with 124 additions and 126 deletions
@@ -777,6 +777,7 @@ int nr_srs_channel_estimation(
const nr_srs_info_t *nr_srs_info,
const c16_t **srs_generated_signal,
c16_t srs_received_signal[][gNB->frame_parms.ofdm_symbol_size * (1 << srs_pdu->num_symbols)],
c16_t srs_received_noise[][gNB->frame_parms.ofdm_symbol_size * (1 << srs_pdu->num_symbols)],
c16_t srs_estimated_channel_freq[][1 << srs_pdu->num_ant_ports]
[gNB->frame_parms.ofdm_symbol_size * (1 << srs_pdu->num_symbols)],
c16_t srs_estimated_channel_time[][1 << srs_pdu->num_ant_ports][gNB->frame_parms.ofdm_symbol_size],
@@ -801,16 +802,6 @@ int nr_srs_channel_estimation(
}
c16_t srs_ls_estimated_channel[frame_parms->ofdm_symbol_size * (1 << srs_pdu->num_symbols)];
uint32_t noise_power_per_rb[srs_pdu->bwp_size];
const uint32_t arr_len = frame_parms->nb_antennas_rx * N_ap * M_sc_b_SRS;
c16_t ch[arr_len];
memset(ch, 0, arr_len * sizeof(c16_t));
c16_t noise[arr_len];
memset(noise, 0, arr_len * sizeof(c16_t));
uint8_t mem_offset = ((16 - ((intptr_t)&srs_estimated_channel_freq[0][0][subcarrier_offset + nr_srs_info->k_0_p[0][0]])) & 0xF)
>> 2; // >> 2 <=> /sizeof(int32_t)
@@ -831,7 +822,7 @@ int nr_srs_channel_estimation(
#endif
uint16_t subcarrier = subcarrier_offset + nr_srs_info->k_0_p[p_index][0];
if (subcarrier > frame_parms->ofdm_symbol_size) {
if (subcarrier >= frame_parms->ofdm_symbol_size) {
subcarrier -= frame_parms->ofdm_symbol_size;
}
@@ -843,19 +834,12 @@ int nr_srs_channel_estimation(
uint16_t subcarrier_cdm = subcarrier;
for (int cdm_idx = 0; cdm_idx < fd_cdm; cdm_idx++) {
int16_t generated_real = srs_generated_signal[p_index][subcarrier_cdm].r;
int16_t generated_imag = srs_generated_signal[p_index][subcarrier_cdm].i;
int16_t received_real = srs_received_signal[ant][subcarrier_cdm].r;
int16_t received_imag = srs_received_signal[ant][subcarrier_cdm].i;
// We know that nr_srs_info->srs_generated_signal_bits bits are enough to represent the generated_real and
// generated_imag. So we only need a nr_srs_info->srs_generated_signal_bits shift to ensure that the result fits into 16
c16_t generated_srs = srs_generated_signal[p_index][subcarrier_cdm];
c16_t received_srs = srs_received_signal[ant][subcarrier_cdm];
// 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
// bits.
ls_estimated.r += (int16_t)(((int32_t)generated_real * received_real + (int32_t)generated_imag * received_imag)
>> nr_srs_info->srs_generated_signal_bits);
ls_estimated.i += (int16_t)(((int32_t)generated_real * received_imag - (int32_t)generated_imag * received_real)
>> nr_srs_info->srs_generated_signal_bits);
ls_estimated = c16maddConjShift(generated_srs, received_srs, ls_estimated, nr_srs_info->srs_generated_signal_bits);
// Subcarrier increment
subcarrier_cdm += K_TC;
@@ -934,7 +918,7 @@ int nr_srs_channel_estimation(
// Subcarrier increment
subcarrier += K_TC;
if (subcarrier >= frame_parms->ofdm_symbol_size) {
subcarrier = subcarrier - frame_parms->ofdm_symbol_size;
subcarrier -= frame_parms->ofdm_symbol_size;
}
} // for (int k = 0; k < M_sc_b_SRS; k++)
@@ -943,25 +927,9 @@ int nr_srs_channel_estimation(
&srs_est[mem_offset],
(frame_parms->ofdm_symbol_size * (1 << srs_pdu->num_symbols)) * sizeof(c16_t));
// Compute noise
subcarrier = subcarrier_offset + nr_srs_info->k_0_p[p_index][0];
if (subcarrier > frame_parms->ofdm_symbol_size) {
subcarrier -= frame_parms->ofdm_symbol_size;
}
uint16_t base_idx = ant * N_ap * M_sc_b_SRS + p_index * M_sc_b_SRS;
for (int k = 0; k < M_sc_b_SRS; k++) {
ch[base_idx + k] = srs_estimated_channel_freq[ant][p_index][subcarrier];
noise[base_idx + k].r = abs(srs_ls_estimated_channel[subcarrier].r - ch[base_idx + k].r);
noise[base_idx + k].i = abs(srs_ls_estimated_channel[subcarrier].i - ch[base_idx + k].i);
subcarrier += K_TC;
if (subcarrier >= frame_parms->ofdm_symbol_size) {
subcarrier = subcarrier - frame_parms->ofdm_symbol_size;
}
}
#ifdef SRS_DEBUG
subcarrier = subcarrier_offset + nr_srs_info->k_0_p[p_index][0];
if (subcarrier > frame_parms->ofdm_symbol_size) {
if (subcarrier >= frame_parms->ofdm_symbol_size) {
subcarrier -= frame_parms->ofdm_symbol_size;
}
@@ -983,13 +951,13 @@ int nr_srs_channel_estimation(
srs_ls_estimated_channel[subcarrier].i,
srs_estimated_channel_freq[ant][p_index][subcarrier].r,
srs_estimated_channel_freq[ant][p_index][subcarrier].i,
noise[base_idx + (k / K_TC)].r,
noise[base_idx + (k / K_TC)].i);
srs_received_noise[ant][subcarrier].r,
srs_received_noise[ant][subcarrier].i);
// Subcarrier increment
subcarrier++;
if (subcarrier >= frame_parms->ofdm_symbol_size) {
subcarrier = subcarrier - frame_parms->ofdm_symbol_size;
subcarrier -= frame_parms->ofdm_symbol_size;
}
}
#endif
@@ -1010,61 +978,71 @@ int nr_srs_channel_estimation(
} // for (int p_index = 0; p_index < N_ap; p_index++)
} // for (int ant = 0; ant < frame_parms->nb_antennas_rx; ant++)
// Compute signal power
uint32_t signal_power = max(signal_energy_nodc(ch, arr_len), 1);
#ifdef SRS_DEBUG
LOG_I(NR_PHY, "signal_power = %u\n", signal_power);
#endif
// Compute wideband SNR
int tot_subcarriers = m_SRS_b * NR_NB_SC_PER_RB;
uint32_t signal_power = 0;
uint32_t noise_power = 0;
for (int ant = 0; ant < frame_parms->nb_antennas_rx; ant++) {
for (int p_index = 0; p_index < N_ap; p_index++) {
uint16_t subcarrier0 = subcarrier_offset + nr_srs_info->k_0_p[p_index][0];
if (subcarrier0 >= frame_parms->ofdm_symbol_size) {
subcarrier0 -= frame_parms->ofdm_symbol_size;
}
if (subcarrier0 + tot_subcarriers < frame_parms->ofdm_symbol_size) {
signal_power += signal_energy_nodc(&srs_estimated_channel_freq[ant][p_index][subcarrier0], tot_subcarriers);
if (p_index == 0)
noise_power += signal_energy_nodc(&srs_received_noise[ant][subcarrier0], tot_subcarriers);
} else {
int size1 = frame_parms->ofdm_symbol_size - subcarrier0;
int size2 = tot_subcarriers - size1;
uint64_t signal_power_p1 = signal_energy_nodc(&srs_estimated_channel_freq[ant][p_index][subcarrier0], size1) * size1;
uint64_t signal_power_p2 = signal_energy_nodc(&srs_estimated_channel_freq[ant][p_index][0], size2) * size2;
signal_power += (signal_power_p1 + signal_power_p2) / tot_subcarriers;
if (p_index == 0) {
uint64_t noise_power_p1 = signal_energy_nodc(&srs_received_noise[ant][subcarrier0], size1) * size1;
uint64_t noise_power_p2 = signal_energy_nodc(&srs_received_noise[ant][0], size2) * size2;
noise_power += (noise_power_p1 + noise_power_p2) / tot_subcarriers;
}
}
}
}
signal_power = max(signal_power / (frame_parms->nb_antennas_rx * N_ap), 1);
noise_power = max(noise_power / (frame_parms->nb_antennas_rx), 1);
if (signal_power == 0) {
LOG_W(NR_PHY, "Received SRS signal power is 0\n");
return -1;
}
// Compute noise power
const uint8_t srs_symbols_per_rb = srs_pdu->comb_size == 0 ? 6 : 3;
const uint8_t n_noise_est = frame_parms->nb_antennas_rx * N_ap * srs_symbols_per_rb;
uint64_t sum_re = 0;
uint64_t sum_re2 = 0;
uint64_t sum_im = 0;
uint64_t sum_im2 = 0;
for (int rb = 0; rb < m_SRS_b; rb++) {
sum_re = 0;
sum_re2 = 0;
sum_im = 0;
sum_im2 = 0;
for (int ant = 0; ant < frame_parms->nb_antennas_rx; ant++) {
for (int p_index = 0; p_index < N_ap; p_index++) {
uint16_t base_idx = ant * N_ap * M_sc_b_SRS + p_index * M_sc_b_SRS + rb * srs_symbols_per_rb;
for (int srs_symb = 0; srs_symb < srs_symbols_per_rb; srs_symb++) {
sum_re = sum_re + noise[base_idx + srs_symb].r;
sum_re2 = sum_re2 + noise[base_idx + srs_symb].r * noise[base_idx + srs_symb].r;
sum_im = sum_im + noise[base_idx + srs_symb].i;
sum_im2 = sum_im2 + noise[base_idx + srs_symb].i * noise[base_idx + srs_symb].i;
} // for (int srs_symb = 0; srs_symb < srs_symbols_per_rb; srs_symb++)
} // for (int p_index = 0; p_index < N_ap; p_index++)
} // for (int ant = 0; ant < frame_parms->nb_antennas_rx; ant++)
noise_power_per_rb[rb] = max(sum_re2 / n_noise_est - (sum_re / n_noise_est) * (sum_re / n_noise_est) + sum_im2 / n_noise_est
- (sum_im / n_noise_est) * (sum_im / n_noise_est),
1);
snr_per_rb[rb] = dB_fixed(signal_power) - dB_fixed(noise_power_per_rb[rb]);
#ifdef SRS_DEBUG
LOG_I(NR_PHY, "noise_power_per_rb[%i] = %i, snr_per_rb[%i] = %i dB\n", rb, noise_power_per_rb[rb], rb, snr_per_rb[rb]);
#endif
} // for (int rb = 0; rb < m_SRS_b; rb++)
const uint32_t noise_power = max(signal_energy_nodc(noise, arr_len), 1);
*snr = dB_fixed(signal_power) - dB_fixed(noise_power);
// Compute SNR per RB
uint16_t subcarrier = subcarrier_offset + nr_srs_info->k_0_p[0][0];
for (int rb = 0; rb < m_SRS_b; rb++) {
if (subcarrier >= frame_parms->ofdm_symbol_size) {
subcarrier -= frame_parms->ofdm_symbol_size;
}
uint32_t noise_power_per_rb = 0;
for (int ant = 0; ant < frame_parms->nb_antennas_rx; ant++) {
if (subcarrier + NR_NB_SC_PER_RB < frame_parms->ofdm_symbol_size) {
noise_power_per_rb += signal_energy_nodc(&srs_received_noise[ant][subcarrier], NR_NB_SC_PER_RB);
} else {
int size1 = frame_parms->ofdm_symbol_size - subcarrier;
int size2 = NR_NB_SC_PER_RB - size1;
uint32_t noise_power_per_rb1 = signal_energy_nodc(&srs_received_noise[ant][subcarrier], size1) * size1;
uint32_t noise_power_per_rb2 = signal_energy_nodc(&srs_received_noise[ant][0], size2) * size2;
noise_power_per_rb += (noise_power_per_rb1 + noise_power_per_rb2) / NR_NB_SC_PER_RB;
}
}
noise_power_per_rb = max(noise_power_per_rb / (frame_parms->nb_antennas_rx), 1);
snr_per_rb[rb] = dB_fixed(signal_power) - dB_fixed(noise_power_per_rb);
subcarrier += NR_NB_SC_PER_RB;
#ifdef SRS_DEBUG
LOG_I(NR_PHY, "noise_power = %u, SNR = %i dB\n", noise_power, *snr);
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]);
#endif
}
#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);
#endif
return 0;
@@ -84,6 +84,7 @@ int nr_srs_channel_estimation(
const nr_srs_info_t *nr_srs_info,
const c16_t **srs_generated_signal,
c16_t srs_received_signal[][gNB->frame_parms.ofdm_symbol_size * (1 << srs_pdu->num_symbols)],
c16_t srs_received_noise[][gNB->frame_parms.ofdm_symbol_size * (1 << srs_pdu->num_symbols)],
c16_t srs_estimated_channel_freq[][1 << srs_pdu->num_ant_ports]
[gNB->frame_parms.ofdm_symbol_size * (1 << srs_pdu->num_symbols)],
c16_t srs_estimated_channel_time[][1 << srs_pdu->num_ant_ports][gNB->frame_parms.ofdm_symbol_size],