/** * * \section COPYRIGHT * * Copyright 2013-2015 The srsLTE Developers. See the * COPYRIGHT file at the top-level directory of this distribution. * * \section LICENSE * * This file is part of the srsLTE library. * * srsLTE is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation, either version 3 of * the License, or (at your option) any later version. * * srsLTE is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * A copy of the GNU Affero General Public License can be found in * the LICENSE file in the top-level directory of this distribution * and at http://www.gnu.org/licenses/. * */ #include #include "srslte/srslte.h" #include "srslte/mex/mexutils.h" /** MEX function to be called from MATLAB to test the channel estimator */ #define ENBCFG prhs[0] #define PDSCHCFG prhs[1] #define TBS prhs[2] #define INPUT prhs[3] #define NOF_INPUTS 4 void help() { mexErrMsgTxt ("[decoded_ok, llr, rm, bits, symbols] = srslte_pdsch(enbConfig, pdschConfig, trblklen, rxWaveform)\n\n"); } extern int indices[2048]; /* 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.nof_prb)) { 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; 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; } 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); float *prbset; mxArray *p; p = mxGetField(PDSCHCFG, 0, "PRBSet"); if (!p) { mexErrMsgTxt("Error field PRBSet not found\n"); return; } // Only localized PRB supported grant.nof_prb = mexutils_read_f(p, &prbset); for (i=0;i NOF_INPUTS) { cf_t *cearray = NULL; nof_re = mexutils_read_cf(prhs[NOF_INPUTS], &cearray); cf_t *cearray_ptr = cearray; for (i=0;i NOF_INPUTS + 1) { noise_power = mxGetScalar(prhs[NOF_INPUTS+1]); } else { noise_power = srslte_chest_dl_get_noise_estimate(&chest); } uint8_t *data_bytes = srslte_vec_malloc(sizeof(uint8_t) * grant.mcs.tbs/8); if (!data_bytes) { return; } int r = srslte_pdsch_decode(&pdsch, &cfg, &softbuffer, input_fft, ce, noise_power, data_bytes); free(data_bytes); uint8_t *data = malloc(grant.mcs.tbs); srslte_bit_pack_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_f(pdsch.e, &plhs[4], cfg.nbits.nof_bits, 1); } srslte_chest_dl_free(&chest); srslte_ofdm_rx_free(&fft); srslte_pdsch_free(&pdsch); for (i=0;i