diff --git a/lib/src/phy/ch_estimation/chest_dl.c b/lib/src/phy/ch_estimation/chest_dl.c index 92ee5f92e..7bfa06c76 100644 --- a/lib/src/phy/ch_estimation/chest_dl.c +++ b/lib/src/phy/ch_estimation/chest_dl.c @@ -323,15 +323,18 @@ static float estimate_noise_pilots(srsran_chest_dl_t* q, srsran_dl_sf_cfg_t* sf, : srsran_refsignal_cs_nof_re(&q->csr_refs, sf, port_id); uint32_t nsymbols = (ch_mode == SRSRAN_SF_MBSFN) ? srsran_refsignal_mbsfn_nof_symbols() : srsran_refsignal_cs_nof_symbols(&q->csr_refs, sf, port_id); + if (nsymbols == 0) { + ERROR("Invalid number of CRS symbols\n"); + return SRSRAN_ERROR; + } + uint32_t nref = npilots / nsymbols; uint32_t fidx = (ch_mode == SRSRAN_SF_MBSFN) ? srsran_refsignal_mbsfn_fidx(1) : srsran_refsignal_cs_fidx(q->cell, 0, port_id, 0); - - cf_t* input2d[nsymbols + 2]; cf_t* tmp_noise = q->tmp_noise; - // Special case for 1 symbol - if (nsymbols == 1) { + // Special case for 1 or 2 symbol + if (nsymbols < 3) { srsran_vec_sc_prod_cfc(q->pilot_estimates + 1, weight, tmp_noise, nref - 2); srsran_vec_sum_ccc(q->pilot_estimates + 0, tmp_noise, tmp_noise, nref - 2); srsran_vec_sum_ccc(q->pilot_estimates + 2, tmp_noise, tmp_noise, nref - 2); @@ -341,30 +344,21 @@ static float estimate_noise_pilots(srsran_chest_dl_t* q, srsran_dl_sf_cfg_t* sf, return sum_power; } + // Convert pilots to 2D to ease access + cf_t* input2d[4]; // The maximum number of symbols is 4 for (int i = 0; i < nsymbols; i++) { - input2d[i + 1] = &q->pilot_estimates[i * nref]; + input2d[i] = &q->pilot_estimates[i * nref]; } - input2d[0] = &q->tmp_noise[nref]; - if (nsymbols > 3) { - srsran_vec_sc_prod_cfc(input2d[2], 2.0f, input2d[0], nref); - srsran_vec_sub_ccc(input2d[0], input2d[4], input2d[0], nref); - } else { - srsran_vec_sc_prod_cfc(input2d[2], 1.0f, input2d[0], nref); - } - - input2d[nsymbols + 1] = &q->tmp_noise[nref * 2]; - if (nsymbols > 3) { - srsran_vec_sc_prod_cfc(input2d[nsymbols - 1], 2.0f, input2d[nsymbols + 1], nref); - srsran_vec_sub_ccc(input2d[nsymbols + 1], input2d[nsymbols - 3], input2d[nsymbols + 1], nref); - } else { - srsran_vec_sc_prod_cfc(input2d[nsymbols - 1], 1.0f, input2d[nsymbols + 1], nref); - } - - for (int i = 1; i < nsymbols + 1; i++) { + // Compares surrounding pilots in time/frequency. It requires at least 3 symbols with pilots. + for (int i = 1; i < nsymbols - 1; i++) { + // Calculate previous and next symbol indexes offset uint32_t offset = ((fidx < 3) ^ (i & 1)) ? 0 : 1; + + // Write estimates from this symbols srsran_vec_sc_prod_cfc(input2d[i], weight, tmp_noise, nref); + // Add the previous symbol estimates and extrapolate first/last element srsran_vec_sum_ccc(&input2d[i - 1][0], &tmp_noise[offset], &tmp_noise[offset], nref - offset); srsran_vec_sum_ccc(&input2d[i - 1][1 - offset], &tmp_noise[0], &tmp_noise[0], nref + offset - 1); if (offset) { @@ -373,6 +367,7 @@ static float estimate_noise_pilots(srsran_chest_dl_t* q, srsran_dl_sf_cfg_t* sf, tmp_noise[nref - 1] += 2.0f * input2d[i - 1][nref - 2] - input2d[i - 1][nref - 1]; } + // Add the next symbol estimates and extrapolate first/last element srsran_vec_sum_ccc(&input2d[i + 1][0], &tmp_noise[offset], &tmp_noise[offset], nref - offset); srsran_vec_sum_ccc(&input2d[i + 1][1 - offset], &tmp_noise[0], &tmp_noise[0], nref + offset - 1); if (offset) { @@ -381,14 +376,18 @@ static float estimate_noise_pilots(srsran_chest_dl_t* q, srsran_dl_sf_cfg_t* sf, tmp_noise[nref - 1] += 2.0f * input2d[i + 1][nref - 2] - input2d[i + 1][nref - 1]; } + // Scale to normalise to this symbol srsran_vec_sc_prod_cfc(tmp_noise, 1.0f / (weight + 4.0f), tmp_noise, nref); + // Subtract this symbol srsran_vec_sub_ccc(input2d[i], tmp_noise, tmp_noise, nref); - sum_power = srsran_vec_avg_power_cf(tmp_noise, nref); + + // The left signal after the subtraction can be considered noise + sum_power += srsran_vec_avg_power_cf(tmp_noise, nref); count++; } - return sum_power / (float)count * sqrtf(weight + 4.0f); + return sum_power / (float)count; } static float estimate_noise_pss(srsran_chest_dl_t* q, cf_t* input, cf_t* ce)