Merge branch 'next' into sync_states

This commit is contained in:
Ismael Gomez 2018-04-12 18:30:19 +02:00
commit ffb8337be7
12 changed files with 174 additions and 66 deletions

View File

@ -494,8 +494,10 @@ typedef struct {
uint32_t cfo_loop_pss_conv;
uint32_t cfo_ref_mask;
bool average_subframe_enabled;
bool estimator_fil_auto;
float estimator_fil_stddev;
uint32_t estimator_fil_order;
std::string sss_algorithm;
float estimator_fil_w;
bool rssi_sensor_enabled;
bool sic_pss_enabled;
float rx_gain_offset;

View File

@ -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);

View File

@ -136,7 +136,7 @@ void log_filter::all_log(srslte::LOG_LEVEL_ENUM level,
}
void log_filter::console(const char * message, ...) {
char *args_msg;
char *args_msg = NULL;
va_list args;
va_start(args, message);
if(vasprintf(&args_msg, message, args) > 0)
@ -147,7 +147,7 @@ void log_filter::console(const char * message, ...) {
void log_filter::error(const char * message, ...) {
if (level >= LOG_LEVEL_ERROR) {
char *args_msg;
char *args_msg = NULL;
va_list args;
va_start(args, message);
if(vasprintf(&args_msg, message, args) > 0)
@ -158,7 +158,7 @@ void log_filter::error(const char * message, ...) {
}
void log_filter::warning(const char * message, ...) {
if (level >= LOG_LEVEL_WARNING) {
char *args_msg;
char *args_msg = NULL;
va_list args;
va_start(args, message);
if(vasprintf(&args_msg, message, args) > 0)
@ -169,7 +169,7 @@ void log_filter::warning(const char * message, ...) {
}
void log_filter::info(const char * message, ...) {
if (level >= LOG_LEVEL_INFO) {
char *args_msg;
char *args_msg = NULL;
va_list args;
va_start(args, message);
if(vasprintf(&args_msg, message, args) > 0)
@ -180,7 +180,7 @@ void log_filter::info(const char * message, ...) {
}
void log_filter::debug(const char * message, ...) {
if (level >= LOG_LEVEL_DEBUG) {
char *args_msg;
char *args_msg = NULL;
va_list args;
va_start(args, message);
if(vasprintf(&args_msg, message, args) > 0)
@ -192,7 +192,7 @@ void log_filter::debug(const char * message, ...) {
void log_filter::error_hex(const uint8_t *hex, int size, const char * message, ...) {
if (level >= LOG_LEVEL_ERROR) {
char *args_msg;
char *args_msg = NULL;
va_list args;
va_start(args, message);
if(vasprintf(&args_msg, message, args) > 0)
@ -203,7 +203,7 @@ void log_filter::error_hex(const uint8_t *hex, int size, const char * message, .
}
void log_filter::warning_hex(const uint8_t *hex, int size, const char * message, ...) {
if (level >= LOG_LEVEL_WARNING) {
char *args_msg;
char *args_msg = NULL;
va_list args;
va_start(args, message);
if(vasprintf(&args_msg, message, args) > 0)
@ -214,7 +214,7 @@ void log_filter::warning_hex(const uint8_t *hex, int size, const char * message,
}
void log_filter::info_hex(const uint8_t *hex, int size, const char * message, ...) {
if (level >= LOG_LEVEL_INFO) {
char *args_msg;
char *args_msg = NULL;
va_list args;
va_start(args, message);
if(vasprintf(&args_msg, message, args) > 0)
@ -225,7 +225,7 @@ void log_filter::info_hex(const uint8_t *hex, int size, const char * message, ..
}
void log_filter::debug_hex(const uint8_t *hex, int size, const char * message, ...) {
if (level >= LOG_LEVEL_DEBUG) {
char *args_msg;
char *args_msg = NULL;
va_list args;
va_start(args, message);
if(vasprintf(&args_msg, message, args) > 0)

View File

@ -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 {
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[2], 1.0f, input2d[0], nref);
}
float power = norm*srslte_vec_avg_power_cf(q->tmp_noise, nref);
return power;
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++;
}
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;
@ -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);
}
/* 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 +615,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);
}

View File

@ -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

View File

@ -176,7 +176,7 @@ float radio::set_tx_power(float power)
float radio::get_max_tx_power()
{
return 10;
return 40;
}
float radio::get_rssi()

View File

@ -1447,6 +1447,8 @@ void rrc::ue::send_connection_reconf(srslte::byte_buffer_t *pdu)
// Get DRB1 configuration
if (get_drbid_config(&conn_reconf->rr_cnfg_ded.drb_to_add_mod_list[0], 1)) {
parent->rrc_log->error("Getting DRB1 configuration\n");
printf("The QCI %d for DRB1 is invalid or not configured.\n", erabs[5].qos_params.qCI.QCI);
return;
} else {
conn_reconf->rr_cnfg_ded.drb_to_add_mod_list_size = 1;
}
@ -1524,8 +1526,10 @@ void rrc::ue::send_connection_reconf_new_bearer(LIBLTE_S1AP_E_RABTOBESETUPLISTBE
uint8_t lcid = id - 2; // Map e.g. E-RAB 5 to LCID 3 (==DRB1)
// Get DRB configuration
if (get_drbid_config(&conn_reconf->rr_cnfg_ded.drb_to_add_mod_list[i], lcid)) {
parent->rrc_log->error("Getting DRB configuration\n");
if (get_drbid_config(&conn_reconf->rr_cnfg_ded.drb_to_add_mod_list[i], lcid-2)) {
parent->rrc_log->error("Getting DRB configuration\n");
printf("ERROR: The QCI %d is invalid or not configured.\n", erabs[lcid+4].qos_params.qCI.QCI);
return;
} else {
conn_reconf->rr_cnfg_ded.drb_to_add_mod_list_size++;
}

View File

@ -134,7 +134,7 @@ class cell_t
}
void set_rsrp(float rsrp) {
if (~isnan(rsrp)) {
if (!isnan(rsrp)) {
this->rsrp = rsrp;
}
in_sync = true;

View File

@ -261,14 +261,22 @@ void parse_args(all_args_t *args, int argc, char *argv[]) {
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.")
("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.sss_algorithm",
bpo::value<string>(&args->expert.phy.sss_algorithm)->default_value("full"),
"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",
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.")

View File

@ -444,12 +444,10 @@ bool phch_worker::extract_fft_and_pdcch_llr() {
// Do always channel estimation to keep track of out-of-sync and send measurements to RRC
// 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);
@ -459,6 +457,12 @@ bool phch_worker::extract_fft_and_pdcch_llr() {
srslte_chest_dl_set_noise_alg(&ue_dl.chest, SRSLTE_NOISE_ALG_PSS);
}
if (srslte_ue_dl_decode_fft_estimate(&ue_dl, tti%10, &cfi) < 0) {
Error("Getting PDCCH FFT estimate\n");
return false;
}
chest_done = true;
if (srslte_ue_dl_decode_fft_estimate(&ue_dl, tti%10, &cfi) < 0) {
Error("Getting PDCCH FFT estimate\n");
return false;

View File

@ -97,7 +97,9 @@ void phy::set_default_args(phy_args_t *args)
args->cfo_integer_enabled = false;
args->cfo_correct_tol_hz = 50;
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)
@ -106,10 +108,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;

View File

@ -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