int srslte_ue_dl_decode_mbsfn(srslte_ue_dl_t * q, uint8_t *data, uint32_t tti) { srslte_ra_dl_grant_t grant; int ret = SRSLTE_ERROR; uint32_t cfi; uint32_t sf_idx = tti%10; if ((ret = srslte_ue_dl_decode_fft_estimate_mbsfn(q, sf_idx, &cfi, SRSLTE_SF_MBSFN)) < 0) { return ret; } float noise_estimate = srslte_chest_dl_get_noise_estimate(&q->chest); // Uncoment next line to do ZF by default in pdsch_ue example //float noise_estimate = 0; grant.sf_type = SRSLTE_SF_MBSFN; grant.mcs[0].idx = 2; grant.tb_en[0] = true; grant.tb_en[1] = false; grant.nof_prb = q->pmch.cell.nof_prb; srslte_dl_fill_ra_mcs(&grant.mcs[0], grant.nof_prb); srslte_softbuffer_rx_reset_tbs(q->softbuffers[0], (uint32_t) grant.mcs[0].tbs); for(int j = 0; j < 2; j++){ for(int f = 0; f < grant.nof_prb; f++){ grant.prb_idx[j][f] = true; } } grant.Qm[0] = srslte_mod_bits_x_symbol(grant.mcs[0].mod); // redundancy version is set to 0 for the PMCH if (srslte_ue_dl_cfg_grant(q, &grant, cfi, sf_idx, SRSLTE_PMCH_RV, SRSLTE_MIMO_TYPE_SINGLE_ANTENNA)) { return SRSLTE_ERROR; } if (q->pmch_cfg.grant.mcs[0].mod > 0 && q->pmch_cfg.grant.mcs[0].tbs >= 0) { ret = srslte_pmch_decode_multi(&q->pmch, &q->pmch_cfg, q->softbuffers[0], q->sf_symbols_m, q->ce_m, noise_estimate, q->current_mbsfn_area_id, data); if (ret == SRSLTE_ERROR) { q->pmch_pkt_errors++; } else if (ret == SRSLTE_ERROR_INVALID_INPUTS) { fprintf(stderr, "Error calling srslte_pmch_decode()\n"); } } q->pmch_pkts_total++; if (ret == SRSLTE_SUCCESS) { return q->pmch_cfg.grant.mcs[0].tbs; } else { return 0; } }
int srslte_ue_dl_decode_rnti_rv_packet(srslte_ue_dl_t *q, srslte_ra_dl_grant_t *grant, uint8_t *data, uint32_t cfi, uint32_t sf_idx, uint16_t rnti, uint32_t rvidx) { int ret = SRSLTE_ERROR; q->nof_detected++; /* Setup PDSCH configuration for this CFI, SFIDX and RVIDX */ if (srslte_ue_dl_cfg_grant(q, grant, cfi, sf_idx, rvidx)) { return SRSLTE_ERROR; } if (q->pdsch_cfg.rv == 0) { srslte_softbuffer_rx_reset_tbs(&q->softbuffer, grant->mcs.tbs); } // Uncoment next line to do ZF by default in pdsch_ue example //float noise_estimate = 0; float noise_estimate = srslte_chest_dl_get_noise_estimate(&q->chest); if (q->pdsch_cfg.grant.mcs.mod > 0 && q->pdsch_cfg.grant.mcs.tbs >= 0) { ret = srslte_pdsch_decode_rnti(&q->pdsch, &q->pdsch_cfg, &q->softbuffer, q->sf_symbols, q->ce, noise_estimate, rnti, data); if (ret == SRSLTE_ERROR) { q->pkt_errors++; } else if (ret == SRSLTE_ERROR_INVALID_INPUTS) { fprintf(stderr, "Error calling srslte_pdsch_decode()\n"); } else if (ret == SRSLTE_SUCCESS) { if (SRSLTE_VERBOSE_ISDEBUG()) { INFO("Decoded Message: ", 0); srslte_vec_fprint_hex(stdout, data, q->pdsch_cfg.grant.mcs.tbs); } } q->pkts_total++; } return ret; }
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); }
int srslte_ue_dl_find_and_decode(srslte_ue_dl_t* q, srslte_dl_sf_cfg_t* sf, srslte_ue_dl_cfg_t* cfg, srslte_pdsch_cfg_t* pdsch_cfg, uint8_t* data[SRSLTE_MAX_CODEWORDS], bool acks[SRSLTE_MAX_CODEWORDS]) { int ret = SRSLTE_ERROR; srslte_dci_dl_t dci_dl; srslte_pmch_cfg_t pmch_cfg; srslte_pdsch_res_t pdsch_res[SRSLTE_MAX_CODEWORDS]; // Use default values for PDSCH decoder ZERO_OBJECT(pmch_cfg); uint32_t mi_set_len; if (q->cell.frame_type == SRSLTE_TDD && !sf->tdd_config.configured) { mi_set_len = 3; } else { mi_set_len = 1; } // Blind search PHICH mi value ZERO_OBJECT(dci_dl); ret = 0; for (uint32_t i = 0; i < mi_set_len && !ret; i++) { if (mi_set_len == 1) { srslte_ue_dl_set_mi_auto(q); } else { srslte_ue_dl_set_mi_manual(q, i); } if ((ret = srslte_ue_dl_decode_fft_estimate(q, sf, cfg)) < 0) { return ret; } ret = srslte_ue_dl_find_dl_dci(q, sf, cfg, pdsch_cfg->rnti, &dci_dl); } if (ret == 1) { // Logging char str[512]; srslte_dci_dl_info(&dci_dl, str, 512); INFO("PDCCH: %s, snr=%.1f dB\n", str, q->chest_res.snr_db); // Force known MBSFN grant if (sf->sf_type == SRSLTE_SF_MBSFN) { dci_dl.rnti = SRSLTE_MRNTI; dci_dl.alloc_type = SRSLTE_RA_ALLOC_TYPE0; dci_dl.type0_alloc.rbg_bitmask = 0xffffffff; dci_dl.tb[0].rv = 0; dci_dl.tb[0].mcs_idx = 2; dci_dl.format = SRSLTE_DCI_FORMAT1; } // Convert DCI message to DL grant if (srslte_ue_dl_dci_to_pdsch_grant(q, sf, cfg, &dci_dl, &pdsch_cfg->grant)) { ERROR("Error unpacking DCI\n"); return SRSLTE_ERROR; } // Calculate RV if not provided in the grant and reset softbuffer for (int i = 0; i < SRSLTE_MAX_CODEWORDS; i++) { if (pdsch_cfg->grant.tb[i].enabled) { if (pdsch_cfg->grant.tb[i].rv < 0) { uint32_t sfn = sf->tti / 10; uint32_t k = (sfn / 2) % 4; pdsch_cfg->grant.tb[i].rv = ((uint32_t)ceilf((float)1.5 * k)) % 4; } srslte_softbuffer_rx_reset_tbs(pdsch_cfg->softbuffers.rx[i], (uint32_t)pdsch_cfg->grant.tb[i].tbs); } } bool decode_enable = false; for (uint32_t tb = 0; tb < SRSLTE_MAX_CODEWORDS; tb++) { if (pdsch_cfg->grant.tb[tb].enabled) { decode_enable = true; pdsch_res[tb].payload = data[tb]; pdsch_res[tb].crc = false; } } if (decode_enable) { if (sf->sf_type == SRSLTE_SF_NORM) { if (srslte_ue_dl_decode_pdsch(q, sf, pdsch_cfg, pdsch_res)) { ERROR("ERROR: Decoding PDSCH\n"); ret = -1; } } else { pmch_cfg.pdsch_cfg = *pdsch_cfg; if (srslte_ue_dl_decode_pmch(q, sf, &pmch_cfg, pdsch_res)) { ERROR("Decoding PMCH\n"); ret = -1; } } } for (uint32_t tb = 0; tb < SRSLTE_MAX_CODEWORDS; tb++) { if (pdsch_cfg->grant.tb[tb].enabled) { acks[tb] = pdsch_res[tb].crc; } } } return ret; }
int srslte_ue_dl_decode_rnti(srslte_ue_dl_t *q, uint8_t *data[SRSLTE_MAX_CODEWORDS], uint32_t tm, uint32_t tti, uint16_t rnti, bool acks[SRSLTE_MAX_CODEWORDS]) { srslte_mimo_type_t mimo_type; srslte_dci_msg_t dci_msg; srslte_ra_dl_dci_t dci_unpacked; srslte_ra_dl_grant_t grant; int ret = SRSLTE_ERROR; uint32_t cfi; uint32_t sf_idx = tti%10; if ((ret = srslte_ue_dl_decode_fft_estimate_mbsfn(q, sf_idx, &cfi, SRSLTE_SF_NORM)) < 0) { return ret; } float noise_estimate = srslte_chest_dl_get_noise_estimate(&q->chest); // Uncoment next line to do ZF by default in pdsch_ue example //float noise_estimate = 0; if (srslte_pdcch_extract_llr_multi(&q->pdcch, q->sf_symbols_m, q->ce_m, noise_estimate, sf_idx, cfi)) { fprintf(stderr, "Error extracting LLRs\n"); return SRSLTE_ERROR; } int found_dci = srslte_ue_dl_find_dl_dci(q, tm, cfi, sf_idx, rnti, &dci_msg); if (found_dci == 1) { if (srslte_dci_msg_to_dl_grant(&dci_msg, rnti, q->cell.nof_prb, q->cell.nof_ports, &dci_unpacked, &grant)) { fprintf(stderr, "Error unpacking DCI\n"); return SRSLTE_ERROR; } /* ===== These lines of code are supposed to be MAC functionality === */ int rvidx[SRSLTE_MAX_CODEWORDS] = {1}; if (dci_unpacked.rv_idx < 0) { uint32_t sfn = tti / 10; uint32_t k = (sfn / 2) % 4; for (int i = 0; i < SRSLTE_MAX_CODEWORDS; i++) { if (grant.tb_en[i]) { rvidx[i] = ((uint32_t) ceilf((float) 1.5 * k)) % 4; srslte_softbuffer_rx_reset_tbs(q->softbuffers[i], (uint32_t) grant.mcs[i].tbs); } } } else { for (int i = 0; i < SRSLTE_MAX_CODEWORDS; i++) { if (grant.tb_en[i]) { switch (i) { case 0: rvidx[i] = (uint32_t) dci_unpacked.rv_idx; break; case 1: rvidx[i] = (uint32_t) dci_unpacked.rv_idx_1; break; default: ERROR("Wrong number of transport blocks"); return SRSLTE_ERROR; } srslte_softbuffer_rx_reset_tbs(q->softbuffers[i], (uint32_t) grant.mcs[i].tbs); } } } switch(dci_msg.format) { case SRSLTE_DCI_FORMAT1: case SRSLTE_DCI_FORMAT1A: case SRSLTE_DCI_FORMAT1C: if (q->cell.nof_ports == 1) { mimo_type = SRSLTE_MIMO_TYPE_SINGLE_ANTENNA; } else { mimo_type = SRSLTE_MIMO_TYPE_TX_DIVERSITY; } break; case SRSLTE_DCI_FORMAT2: if (SRSLTE_RA_DL_GRANT_NOF_TB(&grant) == 1 && dci_unpacked.pinfo == 0) { mimo_type = SRSLTE_MIMO_TYPE_TX_DIVERSITY; } else { mimo_type = SRSLTE_MIMO_TYPE_SPATIAL_MULTIPLEX; } break; case SRSLTE_DCI_FORMAT2A: if (SRSLTE_RA_DL_GRANT_NOF_TB(&grant) == 1 && dci_unpacked.pinfo == 0) { mimo_type = SRSLTE_MIMO_TYPE_TX_DIVERSITY; } else { mimo_type = SRSLTE_MIMO_TYPE_CDD; } break; /* Not implemented formats */ case SRSLTE_DCI_FORMAT0: case SRSLTE_DCI_FORMAT1B: case SRSLTE_DCI_FORMAT1D: case SRSLTE_DCI_FORMAT2B: default: ERROR("Transmission mode not supported."); return SRSLTE_ERROR; } if (srslte_ue_dl_cfg_grant(q, &grant, cfi, sf_idx, rvidx, mimo_type)) { ERROR("Configuing PDSCH"); return SRSLTE_ERROR; } /* ===== End of MAC functionality ========== */ q->nof_detected++; if (q->pdsch_cfg.grant.mcs[0].mod > 0 && q->pdsch_cfg.grant.mcs[0].tbs >= 0) { ret = srslte_pdsch_decode(&q->pdsch, &q->pdsch_cfg, q->softbuffers, q->sf_symbols_m, q->ce_m, noise_estimate, rnti, data, acks); for (int tb = 0; tb < SRSLTE_MAX_TB; tb++) { if (grant.tb_en[tb]) { if (!acks[tb]) { q->pdsch_pkt_errors++; } q->pdsch_pkts_total++; } } if (ret == SRSLTE_ERROR) { } else if (ret == SRSLTE_ERROR_INVALID_INPUTS) { fprintf(stderr, "Error calling srslte_pdsch_decode()\n"); } /* If we are in TM4 (Closed-Loop MIMO), compute condition number */ } /* printf("Saving signal...\n"); srslte_vec_save_file("input", input, sizeof(cf_t)*SRSLTE_SF_LEN_PRB(q->cell.nof_prb)); srslte_ue_dl_save_signal(q, &q->softbuffer, sf_idx, rvidx, rnti, cfi); //exit(-1); */ } if (found_dci == 1 && ret == SRSLTE_SUCCESS) { return q->pdsch_cfg.grant.mcs[0].tbs; } else { return 0; } }