void srslte_interp_linear_vector(srslte_interp_linsrslte_vec_t *q, cf_t *in0, cf_t *in1, cf_t *between, uint32_t M) { uint32_t i; srslte_vec_sub_ccc(in1, in0, q->diff_vec, q->vector_len); srslte_vec_sc_prod_cfc(q->diff_vec, (float) 1/M, q->diff_vec, q->vector_len); srslte_vec_sum_ccc(in0, q->diff_vec, between, q->vector_len); for (i=0;i<M-1;i++) { srslte_vec_sum_ccc(between, q->diff_vec, &between[q->vector_len], q->vector_len); between += q->vector_len; } }
void srslte_interp_linear_offset(srslte_interp_lin_t *q, cf_t *input, cf_t *output, uint32_t off_st, uint32_t off_end) { uint32_t i, j; cf_t diff; i=0; for (j=0;j<off_st;j++) { output[j] = input[i] + (j+1) * (input[i+1]-input[i]) / q->M; } srslte_vec_sub_ccc(&input[1], input, q->diff_vec, (q->vector_len-1)); srslte_vec_sc_prod_cfc(q->diff_vec, (float) 1/q->M, q->diff_vec, q->vector_len-1); for (i=0;i<q->vector_len-1;i++) { for (j=0;j<q->M;j++) { output[i*q->M+j+off_st] = input[i]; q->diff_vec2[i*q->M+j] = q->diff_vec[i]; } srslte_vec_prod_cfc(&q->diff_vec2[i*q->M],q->ramp,&q->diff_vec2[i*q->M],q->M); } srslte_vec_sum_ccc(&output[off_st], q->diff_vec2, &output[off_st], q->M*(q->vector_len-1)); if (q->vector_len > 1) { diff = input[q->vector_len-1]-input[q->vector_len-2]; for (j=0;j<off_end;j++) { output[i*q->M+j+off_st] = input[i] + j * diff / q->M; } } }
int srslte_chest_ul_estimate_pucch(srslte_chest_ul_t *q, cf_t *input, cf_t *ce, srslte_pucch_format_t format, uint32_t n_pucch, uint32_t sf_idx, uint8_t *pucch2_ack_bits) { if (!q->dmrs_signal_configured) { fprintf(stderr, "Error must call srslte_chest_ul_set_cfg() before using the UL estimator\n"); return SRSLTE_ERROR; } int n_rs = srslte_refsignal_dmrs_N_rs(format, q->cell.cp); if (!n_rs) { fprintf(stderr, "Error computing N_rs\n"); return SRSLTE_ERROR; } int nrefs_sf = SRSLTE_NRE*n_rs*2; /* Get references from the input signal */ srslte_refsignal_dmrs_pucch_get(&q->dmrs_signal, format, n_pucch, input, q->pilot_recv_signal); /* Generate known pilots */ uint8_t pucch2_bits[2] = {0, 0}; if (format == SRSLTE_PUCCH_FORMAT_2A || format == SRSLTE_PUCCH_FORMAT_2B) { float max = -1e9; int i_max = 0; int m = 0; if (format == SRSLTE_PUCCH_FORMAT_2A) { m = 2; } else { m = 4; } for (int i=0;i<m;i++) { pucch2_bits[0] = i%2; pucch2_bits[1] = i/2; srslte_refsignal_dmrs_pucch_gen(&q->dmrs_signal, format, n_pucch, sf_idx, pucch2_bits, q->pilot_known_signal); srslte_vec_prod_conj_ccc(q->pilot_recv_signal, q->pilot_known_signal, q->pilot_estimates_tmp[i], nrefs_sf); float x = cabsf(srslte_vec_acc_cc(q->pilot_estimates_tmp[i], nrefs_sf)); if (x >= max) { max = x; i_max = i; } } memcpy(q->pilot_estimates, q->pilot_estimates_tmp[i_max], nrefs_sf*sizeof(cf_t)); pucch2_ack_bits[0] = i_max%2; pucch2_ack_bits[1] = i_max/2; } else { srslte_refsignal_dmrs_pucch_gen(&q->dmrs_signal, format, n_pucch, sf_idx, pucch2_bits, q->pilot_known_signal); /* Use the known DMRS signal to compute Least-squares estimates */ srslte_vec_prod_conj_ccc(q->pilot_recv_signal, q->pilot_known_signal, q->pilot_estimates, nrefs_sf); } if (ce != NULL) { /* FIXME: Currently averaging entire slot, performance good enough? */ for (int ns=0;ns<2;ns++) { // Average all slot for (int i=1;i<n_rs;i++) { srslte_vec_sum_ccc(&q->pilot_estimates[ns*n_rs*SRSLTE_NRE], &q->pilot_estimates[(i+ns*n_rs)*SRSLTE_NRE], &q->pilot_estimates[ns*n_rs*SRSLTE_NRE], SRSLTE_NRE); } srslte_vec_sc_prod_ccc(&q->pilot_estimates[ns*n_rs*SRSLTE_NRE], (float) 1.0/n_rs, &q->pilot_estimates[ns*n_rs*SRSLTE_NRE], SRSLTE_NRE); // Average in freq domain srslte_chest_average_pilots(&q->pilot_estimates[ns*n_rs*SRSLTE_NRE], &q->pilot_recv_signal[ns*n_rs*SRSLTE_NRE], q->smooth_filter, SRSLTE_NRE, 1, q->smooth_filter_len); // Determine n_prb uint32_t n_prb = srslte_pucch_n_prb(&q->dmrs_signal.pucch_cfg, format, n_pucch, q->cell.nof_prb, q->cell.cp, ns); // copy estimates to slot for (int i=0;i<SRSLTE_CP_NSYMB(q->cell.cp);i++) { memcpy(&ce[SRSLTE_RE_IDX(q->cell.nof_prb, i+ns*SRSLTE_CP_NSYMB(q->cell.cp), n_prb*SRSLTE_NRE)], &q->pilot_recv_signal[ns*n_rs*SRSLTE_NRE], sizeof(cf_t)*SRSLTE_NRE); } } } return 0; }
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); }