コード例 #1
0
ファイル: ue_dl.c プロジェクト: mfkiwl/srsLTE
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;
  }
}
コード例 #2
0
ファイル: ue_dl.c プロジェクト: guyt101z/srsLTE
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; 
}
コード例 #3
0
ファイル: pmch_test.c プロジェクト: mfkiwl/srsLTE
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);
}
コード例 #4
0
ファイル: ue_dl.c プロジェクト: srsLTE/srsLTE
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;
}
コード例 #5
0
ファイル: ue_dl.c プロジェクト: mfkiwl/srsLTE
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;
  }
}