Added Time-domain EMA filter for channel estimation

master
ismagom 10 years ago
parent f475069033
commit 5d122ee44f

@ -478,8 +478,9 @@ int main(int argc, char **argv) {
#ifdef PRINT_CHANGE_SCHEDULIGN
if (ue_dl.dl_dci.mcs_idx != old_dl_dci.mcs_idx ||
ue_dl.dl_dci.alloc_type != old_dl_dci.alloc_type ||
ue_dl.dl_dci.type2_alloc.riv != ue_dl.dl_dci.type2_alloc.riv)
memcmp(&ue_dl.dl_dci.type0_alloc, &old_dl_dci.type0_alloc, sizeof(srslte_ra_type0_t)) ||
memcmp(&ue_dl.dl_dci.type1_alloc, &old_dl_dci.type1_alloc, sizeof(srslte_ra_type1_t)) ||
memcmp(&ue_dl.dl_dci.type2_alloc, &old_dl_dci.type2_alloc, sizeof(srslte_ra_type2_t)))
{
memcpy(&old_dl_dci, &ue_dl.dl_dci, sizeof(srslte_ra_dl_dci_t));
fflush(stdout);printf("\nCFI:\t%d\n", ue_dl.cfi);
@ -514,15 +515,14 @@ int main(int argc, char **argv) {
if (gain < 0) {
gain = 10*log10(srslte_agc_get_gain(&ue_sync.agc));
}
printf("CFO: %+6.2f KHz, SFO: %+6.2f Khz, "
"RSRP: %+5.1f dBm, SNR: %4.1f dB, "
"PDCCH-Miss: %5.2f%%, PDSCH-BLER: %5.2f%% Peak: %.2f Gain: %.1f dB\r",
srslte_ue_sync_get_cfo(&ue_sync)/1000, srslte_ue_sync_get_sfo(&ue_sync)/1000,
10*log10(rsrp*1000)-gain-cuhd_get_rx_gain_offset(uhd),
printf("CFO: %+6.2f KHz, "
"SNR: %4.1f dB, "
"PDCCH-Miss: %5.2f%%, PDSCH-BLER: %5.2f%%\r",
srslte_ue_sync_get_cfo(&ue_sync)/1000,
10*log10(rsrp/noise),
100*(1-(float) ue_dl.nof_detected/nof_trials),
(float) 100*ue_dl.pkt_errors/ue_dl.pkts_total,
srslte_agc_get_output_level(&ue_sync.agc), gain);
(float) 100*ue_dl.pkt_errors/ue_dl.pkts_total);
}
break;
}

