diff --git a/lib/include/srslte/phy/ch_estimation/wiener_dl.h b/lib/include/srslte/phy/ch_estimation/wiener_dl.h index fbae735bf..507812bb4 100644 --- a/lib/include/srslte/phy/ch_estimation/wiener_dl.h +++ b/lib/include/srslte/phy/ch_estimation/wiener_dl.h @@ -74,6 +74,8 @@ typedef struct { // Wiener matrices cf_t wm1[SRSLTE_WIENER_DL_MIN_RE][SRSLTE_WIENER_DL_MIN_REF]; cf_t wm2[SRSLTE_WIENER_DL_MIN_RE][SRSLTE_WIENER_DL_MIN_REF]; + bool wm_computed; + bool ready; // Calculation support cf_t hlsv[SRSLTE_WIENER_DL_MIN_RE]; diff --git a/lib/src/phy/ch_estimation/wiener_dl.c b/lib/src/phy/ch_estimation/wiener_dl.c index 78ae72bf4..2646e1951 100644 --- a/lib/src/phy/ch_estimation/wiener_dl.c +++ b/lib/src/phy/ch_estimation/wiener_dl.c @@ -36,53 +36,53 @@ #define SRSLTE_WIENER_LOCAL // Constants -const float hlsv_sum_norm[SRSLTE_WIENER_DL_MIN_RE] = {0.0625, - 0.0638297872326845, - 0.0652173913015123, - 0.0666666666622222, - 0.0681818181756198, - 0.0697674418523526, - 0.0714285714183674, - 0.0731707316948245, - 0.074999999985, - 0.0769230769053254, - 0.078947368400277, - 0.0810810810569759, - 0.0833333333055555, - 0.085714285682449, - 0.0882352940813149, - 0.0909090908677686, - 0.093749999953125, - 0.0967741934953174, - 0.09999999994, - 0.103448275794293, - 0.107142857066327, - 0.111111111024691, - 0.115384615286982, - 0.1199999998896, - 0.124999999875, - 0.130434782466919, - 0.136363636202479, - 0.142857142673469, - 0.14999999979, - 0.157894736601108, - 0.166666666388889, - 0.176470587913495, - 0.187499999625, - 0.19999999956, - 0.214285713765306, - 0.230769230147929, - 0.24999999925, - 0.272727271809917, - 0.29999999886, - 0.333333331888889, - 0.374999998125, - 0.428571426061225, - 0.4999999965, - 0.59999999484, - 0.74999999175, - 0.999999985, - 1.4999999655, +const float hlsv_sum_norm[SRSLTE_WIENER_DL_MIN_RE] = {0.0625f, + 0.0638297872326845f, + 0.0652173913015123f, + 0.0666666666622222f, + 0.0681818181756198f, + 0.0697674418523526f, + 0.0714285714183674f, + 0.0731707316948245f, + 0.074999999985f, + 0.0769230769053254f, + 0.078947368400277f, + 0.0810810810569759f, + 0.0833333333055555f, + 0.085714285682449f, + 0.0882352940813149f, + 0.0909090908677686f, + 0.093749999953125f, + 0.0967741934953174f, + 0.09999999994f, + 0.103448275794293f, + 0.107142857066327f, + 0.111111111024691f, + 0.115384615286982f, + 0.1199999998896f, + 0.124999999875f, + 0.130434782466919f, + 0.136363636202479f, + 0.142857142673469f, + 0.14999999979f, + 0.157894736601108f, + 0.166666666388889f, + 0.176470587913495f, + 0.187499999625f, + 0.19999999956f, + 0.214285713765306f, + 0.230769230147929f, + 0.24999999925f, + 0.272727271809917f, + 0.29999999886f, + 0.333333331888889f, + 0.374999998125f, + 0.428571426061225f, + 0.4999999965f, + 0.59999999484f, + 0.74999999175f, + 0.999999985f, + 1.4999999655f, 2.99999985900001}; // Local state function prototypes @@ -156,7 +156,7 @@ SRSLTE_WIENER_LOCAL srslte_wiener_dl_state_t* srslte_wiener_dl_state_malloc(srsl } for (uint32_t i = 0; i < SRSLTE_WIENER_DL_CXFIFO_SIZE && !ret; i++) { - state->cxfifo[i] = srslte_vec_malloc(NSAMPLES2NBYTES(SRSLTE_WIENER_DL_MIN_RE)); + state->cxfifo[i] = srslte_vec_malloc(NSAMPLES2NBYTES(SRSLTE_WIENER_DL_TIMEFIFO_SIZE)); if (!state->cxfifo[i]) { perror("malloc"); ret = SRSLTE_ERROR; @@ -201,7 +201,7 @@ SRSLTE_WIENER_LOCAL void srslte_wiener_dl_state_reset(srslte_wiener_dl_t* q, srs bzero(state->timefifo, NSAMPLES2NBYTES(SRSLTE_WIENER_DL_TIMEFIFO_SIZE)); for (uint32_t i = 0; i < SRSLTE_WIENER_DL_CXFIFO_SIZE; i++) { - bzero(state->cxfifo[i], NSAMPLES2NBYTES(SRSLTE_WIENER_DL_TFIFO_SIZE)); + bzero(state->cxfifo[i], NSAMPLES2NBYTES(SRSLTE_WIENER_DL_TIMEFIFO_SIZE)); } // Initialise counters and variables @@ -457,8 +457,8 @@ SRSLTE_WIENER_LOCAL uint32_t vec_find_first_smaller_than_cf(cf_t* x, float y, ui uint32_t ret = n; for (uint32_t i = pos; i < n && ret == n; i++) { - if (cabsf(x[i]) > y) { - ret = i; + if (cabsf(x[i]) <= y) { + ret = i - pos + 1; } } @@ -523,12 +523,11 @@ static void estimate_wiener(srslte_wiener_dl_t* q, // Estimate center Resource elements if (q->nof_re > 2 * SRSLTE_WIENER_DL_MIN_RE) { - for (uint32_t prb = SRSLTE_WIENER_DL_MIN_PRB / 2; prb < q->nof_prb - SRSLTE_WIENER_DL_MIN_REF / 2; - prb += SRSLTE_WIENER_DL_MIN_PRB / 2) { - uint32_t ref_idx = prb * 2 - SRSLTE_WIENER_DL_MIN_REF / 2; - uint32_t re_idx = prb * SRSLTE_NRE; - for (uint32_t i = SRSLTE_WIENER_DL_MIN_RE / 4; i < (3 * SRSLTE_WIENER_DL_MIN_RE) / 4; i++) { - h[re_idx + i] = _srslte_vec_dot_prod_ccc_simd(&ref[ref_idx], wm[i], SRSLTE_WIENER_DL_MIN_REF); + for (uint32_t prb = 2; prb < q->nof_prb - 2; prb += 2) { + p_offset = (prb - 1) * 2; + r_offset = prb * SRSLTE_NRE; + for (uint32_t i = 0; i < SRSLTE_NRE * 2; i++) { + h[r_offset + i] = _srslte_vec_dot_prod_ccc_simd(&ref[p_offset], wm[i + SRSLTE_NRE], SRSLTE_WIENER_DL_MIN_REF); } } } @@ -555,7 +554,7 @@ srslte_wiener_dl_run_symbol_1_8(srslte_wiener_dl_t* q, srslte_wiener_dl_state_t* srslte_vec_sc_prod_cfc(q->tmp, 1.0f / SRSLTE_WIENER_DL_CXFIFO_SIZE, q->tmp, SRSLTE_WIENER_DL_TIMEFIFO_SIZE); // Find index of half amplitude - uint32_t halfcx = vec_find_first_smaller_than_cf(q->tmp, cabsf(q->tmp[1]) * 0.5f, SRSLTE_WIENER_DL_TFIFO_SIZE, 2); + uint32_t halfcx = vec_find_first_smaller_than_cf(q->tmp, cabsf(q->tmp[1]) * 0.5f, SRSLTE_WIENER_DL_TIMEFIFO_SIZE, 2); // Update internal states state->sumlen = SRSLTE_MAX(1, floorf(halfcx / 8.0f * SRSLTE_MIN(2.0f, 1.0f + 1.0f / snr_lin))); @@ -621,7 +620,7 @@ SRSLTE_WIENER_LOCAL void srslte_wiener_dl_run_symbol_5_12(srslte_wiener_dl_t* } else if (nsbb >= (q->nof_prb / 2) - 1) { pstart = q->nof_ref - SRSLTE_WIENER_DL_MIN_REF; } else { - pstart = (SRSLTE_WIENER_DL_MIN_REF / 2) * nsbb - 1; + pstart = (SRSLTE_WIENER_DL_MIN_REF / 2) * nsbb - 2; } bzero(q->hlsv, NSAMPLES2NBYTES(SRSLTE_WIENER_DL_MIN_RE)); @@ -693,7 +692,12 @@ SRSLTE_WIENER_LOCAL void srslte_wiener_dl_run_symbol_5_12(srslte_wiener_dl_t* } // Add noise contribution to the square wiener - float N = (__real__ q->acV[0] / SRSLTE_MIN(15, snr_lin * state->sumlen)); + float N = 0.0f; + + if (isnormal(__real__ q->acV[0]) && isnormal(snr_lin) && state->sumlen > 0) { + N = (__real__ q->acV[0] / SRSLTE_MIN(15, snr_lin * state->sumlen)); + } + for (uint32_t i = 0; i < SRSLTE_WIENER_DL_MIN_REF; i++) { q->RH.m[i][i] += N; } @@ -724,20 +728,14 @@ SRSLTE_WIENER_LOCAL void srslte_wiener_dl_run_symbol_5_12(srslte_wiener_dl_t* // Compute Wiener matrices for (uint32_t dim1 = 0; dim1 < SRSLTE_WIENER_DL_MIN_RE; dim1++) { for (uint32_t dim2 = 0; dim2 < SRSLTE_WIENER_DL_MIN_REF; dim2++) { - -#if 0 q->wm2[dim1][dim2] = 0; for (int i = 0; i < SRSLTE_WIENER_DL_MIN_REF; i++) { - q->wm2[dim1][dim2] += q->hH2[dim1][i] * q->invRH.m[dim2][i]; + q->wm2[dim1][dim2] += q->hH2[dim1][i] * q->invRH.m[i][dim2]; } q->wm1[dim1][dim2] = 0; for (int i = 0; i < SRSLTE_WIENER_DL_MIN_REF; i++) { - q->wm1[dim1][dim2] += q->hH1[dim1][i] * q->invRH.m[dim2][i]; + q->wm1[dim1][dim2] += q->hH1[dim1][i] * q->invRH.m[i][dim2]; } -#else - q->wm1[dim1][dim2] = srslte_vec_dot_prod_ccc(q->hH1[dim1], q->invRH.m[dim2], SRSLTE_WIENER_DL_MIN_REF); - q->wm2[dim1][dim2] = srslte_vec_dot_prod_ccc(q->hH2[dim1], q->invRH.m[dim2], SRSLTE_WIENER_DL_MIN_REF); -#endif } } q->wm_computed = true;