int main(int argc, char **argv) { parse_args(argc, argv); srslte_tcod_gentable(); srslte_tcod_t tcod; srslte_tcod_init(&tcod, 6144); uint32_t st=0, end=187; if (long_cb) { st=srslte_cbsegm_cbindex(long_cb); end=st; } for (uint32_t len=st;len<=end;len++) { long_cb = srslte_cbsegm_cbsize(len); printf("Checking long_cb=%d\n", long_cb); for (int i=0;i<long_cb/8;i++) { input_bytes[i] = rand()%256; } srslte_bit_unpack_vector(input_bytes, input_bits, long_cb); if (SRSLTE_VERBOSE_ISINFO()) { printf("Input bits:\n"); for (int i=0;i<long_cb/8;i++) { srslte_vec_fprint_b(stdout, &input_bits[i*8], 8); } } srslte_tcod_encode(&tcod, input_bits, output_bits, long_cb); srslte_tcod_encode_lut(&tcod, input_bytes, parity, len); srslte_bit_unpack_vector(parity, parity_bits, 2*(long_cb+4)); for (int i=0;i<long_cb;i++) { output_bits2[3*i] = input_bits[i]; output_bits2[3*i+1] = parity_bits[i]; output_bits2[3*i+2] = parity_bits[i+long_cb+4]; } if (SRSLTE_VERBOSE_ISINFO()) { srslte_vec_fprint_b(stdout, output_bits2, 3*long_cb); srslte_vec_fprint_b(stdout, output_bits, 3*long_cb); printf("\n"); } for (int i=0;i<2*long_cb;i++) { if (output_bits2[long_cb+i] != output_bits[long_cb+i]) { printf("error in bit %d, len=%d\n", i, len); exit(-1); } } } srslte_tcod_free(&tcod); printf("Done\n"); exit(0); }
void srslte_scrambling_bytes(srslte_sequence_t *s, uint8_t *data, int len) { scrambling_b_word(s->c_bytes, data, len/8); // Scramble last bits if (len%8) { uint8_t tmp_bits[8]; srslte_bit_unpack_vector(&data[len/8], tmp_bits, len%8); scrambling_b(&s->c[8*(len/8)], tmp_bits, len%8); srslte_bit_pack_vector(tmp_bits, &data[len/8], len%8); } }
int main(int argc, char **argv) { parse_args(argc, argv); srslte_tcod_gentable(); srslte_tcod_t tcod; srslte_tcod_init(&tcod, 6144); uint32_t st=0, end=187; if (long_cb) { st=srslte_cbsegm_cbindex(long_cb); end=st; } for (uint32_t len=st;len<=end;len++) { long_cb = srslte_cbsegm_cbsize(len); printf("Checking long_cb=%d\n", long_cb); for (int i=0;i<long_cb/8;i++) { input_bytes[i] = rand()%256; } srslte_bit_unpack_vector(input_bytes, input_bits, long_cb); if (SRSLTE_VERBOSE_ISINFO()) { printf("Input bits:\n"); for (int i=0;i<long_cb/8;i++) { srslte_vec_fprint_b(stdout, &input_bits[i*8], 8); } } srslte_tcod_encode(&tcod, input_bits, output_bits, long_cb); srslte_tcod_encode_lut(&tcod, input_bytes, output_bytes, long_cb); srslte_bit_unpack_vector(output_bytes, output_bits2, 2*long_cb+12); /* de-Interleace bits for comparison */ for (int i=0;i<long_cb;i++) { for (int j=0;j<2;j++) { output_bits3[j*long_cb+i] = output_bits[3*i+j+1]; } } // copy tail memcpy(&output_bits3[2*long_cb], &output_bits[3*long_cb], 12); if (SRSLTE_VERBOSE_ISINFO()) { printf("1st encoder\n"); srslte_vec_fprint_b(stdout, output_bits2, long_cb); srslte_vec_fprint_b(stdout, output_bits3, long_cb); printf("2nd encoder\n"); srslte_vec_fprint_b(stdout, &output_bits2[long_cb], long_cb); srslte_vec_fprint_b(stdout, &output_bits3[long_cb], long_cb); printf("tail\n"); srslte_vec_fprint_b(stdout, &output_bits2[2*long_cb], 12); srslte_vec_fprint_b(stdout, &output_bits3[2*long_cb], 12); printf("\n"); } for (int i=0;i<2*long_cb+12;i++) { if (output_bits2[i] != output_bits3[i]) { printf("error in bit %d, len=%d\n", i, len); exit(-1); } } } srslte_tcod_free(&tcod); printf("Done\n"); exit(0); }
/* 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; }
/* Encode a transport block according to 36.212 5.3.2 * */ static int encode_tb(srslte_sch_t *q, srslte_softbuffer_tx_t *soft_buffer, srslte_cbsegm_t *cb_segm, uint32_t Qm, uint32_t rv, uint32_t nof_e_bits, uint8_t *data, uint8_t *e_bits) { uint8_t parity[3] = {0, 0, 0}; uint32_t par; uint32_t i; uint32_t cb_len, rp, wp, rlen, F, n_e; int ret = SRSLTE_ERROR_INVALID_INPUTS; if (q != NULL && e_bits != NULL && cb_segm != NULL && soft_buffer != NULL) { uint32_t Gp = nof_e_bits / Qm; uint32_t gamma = Gp; if (cb_segm->C > 0) { gamma = Gp%cb_segm->C; } if (data) { /* Compute transport block CRC */ par = srslte_crc_checksum_byte(&q->crc_tb, data, cb_segm->tbs); /* parity bits will be appended later */ parity[0] = (par&(0xff<<16))>>16; parity[1] = (par&(0xff<<8))>>8; parity[2] = par&0xff; if (SRSLTE_VERBOSE_ISDEBUG()) { DEBUG("DATA: ", 0); srslte_vec_fprint_byte(stdout, data, cb_segm->tbs/8); DEBUG("PARITY: ", 0); srslte_vec_fprint_byte(stdout, parity, 3); } } wp = 0; rp = 0; for (i = 0; i < cb_segm->C; i++) { /* Get read lengths */ if (i < cb_segm->C2) { cb_len = cb_segm->K2; } else { cb_len = cb_segm->K1; } if (cb_segm->C > 1) { rlen = cb_len - 24; } else { rlen = cb_len; } if (i == 0) { F = cb_segm->F; } else { F = 0; } if (i <= cb_segm->C - gamma - 1) { n_e = Qm * (Gp/cb_segm->C); } else { n_e = Qm * ((uint32_t) ceilf((float) Gp/cb_segm->C)); } INFO("CB#%d: cb_len: %d, rlen: %d, wp: %d, rp: %d, F: %d, E: %d\n", i, cb_len, rlen - F, wp, rp, F, n_e); if (data) { /* Copy data to another buffer, making space for the Codeblock CRC */ if (i < cb_segm->C - 1) { // Copy data memcpy(&q->cb_in[F/8], &data[rp/8], (rlen - F) * sizeof(uint8_t)/8); } else { INFO("Last CB, appending parity: %d from %d and 24 to %d\n", rlen - F - 24, rp, rlen - 24); /* Append Transport Block parity bits to the last CB */ memcpy(&q->cb_in[F/8], &data[rp/8], (rlen - 24 - F) * sizeof(uint8_t)/8); memcpy(&q->cb_in[(rlen - 24)/8], parity, 3 * sizeof(uint8_t)); } /* Filler bits are treated like zeros for the CB CRC calculation */ for (int j = 0; j < F/8; j++) { q->cb_in[j] = 0; } /* Attach Codeblock CRC */ if (cb_segm->C > 1) { srslte_crc_attach_byte(&q->crc_cb, q->cb_in, rlen); } /* pack bits to temporal buffer for encoding */ srslte_bit_unpack_vector(q->cb_in, q->cb_temp, cb_len); /* Set the filler bits to <NULL> */ for (int j = 0; j < F; j++) { q->cb_temp[j] = SRSLTE_TX_NULL; } if (SRSLTE_VERBOSE_ISDEBUG()) { DEBUG("CB#%d: ", i); srslte_vec_fprint_hex(stdout, q->cb_temp, cb_len); } /* Turbo Encoding */ srslte_tcod_encode(&q->encoder, q->cb_temp, (uint8_t*) q->cb_out, cb_len); if (SRSLTE_VERBOSE_ISDEBUG()) { DEBUG("CB#%d encoded: ", i); srslte_vec_fprint_b(stdout, q->cb_out, 3*cb_len+12); } } /* Rate matching */ if (srslte_rm_turbo_tx(soft_buffer->buffer_b[i], soft_buffer->buff_size, (uint8_t*) q->cb_out, 3 * cb_len + 12, &e_bits[wp], n_e, rv)) { fprintf(stderr, "Error in rate matching\n"); return SRSLTE_ERROR; } /* Set read/write pointers */ rp += (rlen - F); wp += n_e; } INFO("END CB#%d: wp: %d, rp: %d\n", i, wp, rp); ret = SRSLTE_SUCCESS; }
/* 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; }
int main(int argc, char **argv) { int i; uint8_t *rm_bits, *rm_bits2, *rm_bits2_bytes; short *rm_bits_s; float *rm_bits_f; parse_args(argc, argv); srslte_rm_turbo_gentables(); rm_bits_s = srslte_vec_malloc(sizeof(short) * nof_e_bits); if (!rm_bits_s) { perror("malloc"); exit(-1); } rm_bits_f = srslte_vec_malloc(sizeof(float) * nof_e_bits); if (!rm_bits_f) { perror("malloc"); exit(-1); } rm_bits = srslte_vec_malloc(sizeof(uint8_t) * nof_e_bits); if (!rm_bits) { perror("malloc"); exit(-1); } rm_bits2 = malloc(sizeof(uint8_t) * nof_e_bits); if (!rm_bits2) { perror("malloc"); exit(-1); } rm_bits2_bytes = malloc(sizeof(uint8_t) * nof_e_bits/8 + 1); if (!rm_bits2_bytes) { perror("malloc"); exit(-1); } uint32_t st=0, end=188; if (cb_idx != -1) { st=cb_idx; end=cb_idx+1; } uint32_t rv_st=0, rv_end=4; if (rv_idx != -1) { rv_st=rv_idx; rv_end=rv_idx+1; } for (cb_idx=st;cb_idx<end;cb_idx++) { for (rv_idx=rv_st;rv_idx<rv_end;rv_idx++) { uint32_t long_cb_enc = 3*srslte_cbsegm_cbsize(cb_idx)+12; printf("checking cb_idx=%3d rv_idx=%d...", cb_idx, rv_idx); for (i = 0; i < long_cb_enc; i++) { bits[i] = rand() % 2; } bzero(buff_b, BUFFSZ * sizeof(uint8_t)); srslte_rm_turbo_tx(buff_b, BUFFSZ, bits, long_cb_enc, rm_bits, nof_e_bits, 0); if (rv_idx > 0) { srslte_rm_turbo_tx(buff_b, BUFFSZ, bits, long_cb_enc, rm_bits, nof_e_bits, rv_idx); } for (int i=0;i<long_cb_enc/3;i++) { systematic[i] = bits[3*i]; parity[i] = bits[3*i+1]; parity[i+long_cb_enc/3] = bits[3*i+2]; } srslte_bit_pack_vector(systematic, systematic_bytes, long_cb_enc/3); srslte_bit_pack_vector(parity, parity_bytes, 2*long_cb_enc/3); bzero(buff_b, BUFFSZ * sizeof(uint8_t)); bzero(rm_bits2_bytes, nof_e_bits/8); srslte_rm_turbo_tx_lut(buff_b, systematic_bytes, parity_bytes, rm_bits2_bytes, cb_idx, nof_e_bits, 0, 0); if (rv_idx > 0) { bzero(rm_bits2_bytes, nof_e_bits/8); srslte_rm_turbo_tx_lut(buff_b, systematic_bytes, parity_bytes, rm_bits2_bytes, cb_idx, nof_e_bits, 0, rv_idx); } srslte_bit_unpack_vector(rm_bits2_bytes, rm_bits2, nof_e_bits); for (int i=0;i<nof_e_bits;i++) { if (rm_bits2[i] != rm_bits[i]) { printf("Error in TX bit %d\n", i); exit(-1); } } printf("OK TX..."); for (int i=0;i<nof_e_bits;i++) { rm_bits_f[i] = rand()%10-5; rm_bits_s[i] = (short) rm_bits_f[i]; } bzero(buff_f, BUFFSZ*sizeof(float)); srslte_rm_turbo_rx(buff_f, BUFFSZ, rm_bits_f, nof_e_bits, bits_f, long_cb_enc, rv_idx, 0); bzero(bits2_s, long_cb_enc*sizeof(short)); srslte_rm_turbo_rx_lut(rm_bits_s, bits2_s, nof_e_bits, cb_idx, rv_idx); for (int i=0;i<long_cb_enc;i++) { if (bits_f[i] != bits2_s[i]) { printf("error RX in bit %d %f!=%d\n", i, bits_f[i], bits2_s[i]); exit(-1); } } printf("OK RX\n"); } } free(rm_bits); free(rm_bits2); free(rm_bits2_bytes); exit(0); }
int main(int argc, char **argv) { uint32_t frame_cnt; float *llr; short *llr_s; uint8_t *llr_c; uint8_t *data_tx, *data_rx, *data_rx_bytes, *symbols; uint32_t i, j; float var[SNR_POINTS]; uint32_t snr_points; uint32_t errors; uint32_t coded_length; struct timeval tdata[3]; float mean_usec; srslte_tdec_t tdec; srslte_tcod_t tcod; parse_args(argc, argv); if (!seed) { seed = time(NULL); } srand(seed); if (test_known_data) { frame_length = KNOWN_DATA_LEN; } else { frame_length = srslte_cbsegm_cbsize(srslte_cbsegm_cbindex(frame_length)); } coded_length = 3 * (frame_length) + SRSLTE_TCOD_TOTALTAIL; printf(" Frame length: %d\n", frame_length); if (ebno_db < 100.0) { printf(" EbNo: %.2f\n", ebno_db); } data_tx = srslte_vec_malloc(frame_length * sizeof(uint8_t)); if (!data_tx) { perror("malloc"); exit(-1); } data_rx = srslte_vec_malloc(frame_length * sizeof(uint8_t)); if (!data_rx) { perror("malloc"); exit(-1); } data_rx_bytes = srslte_vec_malloc(frame_length * sizeof(uint8_t)); if (!data_rx_bytes) { perror("malloc"); exit(-1); } symbols = srslte_vec_malloc(coded_length * sizeof(uint8_t)); if (!symbols) { perror("malloc"); exit(-1); } llr = srslte_vec_malloc(coded_length * sizeof(float)); if (!llr) { perror("malloc"); exit(-1); } llr_s = srslte_vec_malloc(coded_length * sizeof(short)); if (!llr_s) { perror("malloc"); exit(-1); } llr_c = srslte_vec_malloc(coded_length * sizeof(uint8_t)); if (!llr_c) { perror("malloc"); exit(-1); } if (srslte_tcod_init(&tcod, frame_length)) { fprintf(stderr, "Error initiating Turbo coder\n"); exit(-1); } if (srslte_tdec_init_manual(&tdec, frame_length, tdec_type)) { fprintf(stderr, "Error initiating Turbo decoder\n"); exit(-1); } srslte_tdec_force_not_sb(&tdec); float ebno_inc, esno_db; ebno_inc = (SNR_MAX - SNR_MIN) / SNR_POINTS; if (ebno_db == 100.0) { snr_points = SNR_POINTS; for (i = 0; i < snr_points; i++) { ebno_db = SNR_MIN + i * ebno_inc; esno_db = ebno_db + 10 * log10((double) 1 / 3); var[i] = sqrt(1 / (pow(10, esno_db / 10))); } } else { esno_db = ebno_db + 10 * log10((double) 1 / 3); var[0] = sqrt(1 / (pow(10, esno_db / 10))); snr_points = 1; } for (i = 0; i < snr_points; i++) { mean_usec = 0; errors = 0; frame_cnt = 0; while (frame_cnt < nof_frames) { /* generate data_tx */ for (j = 0; j < frame_length; j++) { if (test_known_data) { data_tx[j] = known_data[j]; } else { data_tx[j] = rand() % 2; } } /* coded BER */ if (test_known_data) { for (j = 0; j < coded_length; j++) { symbols[j] = known_data_encoded[j]; } } else { srslte_tcod_encode(&tcod, data_tx, symbols, frame_length); } for (j = 0; j < coded_length; j++) { llr[j] = symbols[j] ? 1 : -1; } srslte_ch_awgn_f(llr, llr, var[i], coded_length); for (j=0;j<coded_length;j++) { llr_s[j] = (int16_t) (100*llr[j]); } /* decoder */ srslte_tdec_new_cb(&tdec, frame_length); uint32_t t; if (nof_iterations == -1) { t = MAX_ITERATIONS; } else { t = nof_iterations; } gettimeofday(&tdata[1], NULL); for (int k=0;k<nof_repetitions;k++) { srslte_tdec_run_all(&tdec, llr_s, data_rx_bytes, t, frame_length); } gettimeofday(&tdata[2], NULL); get_time_interval(tdata); mean_usec = (tdata[0].tv_sec*1e6+tdata[0].tv_usec)/nof_repetitions; frame_cnt++; uint32_t errors_this = 0; srslte_bit_unpack_vector(data_rx_bytes, data_rx, frame_length); errors_this=srslte_bit_diff(data_tx, data_rx, frame_length); //printf("error[%d]=%d\n", cb, errors_this); errors += errors_this; printf("Eb/No: %2.2f %10d/%d ", SNR_MIN + i * ebno_inc, frame_cnt, nof_frames); printf("BER: %.2e ", (float) errors / (nof_cb*frame_cnt * frame_length)); printf("%3.1f Mbps (%6.2f usec)", (float) (nof_cb*frame_length) / mean_usec, mean_usec); printf("\r"); } printf("\n"); } printf("\n"); if (snr_points == 1) { if (errors) { printf("%d Errors\n", errors/nof_cb); } } if (data_rx_bytes) { free(data_rx_bytes); } free(data_tx); free(symbols); free(llr); free(llr_c); free(llr_s); free(data_rx); srslte_tdec_free(&tdec); srslte_tcod_free(&tcod); printf("\n"); printf("Done\n"); exit(0); }
/* 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<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, (uint16_t) (rnti32 & 0xffff), cfg.rv)) { fprintf(stderr, "Error configuring PDSCH\n"); exit(-1); } /** 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_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_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_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<cell.nof_ports;i++) { free(ce[i]); } free(data); free(input_signal); free(input_fft); return; }