void srslte_ue_dl_free(srslte_ue_dl_t *q) { if (q) { for (int port = 0; port < SRSLTE_MAX_PORTS; port++) { srslte_ofdm_rx_free(&q->fft[port]); } srslte_ofdm_rx_free(&q->fft_mbsfn); srslte_chest_dl_free(&q->chest); srslte_regs_free(&q->regs); srslte_pcfich_free(&q->pcfich); srslte_phich_free(&q->phich); srslte_pdcch_free(&q->pdcch); srslte_pdsch_free(&q->pdsch); srslte_pmch_free(&q->pmch); srslte_cfo_free(&q->sfo_correct); for (int i = 0; i < SRSLTE_MAX_TB; i++) { srslte_softbuffer_rx_free(q->softbuffers[i]); if (q->softbuffers[i]) { free(q->softbuffers[i]); } } for (int j = 0; j < SRSLTE_MAX_PORTS; j++) { if (q->sf_symbols_m[j]) { free(q->sf_symbols_m[j]); } for (uint32_t i=0;i<SRSLTE_MAX_PORTS;i++) { if (q->ce_m[i][j]) { free(q->ce_m[i][j]); } } } bzero(q, sizeof(srslte_ue_dl_t)); } }
int srslte_softbuffer_rx_init(srslte_softbuffer_rx_t *q, uint32_t nof_prb) { int ret = SRSLTE_ERROR_INVALID_INPUTS; if (q != NULL) { bzero(q, sizeof(srslte_softbuffer_rx_t)); ret = srslte_ra_tbs_from_idx(26, nof_prb); if (ret != SRSLTE_ERROR) { q->max_cb = (uint32_t) ret / (SRSLTE_TCOD_MAX_LEN_CB - 24) + 1; ret = SRSLTE_ERROR; q->buffer_f = srslte_vec_malloc(sizeof(int16_t*) * q->max_cb); if (!q->buffer_f) { perror("malloc"); goto clean_exit; } q->data = srslte_vec_malloc(sizeof(uint8_t*) * q->max_cb); if (!q->data) { perror("malloc"); goto clean_exit; } q->cb_crc = srslte_vec_malloc(sizeof(bool) * q->max_cb); if (!q->cb_crc) { perror("malloc"); goto clean_exit; } bzero(q->cb_crc, sizeof(bool) * q->max_cb); // FIXME: Use HARQ buffer limitation based on UE category for (uint32_t i=0;i<q->max_cb;i++) { q->buffer_f[i] = srslte_vec_malloc(sizeof(int16_t) * SOFTBUFFER_SIZE); if (!q->buffer_f[i]) { perror("malloc"); goto clean_exit; } q->data[i] = srslte_vec_malloc(sizeof(uint8_t) * 6144/8); if (!q->data[i]) { perror("malloc"); goto clean_exit; } } //srslte_softbuffer_rx_reset(q); ret = SRSLTE_SUCCESS; } } clean_exit: if (ret != SRSLTE_SUCCESS) { srslte_softbuffer_rx_free(q); } return ret; }
void srslte_ue_dl_free(srslte_ue_dl_t *q) { if (q) { srslte_ofdm_rx_free(&q->fft); srslte_chest_dl_free(&q->chest); srslte_regs_free(&q->regs); srslte_pcfich_free(&q->pcfich); srslte_phich_free(&q->phich); srslte_pdcch_free(&q->pdcch); srslte_pdsch_free(&q->pdsch); srslte_softbuffer_rx_free(&q->softbuffer); if (q->sf_symbols) { free(q->sf_symbols); } for (uint32_t i=0;i<q->cell.nof_ports;i++) { if (q->ce[i]) { free(q->ce[i]); } } bzero(q, sizeof(srslte_ue_dl_t)); } }
int main(int argc, char **argv) { uint32_t i, j, k; int ret = -1; struct timeval t[3]; srslte_softbuffer_tx_t *softbuffers_tx[SRSLTE_MAX_CODEWORDS]; int M=1; parse_args(argc,argv); /* Initialise to zeros */ bzero(&pmch_tx, sizeof(srslte_pmch_t)); bzero(&pmch_rx, sizeof(srslte_pmch_t)); bzero(&pmch_cfg, sizeof(srslte_pdsch_cfg_t)); bzero(ce, sizeof(cf_t*)*SRSLTE_MAX_PORTS); bzero(tx_slot_symbols, sizeof(cf_t*)*SRSLTE_MAX_PORTS); bzero(rx_slot_symbols, sizeof(cf_t*)*SRSLTE_MAX_PORTS); cell.nof_ports = 1; srslte_ra_dl_dci_t dci; bzero(&dci, sizeof(srslte_ra_dl_dci_t)); dci.type0_alloc.rbg_bitmask = 0xffffffff; /* If transport block 0 is enabled */ grant.tb_en[0] = true; grant.tb_en[1] = false; grant.mcs[0].idx = mcs_idx; grant.nof_prb = cell.nof_prb; grant.sf_type = SRSLTE_SF_MBSFN; srslte_dl_fill_ra_mcs(&grant.mcs[0], cell.nof_prb); grant.Qm[0] = srslte_mod_bits_x_symbol(grant.mcs[0].mod); for(int i = 0; i < 2; i++){ for(int j = 0; j < grant.nof_prb; j++){ grant.prb_idx[i][j] = true; } } /* init memory */ for (i=0;i<SRSLTE_MAX_PORTS;i++) { for (j = 0; j < SRSLTE_MAX_PORTS; j++) { ce[i][j] = srslte_vec_malloc(sizeof(cf_t) * NOF_CE_SYMBOLS); if (!ce[i][j]) { perror("srslte_vec_malloc"); goto quit; } for (k = 0; k < NOF_CE_SYMBOLS; k++) { ce[i][j][k] = (i == j) ? 1.0f : 0.0f; } } rx_slot_symbols[i] = srslte_vec_malloc(sizeof(cf_t) * SRSLTE_SF_LEN_RE(cell.nof_prb, cell.cp)); if (!rx_slot_symbols[i]) { perror("srslte_vec_malloc"); goto quit; } } for (i = 0; i < SRSLTE_MAX_CODEWORDS; i++) { softbuffers_tx[i] = calloc(sizeof(srslte_softbuffer_tx_t), 1); if (!softbuffers_tx[i]) { fprintf(stderr, "Error allocating TX soft buffer\n"); } if (srslte_softbuffer_tx_init(softbuffers_tx[i], cell.nof_prb)) { fprintf(stderr, "Error initiating TX soft buffer\n"); goto quit; } } for (i = 0; i < cell.nof_ports; i++) { tx_slot_symbols[i] = calloc(SRSLTE_SF_LEN_RE(cell.nof_prb, cell.cp), sizeof(cf_t)); if (!tx_slot_symbols[i]) { perror("srslte_vec_malloc"); goto quit; } } for (int i = 0; i < SRSLTE_MAX_CODEWORDS; i++) { if (grant.tb_en[i]) { data_tx[i] = srslte_vec_malloc(sizeof(uint8_t) * grant.mcs[i].tbs); if (!data_tx[i]) { perror("srslte_vec_malloc"); goto quit; } bzero(data_tx[i], sizeof(uint8_t) * grant.mcs[i].tbs); data_rx[i] = srslte_vec_malloc(sizeof(uint8_t) * grant.mcs[i].tbs); if (!data_rx[i]) { perror("srslte_vec_malloc"); goto quit; } bzero(data_rx[i], sizeof(uint8_t) * grant.mcs[i].tbs); } } for (i = 0; i < SRSLTE_MAX_CODEWORDS; i++) { softbuffers_rx[i] = calloc(sizeof(srslte_softbuffer_rx_t), 1); if (!softbuffers_rx[i]) { fprintf(stderr, "Error allocating RX soft buffer\n"); goto quit; } if (srslte_softbuffer_rx_init(softbuffers_rx[i], cell.nof_prb)) { fprintf(stderr, "Error initiating RX soft buffer\n"); goto quit; } } #ifdef DO_OFDM for (i = 0; i < cell.nof_ports; i++) { tx_sf_symbols[i] = srslte_vec_malloc(sizeof(cf_t) * SRSLTE_SF_LEN_PRB(cell.nof_prb)); if (srslte_ofdm_tx_init_mbsfn(&ifft_mbsfn[i], SRSLTE_CP_EXT, tx_slot_symbols[i], tx_sf_symbols[i], cell.nof_prb)) { fprintf(stderr, "Error creating iFFT object\n"); exit(-1); } srslte_ofdm_set_non_mbsfn_region(&ifft_mbsfn[i], non_mbsfn_region); srslte_ofdm_set_normalize(&ifft_mbsfn[i], true); } for (i = 0; i < nof_rx_antennas; i++) { rx_sf_symbols[i] = srslte_vec_malloc(sizeof(cf_t) * SRSLTE_SF_LEN_PRB(cell.nof_prb)); if (srslte_ofdm_rx_init_mbsfn(&fft_mbsfn[i], SRSLTE_CP_EXT, rx_sf_symbols[i], rx_slot_symbols[i], cell.nof_prb)) { fprintf(stderr, "Error creating iFFT object\n"); exit(-1); } srslte_ofdm_set_non_mbsfn_region(&fft_mbsfn[i], non_mbsfn_region); srslte_ofdm_set_normalize(&fft_mbsfn[i], true); } #endif /* DO_OFDM */ /* Configure PDSCH */ if (srslte_pmch_cfg(&pmch_cfg, cell, &grant, cfi, subframe)) { fprintf(stderr, "Error configuring PMCH\n"); exit(-1); } if (srslte_pmch_cfg(&pmch_cfg, cell, &grant, cfi, subframe)) { fprintf(stderr, "Error configuring PMCH\n"); exit(-1); } INFO(" Global:\n"); INFO(" nof_prb=%d\n", cell.nof_prb); INFO(" nof_ports=%d\n", cell.nof_ports); INFO(" id=%d\n", cell.id); INFO(" cp=%s\n", srslte_cp_string(cell.cp)); INFO(" phich_length=%d\n", (int) cell.phich_length); INFO(" phich_resources=%d\n", (int) cell.phich_resources); INFO(" nof_prb=%d\n", pmch_cfg.grant.nof_prb); INFO(" sf_idx=%d\n", pmch_cfg.sf_idx); INFO(" mimo_type=%s\n", srslte_mimotype2str(pmch_cfg.mimo_type)); INFO(" nof_layers=%d\n", pmch_cfg.nof_layers); INFO(" nof_tb=%d\n", SRSLTE_RA_DL_GRANT_NOF_TB(&pmch_cfg.grant)); INFO(" Qm=%d\n", pmch_cfg.grant.Qm[0]); INFO(" mcs.idx=0x%X\n", pmch_cfg.grant.mcs[0].idx); INFO(" mcs.tbs=%d\n", pmch_cfg.grant.mcs[0].tbs); INFO(" mcs.mod=%s\n", srslte_mod_string(pmch_cfg.grant.mcs[0].mod)); INFO(" rv=%d\n", pmch_cfg.rv[0]); INFO(" lstart=%d\n", pmch_cfg.nbits[0].lstart); INFO(" nof_bits=%d\n", pmch_cfg.nbits[0].nof_bits); INFO(" nof_re=%d\n", pmch_cfg.nbits[0].nof_re); INFO(" nof_symb=%d\n", pmch_cfg.nbits[0].nof_symb); if (srslte_pmch_init(&pmch_tx, cell.nof_prb)) { fprintf(stderr, "Error creating PMCH object\n"); } srslte_pmch_set_area_id(&pmch_tx, mbsfn_area_id); if (srslte_pmch_init(&pmch_rx, cell.nof_prb)) { fprintf(stderr, "Error creating PMCH object\n"); } srslte_pmch_set_area_id(&pmch_rx, mbsfn_area_id); for (int tb = 0; tb < SRSLTE_MAX_CODEWORDS; tb++) { if (grant.tb_en[tb]) { for (int byte = 0; byte < grant.mcs[tb].tbs / 8; byte++) { data_tx[tb][byte] = (uint8_t) (rand() % 256); } } } if (srslte_pmch_encode(&pmch_tx, &pmch_cfg, softbuffers_tx[0], data_tx[0], mbsfn_area_id, tx_slot_symbols)) { fprintf(stderr, "Error encoding PDSCH\n"); exit(-1); } gettimeofday(&t[2], NULL); get_time_interval(t); printf("ENCODED in %.2f (PHY bitrate=%.2f Mbps. Processing bitrate=%.2f Mbps)\n", (float) t[0].tv_usec/M, (float) (grant.mcs[0].tbs + grant.mcs[1].tbs)/1000.0f, (float) (grant.mcs[0].tbs + grant.mcs[1].tbs)*M/t[0].tv_usec); #ifdef DO_OFDM for (i = 0; i < cell.nof_ports; i++) { /* For each Tx antenna modulate OFDM */ srslte_ofdm_tx_sf(&ifft_mbsfn[i]); } /* combine outputs */ for (j = 0; j < nof_rx_antennas; j++) { for (k = 0; k < NOF_CE_SYMBOLS; k++) { rx_sf_symbols[j][k] = 0.0f; for (i = 0; i < cell.nof_ports; i++) { rx_sf_symbols[j][k] += tx_sf_symbols[i][k] * ce[i][j][k]; } } } #else /* combine outputs */ for (j = 0; j < nof_rx_antennas; j++) { for (k = 0; k < SRSLTE_SF_LEN_RE(cell.nof_prb, cell.cp); k++) { rx_slot_symbols[j][k] = 0.0f; for (i = 0; i < cell.nof_ports; i++) { rx_slot_symbols[j][k] += tx_slot_symbols[i][k] * ce[i][j][k]; } } } #endif int r=0; gettimeofday(&t[1], NULL); #ifdef DO_OFDM /* For each Rx antenna demodulate OFDM */ for (i = 0; i < nof_rx_antennas; i++) { srslte_ofdm_rx_sf(&fft_mbsfn[i]); } #endif for (i = 0; i < SRSLTE_MAX_CODEWORDS; i++) { if (grant.tb_en[i]) { srslte_softbuffer_rx_reset_tbs(softbuffers_rx[i], (uint32_t) grant.mcs[i].tbs); } } r = srslte_pmch_decode(&pmch_rx, &pmch_cfg, softbuffers_rx[0],rx_slot_symbols[0], ce[0],0,mbsfn_area_id, data_rx[0]); gettimeofday(&t[2], NULL); get_time_interval(t); printf("DECODED %s in %.2f (PHY bitrate=%.2f Mbps. Processing bitrate=%.2f Mbps)\n", r?"Error":"OK", (float) t[0].tv_usec/M, (float) (grant.mcs[0].tbs + grant.mcs[1].tbs)/1000.0f, (float) (grant.mcs[0].tbs + grant.mcs[1].tbs)*M/t[0].tv_usec); /* If there is an error in PDSCH decode */ if (r) { ret = -1; goto quit; } /* Check Tx and Rx bytes */ for (int tb = 0; tb < SRSLTE_MAX_CODEWORDS; tb++) { if (grant.tb_en[tb]) { for (int byte = 0; byte < grant.mcs[tb].tbs / 8; byte++) { if (data_tx[tb][byte] != data_rx[tb][byte]) { ERROR("Found BYTE error in TB %d (%02X != %02X), quiting...", tb, data_tx[tb][byte], data_rx[tb][byte]); ret = SRSLTE_ERROR; goto quit; } } } } ret = SRSLTE_SUCCESS; quit: srslte_pmch_free(&pmch_tx); srslte_pmch_free(&pmch_rx); for (i = 0; i < SRSLTE_MAX_CODEWORDS; i++) { srslte_softbuffer_tx_free(softbuffers_tx[i]); if (softbuffers_tx[i]) { free(softbuffers_tx[i]); } srslte_softbuffer_rx_free(softbuffers_rx[i]); if (softbuffers_rx[i]) { free(softbuffers_rx[i]); } if (data_tx[i]) { free(data_tx[i]); } if (data_rx[i]) { free(data_rx[i]); } } for (i=0;i<SRSLTE_MAX_PORTS;i++) { for (j = 0; j < SRSLTE_MAX_PORTS; j++) { if (ce[i][j]) { free(ce[i][j]); } } if (tx_slot_symbols[i]) { free(tx_slot_symbols[i]); } if (rx_slot_symbols[i]) { free(rx_slot_symbols[i]); } } if (ret) { printf("Error\n"); } else { printf("Ok\n"); } exit(ret); }
int main(int argc, char **argv) { srslte_pdsch_t pdsch; uint32_t i, j; uint8_t *data = NULL; cf_t *ce[SRSLTE_MAX_PORTS]; cf_t *slot_symbols[SRSLTE_MAX_PORTS]; int ret = -1; struct timeval t[3]; srslte_pdsch_cfg_t pdsch_cfg; srslte_softbuffer_tx_t softbuffer_tx; srslte_softbuffer_rx_t softbuffer_rx; uint32_t rv; parse_args(argc,argv); bzero(&pdsch, sizeof(srslte_pdsch_t)); bzero(&pdsch_cfg, sizeof(srslte_pdsch_cfg_t)); bzero(ce, sizeof(cf_t*)*SRSLTE_MAX_PORTS); bzero(slot_symbols, sizeof(cf_t*)*SRSLTE_MAX_PORTS); bzero(&softbuffer_rx, sizeof(srslte_softbuffer_rx_t)); bzero(&softbuffer_tx, sizeof(srslte_softbuffer_tx_t)); srslte_ra_dl_grant_t grant; grant.mcs.tbs = tbs; grant.mcs.mod = modulation; grant.Qm = srslte_mod_bits_x_symbol(grant.mcs.mod); grant.nof_prb = cell.nof_prb; // Allocate all PRB for (i=0;i<grant.nof_prb;i++) { grant.prb_idx[0][i] = true; } memcpy(&grant.prb_idx[1], &grant.prb_idx[0], SRSLTE_MAX_PRB * sizeof(bool)); /* Configure PDSCH */ if (srslte_pdsch_cfg(&pdsch_cfg, cell, &grant, cfi, subframe, 1234, 0)) { fprintf(stderr, "Error configuring PDSCH\n"); exit(-1); } /* init memory */ for (i=0;i<cell.nof_ports;i++) { ce[i] = malloc(sizeof(cf_t) * SRSLTE_SF_LEN_RE(cell.nof_prb, cell.cp)); if (!ce[i]) { perror("malloc"); goto quit; } for (j=0;j<SRSLTE_SF_LEN_RE(cell.nof_prb, cell.cp);j++) { ce[i][j] = 1; } slot_symbols[i] = calloc(sizeof(cf_t) , SRSLTE_SF_LEN_RE(cell.nof_prb, cell.cp)); if (!slot_symbols[i]) { perror("malloc"); goto quit; } } data = malloc(sizeof(uint8_t) * tbs/8); if (!data) { perror("malloc"); goto quit; } if (srslte_pdsch_init(&pdsch, cell)) { fprintf(stderr, "Error creating PDSCH object\n"); goto quit; } srslte_pdsch_set_rnti(&pdsch, 1234); if (srslte_softbuffer_tx_init(&softbuffer_tx, cell.nof_prb)) { fprintf(stderr, "Error initiating TX soft buffer\n"); goto quit; } if (srslte_softbuffer_rx_init(&softbuffer_rx, cell.nof_prb)) { fprintf(stderr, "Error initiating RX soft buffer\n"); goto quit; } if (SRSLTE_VERBOSE_ISNONE()) { printf("Decoding TBS: %d\r",grant.mcs.tbs); } for (i=0;i<grant.mcs.tbs/8;i++) { data[i] = rand()%256; } for (rv=0;rv<=rv_idx;rv++) { pdsch_cfg.rv = rv; if (srslte_pdsch_encode(&pdsch, &pdsch_cfg, &softbuffer_tx, data, slot_symbols)) { fprintf(stderr, "Error encoding PDSCH\n"); goto quit; } /* combine outputs */ for (i=0;i<cell.nof_ports;i++) { for (j=0;j<SRSLTE_SF_LEN_RE(cell.nof_prb, cell.cp);j++) { if (i > 0) { slot_symbols[0][j] += slot_symbols[i][j]; } ce[i][j] = 1; } } gettimeofday(&t[1], NULL); int r = srslte_pdsch_decode(&pdsch, &pdsch_cfg, &softbuffer_rx, slot_symbols[0], ce, 0, data); gettimeofday(&t[2], NULL); get_time_interval(t); if (r) { printf("Error decoding TBS: %d\n", grant.mcs.tbs); ret = -1; goto quit; } else { printf("DECODED OK in %d:%d (%.2f Mbps)\n", (int) t[0].tv_sec, (int) t[0].tv_usec, (float) grant.mcs.tbs/t[0].tv_usec); } } ret = 0; quit: srslte_pdsch_free(&pdsch); srslte_softbuffer_tx_free(&softbuffer_tx); srslte_softbuffer_rx_free(&softbuffer_rx); for (i=0;i<cell.nof_ports;i++) { if (ce[i]) { free(ce[i]); } if (slot_symbols[i]) { free(slot_symbols[i]); } } if (data) { free(data); } if (ret) { printf("Error\n"); } else { printf("Ok\n"); } exit(ret); }
/* the gateway function */ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) { int i; srslte_cell_t cell; srslte_ofdm_t ofdm_rx; srslte_pdsch_t pdsch; srslte_chest_dl_t chest; cf_t *input_fft; srslte_pdsch_cfg_t cfg; srslte_softbuffer_rx_t softbuffer; uint32_t rnti32; uint32_t cfi; if (nrhs < NOF_INPUTS) { help(); return; } srslte_verbose = SRSLTE_VERBOSE_DEBUG; bzero(&cfg, sizeof(srslte_pdsch_cfg_t)); if (mexutils_read_cell(ENBCFG, &cell)) { help(); return; } if (mexutils_read_uint32_struct(PDSCHCFG, "RNTI", &rnti32)) { mexErrMsgTxt("Field RNTI not found in pdsch config\n"); return; } if (mexutils_read_uint32_struct(ENBCFG, "CFI", &cfi)) { help(); return; } if (mexutils_read_uint32_struct(ENBCFG, "NSubframe", &cfg.sf_idx)) { help(); return; } if (srslte_ofdm_rx_init(&ofdm_rx, cell.cp, cell.nof_prb)) { fprintf(stderr, "Error initializing FFT\n"); return; } if (srslte_pdsch_init(&pdsch, cell)) { mexErrMsgTxt("Error initiating PDSCH\n"); return; } srslte_pdsch_set_rnti(&pdsch, (uint16_t) (rnti32 & 0xffff)); if (srslte_softbuffer_rx_init(&softbuffer, cell.nof_prb)) { mexErrMsgTxt("Error initiating soft buffer\n"); return; } if (srslte_chest_dl_init(&chest, cell)) { mexErrMsgTxt("Error initializing equalizer\n"); return; } srslte_ra_dl_grant_t grant; grant.mcs.tbs = mxGetScalar(TBS); if (grant.mcs.tbs == 0) { mexErrMsgTxt("Error trblklen is zero\n"); return; } if (srslte_cbsegm(&cfg.cb_segm, grant.mcs.tbs)) { mexErrMsgTxt("Error computing CB segmentation\n"); return; } if (mexutils_read_uint32_struct(PDSCHCFG, "RV", &cfg.rv)) { mexErrMsgTxt("Field RV not found in pdsch config\n"); return; } uint32_t max_iterations = 5; mexutils_read_uint32_struct(PDSCHCFG, "NTurboDecIts", &max_iterations); char *mod_str = mexutils_get_char_struct(PDSCHCFG, "Modulation"); if (!strcmp(mod_str, "QPSK")) { grant.mcs.mod = SRSLTE_MOD_QPSK; } else if (!strcmp(mod_str, "16QAM")) { grant.mcs.mod = SRSLTE_MOD_16QAM; } else if (!strcmp(mod_str, "64QAM")) { grant.mcs.mod = SRSLTE_MOD_64QAM; } else { mexErrMsgTxt("Unknown modulation\n"); return; } mxFree(mod_str); mxArray *p; p = mxGetField(PDSCHCFG, 0, "PRBSet"); if (!p) { mexErrMsgTxt("Error field PRBSet not found\n"); return; } float *prbset_f; uint64_t *prbset; if (mxGetClassID(p) == mxDOUBLE_CLASS) { grant.nof_prb = mexutils_read_f(p, &prbset_f); prbset = malloc(sizeof(uint64_t)*grant.nof_prb); for (i=0;i<grant.nof_prb;i++) { prbset[i] = (uint64_t) prbset_f[i]; } } else { grant.nof_prb = mexutils_read_uint64(p, &prbset); } for (i=0;i<cell.nof_prb;i++) { grant.prb_idx[0][i] = false; for (int j=0;j<grant.nof_prb && !grant.prb_idx[0][i];j++) { if ((int) prbset[j] == i) { grant.prb_idx[0][i] = true; } } grant.prb_idx[1][i] = grant.prb_idx[0][i]; } free(prbset); /* Configure rest of pdsch_cfg parameters */ grant.Qm = srslte_mod_bits_x_symbol(grant.mcs.mod); if (srslte_pdsch_cfg(&cfg, cell, &grant, cfi, cfg.sf_idx, cfg.rv)) { fprintf(stderr, "Error configuring PDSCH\n"); exit(-1); } /** Allocate input buffers */ int nof_retx=1; if (mexutils_isCell(INPUT)) { nof_retx = mexutils_getLength(INPUT); } 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)); } uint8_t *data_bytes = srslte_vec_malloc(sizeof(uint8_t) * grant.mcs.tbs/8); if (!data_bytes) { return; } srslte_sch_set_max_noi(&pdsch.dl_sch, max_iterations); input_fft = NULL; int r=-1; for (int rvIdx=0;rvIdx<nof_retx && r != 0;rvIdx++) { mxArray *tmp = (mxArray*) INPUT; if (mexutils_isCell(INPUT)) { tmp = mexutils_getCellArray(INPUT, rvIdx); if (nof_retx > 1) { cfg.rv = rv_seq[rvIdx%4]; } } // Read input signal cf_t *input_signal = NULL; int insignal_len = mexutils_read_cf(tmp, &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); } 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, cfg.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); } r = srslte_pdsch_decode(&pdsch, &cfg, &softbuffer, input_fft, ce, noise_power, data_bytes); } uint8_t *data = malloc(grant.mcs.tbs); srslte_bit_unpack_vector(data_bytes, data, grant.mcs.tbs); if (nlhs >= 1) { plhs[0] = mxCreateLogicalScalar(r == 0); } if (nlhs >= 2) { mexutils_write_uint8(data, &plhs[1], grant.mcs.tbs, 1); } if (nlhs >= 3) { mexutils_write_cf(pdsch.symbols[0], &plhs[2], cfg.nbits.nof_re, 1); } if (nlhs >= 4) { mexutils_write_cf(pdsch.d, &plhs[3], cfg.nbits.nof_re, 1); } if (nlhs >= 5) { mexutils_write_s(pdsch.e, &plhs[4], cfg.nbits.nof_bits, 1); } srslte_softbuffer_rx_free(&softbuffer); srslte_chest_dl_free(&chest); srslte_pdsch_free(&pdsch); srslte_ofdm_rx_free(&ofdm_rx); for (i=0;i<cell.nof_ports;i++) { free(ce[i]); } free(data_bytes); free(data); if (input_fft) { free(input_fft); } return; }