/* Configures the structure srslte_pdsch_cfg_t from the DL DCI allocation dci_msg. * If dci_msg is NULL, the grant is assumed to be already stored in cfg->grant */ int srslte_pdsch_cfg(srslte_pdsch_cfg_t *cfg, srslte_cell_t cell, srslte_ra_dl_grant_t *grant, uint32_t cfi, uint32_t sf_idx, uint32_t rvidx) { if (cfg && grant) { memcpy(&cfg->grant, grant, sizeof(srslte_ra_dl_grant_t)); } if (srslte_cbsegm(&cfg->cb_segm, cfg->grant.mcs.tbs)) { fprintf(stderr, "Error computing Codeblock segmentation for TBS=%d\n", cfg->grant.mcs.tbs); return SRSLTE_ERROR; } srslte_ra_dl_grant_to_nbits(&cfg->grant, cfi, cell, sf_idx, &cfg->nbits); cfg->sf_idx = sf_idx; cfg->rv = rvidx; return SRSLTE_SUCCESS; }
int srslte_pmch_cfg(srslte_pdsch_cfg_t *cfg, srslte_cell_t cell, srslte_ra_dl_grant_t *grant, uint32_t cfi, uint32_t sf_idx) { if (cfg) { if (grant) { memcpy(&cfg->grant, grant, sizeof(srslte_ra_dl_grant_t)); } if (srslte_cbsegm(&cfg->cb_segm[0], cfg->grant.mcs[0].tbs)) { fprintf(stderr, "Error computing Codeblock segmentation for TBS=%d\n", cfg->grant.mcs[0].tbs); return SRSLTE_ERROR; } srslte_ra_dl_grant_to_nbits(&cfg->grant, cfi, cell, sf_idx, cfg->nbits); cfg->sf_idx = sf_idx; cfg->rv[0] = SRSLTE_PMCH_RV; return SRSLTE_SUCCESS; } else { return SRSLTE_ERROR_INVALID_INPUTS; } }
/* Configures the structure srslte_pdsch_cfg_t from the DL DCI allocation dci_msg. * If dci_msg is NULL, the grant is assumed to be already stored in cfg->grant */ int srslte_pdsch_cfg_mimo(srslte_pdsch_cfg_t *cfg, srslte_cell_t cell, srslte_ra_dl_grant_t *grant, uint32_t cfi, uint32_t sf_idx, int rvidx[SRSLTE_MAX_CODEWORDS], srslte_mimo_type_t mimo_type, uint32_t pmi) { if (cfg && grant) { uint32_t nof_tb = SRSLTE_RA_DL_GRANT_NOF_TB(grant); memcpy(&cfg->grant, grant, sizeof(srslte_ra_dl_grant_t)); for (int cw = 0; cw < SRSLTE_MAX_CODEWORDS; cw++) { if (grant->tb_en[cw]) { if (srslte_cbsegm(&cfg->cb_segm[cw], (uint32_t) cfg->grant.mcs[cw].tbs)) { fprintf(stderr, "Error computing Codeword (%d) segmentation for TBS=%d\n", cw, cfg->grant.mcs[cw].tbs); return SRSLTE_ERROR; } } } srslte_ra_dl_grant_to_nbits(&cfg->grant, cfi, cell, sf_idx, cfg->nbits); cfg->sf_idx = sf_idx; memcpy(cfg->rv, rvidx, sizeof(uint32_t) * SRSLTE_MAX_CODEWORDS); cfg->mimo_type = mimo_type; cfg->tb_cw_swap = grant->tb_cw_swap; /* Check and configure PDSCH transmission modes */ switch(mimo_type) { case SRSLTE_MIMO_TYPE_SINGLE_ANTENNA: if (nof_tb != 1) { ERROR("Wrong number of transport blocks (%d) for single antenna.", nof_tb); return SRSLTE_ERROR; } cfg->nof_layers = 1; break; case SRSLTE_MIMO_TYPE_TX_DIVERSITY: if (nof_tb != 1) { ERROR("Wrong number of transport blocks (%d) for transmit diversity.", nof_tb); return SRSLTE_ERROR; } cfg->nof_layers = cell.nof_ports; break; case SRSLTE_MIMO_TYPE_SPATIAL_MULTIPLEX: if (nof_tb == 1) { cfg->codebook_idx = pmi; cfg->nof_layers = 1; } else if (nof_tb == 2) { cfg->codebook_idx = pmi + 1; cfg->nof_layers = 2; } else { ERROR("Wrong number of transport blocks (%d) for spatial multiplexing.", nof_tb); return SRSLTE_ERROR; } INFO("PDSCH configured for Spatial Multiplex; nof_codewords=%d; nof_layers=%d; codebook_idx=%d;\n", nof_tb, cfg->nof_layers, cfg->codebook_idx); break; case SRSLTE_MIMO_TYPE_CDD: if (nof_tb != 2) { ERROR("Wrong number of transport blocks (%d) for CDD.", nof_tb); return SRSLTE_ERROR; } cfg->nof_layers = 2; break; } return SRSLTE_SUCCESS; } else { return SRSLTE_ERROR_INVALID_INPUTS; } }
/* the gateway function */ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) { srslte_sch_t ulsch; srslte_pusch_cfg_t cfg; srslte_softbuffer_tx_t softbuffer; srslte_uci_data_t uci_data; bzero(&uci_data, sizeof(srslte_uci_data_t)); uint32_t rv; if (nrhs < NOF_INPUTS) { help(); return; } bzero(&cfg, sizeof(srslte_pusch_cfg_t)); if (srslte_sch_init(&ulsch)) { mexErrMsgTxt("Error initiating ULSCH\n"); return; } srslte_cell_t cell; cell.nof_prb = 100; cell.id=1; cell.cp=SRSLTE_CP_NORM; if (srslte_softbuffer_tx_init(&softbuffer, cell.nof_prb)) { mexErrMsgTxt("Error initiating HARQ\n"); return; } uint8_t *trblkin_bits = NULL; cfg.grant.mcs.tbs = mexutils_read_uint8(TRBLKIN, &trblkin_bits); uint8_t *trblkin = srslte_vec_malloc(cfg.grant.mcs.tbs/8); srslte_bit_unpack_vector(trblkin_bits, trblkin, cfg.grant.mcs.tbs); free(trblkin_bits); uint8_t *tmp; uci_data.uci_cqi_len = mexutils_read_uint8(CQI, &tmp); memcpy(uci_data.uci_cqi, tmp, uci_data.uci_cqi_len); free(tmp); uci_data.uci_ri_len = mexutils_read_uint8(RI, &tmp); if (uci_data.uci_ri_len > 0) { uci_data.uci_ri = *tmp; } free(tmp); uci_data.uci_ack_len = mexutils_read_uint8(ACK, &tmp); if (uci_data.uci_ack_len > 0) { uci_data.uci_ack = *tmp; } free(tmp); mexPrintf("TRBL_len: %d, CQI_len: %d, ACK_len: %d, RI_len: %d\n", cfg.grant.mcs.tbs, uci_data.uci_cqi_len, uci_data.uci_ack_len, uci_data.uci_ri_len); if (mexutils_read_uint32_struct(PUSCHCFG, "RV", &rv)) { mexErrMsgTxt("Field RV not found in pdsch config\n"); return; } float beta; if (mexutils_read_float_struct(PUSCHCFG, "BetaCQI", &beta)) { cfg.uci_cfg.I_offset_cqi = 7; } else { cfg.uci_cfg.I_offset_cqi = srslte_sch_find_Ioffset_cqi(beta); } if (mexutils_read_float_struct(PUSCHCFG, "BetaRI", &beta)) { cfg.uci_cfg.I_offset_ri = 2; } else { cfg.uci_cfg.I_offset_ri = srslte_sch_find_Ioffset_ri(beta); } if (mexutils_read_float_struct(PUSCHCFG, "BetaACK", &beta)) { cfg.uci_cfg.I_offset_ack = 0; } else { cfg.uci_cfg.I_offset_ack = srslte_sch_find_Ioffset_ack(beta); } char *mod_str = mexutils_get_char_struct(PUSCHCFG, "Modulation"); if (!strcmp(mod_str, "QPSK")) { cfg.grant.mcs.mod = SRSLTE_MOD_QPSK; } else if (!strcmp(mod_str, "16QAM")) { cfg.grant.mcs.mod = SRSLTE_MOD_16QAM; } else if (!strcmp(mod_str, "64QAM")) { cfg.grant.mcs.mod = SRSLTE_MOD_64QAM; } else { mexErrMsgTxt("Unknown modulation\n"); return; } mxFree(mod_str); float *prbset; mxArray *p; p = mxGetField(PUSCHCFG, 0, "PRBSet"); if (!p) { mexErrMsgTxt("Error field PRBSet not found\n"); return; } uint32_t N_srs = 0; mexutils_read_uint32_struct(PUSCHCFG, "Shortened", &N_srs); cfg.grant.L_prb = mexutils_read_f(p, &prbset); cfg.grant.n_prb[0] = prbset[0]; cfg.grant.n_prb[1] = prbset[0]; free(prbset); cfg.grant.L_prb = mexutils_read_f(p, &prbset); cfg.grant.n_prb[0] = prbset[0]; cfg.grant.n_prb[1] = prbset[0]; cfg.nbits.lstart = 0; cfg.nbits.nof_symb = 2*(SRSLTE_CP_NSYMB(cell.cp)-1) - N_srs; cfg.grant.M_sc = cfg.grant.L_prb*SRSLTE_NRE; cfg.grant.M_sc_init = cfg.grant.M_sc; // FIXME: What should M_sc_init be? cfg.nbits.nof_re = cfg.nbits.nof_symb*cfg.grant.M_sc; cfg.grant.Qm = srslte_mod_bits_x_symbol(cfg.grant.mcs.mod); cfg.nbits.nof_bits = cfg.nbits.nof_re * cfg.grant.Qm; mexPrintf("Q_m: %d, NPRB: %d, RV: %d, Nsrs=%d\n", srslte_mod_bits_x_symbol(cfg.grant.mcs.mod), cfg.grant.L_prb, cfg.rv, N_srs); mexPrintf("I_cqi: %d, I_ri: %d, I_ack=%d\n", cfg.uci_cfg.I_offset_cqi, cfg.uci_cfg.I_offset_ri, cfg.uci_cfg.I_offset_ack); if (srslte_cbsegm(&cfg.cb_segm, cfg.grant.mcs.tbs)) { mexErrMsgTxt("Error configuring HARQ process\n"); return; } uint8_t *q_bits = srslte_vec_malloc(cfg.nbits.nof_bits * sizeof(uint8_t)); if (!q_bits) { return; } uint8_t *g_bits = srslte_vec_malloc(cfg.nbits.nof_bits * sizeof(uint8_t)); if (!g_bits) { return; } if (srslte_ulsch_uci_encode(&ulsch, &cfg, &softbuffer, trblkin, uci_data, g_bits, q_bits)) { mexErrMsgTxt("Error encoding TB\n"); return; } if (rv > 0) { cfg.rv = rv; if (srslte_ulsch_uci_encode(&ulsch, &cfg, &softbuffer, trblkin, uci_data, g_bits, q_bits)) { mexErrMsgTxt("Error encoding TB\n"); return; } } if (nlhs >= 1) { mexutils_write_uint8(q_bits, &plhs[0], cfg.nbits.nof_bits, 1); } srslte_sch_free(&ulsch); srslte_softbuffer_tx_free(&softbuffer); free(trblkin); free(g_bits); free(q_bits); return; }
/* 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; }
/* the gateway function */ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) { int i; srslte_cell_t cell; srslte_pdsch_t pdsch; srslte_chest_dl_t chest; srslte_ofdm_t fft; cf_t *input_fft, *input_signal; int nof_re; srslte_pdsch_cfg_t cfg; srslte_softbuffer_rx_t softbuffer; uint32_t rnti32; uint32_t cfi; if (nrhs < NOF_INPUTS) { help(); return; } 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_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)) { mexErrMsgTxt("Error initiating soft buffer\n"); return; } if (srslte_chest_dl_init(&chest, cell)) { mexErrMsgTxt("Error initializing equalizer\n"); return; } if (srslte_ofdm_rx_init(&fft, cell.cp, cell.nof_prb)) { mexErrMsgTxt("Error initializing FFT\n"); return; } nof_re = 2 * SRSLTE_CP_NORM_NSYMB * cell.nof_prb * SRSLTE_NRE; cfg.grant.mcs.tbs = mxGetScalar(TBS); if (cfg.grant.mcs.tbs == 0) { mexErrMsgTxt("Error trblklen is zero\n"); return; } if (srslte_cbsegm(&cfg.cb_segm, cfg.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; } char *mod_str = mexutils_get_char_struct(PDSCHCFG, "Modulation"); if (!strcmp(mod_str, "QPSK")) { cfg.grant.mcs.mod = SRSLTE_MOD_QPSK; } else if (!strcmp(mod_str, "16QAM")) { cfg.grant.mcs.mod = SRSLTE_MOD_16QAM; } else if (!strcmp(mod_str, "64QAM")) { cfg.grant.mcs.mod = SRSLTE_MOD_64QAM; } else { mexErrMsgTxt("Unknown modulation\n"); return; } mxFree(mod_str); float *prbset; mxArray *p; p = mxGetField(PDSCHCFG, 0, "PRBSet"); if (!p) { mexErrMsgTxt("Error field PRBSet not found\n"); return; } // Only localized PRB supported cfg.grant.nof_prb = mexutils_read_f(p, &prbset); for (i=0;i<cell.nof_prb;i++) { cfg.grant.prb_idx[0][i] = false; for (int j=0;j<cfg.grant.nof_prb && !cfg.grant.prb_idx[0][i];j++) { if ((int) prbset[j] == i) { cfg.grant.prb_idx[0][i] = true; } } } memcpy(&cfg.grant.prb_idx[1], &cfg.grant.prb_idx[0], SRSLTE_MAX_PRB*sizeof(bool)); free(prbset); srslte_dl_dci_to_grant_nof_re(&cfg.grant, cell, cfg.sf_idx, cell.nof_prb<10?(cfi+1):cfi); // Fill rest of grant structure cfg.grant.lstart = cell.nof_prb<10?(cfi+1):cfi; cfg.grant.nof_symb = 2*SRSLTE_CP_NSYMB(cell.cp)-cfg.grant.lstart; cfg.grant.Qm = srslte_mod_bits_x_symbol(cfg.grant.mcs.mod); cfg.grant.nof_bits = cfg.grant.nof_re * cfg.grant.Qm; /** Allocate input buffers */ if (mexutils_read_cf(INPUT, &input_signal) < 0) { mexErrMsgTxt("Error reading input signal\n"); return; } input_fft = srslte_vec_malloc(SRSLTE_SF_LEN_RE(cell.nof_prb, cell.cp) * sizeof(cf_t)); 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)); } srslte_ofdm_rx_sf(&fft, input_signal, input_fft); if (nrhs > NOF_INPUTS) { cf_t *cearray = NULL; nof_re = 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<nof_re/cell.nof_ports;j++) { ce[i][j] = *cearray; cearray++; } } if (cearray_ptr) free(cearray_ptr); } 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 { noise_power = srslte_chest_dl_get_noise_estimate(&chest); } uint8_t *data = malloc(sizeof(uint8_t) * cfg.grant.mcs.tbs); if (!data) { return; } int r = srslte_pdsch_decode(&pdsch, &cfg, &softbuffer, input_fft, ce, noise_power, data); if (nlhs >= 1) { plhs[0] = mxCreateLogicalScalar(r == 0); } if (nlhs >= 2) { mexutils_write_uint8(data, &plhs[1], cfg.grant.mcs.tbs, 1); } if (nlhs >= 3) { mexutils_write_cf(pdsch.symbols[0], &plhs[2], cfg.grant.nof_re, 1); } if (nlhs >= 4) { mexutils_write_cf(pdsch.d, &plhs[3], cfg.grant.nof_re, 1); } if (nlhs >= 5) { mexutils_write_f(pdsch.e, &plhs[4], cfg.grant.nof_bits, 1); } srslte_chest_dl_free(&chest); srslte_ofdm_rx_free(&fft); srslte_pdsch_free(&pdsch); for (i=0;i<cell.nof_ports;i++) { free(ce[i]); } free(data); free(input_signal); free(input_fft); return; }