static int int_2_bits(uint32_t* src, uint8_t* dst, int nbits) { int n; n=nbits/32; for (int i=0;i<n;i++) { srslte_bit_unpack(src[i],&dst,32); } srslte_bit_unpack(src[n],&dst,nbits-n*32); return n; }
/* Decode UCI CQI/PMI over PUCCH */ int16_t srslte_uci_decode_cqi_pucch(srslte_uci_cqi_pucch_t* q, int16_t b_bits[SRSLTE_CQI_MAX_BITS], uint8_t* cqi_data, uint32_t cqi_len) { if (cqi_len < SRSLTE_UCI_MAX_CQI_LEN_PUCCH && b_bits != NULL && cqi_data != NULL) { uint32_t max_w = 0; int32_t max_corr = INT32_MIN; uint32_t nwords = 1 << SRSLTE_UCI_MAX_CQI_LEN_PUCCH; for (uint32_t w=0;w<nwords;w += 1<<(SRSLTE_UCI_MAX_CQI_LEN_PUCCH - cqi_len)) { // Calculate correlation with pregenerated word and select maximum int32_t corr = srslte_vec_dot_prod_sss(q->cqi_table_s[w], b_bits, SRSLTE_UCI_CQI_CODED_PUCCH_B); if (corr > max_corr) { max_corr = corr; max_w = w; } } // Convert word to bits again uint8_t *ptr = cqi_data; srslte_bit_unpack(max_w, &ptr, SRSLTE_UCI_MAX_CQI_LEN_PUCCH); INFO("Decoded CQI: w=%d, corr=%d\n", max_w, max_corr); return max_corr; } else { return SRSLTE_ERROR_INVALID_INPUTS; } }
int srslte_mod_modulate(srslte_modem_table_t* q, uint8_t *bits, cf_t* symbols, uint32_t nbits) { uint32_t i,j,idx; uint8_t *b_ptr=(uint8_t*) bits; j=0; for (i=0;i<nbits;i+=q->nbits_x_symbol) { idx = srslte_bit_unpack(&b_ptr,q->nbits_x_symbol); if (idx < q->nsymbols) { symbols[j] = q->symbol_table[idx]; } else { return SRSLTE_ERROR; } j++; } return j; }
void cqi_pusch_pregen(srslte_uci_cqi_pusch_t *q) { uint8_t word[11]; for (int i=0;i<11;i++) { uint32_t nwords = (1<<(i+1)); q->cqi_table[i] = srslte_vec_malloc(sizeof(uint8_t)*nwords*32); q->cqi_table_s[i] = srslte_vec_malloc(sizeof(int16_t) * nwords * 32); for (uint32_t w=0;w<nwords;w++) { uint8_t *ptr = word; srslte_bit_unpack(w, &ptr, i+1); encode_cqi_pusch_block(word, i + 1, &q->cqi_table[i][32 * w]); for (int j=0;j<32;j++) { q->cqi_table_s[i][32*w+j] = 2*q->cqi_table[i][32*w+j]-1; } } } }
void srslte_uci_cqi_pucch_init(srslte_uci_cqi_pucch_t *q) { uint8_t word[16]; uint32_t nwords = 1 << SRSLTE_UCI_MAX_CQI_LEN_PUCCH; q->cqi_table = srslte_vec_malloc(nwords * sizeof(int8_t *)); q->cqi_table_s = srslte_vec_malloc(nwords * sizeof(int16_t *)); for (uint32_t w = 0; w < nwords; w++) { q->cqi_table[w] = srslte_vec_malloc(SRSLTE_UCI_CQI_CODED_PUCCH_B * sizeof(int8_t)); q->cqi_table_s[w] = srslte_vec_malloc(SRSLTE_UCI_CQI_CODED_PUCCH_B * sizeof(int16_t)); uint8_t *ptr = word; srslte_bit_unpack(w, &ptr, SRSLTE_UCI_MAX_CQI_LEN_PUCCH); srslte_uci_encode_cqi_pucch(word, SRSLTE_UCI_MAX_CQI_LEN_PUCCH, q->cqi_table[w]); for (int j = 0; j < SRSLTE_UCI_CQI_CODED_PUCCH_B; j++) { q->cqi_table_s[w][j] = (int16_t)(2 * q->cqi_table[w][j] - 1); } } }
// For decoding the block-encoded CQI we use ML decoding int decode_cqi_short(srslte_uci_cqi_pusch_t *q, int16_t *q_bits, uint32_t Q, uint8_t *data, uint32_t nof_bits) { if (nof_bits <= 11 && nof_bits > 0 && q != NULL && data != NULL && q_bits != NULL) { // Accumulate all copies of the 32-length sequence if (Q>32) { int i=1; for (;i<Q/32;i++) { srslte_vec_sum_sss(&q_bits[i*32], q_bits, q_bits, 32); } srslte_vec_sum_sss(&q_bits[i*32], q_bits, q_bits, Q%32); } uint32_t max_w = 0; int32_t max_corr = INT32_MIN; for (uint32_t w=0;w<(1<<nof_bits);w++) { // Calculate correlation with pregenerated word and select maximum int32_t corr = srslte_vec_dot_prod_sss(&q->cqi_table_s[nof_bits-1][w*32], q_bits, SRSLTE_MIN(32, Q)); if (corr > max_corr) { max_corr = corr; max_w = w; } } // Convert word to bits again uint8_t *ptr = data; srslte_bit_unpack(max_w, &ptr, nof_bits); INFO("Decoded CQI: w=%d, corr=%d\n", max_w, max_corr); return SRSLTE_SUCCESS; } else { return SRSLTE_ERROR_INVALID_INPUTS; } }
int main(int argc, char **argv) { srslte_dci_msg_t msg; srslte_ra_dl_dci_t ra_dl; int len, rlen; int nof_prb; int nwords; int i; uint8_t *y; if (argc < 3) { usage(argv[0]); exit(-1); } nof_prb = atoi(argv[1]); len = atoi(argv[2]); nwords = (len - 1) / 32 + 1; if (argc < 3 + nwords) { usage(argv[0]); exit(-1); } y = msg.data; rlen = 0; uint32_t x; for (i = 0; i < nwords; i++) { x = strtoul(argv[i + 3], NULL, 16); if (len - rlen < 32) { srslte_bit_unpack(x, &y, len - rlen); } else { srslte_bit_unpack(x, &y, 32); } } printf("DCI message len %d:\n", len); for (i = 0; i < len; i++) { printf("%d, ", msg.data[i]); } printf("\n"); srslte_dci_msg_type_t dci_type; msg.nof_bits = len; if (srslte_dci_msg_get_type(&msg, &dci_type, nof_prb, SRSLTE_SIRNTI)) { fprintf(stderr, "Can't obtain DCI message type\n"); exit(-1); } printf("\n"); printf("Message type:"); srslte_dci_msg_type_fprint(stdout, dci_type); switch (dci_type.type) { case SRSLTE_DCI_MSG_TYPE_PDSCH_SCHED: bzero(&ra_dl, sizeof(srslte_ra_dl_dci_t)); srslte_dci_msg_unpack_pdsch(&msg, &ra_dl, nof_prb, false); srslte_ra_pdsch_fprint(stdout, &ra_dl, nof_prb); break; default: printf("Error expected PDSCH\n"); exit(-1); } printf("\n"); }
/* 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; } }