From 9a7357cc945ecb7165a2178f91d34b883fef0937 Mon Sep 17 00:00:00 2001 From: Andre Puschmann Date: Mon, 9 Apr 2018 17:19:21 +0200 Subject: [PATCH 1/4] bump version to 18.03.1 --- CHANGELOG | 4 ++++ cmake/modules/SRSLTEVersion.cmake | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/CHANGELOG b/CHANGELOG index 9bed0247c..7a3a03e8a 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,6 +1,10 @@ Change Log for Releases ============================== +## 18.03.1 + * Fixed compilation for NEON + * Fixed logging and RLC AM issue + ## 18.03 * Many bug-fixes and improved stability and performance in all parts diff --git a/cmake/modules/SRSLTEVersion.cmake b/cmake/modules/SRSLTEVersion.cmake index 30d2707b0..11b2e79e9 100644 --- a/cmake/modules/SRSLTEVersion.cmake +++ b/cmake/modules/SRSLTEVersion.cmake @@ -20,5 +20,5 @@ SET(SRSLTE_VERSION_MAJOR 18) SET(SRSLTE_VERSION_MINOR 3) -SET(SRSLTE_VERSION_PATCH 0) +SET(SRSLTE_VERSION_PATCH 1) SET(SRSLTE_VERSION_STRING "${SRSLTE_VERSION_MAJOR}.${SRSLTE_VERSION_MINOR}.${SRSLTE_VERSION_PATCH}") From d0d5893a1c9dfcfbefaaa935b65eabce55436e1b Mon Sep 17 00:00:00 2001 From: Xavier Arteaga Date: Fri, 6 Apr 2018 11:20:50 +0200 Subject: [PATCH 2/4] New DL channel noise estimator based on RS --- .../srslte/phy/ch_estimation/chest_dl.h | 8 + lib/src/phy/ch_estimation/chest_dl.c | 149 ++++++++++++++---- 2 files changed, 124 insertions(+), 33 deletions(-) diff --git a/lib/include/srslte/phy/ch_estimation/chest_dl.h b/lib/include/srslte/phy/ch_estimation/chest_dl.h index a521d653e..5f7731305 100644 --- a/lib/include/srslte/phy/ch_estimation/chest_dl.h +++ b/lib/include/srslte/phy/ch_estimation/chest_dl.h @@ -74,6 +74,7 @@ typedef struct { float snr_vector[12000]; float pilot_power[12000]; #endif + bool smooth_filter_auto; uint32_t smooth_filter_len; float smooth_filter[SRSLTE_CHEST_MAX_SMOOTH_FIL_LEN]; @@ -123,6 +124,13 @@ SRSLTE_API void srslte_chest_dl_set_smooth_filter(srslte_chest_dl_t *q, SRSLTE_API void srslte_chest_dl_set_smooth_filter3_coeff(srslte_chest_dl_t* q, float w); +SRSLTE_API void srslte_chest_dl_set_smooth_filter_gauss(srslte_chest_dl_t* q, + uint32_t order, + float std_dev); + +SRSLTE_API void srslte_chest_dl_set_smooth_filter_auto(srslte_chest_dl_t* q, + bool enable); + SRSLTE_API void srslte_chest_dl_set_noise_alg(srslte_chest_dl_t *q, srslte_chest_dl_noise_alg_t noise_estimation_alg); diff --git a/lib/src/phy/ch_estimation/chest_dl.c b/lib/src/phy/ch_estimation/chest_dl.c index e719b22c0..06bc43d66 100644 --- a/lib/src/phy/ch_estimation/chest_dl.c +++ b/lib/src/phy/ch_estimation/chest_dl.c @@ -155,6 +155,7 @@ int srslte_chest_dl_init(srslte_chest_dl_t *q, uint32_t max_prb) q->rsrp_neighbour = false; + q->smooth_filter_auto = false; q->smooth_filter_len = 3; srslte_chest_dl_set_smooth_filter3_coeff(q, 0.1); @@ -263,41 +264,66 @@ int srslte_chest_dl_set_cell(srslte_chest_dl_t *q, srslte_cell_t cell) /* Uses the difference between the averaged and non-averaged pilot estimates */ static float estimate_noise_pilots(srslte_chest_dl_t *q, uint32_t port_id, srslte_sf_t ch_mode) { - int nref=SRSLTE_REFSIGNAL_NUM_SF(q->cell.nof_prb, port_id); + const float weight = 1.0f; + float sum_power = 0.0f; + uint32_t count = 0; + uint32_t npilots = SRSLTE_REFSIGNAL_NUM_SF(q->cell.nof_prb, port_id); + uint32_t nsymbols = + (ch_mode == SRSLTE_SF_MBSFN) ? srslte_refsignal_mbsfn_nof_symbols() : srslte_refsignal_cs_nof_symbols(port_id); + uint32_t nref = npilots / nsymbols; + uint32_t fidx = srslte_refsignal_cs_fidx(q->cell, 0, port_id, 0); - if (q->average_subframe) { - if (ch_mode == SRSLTE_SF_MBSFN) { - nref /= 4; - } else { - nref /= 2; - } + cf_t *input2d[nsymbols + 2]; + cf_t *tmp_noise = q->tmp_noise; + + for (int i = 0; i < nsymbols; i++) { + input2d[i + 1] = &q->pilot_estimates[i * nref]; } - /* Substract noisy pilot estimates */ - srslte_vec_sub_ccc(q->pilot_estimates_average, q->pilot_estimates, q->tmp_noise, nref); - -#ifdef FREQ_SEL_SNR - /* Compute frequency-selective SNR */ - srslte_vec_abs_square_cf(q->tmp_noise, q->snr_vector, nref); - srslte_vec_abs_square_cf(q->pilot_estimates, q->pilot_power, nref); - srslte_vec_div_fff(q->pilot_power, q->snr_vector, q->snr_vector, nref); - - srslte_vec_fprint_f(stdout, q->snr_vector, nref); -#endif - - /* Compute average power. Normalized for filter len 3 using matlab */ - float norm = 1; - if (q->average_subframe) { - norm = 32; + input2d[0] = &q->tmp_noise[0]; + if (nsymbols > 3) { + srslte_vec_sc_prod_cfc(input2d[2], 2.0f, input2d[0], nref); + srslte_vec_sub_ccc(input2d[0], input2d[4], input2d[0], nref); + } else { + srslte_vec_sc_prod_cfc(input2d[2], 1.0f, input2d[0], nref); + } + + input2d[nsymbols + 1] = &q->tmp_noise[nref]; + if (nsymbols > 3) { + srslte_vec_sc_prod_cfc(input2d[nsymbols - 1], 2.0f, input2d[nsymbols + 1], nref); + srslte_vec_sub_ccc(input2d[nsymbols + 1], input2d[nsymbols - 3], input2d[nsymbols + 1], nref); } else { - if (q->smooth_filter_len == 3) { - float a = q->smooth_filter[0]; - float norm3 = 6.143*a*a+0.04859*a-0.002774; - norm /= norm3; + srslte_vec_sc_prod_cfc(input2d[nsymbols - 1], 1.0f, input2d[nsymbols + 1], nref); + } + + for (int i = 1; i < nsymbols + 1; i++) { + uint32_t offset = ((fidx < 3) ^ (i & 1)) ? 0 : 1; + srslte_vec_sc_prod_cfc(input2d[i], weight, tmp_noise, nref); + + srslte_vec_sum_ccc(&input2d[i - 1][0], &tmp_noise[offset], &tmp_noise[offset], nref - offset); + srslte_vec_sum_ccc(&input2d[i - 1][1 - offset], &tmp_noise[0], &tmp_noise[0], nref + offset - 1); + if (offset) { + tmp_noise[0] += 2.0f * input2d[i - 1][0] - input2d[i - 1][1]; + } else { + tmp_noise[nref - 1] += 2.0f * input2d[i - 1][nref - 2] - input2d[i - 1][nref - 1]; + } + + srslte_vec_sum_ccc(&input2d[i + 1][0], &tmp_noise[offset], &tmp_noise[offset], nref - offset); + srslte_vec_sum_ccc(&input2d[i + 1][1 - offset], &tmp_noise[0], &tmp_noise[0], nref + offset - 1); + if (offset) { + tmp_noise[0] += 2.0f * input2d[i + 1][0] - input2d[i + 1][1]; + } else { + tmp_noise[nref - 1] += 2.0f * input2d[i + 1][nref - 2] - input2d[i + 1][nref - 1]; } + + srslte_vec_sc_prod_cfc(tmp_noise, 1.0f / (weight + 4.0f), tmp_noise, nref); + + srslte_vec_sub_ccc(input2d[i], tmp_noise, tmp_noise, nref); + sum_power = srslte_vec_avg_power_cf(tmp_noise, nref); + count++; } - float power = norm*srslte_vec_avg_power_cf(q->tmp_noise, nref); - return power; + + return sum_power / (float) count * sqrtf(weight + 4.0f); } static float estimate_noise_pss(srslte_chest_dl_t *q, cf_t *input, cf_t *ce) @@ -443,6 +469,53 @@ void srslte_chest_dl_set_smooth_filter3_coeff(srslte_chest_dl_t* q, float w) q->smooth_filter[1] = 1-2*w; } +void srslte_chest_dl_set_smooth_filter_gauss(srslte_chest_dl_t* q, uint32_t order, float std_dev) +{ + const uint32_t filterlen = order + 1; + const int center = (filterlen - 1) / 2; + float *filter = q->smooth_filter; + float norm_p = 0.0f; + + if (filterlen) { + + for (int i = 0; i < filterlen; i++) { + filter[i] = expf(-powf(i - center, 2) / (2.0f * powf(std_dev, 2))); + norm_p += powf(filter[i], 2); + } + + const float norm = srslte_vec_acc_ff(filter, filterlen); + + srslte_vec_sc_prod_fff(filter, 1.0f / norm, filter, filterlen); + q->smooth_filter_len = filterlen; + } +} + +void srslte_chest_dl_set_smooth_filter_auto(srslte_chest_dl_t *q, bool enable) { + q->smooth_filter_auto = enable; +} + +uint32_t srslte_chest_dl_interleave_pilots(srslte_chest_dl_t *q, cf_t *input, cf_t *tmp, cf_t *output, uint32_t port_id, srslte_sf_t ch_mode) { + uint32_t nsymbols = (ch_mode == SRSLTE_SF_MBSFN)?srslte_refsignal_mbsfn_nof_symbols(port_id):srslte_refsignal_cs_nof_symbols(port_id); + uint32_t nref = (ch_mode == SRSLTE_SF_MBSFN)?6*q->cell.nof_prb:2*q->cell.nof_prb; + + if (srslte_refsignal_cs_fidx(q->cell, 0, port_id, 0) < 3) { + srslte_vec_interleave(input, &input[nref], tmp, nref); + for (int l = 2; l < nsymbols - 1; l += 2) { + srslte_vec_interleave_add(&input[l * nref], &input[(l + 1) * nref], tmp, nref); + } + } else { + srslte_vec_interleave(&input[nref], input, tmp, nref); + for (int l = 2; l < nsymbols - 1; l += 2) { + srslte_vec_interleave_add(&input[(l + 1) * nref], &input[l * nref], tmp, nref); + } + } + + nref *= 2; + srslte_vec_sc_prod_cfc(tmp, 2.0f / nsymbols, output, nref); + + return nref; +} + static void average_pilots(srslte_chest_dl_t *q, cf_t *input, cf_t *output, uint32_t port_id, srslte_sf_t ch_mode) { uint32_t nsymbols = (ch_mode == SRSLTE_SF_MBSFN)?srslte_refsignal_mbsfn_nof_symbols(port_id):srslte_refsignal_cs_nof_symbols(port_id); uint32_t nref = (ch_mode == SRSLTE_SF_MBSFN)?6*q->cell.nof_prb:2*q->cell.nof_prb; @@ -519,11 +592,23 @@ float chest_estimate_cfo(srslte_chest_dl_t *q) } void chest_interpolate_noise_est(srslte_chest_dl_t *q, cf_t *input, cf_t *ce, uint32_t sf_idx, uint32_t port_id, uint32_t rxant_id, srslte_sf_t ch_mode){ + uint32_t npilots = SRSLTE_REFSIGNAL_NUM_SF(q->cell.nof_prb, port_id); + uint32_t nsymbols = (ch_mode == SRSLTE_SF_MBSFN)?srslte_refsignal_mbsfn_nof_symbols():srslte_refsignal_cs_nof_symbols(port_id); + if (q->cfo_estimate_enable && ((1<cfo_estimate_sf_mask)) { q->cfo = chest_estimate_cfo(q); } + /* Estimate noise */ + if (q->noise_alg == SRSLTE_NOISE_ALG_REFS) { + q->noise_estimate[rxant_id][port_id] = estimate_noise_pilots(q, port_id, ch_mode); + } + if (ce != NULL) { + if (q->smooth_filter_auto) { + srslte_chest_dl_set_smooth_filter_gauss(q, 4, q->noise_estimate[rxant_id][port_id] * 200.0f); + } + /* Smooth estimates (if applicable) and interpolate */ if (q->smooth_filter_len == 0 || (q->smooth_filter_len == 3 && q->smooth_filter[0] == 0)) { interpolate_pilots(q, q->pilot_estimates, ce, port_id, ch_mode); @@ -533,13 +618,11 @@ void chest_interpolate_noise_est(srslte_chest_dl_t *q, cf_t *input, cf_t *ce, ui } /* Estimate noise power */ - if (q->noise_alg == SRSLTE_NOISE_ALG_REFS && q->smooth_filter_len > 0) { - q->noise_estimate[rxant_id][port_id] = estimate_noise_pilots(q, port_id, ch_mode); - } else if (q->noise_alg == SRSLTE_NOISE_ALG_PSS) { + if (q->noise_alg == SRSLTE_NOISE_ALG_PSS) { if (sf_idx == 0 || sf_idx == 5) { q->noise_estimate[rxant_id][port_id] = estimate_noise_pss(q, input, ce); } - } else { + } else if (q->noise_alg != SRSLTE_NOISE_ALG_REFS) { if (sf_idx == 0 || sf_idx == 5) { q->noise_estimate[rxant_id][port_id] = estimate_noise_empty_sc(q, input); } From 15173c5c3054a6a75eeab9ec3970ae149e430a00 Mon Sep 17 00:00:00 2001 From: Xavier Arteaga Date: Fri, 6 Apr 2018 13:24:25 +0200 Subject: [PATCH 3/4] Added gaussian filter configuration options in srsue.conf --- lib/include/srslte/interfaces/ue_interfaces.h | 6 ++++-- lib/src/phy/ch_estimation/chest_dl.c | 3 --- srsue/src/main.cc | 16 ++++++++++++---- srsue/src/phy/phch_worker.cc | 12 +++++------- srsue/src/phy/phy.cc | 8 +++----- srsue/ue.conf.example | 8 ++++++-- 6 files changed, 30 insertions(+), 23 deletions(-) diff --git a/lib/include/srslte/interfaces/ue_interfaces.h b/lib/include/srslte/interfaces/ue_interfaces.h index b1c0672d3..f9e8c09c2 100644 --- a/lib/include/srslte/interfaces/ue_interfaces.h +++ b/lib/include/srslte/interfaces/ue_interfaces.h @@ -487,9 +487,11 @@ typedef struct { uint32_t cfo_loop_pss_conv; uint32_t cfo_ref_mask; bool average_subframe_enabled; - int time_correct_period; + bool estimator_fil_auto; + float estimator_fil_stddev; + uint32_t estimator_fil_order; + int time_correct_period; std::string sss_algorithm; - float estimator_fil_w; bool rssi_sensor_enabled; bool sic_pss_enabled; float rx_gain_offset; diff --git a/lib/src/phy/ch_estimation/chest_dl.c b/lib/src/phy/ch_estimation/chest_dl.c index 06bc43d66..238cd1a18 100644 --- a/lib/src/phy/ch_estimation/chest_dl.c +++ b/lib/src/phy/ch_estimation/chest_dl.c @@ -592,9 +592,6 @@ float chest_estimate_cfo(srslte_chest_dl_t *q) } void chest_interpolate_noise_est(srslte_chest_dl_t *q, cf_t *input, cf_t *ce, uint32_t sf_idx, uint32_t port_id, uint32_t rxant_id, srslte_sf_t ch_mode){ - uint32_t npilots = SRSLTE_REFSIGNAL_NUM_SF(q->cell.nof_prb, port_id); - uint32_t nsymbols = (ch_mode == SRSLTE_SF_MBSFN)?srslte_refsignal_mbsfn_nof_symbols():srslte_refsignal_cs_nof_symbols(port_id); - if (q->cfo_estimate_enable && ((1<cfo_estimate_sf_mask)) { q->cfo = chest_estimate_cfo(q); } diff --git a/srsue/src/main.cc b/srsue/src/main.cc index a30892cc7..4acb7c8d9 100644 --- a/srsue/src/main.cc +++ b/srsue/src/main.cc @@ -261,6 +261,18 @@ void parse_args(all_args_t *args, int argc, char *argv[]) { bpo::value(&args->expert.phy.average_subframe_enabled)->default_value(true), "Averages in the time domain the channel estimates within 1 subframe. Needs accurate CFO correction.") + ("expert.estimator_fil_auto", + bpo::value(&args->expert.phy.estimator_fil_auto)->default_value(false), + "The channel estimator smooths the channel estimate with an adaptative filter.") + + ("expert.estimator_fil_stddev", + bpo::value(&args->expert.phy.estimator_fil_stddev)->default_value(1.0f), + "Sets the channel estimator smooth gaussian filter standard deviation.") + + ("expert.estimator_fil_order", + bpo::value(&args->expert.phy.estimator_fil_order)->default_value(4), + "Sets the channel estimator smooth gaussian filter order (even values perform better).") + ("expert.time_correct_period", bpo::value(&args->expert.phy.time_correct_period)->default_value(5), "Period for sampling time offset correction.") @@ -269,10 +281,6 @@ void parse_args(all_args_t *args, int argc, char *argv[]) { bpo::value(&args->expert.phy.sss_algorithm)->default_value("full"), "Selects the SSS estimation algorithm.") - ("expert.estimator_fil_w", - bpo::value(&args->expert.phy.estimator_fil_w)->default_value(0.1), - "Chooses the coefficients for the 3-tap channel estimator centered filter.") - ("expert.pdsch_csi_enabled", bpo::value(&args->expert.phy.pdsch_csi_enabled)->default_value(false), "Stores the Channel State Information and uses it for weightening the softbits. It is only compatible with TM1.") diff --git a/srsue/src/phy/phch_worker.cc b/srsue/src/phy/phch_worker.cc index 7ac2ed040..282299bf0 100644 --- a/srsue/src/phy/phch_worker.cc +++ b/srsue/src/phy/phch_worker.cc @@ -441,13 +441,11 @@ bool phch_worker::extract_fft_and_pdcch_llr() { if (phy->get_pending_ack(tti) || decode_pdcch) { // Setup estimator filter - float w_coeff = phy->args->estimator_fil_w; - if (w_coeff > 0.0) { - srslte_chest_dl_set_smooth_filter3_coeff(&ue_dl.chest, w_coeff); - } else if (w_coeff == 0.0) { - srslte_chest_dl_set_smooth_filter(&ue_dl.chest, NULL, 0); - } - + srslte_chest_dl_set_smooth_filter_gauss(&ue_dl.chest, + phy->args->estimator_fil_order, + phy->args->estimator_fil_stddev); + srslte_chest_dl_set_smooth_filter_auto(&ue_dl.chest, phy->args->estimator_fil_auto); + if (!phy->args->snr_estim_alg.compare("refs")) { srslte_chest_dl_set_noise_alg(&ue_dl.chest, SRSLTE_NOISE_ALG_REFS); } else if (!phy->args->snr_estim_alg.compare("empty")) { diff --git a/srsue/src/phy/phy.cc b/srsue/src/phy/phy.cc index 90dbc2833..be0e2b411 100644 --- a/srsue/src/phy/phy.cc +++ b/srsue/src/phy/phy.cc @@ -98,7 +98,9 @@ void phy::set_default_args(phy_args_t *args) args->cfo_correct_tol_hz = 50; args->time_correct_period = 5; args->sss_algorithm = "full"; - args->estimator_fil_w = 0.1; + args->estimator_fil_auto = false; + args->estimator_fil_stddev = 1.0f; + args->estimator_fil_order = 4; } bool phy::check_args(phy_args_t *args) @@ -107,10 +109,6 @@ bool phy::check_args(phy_args_t *args) log_h->console("Error in PHY args: nof_phy_threads must be 1, 2 or 3\n"); return false; } - if (args->estimator_fil_w > 1.0) { - log_h->console("Error in PHY args: estimator_fil_w must be 0<=w<=1\n"); - return false; - } if (args->snr_ema_coeff > 1.0) { log_h->console("Error in PHY args: snr_ema_coeff must be 0<=w<=1\n"); return false; diff --git a/srsue/ue.conf.example b/srsue/ue.conf.example index a3de1a678..531381431 100644 --- a/srsue/ue.conf.example +++ b/srsue/ue.conf.example @@ -150,7 +150,9 @@ enable = false # sampling frequency offset. Default is enabled. # sss_algorithm: Selects the SSS estimation algorithm. Can choose between # {full, partial, diff}. -# estimator_fil_w: Chooses the coefficients for the 3-tap channel estimator centered filter. +# estimator_fil_auto: The channel estimator smooths the channel estimate with an adaptative filter. +# estimator_fil_stddev: Sets the channel estimator smooth gaussian filter standard deviation. +# estimator_fil_order: Sets the channel estimator smooth gaussian filter order (even values perform better). # The taps are [w, 1-2w, w] # metrics_period_secs: Sets the period at which metrics are requested from the UE. # @@ -204,7 +206,9 @@ enable = false #time_correct_period = 5 #sfo_correct_disable = false #sss_algorithm = full -#estimator_fil_w = 0.1 +#estimator_fil_auto = false +#estimator_fil_stddev = 1.0 +#estimator_fil_order = 4 #average_subframe_enabled = true #sic_pss_enabled = true #pregenerate_signals = false From 09e6f164a489f3b5050751ce2fa0322ff9b704b9 Mon Sep 17 00:00:00 2001 From: Xavier Arteaga Date: Tue, 10 Apr 2018 13:17:59 +0200 Subject: [PATCH 4/4] UE synchronizer can miss up to 100 PSS. This reduces PSS lost of synch for slow fading channels such as EVA5. --- lib/src/phy/ue/ue_sync.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/src/phy/ue/ue_sync.c b/lib/src/phy/ue/ue_sync.c index b66cf5b53..38355af92 100644 --- a/lib/src/phy/ue/ue_sync.c +++ b/lib/src/phy/ue/ue_sync.c @@ -41,7 +41,7 @@ #define MAX_TIME_OFFSET 128 -#define TRACK_MAX_LOST 4 +#define TRACK_MAX_LOST 100 #define TRACK_FRAME_SIZE 32 #define FIND_NOF_AVG_FRAMES 4 #define DEFAULT_SAMPLE_OFFSET_CORRECT_PERIOD 0