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); }
int decode_cqi_long(srslte_uci_cqi_pusch_t *q, int16_t *q_bits, uint32_t Q, uint8_t *data, uint32_t nof_bits) { int ret = SRSLTE_ERROR_INVALID_INPUTS; if (nof_bits + 8 < SRSLTE_UCI_MAX_CQI_LEN_PUSCH && q != NULL && data != NULL && q_bits != NULL) { srslte_rm_conv_rx_s(q_bits, Q, q->encoded_cqi_s, 3 * (nof_bits + 8)); DEBUG("cconv_rx="); if (SRSLTE_VERBOSE_ISDEBUG()) { srslte_vec_fprint_s(stdout, q->encoded_cqi_s, 3 * (nof_bits + 8)); } srslte_viterbi_decode_s(&q->viterbi, q->encoded_cqi_s, q->tmp_cqi, nof_bits + 8); DEBUG("cqi_crc_rx="); if (SRSLTE_VERBOSE_ISDEBUG()) { srslte_vec_fprint_b(stdout, q->tmp_cqi, nof_bits+8); } ret = srslte_crc_checksum(&q->crc, q->tmp_cqi, nof_bits + 8); if (ret == 0) { memcpy(data, q->tmp_cqi, nof_bits*sizeof(uint8_t)); ret = 1; } else { ret = 0; } } return ret; }
/* Encode UCI CQI/PMI for payloads greater than 11 bits (go through CRC, conv coder and rate match) */ int encode_cqi_long(srslte_uci_cqi_pusch_t *q, uint8_t *data, uint32_t nof_bits, uint8_t *q_bits, uint32_t Q) { srslte_convcoder_t encoder; if (nof_bits + 8 < SRSLTE_UCI_MAX_CQI_LEN_PUSCH && q != NULL && data != NULL && q_bits != NULL) { int poly[3] = { 0x6D, 0x4F, 0x57 }; encoder.K = 7; encoder.R = 3; encoder.tail_biting = true; memcpy(encoder.poly, poly, 3 * sizeof(int)); memcpy(q->tmp_cqi, data, sizeof(uint8_t) * nof_bits); srslte_crc_attach(&q->crc, q->tmp_cqi, nof_bits); DEBUG("cqi_crc_tx="); if (SRSLTE_VERBOSE_ISDEBUG()) { srslte_vec_fprint_b(stdout, q->tmp_cqi, nof_bits+8); } srslte_convcoder_encode(&encoder, q->tmp_cqi, q->encoded_cqi, nof_bits + 8); DEBUG("cconv_tx="); if (SRSLTE_VERBOSE_ISDEBUG()) { srslte_vec_fprint_b(stdout, q->encoded_cqi, 3 * (nof_bits + 8)); } srslte_rm_conv_tx(q->encoded_cqi, 3 * (nof_bits + 8), q_bits, Q); return SRSLTE_SUCCESS; } else { return SRSLTE_ERROR_INVALID_INPUTS; } }
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); }
/* 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; }
int main(int argc, char **argv) { srslte_pusch_t pusch; uint8_t *data = NULL; cf_t *sf_symbols = NULL; cf_t *ce = NULL; int ret = -1; struct timeval t[3]; srslte_pusch_cfg_t cfg; srslte_softbuffer_tx_t softbuffer_tx; srslte_softbuffer_rx_t softbuffer_rx; parse_args(argc,argv); bzero(&cfg, sizeof(srslte_pusch_cfg_t)); srslte_ra_ul_dci_t dci; dci.freq_hop_fl = freq_hop; if (riv < 0) { dci.type2_alloc.L_crb = L_prb; dci.type2_alloc.RB_start = n_prb; } else { dci.type2_alloc.riv = riv; } dci.mcs_idx = mcs_idx; srslte_ra_ul_grant_t grant; if (srslte_ra_ul_dci_to_grant(&dci, cell.nof_prb, 0, &grant, 0)) { fprintf(stderr, "Error computing resource allocation\n"); return ret; } srslte_pusch_hopping_cfg_t ul_hopping; ul_hopping.n_sb = 1; ul_hopping.hopping_offset = 0; ul_hopping.hop_mode = SRSLTE_PUSCH_HOP_MODE_INTER_SF; if (srslte_pusch_init(&pusch, cell)) { fprintf(stderr, "Error creating PDSCH object\n"); goto quit; } /* Configure PUSCH */ printf("Encoding rv_idx=%d\n",rv_idx); srslte_uci_cfg_t uci_cfg; uci_cfg.I_offset_cqi = 6; uci_cfg.I_offset_ri = 2; uci_cfg.I_offset_ack = 4; if (srslte_pusch_cfg(&pusch, &cfg, &grant, &uci_cfg, &ul_hopping, NULL, subframe, 0, 0)) { fprintf(stderr, "Error configuring PDSCH\n"); exit(-1); } srslte_pusch_set_rnti(&pusch, 1234); srslte_uci_data_t uci_data_tx; srslte_uci_data_t uci_data_rx; bzero(&uci_data_tx, sizeof(srslte_uci_data_t)); uci_data_tx.uci_cqi_len = 4; uci_data_tx.uci_ri_len = 0; uci_data_tx.uci_ack_len = 0; memcpy(&uci_data_rx, &uci_data_tx, sizeof(srslte_uci_data_t)); for (uint32_t i=0;i<20;i++) { uci_data_tx.uci_cqi [i] = 1; } uci_data_tx.uci_ri = 1; uci_data_tx.uci_ack = 1; uint32_t nof_re = SRSLTE_NRE*cell.nof_prb*2*SRSLTE_CP_NSYMB(cell.cp); sf_symbols = srslte_vec_malloc(sizeof(cf_t) * nof_re); if (!sf_symbols) { perror("malloc"); exit(-1); } data = srslte_vec_malloc(sizeof(uint8_t) * cfg.grant.mcs.tbs); if (!data) { perror("malloc"); exit(-1); } for (uint32_t i=0;i<cfg.grant.mcs.tbs/8;i++) { data[i] = 1; } if (srslte_softbuffer_tx_init(&softbuffer_tx, 100)) { fprintf(stderr, "Error initiating soft buffer\n"); goto quit; } if (srslte_softbuffer_rx_init(&softbuffer_rx, 100)) { fprintf(stderr, "Error initiating soft buffer\n"); goto quit; } uint32_t ntrials = 100; if (srslte_pusch_uci_encode(&pusch, &cfg, &softbuffer_tx, data, uci_data_tx, sf_symbols)) { fprintf(stderr, "Error encoding TB\n"); exit(-1); } if (rv_idx > 0) { cfg.rv = rv_idx; if (srslte_pusch_uci_encode(&pusch, &cfg, &softbuffer_tx, data, uci_data_tx, sf_symbols)) { fprintf(stderr, "Error encoding TB\n"); exit(-1); } } ce = srslte_vec_malloc(sizeof(cf_t) * SRSLTE_SF_LEN_RE(cell.nof_prb, cell.cp)); if (!ce) { perror("srslte_vec_malloc"); goto quit; } for (int j=0;j<SRSLTE_SF_LEN_RE(cell.nof_prb, cell.cp);j++) { ce[j] = 1; } gettimeofday(&t[1], NULL); int r = srslte_pusch_uci_decode(&pusch, &cfg, &softbuffer_rx, sf_symbols, ce, 0, data, &uci_data_rx); gettimeofday(&t[2], NULL); get_time_interval(t); if (r) { printf("Error decoding\n"); ret = -1; } else { ret = 0; printf("DECODED OK in %d:%d (TBS: %d bits, TX: %.2f Mbps, Processing: %.2f Mbps)\n", (int) t[0].tv_sec, (int) t[0].tv_usec/ntrials, cfg.grant.mcs.tbs, (float) cfg.grant.mcs.tbs/1000, (float) cfg.grant.mcs.tbs/t[0].tv_usec*ntrials); } if (uci_data_tx.uci_ack_len) { if (uci_data_tx.uci_ack != uci_data_rx.uci_ack) { printf("UCI ACK bit error: %d != %d\n", uci_data_tx.uci_ack, uci_data_rx.uci_ack); } } if (uci_data_tx.uci_ri_len) { if (uci_data_tx.uci_ri != uci_data_rx.uci_ri) { printf("UCI RI bit error: %d != %d\n", uci_data_tx.uci_ri, uci_data_rx.uci_ri); } } if (uci_data_tx.uci_cqi_len) { printf("cqi_tx="); srslte_vec_fprint_b(stdout, uci_data_tx.uci_cqi, uci_data_tx.uci_cqi_len); printf("cqi_rx="); srslte_vec_fprint_b(stdout, uci_data_rx.uci_cqi, uci_data_rx.uci_cqi_len); } quit: srslte_pusch_free(&pusch); srslte_softbuffer_tx_free(&softbuffer_tx); if (sf_symbols) { free(sf_symbols); } if (data) { free(data); } if (ce) { free(ce); } if (ret) { printf("Error\n"); } else { printf("Ok\n"); } exit(ret); }
/* Decode a transport block according to 36.212 5.3.2 * */ static int decode_tb(srslte_sch_t *q, srslte_softbuffer_rx_t *softbuffer, srslte_cbsegm_t *cb_segm, uint32_t Qm, uint32_t rv, uint32_t nof_e_bits, float *e_bits, uint8_t *data) { uint8_t parity[24]; uint8_t *p_parity = parity; uint32_t par_rx, par_tx; uint32_t i; uint32_t cb_len, rp, wp, rlen, F, n_e; if (q != NULL && data != NULL && softbuffer != NULL && e_bits != NULL && cb_segm != NULL) { if (cb_segm->tbs == 0 || cb_segm->C == 0) { return SRSLTE_SUCCESS; } rp = 0; rp = 0; wp = 0; uint32_t Gp = nof_e_bits / Qm; uint32_t gamma=Gp; if (cb_segm->C>0) { gamma = Gp%cb_segm->C; } bool early_stop = true; for (i = 0; i < cb_segm->C && early_stop; i++) { /* Get read/write 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; } else { rlen = cb_len - 24; } 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); /* Rate Unmatching */ if (srslte_rm_turbo_rx(softbuffer->buffer_f[i], softbuffer->buff_size, &e_bits[rp], n_e, (float*) q->cb_out, 3 * cb_len + 12, rv, F)) { fprintf(stderr, "Error in rate matching\n"); return SRSLTE_ERROR; } if (SRSLTE_VERBOSE_ISDEBUG()) { DEBUG("CB#%d RMOUT: ", i); srslte_vec_fprint_f(stdout, q->cb_out, 3*cb_len+12); } /* Turbo Decoding with CRC-based early stopping */ q->nof_iterations = 0; uint32_t len_crc; uint8_t *cb_in_ptr; srslte_crc_t *crc_ptr; early_stop = false; srslte_tdec_reset(&q->decoder, cb_len); do { srslte_tdec_iteration(&q->decoder, (float*) q->cb_out, cb_len); q->nof_iterations++; if (cb_segm->C > 1) { len_crc = cb_len; cb_in_ptr = q->cb_in; crc_ptr = &q->crc_cb; } else { len_crc = cb_segm->tbs+24; cb_in_ptr = &q->cb_in[F]; crc_ptr = &q->crc_tb; } srslte_tdec_decision(&q->decoder, q->cb_in, cb_len); /* Check Codeblock CRC and stop early if incorrect */ if (!srslte_crc_checksum(crc_ptr, cb_in_ptr, len_crc)) { early_stop = true; } } while (q->nof_iterations < SRSLTE_PDSCH_MAX_TDEC_ITERS && !early_stop); q->average_nof_iterations = SRSLTE_VEC_EMA((float) q->nof_iterations, q->average_nof_iterations, 0.2); if (SRSLTE_VERBOSE_ISDEBUG()) { DEBUG("CB#%d IN: ", i); srslte_vec_fprint_b(stdout, q->cb_in, cb_len); } // If CB CRC is not correct, early_stop will be false and wont continue with rest of CBs /* Copy data to another buffer, removing the Codeblock CRC */ if (i < cb_segm->C - 1) { memcpy(&data[wp], &q->cb_in[F], (rlen - F) * sizeof(uint8_t)); } else { DEBUG("Last CB, appending parity: %d to %d from %d and 24 from %d\n", rlen - F - 24, wp, F, rlen - 24); /* Append Transport Block parity bits to the last CB */ memcpy(&data[wp], &q->cb_in[F], (rlen - F - 24) * sizeof(uint8_t)); memcpy(parity, &q->cb_in[rlen - 24], 24 * sizeof(uint8_t)); } /* Set read/write pointers */ wp += (rlen - F); rp += n_e; } if (!early_stop) { INFO("CB %d failed. TB is erroneous.\n",i-1); return SRSLTE_ERROR; } else { INFO("END CB#%d: wp: %d, rp: %d\n", i, wp, rp); // Compute transport block CRC par_rx = srslte_crc_checksum(&q->crc_tb, data, cb_segm->tbs); // check parity bits par_tx = srslte_bit_unpack(&p_parity, 24); if (!par_rx) { INFO("\n\tCAUTION!! Received all-zero transport block\n\n", 0); } if (par_rx == par_tx) { INFO("TB decoded OK\n",i); return SRSLTE_SUCCESS; } else { INFO("Error in TB parity\n",i); return SRSLTE_ERROR; } } } else { return SRSLTE_ERROR_INVALID_INPUTS; } }