Merge branch 'next' of github.com:softwareradiosystems/srsLTE into next

master
Francisco Paisana 7 years ago
commit 9f48233925

@ -1,6 +1,10 @@
Change Log for Releases Change Log for Releases
============================== ==============================
## 18.03.1
* Fixed compilation for NEON
* Fixed logging and RLC AM issue
## 18.03 ## 18.03
* Many bug-fixes and improved stability and performance in all parts * Many bug-fixes and improved stability and performance in all parts

@ -20,5 +20,5 @@
SET(SRSLTE_VERSION_MAJOR 18) SET(SRSLTE_VERSION_MAJOR 18)
SET(SRSLTE_VERSION_MINOR 3) 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}") SET(SRSLTE_VERSION_STRING "${SRSLTE_VERSION_MAJOR}.${SRSLTE_VERSION_MINOR}.${SRSLTE_VERSION_PATCH}")

@ -487,9 +487,11 @@ typedef struct {
uint32_t cfo_loop_pss_conv; uint32_t cfo_loop_pss_conv;
uint32_t cfo_ref_mask; uint32_t cfo_ref_mask;
bool average_subframe_enabled; 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; std::string sss_algorithm;
float estimator_fil_w;
bool rssi_sensor_enabled; bool rssi_sensor_enabled;
bool sic_pss_enabled; bool sic_pss_enabled;
float rx_gain_offset; float rx_gain_offset;

@ -74,6 +74,7 @@ typedef struct {
float snr_vector[12000]; float snr_vector[12000];
float pilot_power[12000]; float pilot_power[12000];
#endif #endif
bool smooth_filter_auto;
uint32_t smooth_filter_len; uint32_t smooth_filter_len;
float smooth_filter[SRSLTE_CHEST_MAX_SMOOTH_FIL_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, SRSLTE_API void srslte_chest_dl_set_smooth_filter3_coeff(srslte_chest_dl_t* q,
float w); 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_API void srslte_chest_dl_set_noise_alg(srslte_chest_dl_t *q,
srslte_chest_dl_noise_alg_t noise_estimation_alg); srslte_chest_dl_noise_alg_t noise_estimation_alg);

@ -155,6 +155,7 @@ int srslte_chest_dl_init(srslte_chest_dl_t *q, uint32_t max_prb)
q->rsrp_neighbour = false; q->rsrp_neighbour = false;
q->smooth_filter_auto = false;
q->smooth_filter_len = 3; q->smooth_filter_len = 3;
srslte_chest_dl_set_smooth_filter3_coeff(q, 0.1); 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 */ /* 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) 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) { cf_t *input2d[nsymbols + 2];
if (ch_mode == SRSLTE_SF_MBSFN) { cf_t *tmp_noise = q->tmp_noise;
nref /= 4;
} else { for (int i = 0; i < nsymbols; i++) {
nref /= 2; input2d[i + 1] = &q->pilot_estimates[i * nref];
}
} }
/* Substract noisy pilot estimates */ input2d[0] = &q->tmp_noise[0];
srslte_vec_sub_ccc(q->pilot_estimates_average, q->pilot_estimates, q->tmp_noise, nref); if (nsymbols > 3) {
srslte_vec_sc_prod_cfc(input2d[2], 2.0f, input2d[0], nref);
#ifdef FREQ_SEL_SNR srslte_vec_sub_ccc(input2d[0], input2d[4], input2d[0], nref);
/* 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;
} else { } else {
if (q->smooth_filter_len == 3) { srslte_vec_sc_prod_cfc(input2d[2], 1.0f, input2d[0], nref);
float a = q->smooth_filter[0]; }
float norm3 = 6.143*a*a+0.04859*a-0.002774;
norm /= norm3; 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 {
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) 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; 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) { 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 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; uint32_t nref = (ch_mode == SRSLTE_SF_MBSFN)?6*q->cell.nof_prb:2*q->cell.nof_prb;
@ -523,7 +596,16 @@ void chest_interpolate_noise_est(srslte_chest_dl_t *q, cf_t *input, cf_t *ce, ui
q->cfo = chest_estimate_cfo(q); 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 (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 */ /* Smooth estimates (if applicable) and interpolate */
if (q->smooth_filter_len == 0 || (q->smooth_filter_len == 3 && q->smooth_filter[0] == 0)) { 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); interpolate_pilots(q, q->pilot_estimates, ce, port_id, ch_mode);
@ -533,13 +615,11 @@ void chest_interpolate_noise_est(srslte_chest_dl_t *q, cf_t *input, cf_t *ce, ui
} }
/* Estimate noise power */ /* Estimate noise power */
if (q->noise_alg == SRSLTE_NOISE_ALG_REFS && q->smooth_filter_len > 0) { if (q->noise_alg == SRSLTE_NOISE_ALG_PSS) {
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 (sf_idx == 0 || sf_idx == 5) { if (sf_idx == 0 || sf_idx == 5) {
q->noise_estimate[rxant_id][port_id] = estimate_noise_pss(q, input, ce); 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) { if (sf_idx == 0 || sf_idx == 5) {
q->noise_estimate[rxant_id][port_id] = estimate_noise_empty_sc(q, input); q->noise_estimate[rxant_id][port_id] = estimate_noise_empty_sc(q, input);
} }

@ -41,7 +41,7 @@
#define MAX_TIME_OFFSET 128 #define MAX_TIME_OFFSET 128
#define TRACK_MAX_LOST 4 #define TRACK_MAX_LOST 100
#define TRACK_FRAME_SIZE 32 #define TRACK_FRAME_SIZE 32
#define FIND_NOF_AVG_FRAMES 4 #define FIND_NOF_AVG_FRAMES 4
#define DEFAULT_SAMPLE_OFFSET_CORRECT_PERIOD 0 #define DEFAULT_SAMPLE_OFFSET_CORRECT_PERIOD 0

@ -261,6 +261,18 @@ void parse_args(all_args_t *args, int argc, char *argv[]) {
bpo::value<bool>(&args->expert.phy.average_subframe_enabled)->default_value(true), bpo::value<bool>(&args->expert.phy.average_subframe_enabled)->default_value(true),
"Averages in the time domain the channel estimates within 1 subframe. Needs accurate CFO correction.") "Averages in the time domain the channel estimates within 1 subframe. Needs accurate CFO correction.")
("expert.estimator_fil_auto",
bpo::value<bool>(&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<float>(&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<uint32_t>(&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", ("expert.time_correct_period",
bpo::value<int>(&args->expert.phy.time_correct_period)->default_value(5), bpo::value<int>(&args->expert.phy.time_correct_period)->default_value(5),
"Period for sampling time offset correction.") "Period for sampling time offset correction.")
@ -269,10 +281,6 @@ void parse_args(all_args_t *args, int argc, char *argv[]) {
bpo::value<string>(&args->expert.phy.sss_algorithm)->default_value("full"), bpo::value<string>(&args->expert.phy.sss_algorithm)->default_value("full"),
"Selects the SSS estimation algorithm.") "Selects the SSS estimation algorithm.")
("expert.estimator_fil_w",
bpo::value<float>(&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", ("expert.pdsch_csi_enabled",
bpo::value<bool>(&args->expert.phy.pdsch_csi_enabled)->default_value(false), bpo::value<bool>(&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.") "Stores the Channel State Information and uses it for weightening the softbits. It is only compatible with TM1.")

@ -441,13 +441,11 @@ bool phch_worker::extract_fft_and_pdcch_llr() {
if (phy->get_pending_ack(tti) || decode_pdcch) { if (phy->get_pending_ack(tti) || decode_pdcch) {
// Setup estimator filter // Setup estimator filter
float w_coeff = phy->args->estimator_fil_w; srslte_chest_dl_set_smooth_filter_gauss(&ue_dl.chest,
if (w_coeff > 0.0) { phy->args->estimator_fil_order,
srslte_chest_dl_set_smooth_filter3_coeff(&ue_dl.chest, w_coeff); phy->args->estimator_fil_stddev);
} else if (w_coeff == 0.0) { srslte_chest_dl_set_smooth_filter_auto(&ue_dl.chest, phy->args->estimator_fil_auto);
srslte_chest_dl_set_smooth_filter(&ue_dl.chest, NULL, 0);
}
if (!phy->args->snr_estim_alg.compare("refs")) { if (!phy->args->snr_estim_alg.compare("refs")) {
srslte_chest_dl_set_noise_alg(&ue_dl.chest, SRSLTE_NOISE_ALG_REFS); srslte_chest_dl_set_noise_alg(&ue_dl.chest, SRSLTE_NOISE_ALG_REFS);
} else if (!phy->args->snr_estim_alg.compare("empty")) { } else if (!phy->args->snr_estim_alg.compare("empty")) {

@ -98,7 +98,9 @@ void phy::set_default_args(phy_args_t *args)
args->cfo_correct_tol_hz = 50; args->cfo_correct_tol_hz = 50;
args->time_correct_period = 5; args->time_correct_period = 5;
args->sss_algorithm = "full"; 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) 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"); log_h->console("Error in PHY args: nof_phy_threads must be 1, 2 or 3\n");
return false; 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) { if (args->snr_ema_coeff > 1.0) {
log_h->console("Error in PHY args: snr_ema_coeff must be 0<=w<=1\n"); log_h->console("Error in PHY args: snr_ema_coeff must be 0<=w<=1\n");
return false; return false;

@ -150,7 +150,9 @@ enable = false
# sampling frequency offset. Default is enabled. # sampling frequency offset. Default is enabled.
# sss_algorithm: Selects the SSS estimation algorithm. Can choose between # sss_algorithm: Selects the SSS estimation algorithm. Can choose between
# {full, partial, diff}. # {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] # The taps are [w, 1-2w, w]
# metrics_period_secs: Sets the period at which metrics are requested from the UE. # metrics_period_secs: Sets the period at which metrics are requested from the UE.
# #
@ -204,7 +206,9 @@ enable = false
#time_correct_period = 5 #time_correct_period = 5
#sfo_correct_disable = false #sfo_correct_disable = false
#sss_algorithm = full #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 #average_subframe_enabled = true
#sic_pss_enabled = true #sic_pss_enabled = true
#pregenerate_signals = false #pregenerate_signals = false

Loading…
Cancel
Save