@ -76,6 +76,7 @@ typedef struct {
float rssi[SRSLTE_MAX_PORTS];
float rsrp[SRSLTE_MAX_PORTS];
float noise_estimate[SRSLTE_MAX_PORTS];
float filter_time_ema;
} srslte_chest_dl_t;
@ -92,6 +93,9 @@ SRSLTE_API int srslte_chest_dl_set_filter_time(srslte_chest_dl_t *q,
float *filter,
uint32_t filter_len);
SRSLTE_API void srslte_chest_dl_set_filter_time_ema(srslte_chest_dl_t *q,
float ema_coefficient);
SRSLTE_API int srslte_chest_dl_estimate(srslte_chest_dl_t *q,
cf_t *input,
cf_t *ce[SRSLTE_MAX_PORTS],

@ -83,6 +83,9 @@ SRSLTE_API void srslte_vec_sum_ccc(cf_t *x, cf_t *y, cf_t *z, uint32_t len);
SRSLTE_API void srslte_vec_sub_fff(float *x, float *y, float *z, uint32_t len);
SRSLTE_API void srslte_vec_sub_ccc(cf_t *x, cf_t *y, cf_t *z, uint32_t len);
/* EMA filter: output=coeff*new_data + (1-coeff)*average */
SRSLTE_API void srslte_vec_ema_filter(cf_t *new_data, cf_t *average, cf_t *output, float coeff, uint32_t len);
/* Square distance */
SRSLTE_API void srslte_vec_square_dist(cf_t symbol, cf_t *points, float *distance, uint32_t npoints);

@ -126,11 +126,10 @@ int srslte_chest_dl_init(srslte_chest_dl_t *q, srslte_cell_t cell)
//float f[3]={0.2, 0.6, 0.2};
//srslte_chest_dl_set_filter_freq(q, f, 3);
float f[5]={0.1, 0.2, 0.4, 0.2, 0.1};
srslte_chest_dl_set_filter_freq(q, f, 5);
float f[9]={0.025, 0.075, 0.05, 0.15, 0.4, 0.15, 0.05, 0.075, 0.025};
srslte_chest_dl_set_filter_freq(q, f, 9);
float t[2]={0.5, 0.5};
srslte_chest_dl_set_filter_time(q, t, 0);
//srslte_chest_dl_set_filter_time_ema(q, 0.8);
q->cell = cell;
}
@ -191,6 +190,10 @@ int srslte_chest_dl_set_filter_freq(srslte_chest_dl_t *q, float *filter, uint32_
}
}
void srslte_chest_dl_set_filter_time_ema(srslte_chest_dl_t *q, float ema_coefficient) {
q->filter_time_ema = ema_coefficient;
}
int srslte_chest_dl_set_filter_time(srslte_chest_dl_t *q, float *filter, uint32_t filter_len) {
if (filter_len <= SRSLTE_CHEST_MAX_FILTER_TIME_LEN) {
q->filter_time_len = filter_len;
@ -263,31 +266,62 @@ static void average_pilots(srslte_chest_dl_t *q, uint32_t port_id)
q->noise_estimate[port_id] = estimate_noise_port(q, port_id, q->tmp_freqavg);
#endif
for (l=0;l<srslte_refsignal_cs_nof_symbols(port_id);l++) {
/* Filter in time domain. */
if (q->filter_time_len > 0) {
/* Move last symbols */
for (i=0;i<q->filter_time_len-1;i++) {
memcpy(q->tmp_timeavg[i], q->tmp_timeavg[i+1], nref*sizeof(cf_t));
}
/* Save last symbol to buffer */
memcpy(q->tmp_timeavg[q->filter_time_len-1], &pilot_tmp(0), nref*sizeof(cf_t));
/* Multiply all symbols by filter and add them */
if (l > 0) {
bzero(&pilot_avg(0), nref * sizeof(cf_t));
for (i=0;i<q->filter_time_len;i++) {
srslte_vec_sc_prod_cfc(q->tmp_timeavg[i], q->filter_time[i], q->tmp_timeavg_mult, nref);
srslte_vec_sum_ccc(q->tmp_timeavg_mult, &pilot_avg(0), &pilot_avg(0), nref);
}
//#define EMA_VEC
/* Filter with Exponential moving average (IIR) */
if (q->filter_time_ema > 0) {
#ifdef EMA_VEC
srslte_vec_ema_filter(&q->tmp_freqavg[0],
&q->pilot_estimates_average[port_id][2*q->cell.nof_prb*srslte_refsignal_cs_nof_symbols(port_id)],
&q->pilot_estimates_average[port_id][0],
q->filter_time_ema,
nref);
for (l=1;l<srslte_refsignal_cs_nof_symbols(port_id);l++) {
srslte_vec_ema_filter(&q->tmp_freqavg[2*q->cell.nof_prb*l],
&q->pilot_estimates_average[port_id][2*q->cell.nof_prb*(l-1)],
&q->pilot_estimates_average[port_id][2*q->cell.nof_prb*l],
q->filter_time_ema,
nref);
}
#else
for (i=0;i<nref;i++) {
l=0;
pilot_avg(i) = SRSLTE_VEC_EMA(pilot_tmp(i), q->pilot_estimates_average[port_id][
SRSLTE_REFSIGNAL_PILOT_IDX(i,srslte_refsignal_cs_nof_symbols(port_id),q->cell)], q->filter_time_ema);
for (l=1;l<srslte_refsignal_cs_nof_symbols(port_id);l++) {
pilot_avg(i) = SRSLTE_VEC_EMA(pilot_tmp(i), q->pilot_estimates_average[port_id][SRSLTE_REFSIGNAL_PILOT_IDX(i,l-1,q->cell)], q->filter_time_ema);
}
}
#endif
} else {
/* Filter with FIR or don't filter */
for (l=0;l<srslte_refsignal_cs_nof_symbols(port_id);l++) {
/* Filter in time domain. */
if (q->filter_time_len > 0) {
/* Move last symbols */
for (i=0;i<q->filter_time_len-1;i++) {
memcpy(q->tmp_timeavg[i], q->tmp_timeavg[i+1], nref*sizeof(cf_t));
}
/* Save last symbol to buffer */
memcpy(q->tmp_timeavg[q->filter_time_len-1], &pilot_tmp(0), nref*sizeof(cf_t));
/* Multiply all symbols by filter and add them */
if (l > 0) {
bzero(&pilot_avg(0), nref * sizeof(cf_t));
for (i=0;i<q->filter_time_len;i++) {
srslte_vec_sc_prod_cfc(q->tmp_timeavg[i], q->filter_time[i], q->tmp_timeavg_mult, nref);
srslte_vec_sum_ccc(q->tmp_timeavg_mult, &pilot_avg(0), &pilot_avg(0), nref);
}
} else {
memcpy(&pilot_avg(0), &pilot_tmp(0), nref * sizeof(cf_t));
}
} else {
memcpy(&pilot_avg(0), &pilot_tmp(0), nref * sizeof(cf_t));
memcpy(&pilot_avg(0), &pilot_tmp(0), nref * sizeof(cf_t));
}
} else {
memcpy(&pilot_avg(0), &pilot_tmp(0), nref * sizeof(cf_t));
}
}
}
}
#define cesymb(i) ce[SRSLTE_RE_IDX(q->cell.nof_prb,i,0)]

@ -38,6 +38,8 @@
#define MAX_CANDIDATES 64
#define PDSCH_DO_ZF
int srslte_ue_dl_init(srslte_ue_dl_t *q,
srslte_cell_t cell)
{
@ -225,9 +227,18 @@ int srslte_ue_dl_decode_rnti_rv_packet(srslte_ue_dl_t *q, srslte_dci_msg_t *dci_
if (q->pdsch_cfg.rv == 0) {
srslte_softbuffer_rx_reset(&q->softbuffer);
}
#ifdef PDSCH_DO_ZF
float noise_estimate = 0;
#else
float noise_estimate = srslte_chest_dl_get_noise_estimate(&q->chest);
#endif
if (q->pdsch_cfg.grant.mcs.mod > 0 && q->pdsch_cfg.grant.mcs.tbs >= 0) {
ret = srslte_pdsch_decode_rnti(&q->pdsch, &q->pdsch_cfg, &q->softbuffer,
q->sf_symbols, q->ce, 0, rnti, data);
q->sf_symbols, q->ce,
noise_estimate,
rnti, data);
if (ret == SRSLTE_ERROR) {
q->pkt_errors++;

@ -62,6 +62,12 @@ float srslte_vec_acc_ff(float *x, uint32_t len) {
#endif
}
void srslte_vec_ema_filter(cf_t *new_data, cf_t *average, cf_t *output, float coeff, uint32_t len) {
srslte_vec_sc_prod_cfc(new_data, coeff, new_data, len);
srslte_vec_sc_prod_cfc(average, 1-coeff, output, len);
srslte_vec_sum_ccc(output, new_data, output, len);
}
cf_t srslte_vec_acc_cc(cf_t *x, uint32_t len) {
int i;
cf_t z=0;

Loading…
Cancel
Save