/* Computes channel estimates for each reference in a slot and port. * Saves the nof_prb * 12 * nof_symbols channel estimates in the array ce */ void chest_ce_slot_port(chest_t *q, cf_t *input, cf_t *ce, int nslot, int port_id) { int i, j; cf_t x[2], y[MAX_NSYMB]; assert(nslot >= 0 && nslot < NSLOTS_X_FRAME); assert(port_id >= 0 && port_id < q->nof_ports); assert(q->refsignal[port_id][nslot].nsymbols <= 2); refsignal_t *r = &q->refsignal[port_id][nslot]; INFO("Estimating channel using %d reference signals\n", r->nof_refs); for (i=0;i<r->nof_refs;i++) { chest_ce_ref(q, input, nslot, port_id, i); } /* interpolate the symbols with references * in the freq domain */ for (i=0;i<r->nsymbols;i++) { interp_linear_offset(&r->ch_est[i * r->nof_refs/2], &ce[r->symbols_ref[i] * q->nof_prb * RE_X_RB], RE_X_RB/2, r->nof_refs/2, r->voffset, RE_X_RB/2-r->voffset); } /* now interpolate in the time domain */ for (i=0;i<q->nof_prb * RE_X_RB; i++) { for (j=0;j<r->nsymbols;j++) { x[j] = ce[r->symbols_ref[j] * q->nof_prb * RE_X_RB + i]; } interp_linear_offset(x, y, r->symbols_ref[1]-r->symbols_ref[0], 2, r->symbols_ref[0], 3); for (j=0;j<q->nof_symbols;j++) { ce[j * q->nof_prb * RE_X_RB + i] = y[j]; } } }
/* Computes channel estimates for each reference in a slot and port. * Saves the nof_prb * 12 * nof_symbols channel estimates in the array ce */ int chest_ce_slot_port(chest_t *q, cf_t *input, cf_t *ce, uint32_t nslot, uint32_t port_id) { uint32_t i, j; cf_t x[2], y[MAX_NSYMB]; int ret = LIBLTE_ERROR_INVALID_INPUTS; if (q != NULL && input != NULL && nslot < NSLOTS_X_FRAME && port_id < q->nof_ports) { if (q->refsignal[port_id][nslot].nsymbols <= 2) { refsignal_t *r = &q->refsignal[port_id][nslot]; DEBUG("Estimating channel slot=%d port=%d using %d reference signals\n", nslot, port_id, r->nof_refs); for (i=0;i<r->nof_refs;i++) { chest_ce_ref(q, input, nslot, port_id, i); } /* interpolate the symbols with references * in the freq domain */ for (i=0;i<r->nsymbols;i++) { #ifdef VOLK_INTERP interp_run_offset(&q->interp_freq[port_id], &r->ch_est[i * r->nof_refs/2], &ce[r->symbols_ref[i] * q->nof_re], r->voffset, RE_X_RB/2-r->voffset); #else interp_linear_offset(&r->ch_est[i * r->nof_refs/2], &ce[r->symbols_ref[i] * q->nof_re], RE_X_RB/2, r->nof_refs/2, r->voffset, RE_X_RB/2-r->voffset); #endif } /* now interpolate in the time domain */ for (i=0;i<q->nof_re; i++) { if (r->nsymbols > 1) { for (j=0;j<r->nsymbols;j++) { x[j] = ce[r->symbols_ref[j] * q->nof_re + i]; } #ifdef VOLK_INTERP interp_run_offset(&q->interp_time[port_id], x, y, r->symbols_ref[0], 3); #else interp_linear_offset(x, y, r->symbols_ref[1]-r->symbols_ref[0], 2, r->symbols_ref[0], 3); #endif } else { for (j=0;j<MAX_NSYMB;j++) { y[j] = ce[r->symbols_ref[0] * q->nof_re + i]; } } for (j=0;j<q->nof_symbols;j++) { ce[j * q->nof_re + i] = y[j]; } } ret = LIBLTE_SUCCESS; } } return ret; }
/* Performs 1st order linear interpolation */ void interp_linear(cf_t *input, cf_t *output, int M, int len) { interp_linear_offset(input, output, M, len, 0, 0); }