Beispiel #1
0
static void pdsch_decode_debug(srslte_pdsch_t *q, srslte_pdsch_cfg_t *cfg,
                               cf_t *sf_symbols[SRSLTE_MAX_PORTS], cf_t *ce[SRSLTE_MAX_PORTS][SRSLTE_MAX_PORTS])
{
  if (SRSLTE_VERBOSE_ISDEBUG()) {
    char filename[FILENAME_MAX];
    for (int j = 0; j < q->nof_rx_antennas; j++) {
      if (snprintf(filename, FILENAME_MAX, "subframe_p%d.dat", j) < 0) {
        ERROR("Generating file name");
        break;
      }
      DEBUG("SAVED FILE %s: received subframe symbols\n", filename);
      srslte_vec_save_file(filename, sf_symbols[j], SRSLTE_SF_LEN_RE(q->cell.nof_prb, q->cell.cp)*sizeof(cf_t));

      for (int i = 0; i < q->cell.nof_ports; i++) {
        if (snprintf(filename, FILENAME_MAX, "hest_%d%d.dat", i, j) < 0) {
          ERROR("Generating file name");
          break;
        }
        DEBUG("SAVED FILE %s: channel estimates for Tx %d and Rx %d\n", filename, j, i);
        srslte_vec_save_file(filename, ce[i][j], SRSLTE_SF_LEN_RE(q->cell.nof_prb, q->cell.cp)*sizeof(cf_t));
      }
    }
    for (int i=0;i<cfg->nof_layers;i++) {
      if (snprintf(filename, FILENAME_MAX, "pdsch_symbols_%d.dat", i) < 0) {
        ERROR("Generating file name");
        break;
      }
      DEBUG("SAVED FILE %s: symbols after equalization\n", filename);
      srslte_vec_save_file(filename, q->d[i], cfg->nbits[0].nof_re*sizeof(cf_t));

      if (snprintf(filename, FILENAME_MAX, "llr_%d.dat", i) < 0) {
        ERROR("Generating file name");
        break;
      }
      DEBUG("SAVED FILE %s: LLR estimates after demodulation and descrambling\n", filename);
      srslte_vec_save_file(filename, q->e[i], cfg->nbits[0].nof_bits*sizeof(int16_t));
    }
  }
}
Beispiel #2
0
void srslte_enb_dl_save_signal(srslte_enb_dl_t* q)
{
  char tmpstr[64];

  uint32_t tti = q->dl_sf.tti;

  snprintf(tmpstr, 64, "sf_symbols_%d", tti);
  srslte_vec_save_file(tmpstr, q->sf_symbols[0], SRSLTE_NOF_RE(q->cell) * sizeof(cf_t));

  /*
  int cb_len = q->pdsch_cfg.cb_segm[0].K1;
  for (int i=0;i<q->pdsch_cfg.cb_segm[0].C;i++) {
    snprintf(tmpstr,64,"output/rmout_%d_%d",i,tti);
    srslte_bit_unpack_vector(softbuffer->buffer_b[i], q->tmp, (3*cb_len+12));
    srslte_vec_save_file(tmpstr, q->tmp, (3*cb_len+12)*sizeof(uint8_t));
  }*/

  // printf("Saved files for tti=%d, sf=%d, cfi=%d, mcs=%d, tbs=%d, rv=%d, rnti=0x%x\n", tti, tti%10, cfi,
  //       q->dci.mcs[0].idx, q->dci.mcs[0].tbs, rv_idx, rnti);
}
Beispiel #3
0
/** 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;
  }
}
Beispiel #4
0
/** 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;
    }
}
Beispiel #5
0
int main(int argc, char **argv) {
  parse_args(argc, argv);
  
  uint32_t flen = srslte_sampling_freq_hz(nof_prb)/1000;
  
  cf_t *rx_buffer = malloc(sizeof(cf_t)*flen*nof_frames);
  if (!rx_buffer) {
    perror("malloc");
    exit(-1);
  }

  cf_t *tx_buffer = malloc(sizeof(cf_t)*(flen+time_adv_samples));
  if (!tx_buffer) {
    perror("malloc");
    exit(-1);
  }
  bzero(tx_buffer, sizeof(cf_t)*(flen+time_adv_samples));
  
  cf_t *zeros = calloc(sizeof(cf_t),flen);
  if (!zeros) {
    perror("calloc");
    exit(-1);
  }

  float time_adv_sec = (float) time_adv_samples/srslte_sampling_freq_hz(nof_prb);
 
  // Send through RF 
  srslte_rf_t rf; 
  printf("Opening RF device...\n");
  if (srslte_rf_open(&rf, rf_args)) {
    fprintf(stderr, "Error opening rf\n");
    exit(-1);
  }
  srslte_rf_set_master_clock_rate(&rf, 30.72e6);        
  
  int srate = srslte_sampling_freq_hz(nof_prb);    
  if (srate < 10e6) {          
    srslte_rf_set_master_clock_rate(&rf, 4*srate);        
  } else {
    srslte_rf_set_master_clock_rate(&rf, srate);        
  }
  srslte_rf_set_rx_srate(&rf, (double) srate);
  srslte_rf_set_tx_srate(&rf, (double) srate);
  
  
  printf("Subframe len:   %d samples\n", flen);
  printf("Time advance:   %f us\n",time_adv_sec*1e6);
  printf("Set TX/RX rate: %.2f MHz\n", (float) srate / 1000000);
  printf("Set RX gain:    %.1f dB\n", srslte_rf_set_rx_gain(&rf, rf_rx_gain));
  printf("Set TX gain:    %.1f dB\n", srslte_rf_set_tx_gain(&rf, srslte_rf_tx_gain));
  printf("Set TX/RX freq: %.2f MHz\n", srslte_rf_set_rx_freq(&rf, rf_freq) / 1000000);
  srslte_rf_set_tx_freq(&rf, rf_freq);
  
  sleep(1);
  
  if (input_filename) {
    srslte_vec_load_file(input_filename, &tx_buffer[time_adv_samples], flen*sizeof(cf_t));
  } else {
    for (int i=0;i<flen-time_adv_samples;i++) {
      tx_buffer[i+time_adv_samples] = 0.3*cexpf(_Complex_I*2*M_PI*tone_offset_hz*((float) i/(float) srate));       
    }
    srslte_vec_save_file("srslte_rf_txrx_tone", tx_buffer, flen*sizeof(cf_t));
  }

  srslte_timestamp_t tstamp; 
  
  srslte_rf_start_rx_stream(&rf);
  uint32_t nframe=0;
  

  while(nframe<nof_frames) {
    printf("Rx subframe %d\n", nframe);
    srslte_rf_recv_with_time(&rf, &rx_buffer[flen*nframe], flen, true, &tstamp.full_secs, &tstamp.frac_secs);
    nframe++;
    if (nframe==9) {
      srslte_timestamp_add(&tstamp, 0, 2e-3-time_adv_sec);
      srslte_rf_send_timed2(&rf, tx_buffer, flen+time_adv_samples, tstamp.full_secs, tstamp.frac_secs, true, true);      
      printf("Transmitting Signal\n");        
    }

  }

  srslte_vec_save_file(output_filename, &rx_buffer[10*flen], flen*sizeof(cf_t));

  free(tx_buffer);
  free(rx_buffer);

  printf("Done\n");
  exit(0);
}
Beispiel #6
0
int main(int argc, char **argv) {
  parse_args(argc, argv);

  srslte_prach_t *p = (srslte_prach_t*)malloc(sizeof(srslte_prach_t));

  bool high_speed_flag      = false;

  cf_t preamble[MAX_LEN];
  memset(preamble, 0, sizeof(cf_t)*MAX_LEN);

  srslte_prach_init(p,
             srslte_symbol_sz(nof_prb),
             preamble_format,
             root_seq_idx,
             high_speed_flag,
             zero_corr_zone);

  uint32_t flen = srslte_sampling_freq_hz(nof_prb)/1000;

  printf("Generating PRACH\n");
  bzero(preamble, flen*sizeof(cf_t));
  srslte_prach_gen(p,
            seq_idx,
            frequency_offset,
            preamble);
  
  
  uint32_t prach_len = p->N_seq;
  
  srslte_vec_save_file("generated",preamble,prach_len*sizeof(cf_t));
  
  cf_t *buffer = malloc(sizeof(cf_t)*flen*nof_frames);
  
  // Send through UHD 
  void *uhd; 
  printf("Opening UHD device...\n");
  if (cuhd_open(uhd_args, &uhd)) {
    fprintf(stderr, "Error opening uhd\n");
    exit(-1);
  }
  printf("Subframe len:   %d samples\n", flen);
  printf("Set TX/RX rate: %.2f MHz\n", cuhd_set_rx_srate(uhd, srslte_sampling_freq_hz(nof_prb)) / 1000000);
  printf("Set RX gain: %.1f dB\n", cuhd_set_rx_gain(uhd, uhd_gain));
  printf("Set TX gain: %.1f dB\n", cuhd_set_tx_gain(uhd, uhd_gain));
  printf("Set TX/RX freq: %.2f MHz\n", cuhd_set_rx_freq(uhd, uhd_freq) / 1000000);
  cuhd_set_tx_srate(uhd, srslte_sampling_freq_hz(nof_prb));
  cuhd_set_tx_freq_offset(uhd, uhd_freq, 8e6);  
  sleep(1);
  
  cf_t *zeros = calloc(sizeof(cf_t),flen);
  
  FILE *f = NULL; 
  if (output_filename) {        
    f = fopen(output_filename, "w");
  }
  
  srslte_timestamp_t tstamp; 
  
  cuhd_start_rx_stream(uhd);
  uint32_t nframe=0;
  
  while(nframe<nof_frames) {
    printf("Rx subframe %d\n", nframe);
    cuhd_recv_with_time(uhd, &buffer[flen*nframe], flen, true, &tstamp.full_secs, &tstamp.frac_secs);
    nframe++;
    if (nframe==9 || nframe==8) {
      srslte_timestamp_add(&tstamp, 0, 2e-3);
      if (nframe==8) {
        cuhd_send_timed2(uhd, zeros, flen, tstamp.full_secs, tstamp.frac_secs, true, false);      
        printf("Transmitting zeros\n");        
      } else {
        cuhd_send_timed2(uhd, preamble, flen, tstamp.full_secs, tstamp.frac_secs, true, true);      
        printf("Transmitting PRACH\n");      
      }
    }

  }
  if (f) {
    fwrite(&buffer[10*flen], flen*sizeof(cf_t), 1, f);
  }
  if (f) {
    fclose(f);
  }

  srslte_prach_free(p);
  free(p);

  printf("Done\n");
  exit(0);
}
Beispiel #7
0
void srslte_ue_dl_save_signal(srslte_ue_dl_t* q, srslte_dl_sf_cfg_t* sf, srslte_pdsch_cfg_t* pdsch_cfg)
{
  uint32_t cfi = sf->cfi;
  uint32_t tti = sf->tti % 10;

  srslte_vec_save_file("sf_symbols", q->sf_symbols, SRSLTE_NOF_RE(q->cell) * sizeof(cf_t));
  printf("%d samples\n", SRSLTE_NOF_RE(q->cell));
  srslte_vec_save_file("ce0", q->chest_res.ce[0], SRSLTE_NOF_RE(q->cell) * sizeof(cf_t));
  if (q->cell.nof_ports > 1) {
    srslte_vec_save_file("ce1", q->chest_res.ce[1], SRSLTE_NOF_RE(q->cell) * sizeof(cf_t));
  }
  srslte_vec_save_file("pcfich_ce0", q->pcfich.ce[0], q->pcfich.nof_symbols * sizeof(cf_t));
  srslte_vec_save_file("pcfich_ce1", q->pcfich.ce[1], q->pcfich.nof_symbols * sizeof(cf_t));
  srslte_vec_save_file("pcfich_symbols", q->pcfich.symbols[0], q->pcfich.nof_symbols * sizeof(cf_t));
  srslte_vec_save_file("pcfich_eq_symbols", q->pcfich.d, q->pcfich.nof_symbols * sizeof(cf_t));
  srslte_vec_save_file("pcfich_llr", q->pcfich.data_f, PCFICH_CFI_LEN * sizeof(float));

  srslte_vec_save_file("pdcch_ce0", q->pdcch.ce[0], q->pdcch.nof_cce[cfi - 1] * 36 * sizeof(cf_t));
  srslte_vec_save_file("pdcch_ce1", q->pdcch.ce[1], q->pdcch.nof_cce[cfi - 1] * 36 * sizeof(cf_t));
  srslte_vec_save_file("pdcch_symbols", q->pdcch.symbols[0], q->pdcch.nof_cce[cfi - 1] * 36 * sizeof(cf_t));
  srslte_vec_save_file("pdcch_eq_symbols", q->pdcch.d, q->pdcch.nof_cce[cfi - 1] * 36 * sizeof(cf_t));
  srslte_vec_save_file("pdcch_llr", q->pdcch.llr, q->pdcch.nof_cce[cfi - 1] * 72 * sizeof(float));

  srslte_vec_save_file("pdsch_symbols", q->pdsch.d[0], pdsch_cfg->grant.nof_re * sizeof(cf_t));
  srslte_vec_save_file("llr", q->pdsch.e[0], pdsch_cfg->grant.tb[0].nof_bits * sizeof(cf_t));
  printf("Saved files for tti=%d, sf=%d, cfi=%d, tbs=%d, rv=%d\n",
         tti,
         tti % 10,
         cfi,
         pdsch_cfg->grant.tb[0].tbs,
         pdsch_cfg->grant.tb[0].rv);
}
Beispiel #8
0
void srslte_ue_dl_save_signal(srslte_ue_dl_t *q, srslte_softbuffer_rx_t *softbuffer, uint32_t tti, uint32_t rv_idx) {
  srslte_vec_save_file("sf_symbols", q->sf_symbols, SRSLTE_SF_LEN_RE(q->cell.nof_prb, q->cell.cp)*sizeof(cf_t));
  printf("%d samples\n", SRSLTE_SF_LEN_RE(q->cell.nof_prb, q->cell.cp));
  srslte_vec_save_file("ce0", q->ce[0], SRSLTE_SF_LEN_RE(q->cell.nof_prb, q->cell.cp)*sizeof(cf_t));
  if (q->cell.nof_ports > 1) {
    srslte_vec_save_file("ce1", q->ce[1], SRSLTE_SF_LEN_RE(q->cell.nof_prb, q->cell.cp)*sizeof(cf_t));
  }
  srslte_vec_save_file("pcfich_ce0", q->pcfich.ce[0], q->pcfich.nof_symbols*sizeof(cf_t));
  srslte_vec_save_file("pcfich_ce1", q->pcfich.ce[1], q->pcfich.nof_symbols*sizeof(cf_t));
  srslte_vec_save_file("pcfich_symbols", q->pcfich.symbols[0], q->pcfich.nof_symbols*sizeof(cf_t));
  srslte_vec_save_file("pcfich_eq_symbols", q->pcfich.d, q->pcfich.nof_symbols*sizeof(cf_t));
  srslte_vec_save_file("pcfich_llr", q->pcfich.data_f, PCFICH_CFI_LEN*sizeof(float));
  
  srslte_vec_save_file("pdcch_ce0", q->pdcch.ce[0], q->pdcch.nof_cce*36*sizeof(cf_t));
  srslte_vec_save_file("pdcch_ce1", q->pdcch.ce[1], q->pdcch.nof_cce*36*sizeof(cf_t));
  srslte_vec_save_file("pdcch_symbols", q->pdcch.symbols[0], q->pdcch.nof_cce*36*sizeof(cf_t));
  srslte_vec_save_file("pdcch_eq_symbols", q->pdcch.d, q->pdcch.nof_cce*36*sizeof(cf_t));
  srslte_vec_save_file("pdcch_llr", q->pdcch.llr, q->pdcch.nof_cce*72*sizeof(float));
  
  
  srslte_vec_save_file("pdsch_symbols", q->pdsch.d, q->pdsch_cfg.nbits.nof_re*sizeof(cf_t));
  srslte_vec_save_file("llr", q->pdsch.e, q->pdsch_cfg.nbits.nof_bits*sizeof(cf_t));
  int cb_len = q->pdsch_cfg.cb_segm.K1; 
  for (int i=0;i<q->pdsch_cfg.cb_segm.C;i++) {
    char tmpstr[64]; 
    snprintf(tmpstr,64,"rmout_%d.dat",i);
    srslte_vec_save_file(tmpstr, softbuffer->buffer_f[i], (3*cb_len+12)*sizeof(int16_t));  
  }
  printf("Saved files for tti=%d, sf=%d, cfi=%d, mcs=%d, rv=%d, rnti=%d\n", tti, tti%10, q->cfi, 
         q->pdsch_cfg.grant.mcs.idx, rv_idx, q->current_rnti);
}