int srslte_ue_dl_decode_phich(srslte_ue_dl_t* q, srslte_dl_sf_cfg_t* sf, srslte_ue_dl_cfg_t* cfg, srslte_phich_grant_t* grant, srslte_phich_res_t* result) { srslte_phich_resource_t n_phich; uint32_t sf_idx = sf->tti % 10; set_mi_value(q, sf, cfg); srslte_phich_calc(&q->phich, grant, &n_phich); INFO("Decoding PHICH sf_idx=%d, n_prb_lowest=%d, n_dmrs=%d, I_phich=%d, n_group=%d, n_seq=%d, Ngroups=%d, Nsf=%d\n", sf_idx, grant->n_prb_lowest, grant->n_dmrs, grant->I_phich, n_phich.ngroup, n_phich.nseq, srslte_phich_ngroups(&q->phich), srslte_phich_nsf(&q->phich)); if (!srslte_phich_decode(&q->phich, sf, &q->chest_res, n_phich, q->sf_symbols, result)) { INFO("Decoded PHICH %d with distance %f\n", result->ack_value, result->distance); return 0; } else { ERROR("Error decoding PHICH\n"); return -1; } }
/* Computes n_group and n_seq according to Section 9.1.2 in 36.213 and calls phich processing function */ bool srslte_ue_dl_decode_phich(srslte_ue_dl_t *q, uint32_t sf_idx, uint32_t n_prb_lowest, uint32_t n_dmrs) { uint8_t ack_bit; float distance; uint32_t Ngroups = srslte_phich_ngroups(&q->phich); uint32_t ngroup = (n_prb_lowest+n_dmrs)%Ngroups; uint32_t nseq = ((n_prb_lowest/Ngroups)+n_dmrs)%(2*srslte_phich_nsf(&q->phich)); DEBUG("Decoding PHICH sf_idx=%d, n_prb_lowest=%d, n_dmrs=%d, n_group=%d, n_seq=%d\n", sf_idx, n_prb_lowest, n_dmrs, ngroup, nseq); if (!srslte_phich_decode(&q->phich, q->sf_symbols, q->ce, 0, ngroup, nseq, sf_idx, &ack_bit, &distance)) { INFO("Decoded PHICH %d with distance %f\n", ack_bit, distance); } else { fprintf(stderr, "Error decoding PHICH\n"); return false; } if (ack_bit && distance > 1.5) { return true; } else { return false; } }
bool srslte_ue_dl_decode_phich(srslte_ue_dl_t *q, uint32_t sf_idx, uint32_t n_prb_lowest, uint32_t n_dmrs) { uint8_t ack_bit; float distance; uint32_t ngroup, nseq; srslte_phich_calc(&q->phich, n_prb_lowest, n_dmrs, &ngroup, &nseq); INFO("Decoding PHICH sf_idx=%d, n_prb_lowest=%d, n_dmrs=%d, n_group=%d, n_seq=%d, Ngroups=%d, Nsf=%d\n", sf_idx, n_prb_lowest, n_dmrs, ngroup, nseq, srslte_phich_ngroups(&q->phich), srslte_phich_nsf(&q->phich)); if (!srslte_phich_decode(&q->phich, q->sf_symbols_m, q->ce_m, 0, ngroup, nseq, sf_idx, &ack_bit, &distance)) { q->last_phich_corr = distance; INFO("Decoded PHICH %d with distance %f\n", ack_bit, distance); } else { fprintf(stderr, "Error decoding PHICH\n"); return false; } if (ack_bit) { return true; } else { return false; } }
int main(int argc, char **argv) { srslte_phich_t phich; srslte_regs_t regs; int i, j; cf_t *ce[SRSLTE_MAX_PORTS]; int nof_re; cf_t *slot_symbols[SRSLTE_MAX_PORTS]; uint8_t ack[50][SRSLTE_PHICH_NORM_NSEQUENCES], ack_rx; uint32_t nsf; float distance; int cid, max_cid; uint32_t ngroup, nseq, max_nseq; parse_args(argc,argv); max_nseq = SRSLTE_CP_ISNORM(cell.cp)?SRSLTE_PHICH_NORM_NSEQUENCES:SRSLTE_PHICH_EXT_NSEQUENCES; nof_re = SRSLTE_CP_NORM_NSYMB * cell.nof_prb * SRSLTE_NRE; /* init memory */ for (i=0;i<SRSLTE_MAX_PORTS;i++) { ce[i] = malloc(sizeof(cf_t) * nof_re); if (!ce[i]) { perror("malloc"); exit(-1); } for (j=0;j<nof_re;j++) { ce[i][j] = 1; } slot_symbols[i] = malloc(sizeof(cf_t) * nof_re); if (!slot_symbols[i]) { perror("malloc"); exit(-1); } } if (cell.id == 1000) { cid = 0; max_cid = 503; } else { cid = cell.id; max_cid = cell.id; } while(cid <= max_cid) { cell.id = cid; printf("Testing CellID=%d...\n", cid); if (srslte_regs_init(®s, cell)) { fprintf(stderr, "Error initiating regs\n"); exit(-1); } if (srslte_phich_init(&phich, ®s, cell)) { fprintf(stderr, "Error creating PBCH object\n"); exit(-1); } for (nsf=0;nsf<10;nsf++) { srslte_phich_reset(&phich, slot_symbols); /* Transmit all PHICH groups and sequence numbers */ for (ngroup=0;ngroup<srslte_phich_ngroups(&phich);ngroup++) { for (nseq=0;nseq<max_nseq;nseq++) { ack[ngroup][nseq] = rand()%2; srslte_phich_encode(&phich, ack[ngroup][nseq], ngroup, nseq, nsf, slot_symbols); } } /* combine outputs */ for (i=1;i<cell.nof_ports;i++) { for (j=0;j<nof_re;j++) { slot_symbols[0][j] += slot_symbols[i][j]; } } /* Receive all PHICH groups and sequence numbers */ for (ngroup=0;ngroup<srslte_phich_ngroups(&phich);ngroup++) { for (nseq=0;nseq<max_nseq;nseq++) { if (srslte_phich_decode(&phich, slot_symbols[0], ce, 0, ngroup, nseq, nsf, &ack_rx, &distance)<0) { printf("Error decoding ACK\n"); exit(-1); } INFO("%d/%d, ack_tx: %d, ack_rx: %d, ns: %d, distance: %f\n", ngroup, nseq, ack[ngroup][nseq], ack_rx, nsf, distance); if (ack[ngroup][nseq] != ack_rx) { printf("Invalid received ACK: %d!=%d\n", ack[ngroup][nseq], ack_rx); exit(-1); } if (distance < 1.5) { printf("Error\n"); exit(-1); } } } } srslte_phich_free(&phich); srslte_regs_free(®s); cid++; } for (i=0;i<SRSLTE_MAX_PORTS;i++) { free(ce[i]); free(slot_symbols[i]); } printf("OK\n"); exit(0); }
/* the gateway function */ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) { int i; srslte_cell_t cell; srslte_phich_t phich; srslte_chest_dl_t chest; srslte_ofdm_t ofdm_rx; srslte_regs_t regs; uint32_t sf_idx; cf_t *input_fft, *input_signal; if (nrhs < NOF_INPUTS) { help(); return; } if (mexutils_read_cell(ENBCFG, &cell)) { help(); return; } if (mexutils_read_uint32_struct(ENBCFG, "NSubframe", &sf_idx)) { help(); return; } if (srslte_chest_dl_init(&chest, cell)) { mexErrMsgTxt("Error initializing equalizer\n"); return; } if (srslte_ofdm_rx_init(&ofdm_rx, cell.cp, cell.nof_prb)) { mexErrMsgTxt("Error initializing FFT\n"); return; } if (srslte_regs_init(®s, cell)) { mexErrMsgTxt("Error initiating regs\n"); return; } if (srslte_phich_init(&phich, ®s, cell)) { mexErrMsgTxt("Error creating PHICH object\n"); return; } // Read input signal input_signal = NULL; int insignal_len = mexutils_read_cf(INPUT, &input_signal); if (insignal_len < 0) { mexErrMsgTxt("Error reading input signal\n"); return; } if (insignal_len == SRSLTE_SF_LEN_RE(cell.nof_prb, cell.cp)) { input_fft = input_signal; } else { input_fft = srslte_vec_malloc(SRSLTE_SF_LEN_RE(cell.nof_prb, cell.cp) * sizeof(cf_t)); srslte_ofdm_rx_sf(&ofdm_rx, input_signal, input_fft); free(input_signal); } cf_t *ce[SRSLTE_MAX_PORTS]; for (i=0;i<cell.nof_ports;i++) { ce[i] = srslte_vec_malloc(SRSLTE_SF_LEN_RE(cell.nof_prb, cell.cp) * sizeof(cf_t)); } if (nrhs > NOF_INPUTS) { cf_t *cearray = NULL; mexutils_read_cf(prhs[NOF_INPUTS], &cearray); cf_t *cearray_ptr = cearray; for (i=0;i<cell.nof_ports;i++) { for (int j=0;j<SRSLTE_SF_LEN_RE(cell.nof_prb, cell.cp);j++) { ce[i][j] = *cearray_ptr; cearray_ptr++; } } if (cearray) { free(cearray); } } else { srslte_chest_dl_estimate(&chest, input_fft, ce, sf_idx); } float noise_power; if (nrhs > NOF_INPUTS + 1) { noise_power = mxGetScalar(prhs[NOF_INPUTS+1]); } else if (nrhs > NOF_INPUTS) { noise_power = 0; } else { noise_power = srslte_chest_dl_get_noise_estimate(&chest); } // Read hires values float *hires = NULL; int nhires = mexutils_read_f(HIRES, &hires); if (nhires != 2) { mexErrMsgTxt("Expecting 2 values for hires parameter\n"); return; } uint32_t ngroup = (uint32_t) hires[0]; uint32_t nseq = (uint32_t) hires[1]; uint8_t ack; float corr_res; int n = srslte_phich_decode(&phich, input_fft, ce, noise_power, ngroup, nseq, sf_idx, &ack, &corr_res); if (nlhs >= 1) { if (n < 0) { plhs[0] = mxCreateDoubleScalar(-1); } else { plhs[0] = mxCreateDoubleScalar(ack); } } if (nlhs >= 2) { mexutils_write_cf(phich.z, &plhs[1], 1, SRSLTE_PHICH_NBITS); } srslte_chest_dl_free(&chest); srslte_ofdm_rx_free(&ofdm_rx); srslte_phich_free(&phich); srslte_regs_free(®s); for (i=0;i<cell.nof_ports;i++) { free(ce[i]); } free(input_fft); return; }