static int srslte_pdsch_codeword_decode(srslte_pdsch_t *q, srslte_pdsch_cfg_t *cfg, srslte_softbuffer_rx_t *softbuffer, uint16_t rnti, uint8_t *data, uint32_t codeword_idx, uint32_t tb_idx, bool *ack) { srslte_ra_nbits_t *nbits = &cfg->nbits[tb_idx]; srslte_ra_mcs_t *mcs = &cfg->grant.mcs[tb_idx]; uint32_t rv = cfg->rv[tb_idx]; int ret = SRSLTE_ERROR_INVALID_INPUTS; if (softbuffer && data && ack) { INFO("Decoding PDSCH SF: %d (CW%d -> TB%d), Mod %s, NofBits: %d, NofSymbols: %d, NofBitsE: %d, rv_idx: %d\n", cfg->sf_idx, codeword_idx, tb_idx, srslte_mod_string(mcs->mod), mcs->tbs, nbits->nof_re, nbits->nof_bits, rv); /* demodulate symbols * The MAX-log-MAP algorithm used in turbo decoding is unsensitive to SNR estimation, * thus we don't need tot set it in the LLRs normalization */ srslte_demod_soft_demodulate_s(mcs->mod, q->d[codeword_idx], q->e[codeword_idx], nbits->nof_re); /* Select scrambling sequence */ srslte_sequence_t *seq = get_user_sequence(q, rnti, codeword_idx, cfg->sf_idx, nbits->nof_bits); /* Bit scrambling */ srslte_scrambling_s_offset(seq, q->e[codeword_idx], 0, nbits->nof_bits); /* Return */ ret = srslte_dlsch_decode2(&q->dl_sch, cfg, softbuffer, q->e[codeword_idx], data, tb_idx); q->last_nof_iterations[codeword_idx] = srslte_sch_last_noi(&q->dl_sch); if (ret == SRSLTE_SUCCESS) { *ack = true; } else if (ret == SRSLTE_ERROR) { *ack = false; ret = SRSLTE_SUCCESS; } else if (ret == SRSLTE_ERROR_INVALID_INPUTS) { *ack = false; ret = SRSLTE_ERROR; } } else { ERROR("Detected NULL pointer in TB%d &softbuffer=%p &data=%p &ack=%p", codeword_idx, softbuffer, (void*)data, ack); } return ret; }
static int srslte_pdsch_codeword_encode(srslte_pdsch_t *q, srslte_pdsch_cfg_t *cfg, srslte_softbuffer_tx_t *softbuffer, uint16_t rnti, uint8_t *data, uint32_t codeword_idx, uint32_t tb_idx) { srslte_ra_nbits_t *nbits = &cfg->nbits[tb_idx]; srslte_ra_mcs_t *mcs = &cfg->grant.mcs[tb_idx]; uint32_t rv = cfg->rv[tb_idx]; bool valid_inputs = true; if (!softbuffer) { ERROR("Error encoding (TB%d -> CW%d), softbuffer=NULL", tb_idx, codeword_idx); valid_inputs = false; } if (nbits->nof_bits && valid_inputs) { INFO("Encoding PDSCH SF: %d (TB%d -> CW%d), Mod %s, NofBits: %d, NofSymbols: %d, NofBitsE: %d, rv_idx: %d\n", cfg->sf_idx, tb_idx, codeword_idx, srslte_mod_string(mcs->mod), mcs->tbs, nbits->nof_re, nbits->nof_bits, rv); /* Channel coding */ if (srslte_dlsch_encode2(&q->dl_sch, cfg, softbuffer, data, q->e[codeword_idx], tb_idx)) { ERROR("Error encoding (TB%d -> CW%d)", tb_idx, codeword_idx); return SRSLTE_ERROR; } /* Select scrambling sequence */ srslte_sequence_t *seq = get_user_sequence(q, rnti, codeword_idx, cfg->sf_idx, nbits->nof_bits); /* Bit scrambling */ srslte_scrambling_bytes(seq, (uint8_t *) q->e[codeword_idx], nbits->nof_bits); /* Bit mapping */ srslte_mod_modulate_bytes(&q->mod[mcs->mod], (uint8_t *) q->e[codeword_idx], q->d[codeword_idx], nbits->nof_bits); } else { return SRSLTE_ERROR_INVALID_INPUTS; } return SRSLTE_SUCCESS; }
int srslte_pmch_encode(srslte_pmch_t *q, srslte_pdsch_cfg_t *cfg, srslte_softbuffer_tx_t *softbuffer, uint8_t *data, uint16_t area_id, cf_t *sf_symbols[SRSLTE_MAX_PORTS]) { int i; /* Set pointers for layermapping & precoding */ cf_t *x[SRSLTE_MAX_LAYERS]; int ret = SRSLTE_ERROR_INVALID_INPUTS; if (q != NULL && cfg != NULL) { for (i=0;i<q->cell.nof_ports;i++) { if (sf_symbols[i] == NULL) { return SRSLTE_ERROR_INVALID_INPUTS; } } if (cfg->grant.mcs[0].tbs == 0) { return SRSLTE_ERROR_INVALID_INPUTS; } if (cfg->nbits[0].nof_re > q->max_re) { fprintf(stderr, "Error too many RE per subframe (%d). PMCH configured for %d RE (%d PRB)\n", cfg->nbits[0].nof_re, q->max_re, q->cell.nof_prb); return SRSLTE_ERROR_INVALID_INPUTS; } INFO("Encoding PMCH SF: %d, Mod %s, NofBits: %d, NofSymbols: %d, NofBitsE: %d, rv_idx: %d\n", cfg->sf_idx, srslte_mod_string(cfg->grant.mcs[0].mod), cfg->grant.mcs[0].tbs, cfg->nbits[0].nof_re, cfg->nbits[0].nof_bits, 0); /* number of layers equals number of ports */ for (i = 0; i < q->cell.nof_ports; i++) { x[i] = q->x[i]; } memset(&x[q->cell.nof_ports], 0, sizeof(cf_t*) * (SRSLTE_MAX_LAYERS - q->cell.nof_ports)); // TODO: use tb_encode directly if (srslte_dlsch_encode(&q->dl_sch, cfg, softbuffer, data, q->e)) { fprintf(stderr, "Error encoding TB\n"); return SRSLTE_ERROR; } /* scramble */ srslte_scrambling_bytes(&q->seqs[area_id]->seq[cfg->sf_idx], (uint8_t*) q->e, cfg->nbits[0].nof_bits); srslte_mod_modulate_bytes(&q->mod[cfg->grant.mcs[0].mod], (uint8_t*) q->e, q->d, cfg->nbits[0].nof_bits); /* No tx diversity in MBSFN */ memcpy(q->symbols[0], q->d, cfg->nbits[0].nof_re * sizeof(cf_t)); /* mapping to resource elements */ for (i = 0; i < q->cell.nof_ports; i++) { srslte_pmch_put(q, q->symbols[i], sf_symbols[i], cfg->nbits[0].lstart); } ret = SRSLTE_SUCCESS; } return ret; }
/** Decodes the pmch from the received symbols */ int srslte_pmch_decode_multi(srslte_pmch_t *q, srslte_pdsch_cfg_t *cfg, srslte_softbuffer_rx_t *softbuffer, cf_t *sf_symbols[SRSLTE_MAX_PORTS], cf_t *ce[SRSLTE_MAX_PORTS][SRSLTE_MAX_PORTS], float noise_estimate, uint16_t area_id, uint8_t *data) { /* Set pointers for layermapping & precoding */ uint32_t i, n; cf_t *x[SRSLTE_MAX_LAYERS]; if (q != NULL && sf_symbols != NULL && data != NULL && cfg != NULL) { INFO("Decoding PMCH SF: %d, MBSFN area ID: 0x%x, Mod %s, TBS: %d, NofSymbols: %d, NofBitsE: %d, rv_idx: %d, C_prb=%d, cfi=%d\n", cfg->sf_idx, area_id, srslte_mod_string(cfg->grant.mcs[0].mod), cfg->grant.mcs[0].tbs, cfg->nbits[0].nof_re, cfg->nbits[0].nof_bits, 0, cfg->grant.nof_prb, cfg->nbits[0].lstart-1); /* number of layers equals number of ports */ for (i = 0; i < q->cell.nof_ports; i++) { x[i] = q->x[i]; } memset(&x[q->cell.nof_ports], 0, sizeof(cf_t*) * (SRSLTE_MAX_LAYERS - q->cell.nof_ports)); for (int j=0;j<q->nof_rx_antennas;j++) { /* extract symbols */ n = srslte_pmch_get(q, sf_symbols[j], q->symbols[j], cfg->nbits[0].lstart); if (n != cfg->nbits[0].nof_re) { fprintf(stderr, "PMCH 1 extract symbols error expecting %d symbols but got %d, lstart %d\n", cfg->nbits[0].nof_re, n, cfg->nbits[0].lstart); return SRSLTE_ERROR; } /* extract channel estimates */ for (i = 0; i < q->cell.nof_ports; i++) { n = srslte_pmch_get(q, ce[i][j], q->ce[i][j], cfg->nbits[0].lstart); if (n != cfg->nbits[0].nof_re) { fprintf(stderr, "PMCH 2 extract chest error expecting %d symbols but got %d\n", cfg->nbits[0].nof_re, n); return SRSLTE_ERROR; } } } // No tx diversity in MBSFN srslte_predecoding_single_multi(q->symbols, q->ce[0], q->d, NULL, q->nof_rx_antennas, cfg->nbits[0].nof_re, 1.0f, noise_estimate); if (SRSLTE_VERBOSE_ISDEBUG()) { DEBUG("SAVED FILE subframe.dat: received subframe symbols\n"); srslte_vec_save_file("subframe.dat", sf_symbols, SRSLTE_SF_LEN_RE(q->cell.nof_prb, q->cell.cp)*sizeof(cf_t)); DEBUG("SAVED FILE hest0.dat: channel estimates for port 4\n"); srslte_vec_save_file("hest0.dat", ce[0], SRSLTE_SF_LEN_RE(q->cell.nof_prb, q->cell.cp)*sizeof(cf_t)); DEBUG("SAVED FILE pmch_symbols.dat: symbols after equalization\n"); srslte_vec_save_file("pmch_symbols.bin", q->d, cfg->nbits[0].nof_re*sizeof(cf_t)); } /* demodulate symbols * The MAX-log-MAP algorithm used in turbo decoding is unsensitive to SNR estimation, * thus we don't need tot set it in thde LLRs normalization */ srslte_demod_soft_demodulate_s(cfg->grant.mcs[0].mod, q->d, q->e, cfg->nbits[0].nof_re); /* descramble */ srslte_scrambling_s_offset(&q->seqs[area_id]->seq[cfg->sf_idx], q->e, 0, cfg->nbits[0].nof_bits); if (SRSLTE_VERBOSE_ISDEBUG()) { DEBUG("SAVED FILE llr.dat: LLR estimates after demodulation and descrambling\n"); srslte_vec_save_file("llr.dat", q->e, cfg->nbits[0].nof_bits*sizeof(int16_t)); } return srslte_dlsch_decode(&q->dl_sch, cfg, softbuffer, q->e, data); } else { return SRSLTE_ERROR_INVALID_INPUTS; } }
/** Converts the PDSCH data bits to symbols mapped to the slot ready for transmission */ int srslte_pdsch_encode_rnti(srslte_pdsch_t *q, srslte_pdsch_cfg_t *cfg, srslte_softbuffer_tx_t *softbuffer, uint8_t *data, uint16_t rnti, cf_t *sf_symbols[SRSLTE_MAX_PORTS]) { int i; /* Set pointers for layermapping & precoding */ cf_t *x[SRSLTE_MAX_LAYERS]; int ret = SRSLTE_ERROR_INVALID_INPUTS; if (q != NULL && data != NULL && cfg != NULL) { for (i=0; i<q->cell.nof_ports; i++) { if (sf_symbols[i] == NULL) { return SRSLTE_ERROR_INVALID_INPUTS; } } if (cfg->grant.mcs.tbs == 0) { return SRSLTE_ERROR_INVALID_INPUTS; } if (cfg->nbits.nof_re > q->max_re) { fprintf(stderr, "Error too many RE per subframe (%d). PDSCH configured for %d RE (%d PRB)\n", cfg->nbits.nof_re, q->max_re, q->cell.nof_prb); return SRSLTE_ERROR_INVALID_INPUTS; } INFO("Encoding PDSCH SF: %d, Mod %s, NofBits: %d, NofSymbols: %d, NofBitsE: %d, rv_idx: %d\n", cfg->sf_idx, srslte_mod_string(cfg->grant.mcs.mod), cfg->grant.mcs.tbs, cfg->nbits.nof_re, cfg->nbits.nof_bits, cfg->rv); /* number of layers equals number of ports */ for (i = 0; i < q->cell.nof_ports; i++) { x[i] = q->x[i]; } memset(&x[q->cell.nof_ports], 0, sizeof(cf_t*) * (SRSLTE_MAX_LAYERS - q->cell.nof_ports)); if (srslte_dlsch_encode(&q->dl_sch, cfg, softbuffer, data, q->e)) { fprintf(stderr, "Error encoding TB\n"); return SRSLTE_ERROR; } if (rnti != q->rnti) { srslte_sequence_t seq; if (srslte_sequence_pdsch(&seq, rnti, 0, 2 * cfg->sf_idx, q->cell.id, cfg->nbits.nof_bits)) { return SRSLTE_ERROR; } srslte_scrambling_bytes_offset(&seq, (uint8_t*) q->e, 0, cfg->nbits.nof_bits); srslte_sequence_free(&seq); } else { srslte_scrambling_bytes_offset(&q->seq[cfg->sf_idx], (uint8_t*) q->e, 0, cfg->nbits.nof_bits); } srslte_mod_modulate_bytes(&q->mod[cfg->grant.mcs.mod], (uint8_t*) q->e, q->d, cfg->nbits.nof_bits); /* TODO: only diversity supported */ if (q->cell.nof_ports > 1) { srslte_layermap_diversity(q->d, x, q->cell.nof_ports, cfg->nbits.nof_re); srslte_precoding_diversity(&q->precoding, x, q->symbols, q->cell.nof_ports, cfg->nbits.nof_re / q->cell.nof_ports); } else { memcpy(q->symbols[0], q->d, cfg->nbits.nof_re * sizeof(cf_t)); } /* mapping to resource elements */ for (i = 0; i < q->cell.nof_ports; i++) { srslte_pdsch_put(q, q->symbols[i], sf_symbols[i], &cfg->grant, cfg->nbits.lstart, cfg->sf_idx); } ret = SRSLTE_SUCCESS; } return ret; }
/** Decodes the PDSCH from the received symbols */ int srslte_pdsch_decode_rnti(srslte_pdsch_t *q, srslte_pdsch_cfg_t *cfg, srslte_softbuffer_rx_t *softbuffer, cf_t *sf_symbols, cf_t *ce[SRSLTE_MAX_PORTS], float noise_estimate, uint16_t rnti, uint8_t *data) { /* Set pointers for layermapping & precoding */ uint32_t i, n; cf_t *x[SRSLTE_MAX_LAYERS]; if (q != NULL && sf_symbols != NULL && data != NULL && cfg != NULL) { INFO("Decoding PDSCH SF: %d, RNTI: 0x%x, Mod %s, TBS: %d, NofSymbols: %d, NofBitsE: %d, rv_idx: %d, C_prb=%d\n", cfg->sf_idx, rnti, srslte_mod_string(cfg->grant.mcs.mod), cfg->grant.mcs.tbs, cfg->nbits.nof_re, cfg->nbits.nof_bits, cfg->rv, cfg->grant.nof_prb); /* number of layers equals number of ports */ for (i = 0; i < q->cell.nof_ports; i++) { x[i] = q->x[i]; } memset(&x[q->cell.nof_ports], 0, sizeof(cf_t*) * (SRSLTE_MAX_LAYERS - q->cell.nof_ports)); /* extract symbols */ n = srslte_pdsch_get(q, sf_symbols, q->symbols[0], &cfg->grant, cfg->nbits.lstart, cfg->sf_idx); if (n != cfg->nbits.nof_re) { fprintf(stderr, "Error expecting %d symbols but got %d\n", cfg->nbits.nof_re, n); return SRSLTE_ERROR; } /* extract channel estimates */ for (i = 0; i < q->cell.nof_ports; i++) { n = srslte_pdsch_get(q, ce[i], q->ce[i], &cfg->grant, cfg->nbits.lstart, cfg->sf_idx); if (n != cfg->nbits.nof_re) { fprintf(stderr, "Error expecting %d symbols but got %d\n", cfg->nbits.nof_re, n); return SRSLTE_ERROR; } } /* TODO: only diversity is supported */ if (q->cell.nof_ports == 1) { /* no need for layer demapping */ srslte_predecoding_single(q->symbols[0], q->ce[0], q->d, cfg->nbits.nof_re, noise_estimate); } else { srslte_predecoding_diversity(&q->precoding, q->symbols[0], q->ce, x, q->cell.nof_ports, cfg->nbits.nof_re, noise_estimate); srslte_layerdemap_diversity(x, q->d, q->cell.nof_ports, cfg->nbits.nof_re / q->cell.nof_ports); } if (SRSLTE_VERBOSE_ISDEBUG()) { DEBUG("SAVED FILE pdsch_symbols.dat: symbols after equalization\n",0); srslte_vec_save_file("pdsch_symbols.dat", q->d, cfg->nbits.nof_re*sizeof(cf_t)); } /* demodulate symbols * The MAX-log-MAP algorithm used in turbo decoding is unsensitive to SNR estimation, * thus we don't need tot set it in the LLRs normalization */ srslte_demod_soft_demodulate_s(cfg->grant.mcs.mod, q->d, q->e, cfg->nbits.nof_re); /* descramble */ if (rnti != q->rnti) { srslte_sequence_t seq; if (srslte_sequence_pdsch(&seq, rnti, 0, 2 * cfg->sf_idx, q->cell.id, cfg->nbits.nof_bits)) { return SRSLTE_ERROR; } srslte_scrambling_s_offset(&seq, q->e, 0, cfg->nbits.nof_bits); srslte_sequence_free(&seq); } else { srslte_scrambling_s_offset(&q->seq[cfg->sf_idx], q->e, 0, cfg->nbits.nof_bits); } if (SRSLTE_VERBOSE_ISDEBUG()) { DEBUG("SAVED FILE llr.dat: LLR estimates after demodulation and descrambling\n",0); srslte_vec_save_file("llr.dat", q->e, cfg->nbits.nof_bits*sizeof(int16_t)); } return srslte_dlsch_decode(&q->dl_sch, cfg, softbuffer, q->e, data); } else { return SRSLTE_ERROR_INVALID_INPUTS; } }
int main(int argc, char **argv) { uint32_t i, j, k; int ret = -1; struct timeval t[3]; srslte_softbuffer_tx_t *softbuffers_tx[SRSLTE_MAX_CODEWORDS]; int M=1; parse_args(argc,argv); /* Initialise to zeros */ bzero(&pmch_tx, sizeof(srslte_pmch_t)); bzero(&pmch_rx, sizeof(srslte_pmch_t)); bzero(&pmch_cfg, sizeof(srslte_pdsch_cfg_t)); bzero(ce, sizeof(cf_t*)*SRSLTE_MAX_PORTS); bzero(tx_slot_symbols, sizeof(cf_t*)*SRSLTE_MAX_PORTS); bzero(rx_slot_symbols, sizeof(cf_t*)*SRSLTE_MAX_PORTS); cell.nof_ports = 1; srslte_ra_dl_dci_t dci; bzero(&dci, sizeof(srslte_ra_dl_dci_t)); dci.type0_alloc.rbg_bitmask = 0xffffffff; /* If transport block 0 is enabled */ grant.tb_en[0] = true; grant.tb_en[1] = false; grant.mcs[0].idx = mcs_idx; grant.nof_prb = cell.nof_prb; grant.sf_type = SRSLTE_SF_MBSFN; srslte_dl_fill_ra_mcs(&grant.mcs[0], cell.nof_prb); grant.Qm[0] = srslte_mod_bits_x_symbol(grant.mcs[0].mod); for(int i = 0; i < 2; i++){ for(int j = 0; j < grant.nof_prb; j++){ grant.prb_idx[i][j] = true; } } /* init memory */ for (i=0;i<SRSLTE_MAX_PORTS;i++) { for (j = 0; j < SRSLTE_MAX_PORTS; j++) { ce[i][j] = srslte_vec_malloc(sizeof(cf_t) * NOF_CE_SYMBOLS); if (!ce[i][j]) { perror("srslte_vec_malloc"); goto quit; } for (k = 0; k < NOF_CE_SYMBOLS; k++) { ce[i][j][k] = (i == j) ? 1.0f : 0.0f; } } rx_slot_symbols[i] = srslte_vec_malloc(sizeof(cf_t) * SRSLTE_SF_LEN_RE(cell.nof_prb, cell.cp)); if (!rx_slot_symbols[i]) { perror("srslte_vec_malloc"); goto quit; } } for (i = 0; i < SRSLTE_MAX_CODEWORDS; i++) { softbuffers_tx[i] = calloc(sizeof(srslte_softbuffer_tx_t), 1); if (!softbuffers_tx[i]) { fprintf(stderr, "Error allocating TX soft buffer\n"); } if (srslte_softbuffer_tx_init(softbuffers_tx[i], cell.nof_prb)) { fprintf(stderr, "Error initiating TX soft buffer\n"); goto quit; } } for (i = 0; i < cell.nof_ports; i++) { tx_slot_symbols[i] = calloc(SRSLTE_SF_LEN_RE(cell.nof_prb, cell.cp), sizeof(cf_t)); if (!tx_slot_symbols[i]) { perror("srslte_vec_malloc"); goto quit; } } for (int i = 0; i < SRSLTE_MAX_CODEWORDS; i++) { if (grant.tb_en[i]) { data_tx[i] = srslte_vec_malloc(sizeof(uint8_t) * grant.mcs[i].tbs); if (!data_tx[i]) { perror("srslte_vec_malloc"); goto quit; } bzero(data_tx[i], sizeof(uint8_t) * grant.mcs[i].tbs); data_rx[i] = srslte_vec_malloc(sizeof(uint8_t) * grant.mcs[i].tbs); if (!data_rx[i]) { perror("srslte_vec_malloc"); goto quit; } bzero(data_rx[i], sizeof(uint8_t) * grant.mcs[i].tbs); } } for (i = 0; i < SRSLTE_MAX_CODEWORDS; i++) { softbuffers_rx[i] = calloc(sizeof(srslte_softbuffer_rx_t), 1); if (!softbuffers_rx[i]) { fprintf(stderr, "Error allocating RX soft buffer\n"); goto quit; } if (srslte_softbuffer_rx_init(softbuffers_rx[i], cell.nof_prb)) { fprintf(stderr, "Error initiating RX soft buffer\n"); goto quit; } } #ifdef DO_OFDM for (i = 0; i < cell.nof_ports; i++) { tx_sf_symbols[i] = srslte_vec_malloc(sizeof(cf_t) * SRSLTE_SF_LEN_PRB(cell.nof_prb)); if (srslte_ofdm_tx_init_mbsfn(&ifft_mbsfn[i], SRSLTE_CP_EXT, tx_slot_symbols[i], tx_sf_symbols[i], cell.nof_prb)) { fprintf(stderr, "Error creating iFFT object\n"); exit(-1); } srslte_ofdm_set_non_mbsfn_region(&ifft_mbsfn[i], non_mbsfn_region); srslte_ofdm_set_normalize(&ifft_mbsfn[i], true); } for (i = 0; i < nof_rx_antennas; i++) { rx_sf_symbols[i] = srslte_vec_malloc(sizeof(cf_t) * SRSLTE_SF_LEN_PRB(cell.nof_prb)); if (srslte_ofdm_rx_init_mbsfn(&fft_mbsfn[i], SRSLTE_CP_EXT, rx_sf_symbols[i], rx_slot_symbols[i], cell.nof_prb)) { fprintf(stderr, "Error creating iFFT object\n"); exit(-1); } srslte_ofdm_set_non_mbsfn_region(&fft_mbsfn[i], non_mbsfn_region); srslte_ofdm_set_normalize(&fft_mbsfn[i], true); } #endif /* DO_OFDM */ /* Configure PDSCH */ if (srslte_pmch_cfg(&pmch_cfg, cell, &grant, cfi, subframe)) { fprintf(stderr, "Error configuring PMCH\n"); exit(-1); } if (srslte_pmch_cfg(&pmch_cfg, cell, &grant, cfi, subframe)) { fprintf(stderr, "Error configuring PMCH\n"); exit(-1); } INFO(" Global:\n"); INFO(" nof_prb=%d\n", cell.nof_prb); INFO(" nof_ports=%d\n", cell.nof_ports); INFO(" id=%d\n", cell.id); INFO(" cp=%s\n", srslte_cp_string(cell.cp)); INFO(" phich_length=%d\n", (int) cell.phich_length); INFO(" phich_resources=%d\n", (int) cell.phich_resources); INFO(" nof_prb=%d\n", pmch_cfg.grant.nof_prb); INFO(" sf_idx=%d\n", pmch_cfg.sf_idx); INFO(" mimo_type=%s\n", srslte_mimotype2str(pmch_cfg.mimo_type)); INFO(" nof_layers=%d\n", pmch_cfg.nof_layers); INFO(" nof_tb=%d\n", SRSLTE_RA_DL_GRANT_NOF_TB(&pmch_cfg.grant)); INFO(" Qm=%d\n", pmch_cfg.grant.Qm[0]); INFO(" mcs.idx=0x%X\n", pmch_cfg.grant.mcs[0].idx); INFO(" mcs.tbs=%d\n", pmch_cfg.grant.mcs[0].tbs); INFO(" mcs.mod=%s\n", srslte_mod_string(pmch_cfg.grant.mcs[0].mod)); INFO(" rv=%d\n", pmch_cfg.rv[0]); INFO(" lstart=%d\n", pmch_cfg.nbits[0].lstart); INFO(" nof_bits=%d\n", pmch_cfg.nbits[0].nof_bits); INFO(" nof_re=%d\n", pmch_cfg.nbits[0].nof_re); INFO(" nof_symb=%d\n", pmch_cfg.nbits[0].nof_symb); if (srslte_pmch_init(&pmch_tx, cell.nof_prb)) { fprintf(stderr, "Error creating PMCH object\n"); } srslte_pmch_set_area_id(&pmch_tx, mbsfn_area_id); if (srslte_pmch_init(&pmch_rx, cell.nof_prb)) { fprintf(stderr, "Error creating PMCH object\n"); } srslte_pmch_set_area_id(&pmch_rx, mbsfn_area_id); for (int tb = 0; tb < SRSLTE_MAX_CODEWORDS; tb++) { if (grant.tb_en[tb]) { for (int byte = 0; byte < grant.mcs[tb].tbs / 8; byte++) { data_tx[tb][byte] = (uint8_t) (rand() % 256); } } } if (srslte_pmch_encode(&pmch_tx, &pmch_cfg, softbuffers_tx[0], data_tx[0], mbsfn_area_id, tx_slot_symbols)) { fprintf(stderr, "Error encoding PDSCH\n"); exit(-1); } gettimeofday(&t[2], NULL); get_time_interval(t); printf("ENCODED in %.2f (PHY bitrate=%.2f Mbps. Processing bitrate=%.2f Mbps)\n", (float) t[0].tv_usec/M, (float) (grant.mcs[0].tbs + grant.mcs[1].tbs)/1000.0f, (float) (grant.mcs[0].tbs + grant.mcs[1].tbs)*M/t[0].tv_usec); #ifdef DO_OFDM for (i = 0; i < cell.nof_ports; i++) { /* For each Tx antenna modulate OFDM */ srslte_ofdm_tx_sf(&ifft_mbsfn[i]); } /* combine outputs */ for (j = 0; j < nof_rx_antennas; j++) { for (k = 0; k < NOF_CE_SYMBOLS; k++) { rx_sf_symbols[j][k] = 0.0f; for (i = 0; i < cell.nof_ports; i++) { rx_sf_symbols[j][k] += tx_sf_symbols[i][k] * ce[i][j][k]; } } } #else /* combine outputs */ for (j = 0; j < nof_rx_antennas; j++) { for (k = 0; k < SRSLTE_SF_LEN_RE(cell.nof_prb, cell.cp); k++) { rx_slot_symbols[j][k] = 0.0f; for (i = 0; i < cell.nof_ports; i++) { rx_slot_symbols[j][k] += tx_slot_symbols[i][k] * ce[i][j][k]; } } } #endif int r=0; gettimeofday(&t[1], NULL); #ifdef DO_OFDM /* For each Rx antenna demodulate OFDM */ for (i = 0; i < nof_rx_antennas; i++) { srslte_ofdm_rx_sf(&fft_mbsfn[i]); } #endif for (i = 0; i < SRSLTE_MAX_CODEWORDS; i++) { if (grant.tb_en[i]) { srslte_softbuffer_rx_reset_tbs(softbuffers_rx[i], (uint32_t) grant.mcs[i].tbs); } } r = srslte_pmch_decode(&pmch_rx, &pmch_cfg, softbuffers_rx[0],rx_slot_symbols[0], ce[0],0,mbsfn_area_id, data_rx[0]); gettimeofday(&t[2], NULL); get_time_interval(t); printf("DECODED %s in %.2f (PHY bitrate=%.2f Mbps. Processing bitrate=%.2f Mbps)\n", r?"Error":"OK", (float) t[0].tv_usec/M, (float) (grant.mcs[0].tbs + grant.mcs[1].tbs)/1000.0f, (float) (grant.mcs[0].tbs + grant.mcs[1].tbs)*M/t[0].tv_usec); /* If there is an error in PDSCH decode */ if (r) { ret = -1; goto quit; } /* Check Tx and Rx bytes */ for (int tb = 0; tb < SRSLTE_MAX_CODEWORDS; tb++) { if (grant.tb_en[tb]) { for (int byte = 0; byte < grant.mcs[tb].tbs / 8; byte++) { if (data_tx[tb][byte] != data_rx[tb][byte]) { ERROR("Found BYTE error in TB %d (%02X != %02X), quiting...", tb, data_tx[tb][byte], data_rx[tb][byte]); ret = SRSLTE_ERROR; goto quit; } } } } ret = SRSLTE_SUCCESS; quit: srslte_pmch_free(&pmch_tx); srslte_pmch_free(&pmch_rx); for (i = 0; i < SRSLTE_MAX_CODEWORDS; i++) { srslte_softbuffer_tx_free(softbuffers_tx[i]); if (softbuffers_tx[i]) { free(softbuffers_tx[i]); } srslte_softbuffer_rx_free(softbuffers_rx[i]); if (softbuffers_rx[i]) { free(softbuffers_rx[i]); } if (data_tx[i]) { free(data_tx[i]); } if (data_rx[i]) { free(data_rx[i]); } } for (i=0;i<SRSLTE_MAX_PORTS;i++) { for (j = 0; j < SRSLTE_MAX_PORTS; j++) { if (ce[i][j]) { free(ce[i][j]); } } if (tx_slot_symbols[i]) { free(tx_slot_symbols[i]); } if (rx_slot_symbols[i]) { free(rx_slot_symbols[i]); } } if (ret) { printf("Error\n"); } else { printf("Ok\n"); } exit(ret); }
/** Decodes the PDSCH from the received symbols */ int srslte_pdsch_decode(srslte_pdsch_t *q, srslte_pdsch_cfg_t *cfg, srslte_softbuffer_rx_t *softbuffers[SRSLTE_MAX_CODEWORDS], cf_t *sf_symbols[SRSLTE_MAX_PORTS], cf_t *ce[SRSLTE_MAX_PORTS][SRSLTE_MAX_PORTS], float noise_estimate, uint16_t rnti, uint8_t *data[SRSLTE_MAX_CODEWORDS], bool acks[SRSLTE_MAX_CODEWORDS]) { /* Set pointers for layermapping & precoding */ uint32_t i; cf_t *x[SRSLTE_MAX_LAYERS]; if (q != NULL && sf_symbols != NULL && data != NULL && cfg != NULL) { uint32_t nof_tb = SRSLTE_RA_DL_GRANT_NOF_TB(&cfg->grant); INFO("Decoding PDSCH SF: %d, RNTI: 0x%x, NofSymbols: %d, C_prb=%d, mimo_type=%s, nof_layers=%d, nof_tb=%d\n", cfg->sf_idx, rnti, cfg->nbits[0].nof_re, cfg->grant.nof_prb, srslte_mod_string(cfg->grant.mcs->mod), cfg->nof_layers, nof_tb); // Extract Symbols and Channel Estimates for (int j=0;j<q->nof_rx_antennas;j++) { int n = srslte_pdsch_get(q, sf_symbols[j], q->symbols[j], &cfg->grant, cfg->nbits[0].lstart, cfg->sf_idx); if (n != cfg->nbits[0].nof_re) { fprintf(stderr, "Error expecting %d symbols but got %d\n", cfg->nbits[0].nof_re, n); return SRSLTE_ERROR; } for (i = 0; i < q->cell.nof_ports; i++) { n = srslte_pdsch_get(q, ce[i][j], q->ce[i][j], &cfg->grant, cfg->nbits[0].lstart, cfg->sf_idx); if (n != cfg->nbits[0].nof_re) { fprintf(stderr, "Error expecting %d symbols but got %d\n", cfg->nbits[0].nof_re, n); return SRSLTE_ERROR; } } } // Prepare layers int nof_symbols [SRSLTE_MAX_CODEWORDS]; nof_symbols[0] = cfg->nbits[0].nof_re * nof_tb / cfg->nof_layers; nof_symbols[1] = cfg->nbits[1].nof_re * nof_tb / cfg->nof_layers; if (cfg->nof_layers == nof_tb) { /* Skip layer demap */ for (i = 0; i < cfg->nof_layers; i++) { x[i] = q->d[i]; } } else { /* number of layers equals number of ports */ for (i = 0; i < cfg->nof_layers; i++) { x[i] = q->x[i]; } memset(&x[cfg->nof_layers], 0, sizeof(cf_t*) * (SRSLTE_MAX_LAYERS - cfg->nof_layers)); } float pdsch_scaling = 1.0f; if (q->rho_a != 0.0f) { pdsch_scaling = q->rho_a; } // Pre-decoder if (srslte_predecoding_type(q->symbols, q->ce, x, q->nof_rx_antennas, q->cell.nof_ports, cfg->nof_layers, cfg->codebook_idx, cfg->nbits[0].nof_re, cfg->mimo_type, pdsch_scaling, noise_estimate)<0) { DEBUG("Error predecoding\n"); return SRSLTE_ERROR; } // Layer demapping only if necessary if (cfg->nof_layers != nof_tb) { srslte_layerdemap_type(x, q->d, cfg->nof_layers, nof_tb, nof_symbols[0], nof_symbols, cfg->mimo_type); } /* Codeword decoding: Implementation of 3GPP 36.212 Table 5.3.3.1.5-1 and Table 5.3.3.1.5-2 */ uint32_t cw_idx = (nof_tb == SRSLTE_MAX_TB && cfg->tb_cw_swap) ? 1 : 0; for (uint32_t tb_idx = 0; tb_idx < SRSLTE_MAX_TB; tb_idx++) { /* Decode only if transport block is enabled and the default ACK is not true */ if (cfg->grant.tb_en[tb_idx]) { if (!acks[tb_idx]) { int ret = srslte_pdsch_codeword_decode(q, cfg, softbuffers[tb_idx], rnti, data[tb_idx], cw_idx, tb_idx, &acks[tb_idx]); /* Check if there has been any execution error */ if (ret) { return ret; } } cw_idx = (cw_idx + 1) % SRSLTE_MAX_CODEWORDS; } } pdsch_decode_debug(q, cfg, sf_symbols, ce); return SRSLTE_SUCCESS; } else { return SRSLTE_ERROR_INVALID_INPUTS; } }
static int srslte_pdsch_codeword_decode(srslte_pdsch_t *q, srslte_pdsch_cfg_t *cfg, srslte_softbuffer_rx_t *softbuffer, uint16_t rnti, uint8_t *data, uint32_t codeword_idx, uint32_t tb_idx, bool *ack) { srslte_ra_nbits_t *nbits = &cfg->nbits[tb_idx]; srslte_ra_mcs_t *mcs = &cfg->grant.mcs[tb_idx]; uint32_t rv = cfg->rv[tb_idx]; int ret = SRSLTE_ERROR_INVALID_INPUTS; if (softbuffer && data && ack) { INFO("Decoding PDSCH SF: %d (CW%d -> TB%d), Mod %s, NofBits: %d, NofSymbols: %d, NofBitsE: %d, rv_idx: %d\n", cfg->sf_idx, codeword_idx, tb_idx, srslte_mod_string(mcs->mod), mcs->tbs, nbits->nof_re, nbits->nof_bits, rv); /* demodulate symbols * The MAX-log-MAP algorithm used in turbo decoding is unsensitive to SNR estimation, * thus we don't need tot set it in the LLRs normalization */ srslte_demod_soft_demodulate_s(mcs->mod, q->d[codeword_idx], q->e[codeword_idx], nbits->nof_re); /* Select scrambling sequence */ srslte_sequence_t *seq = get_user_sequence(q, rnti, codeword_idx, cfg->sf_idx, nbits->nof_bits); /* Bit scrambling */ srslte_scrambling_s_offset(seq, q->e[codeword_idx], 0, nbits->nof_bits); uint32_t qm = nbits->nof_bits/nbits->nof_re; switch(cfg->grant.mcs[tb_idx].mod) { case SRSLTE_MOD_BPSK: qm = 1; break; case SRSLTE_MOD_QPSK: qm = 2; break; case SRSLTE_MOD_16QAM: qm = 4; break; case SRSLTE_MOD_64QAM: qm = 6; break; default: ERROR("No modulation"); } int16_t *e = q->e[codeword_idx]; if (q->csi_enabled) { const uint32_t csi_max_idx = srslte_vec_max_fi(q->csi[codeword_idx], nbits->nof_bits / qm); float csi_max = 1.0f; if (csi_max_idx < nbits->nof_bits / qm) { csi_max = q->csi[codeword_idx][csi_max_idx]; } for (int i = 0; i < nbits->nof_bits / qm; i++) { const float csi = q->csi[codeword_idx][i] / csi_max; for (int k = 0; k < qm; k++) { e[qm * i + k] = (int16_t) ((float) e[qm * i + k] * csi); } } } /* Return */ ret = srslte_dlsch_decode2(&q->dl_sch, cfg, softbuffer, q->e[codeword_idx], data, tb_idx); q->last_nof_iterations[codeword_idx] = srslte_sch_last_noi(&q->dl_sch); if (ret == SRSLTE_SUCCESS) { *ack = true; } else if (ret == SRSLTE_ERROR) { *ack = false; ret = SRSLTE_SUCCESS; } else if (ret == SRSLTE_ERROR_INVALID_INPUTS) { *ack = false; ret = SRSLTE_ERROR; } } else { ERROR("Detected NULL pointer in TB%d &softbuffer=%p &data=%p &ack=%p", codeword_idx, softbuffer, (void*)data, ack); } return ret; }