Ejemplo n.º 1
0
int main(int argc, char **argv) {
  uint32_t cfi;
  float cfi_corr; 
  int n;

  if (argc < 3) {
    usage(argv[0]);
    exit(-1);
  }

  parse_args(argc,argv);

  if (base_init()) {
    fprintf(stderr, "Error initializing receiver\n");
    exit(-1);
  }

  n = srslte_filesource_read(&fsrc, input_buffer, flen);

  srslte_ofdm_rx_sf(&fft, input_buffer, fft_buffer);

  if (fmatlab) {
    fprintf(fmatlab, "infft=");
    srslte_vec_fprint_c(fmatlab, input_buffer, flen);
    fprintf(fmatlab, ";\n");

    fprintf(fmatlab, "outfft=");
    srslte_vec_sc_prod_cfc(fft_buffer, 1000.0, fft_buffer, SRSLTE_CP_NSYMB(cell.cp) * cell.nof_prb * SRSLTE_NRE);
    srslte_vec_fprint_c(fmatlab, fft_buffer, SRSLTE_CP_NSYMB(cell.cp) * cell.nof_prb * SRSLTE_NRE);
    fprintf(fmatlab, ";\n");
    srslte_vec_sc_prod_cfc(fft_buffer, 0.001, fft_buffer,   SRSLTE_CP_NSYMB(cell.cp) * cell.nof_prb * SRSLTE_NRE);
  }

  /* Get channel estimates for each port */
  srslte_chest_dl_estimate(&chest, fft_buffer, ce, 0);

  INFO("Decoding PCFICH\n", 0);

  
  n = srslte_pcfich_decode(&pcfich, fft_buffer, ce, srslte_chest_dl_get_noise_estimate(&chest),  0, &cfi, &cfi_corr);
  printf("cfi: %d, distance: %f\n", cfi, cfi_corr);

  base_free();

  if (n < 0) {
    fprintf(stderr, "Error decoding PCFICH\n");
    exit(-1);
  } else if (n == 0) {
    printf("Could not decode PCFICH\n");
    exit(-1);
  } else {
    if (cfi_corr > 2.8 && cfi == 1) {
      exit(0);
    } else {
      exit(-1);
    }
  }
}
Ejemplo n.º 2
0
int srslte_ofdm_init_(srslte_ofdm_t *q, srslte_cp_t cp, int symbol_sz, int nof_prb, srslte_dft_dir_t dir) {

  if (srslte_dft_plan_c(&q->fft_plan, symbol_sz, dir)) {
    fprintf(stderr, "Error: Creating DFT plan\n");
    return -1;
  }
  q->tmp = srslte_vec_malloc((uint32_t) symbol_sz * sizeof(cf_t));
  if (!q->tmp) {
    perror("malloc");
    return -1;
  }

  srslte_dft_plan_set_mirror(&q->fft_plan, true);
  srslte_dft_plan_set_dc(&q->fft_plan, true);

  q->symbol_sz = (uint32_t) symbol_sz;
  q->nof_symbols = SRSLTE_CP_NSYMB(cp);
  q->cp = cp;
  q->freq_shift = false;
  q->shift_buffer = NULL; 
  q->nof_re = nof_prb * SRSLTE_NRE;
  q->nof_guards = ((symbol_sz - q->nof_re) / 2);
  q->slot_sz = SRSLTE_SLOT_LEN(symbol_sz);
  
  DEBUG("Init %s symbol_sz=%d, nof_symbols=%d, cp=%s, nof_re=%d, nof_guards=%d\n",
      dir==SRSLTE_DFT_FORWARD?"FFT":"iFFT", q->symbol_sz, q->nof_symbols,
          q->cp==SRSLTE_CP_NORM?"Normal":"Extended", q->nof_re, q->nof_guards);

  return SRSLTE_SUCCESS;
}
Ejemplo n.º 3
0
int srslte_ue_dl_decode_fft_estimate(srslte_ue_dl_t *q, cf_t *input, uint32_t sf_idx, uint32_t *cfi) {
  if (input && q && cfi && sf_idx < SRSLTE_NSUBFRAMES_X_FRAME) {
    
    /* Run FFT for all subframe data */
    srslte_ofdm_rx_sf(&q->fft, input, q->sf_symbols);
    
    /* Correct SFO multiplying by complex exponential in the time domain */
    if (q->sample_offset) {
      struct timeval t[3];
      gettimeofday(&t[1], NULL);
      for (int i=0;i<2*SRSLTE_CP_NSYMB(q->cell.cp);i++) {
        srslte_cfo_correct(&q->sfo_correct, 
                         &q->sf_symbols[i*q->cell.nof_prb*SRSLTE_NRE], 
                         &q->sf_symbols[i*q->cell.nof_prb*SRSLTE_NRE], 
                         q->sample_offset / q->fft.symbol_sz);
      }
      gettimeofday(&t[2], NULL);
      get_time_interval(t);
    }
    
    return srslte_ue_dl_decode_estimate(q, sf_idx, cfi); 
  } else {
    return SRSLTE_ERROR_INVALID_INPUTS; 
  }
}
Ejemplo n.º 4
0
/** 36.211 10.3 section 6.11.1.2
 */
void srslte_pss_put_slot(cf_t *pss_signal, cf_t *slot, uint32_t nof_prb, srslte_cp_t cp) {
  int k;
  k = (SRSLTE_CP_NSYMB(cp) - 1) * nof_prb * SRSLTE_NRE + nof_prb * SRSLTE_NRE / 2 - 31;
  memset(&slot[k - 5], 0, 5 * sizeof(cf_t));
  memcpy(&slot[k], pss_signal, SRSLTE_PSS_LEN * sizeof(cf_t));
  memset(&slot[k + SRSLTE_PSS_LEN], 0, 5 * sizeof(cf_t));
}
Ejemplo n.º 5
0
void srslte_ue_dl_set_power_alloc(srslte_ue_dl_t *q, float rho_a, float rho_b) {
  if (q) {
    srslte_pdsch_set_power_allocation(&q->pdsch, rho_a);
    q->rho_b = rho_b;

    uint32_t nof_symbols_slot = SRSLTE_CP_NSYMB(q->cell.cp);
    uint32_t nof_re_symbol = SRSLTE_NRE * q->cell.nof_prb;

    /* Apply rho_b if required according to 3GPP 36.213 Table 5.2-2 */
    if (rho_b != 0.0f && rho_b != 1.0f) {
      float scaling = 1.0f / rho_b;
      for (uint32_t i = 0; i < q->nof_rx_antennas; i++) {
        for (uint32_t j = 0; j < 2; j++) {
          cf_t *ptr;
          ptr = q->sf_symbols_m[i] + nof_re_symbol * (j * nof_symbols_slot + 0);
          srslte_vec_sc_prod_cfc(ptr, scaling, ptr, nof_re_symbol);
          if (q->cell.cp == SRSLTE_CP_NORM) {
            ptr = q->sf_symbols_m[i] + nof_re_symbol * (j * nof_symbols_slot + 4);
            srslte_vec_sc_prod_cfc(ptr, scaling, ptr, nof_re_symbol);
          } else {
            ptr = q->sf_symbols_m[i] + nof_re_symbol * (j * nof_symbols_slot + 3);
            srslte_vec_sc_prod_cfc(ptr, scaling, ptr, nof_re_symbol);
          }
          if (q->cell.nof_ports == 4) {
            ptr = q->sf_symbols_m[i] + nof_re_symbol * (j * nof_symbols_slot + 1);
            srslte_vec_sc_prod_cfc(ptr, scaling, ptr, nof_re_symbol);
          }
        }
      }
    }
  }
}
Ejemplo n.º 6
0
void srslte_enb_dl_prepare_power_allocation(srslte_enb_dl_t *q)
{
  uint32_t nof_symbols_slot = SRSLTE_CP_NSYMB(q->cell.cp);
  uint32_t nof_re_symbol = SRSLTE_NRE * q->cell.nof_prb;

  if (q->rho_b != 0.0f && q->rho_b != 1.0f) {
    float scaling = 1.0f / q->rho_b;
    for (uint32_t i = 0; i < q->cell.nof_ports; i++) {
      for (uint32_t j = 0; j < 2; j++) {
        cf_t *ptr;
        ptr = q->sf_symbols[i] + nof_re_symbol * (j * nof_symbols_slot + 0);
        srslte_vec_sc_prod_cfc(ptr, scaling, ptr, nof_re_symbol);
        if (q->cell.cp == SRSLTE_CP_NORM) {
          ptr = q->sf_symbols[i] + nof_re_symbol * (j * nof_symbols_slot + 4);
          srslte_vec_sc_prod_cfc(ptr, scaling, ptr, nof_re_symbol);
        } else {
          ptr = q->sf_symbols[i] + nof_re_symbol * (j * nof_symbols_slot + 3);
          srslte_vec_sc_prod_cfc(ptr, scaling, ptr, nof_re_symbol);
        }
        if (q->cell.nof_ports == 4) {
          ptr = q->sf_symbols[i] + nof_re_symbol * (j * nof_symbols_slot + 1);
          srslte_vec_sc_prod_cfc(ptr, scaling, ptr, nof_re_symbol);
        }
      }
    }
  }
}
Ejemplo n.º 7
0
uint32_t srslte_sfidx_tdd_nof_dw_slot(srslte_tdd_config_t tdd_config, uint32_t slot, srslte_cp_t cp)
{
  uint32_t n = srslte_sfidx_tdd_nof_dw(tdd_config);
  if (n < SRSLTE_CP_NSYMB(cp)) {
    if (slot == 1) {
      return 0;
    } else {
      return n;
    }
  } else {
    if (slot == 1) {
      return n - SRSLTE_CP_NSYMB(cp);
    } else {
      return SRSLTE_CP_NSYMB(cp);
    }
  }
}
Ejemplo n.º 8
0
/* Generates n_cs_cell according to Sec 5.4 of 36.211 */
int srslte_pucch_n_cs_cell(srslte_cell_t cell, uint32_t n_cs_cell[SRSLTE_NSLOTS_X_FRAME][SRSLTE_CP_NORM_NSYMB]) 
{
  srslte_sequence_t seq; 
  bzero(&seq, sizeof(srslte_sequence_t));

  srslte_sequence_LTE_pr(&seq, 8*SRSLTE_CP_NSYMB(cell.cp)*SRSLTE_NSLOTS_X_FRAME, cell.id);

  for (uint32_t ns=0;ns<SRSLTE_NSLOTS_X_FRAME;ns++) {
    for (uint32_t l=0;l<SRSLTE_CP_NSYMB(cell.cp);l++) {
      n_cs_cell[ns][l] = 0; 
      for (uint32_t i=0;i<8;i++) {
        n_cs_cell[ns][l] += seq.c[8*SRSLTE_CP_NSYMB(cell.cp)*ns+8*l+i]<<i;
      }
    }
  }
  srslte_sequence_free(&seq);
  return SRSLTE_SUCCESS;
}
Ejemplo n.º 9
0
/** 36.211 10.3 section 6.11.2.2
 */
void srslte_sss_put_slot(float *sss, cf_t *slot, uint32_t nof_prb, srslte_cp_t cp) {
  uint32_t i, k;

  k = (SRSLTE_CP_NSYMB(cp) - 2) * nof_prb * SRSLTE_NRE + nof_prb * SRSLTE_NRE / 2 - 31;
  
  if (k > 5) {
    memset(&slot[k - 5], 0, 5 * sizeof(cf_t));
    for (i = 0; i < SRSLTE_SSS_LEN; i++) {
      __real__ slot[k + i] = sss[i];
      __imag__ slot[k + i] = 0;
    }
    memset(&slot[k + SRSLTE_SSS_LEN], 0, 5 * sizeof(cf_t));
  }
}
Ejemplo n.º 10
0
static void interpolate_pilots(srslte_chest_ul_t *q, cf_t *ce, uint32_t nrefs, uint32_t n_prb[2]) 
{
  uint32_t L1 = SRSLTE_REFSIGNAL_UL_L(0, q->cell.cp);
  uint32_t L2 = SRSLTE_REFSIGNAL_UL_L(1, q->cell.cp); 
  uint32_t NL = 2*SRSLTE_CP_NSYMB(q->cell.cp);
    
  /* Interpolate in the time domain between symbols */
  srslte_interp_linear_vector3(&q->srslte_interp_linvec, 
                               &cesymb(L2), &cesymb(L1), &cesymb(L1), &cesymb(L1-1), (L2-L1), L1,        false, nrefs);
  srslte_interp_linear_vector3(&q->srslte_interp_linvec, 
                               &cesymb(L1), &cesymb(L2), NULL,        &cesymb(L1+1), (L2-L1), (L2-L1)-1, true,  nrefs);
  srslte_interp_linear_vector3(&q->srslte_interp_linvec, 
                               &cesymb(L1), &cesymb(L2), &cesymb(L2), &cesymb(L2+1), (L2-L1), (NL-L2)-1, true,  nrefs);
  
}
Ejemplo n.º 11
0
int srslte_ue_dl_decode_fft_estimate_noguru(srslte_ue_dl_t *q, cf_t *input[SRSLTE_MAX_PORTS], uint32_t sf_idx, uint32_t *cfi)
{
  if (input && q && sf_idx < SRSLTE_NSUBFRAMES_X_FRAME) {

    /* Run FFT for all subframe data */
    for (int j=0;j<q->nof_rx_antennas;j++) {
      srslte_ofdm_rx_sf_ng(&q->fft[j], input[j], q->sf_symbols_m[j]);

      /* Correct SFO multiplying by complex exponential in the time domain */
      if (q->sample_offset) {
        int nsym = SRSLTE_CP_NSYMB(q->cell.cp);
        for (int i=0;i<2*nsym;i++) {
          srslte_cfo_correct(&q->sfo_correct,
                             &q->sf_symbols_m[j][i*q->cell.nof_prb*SRSLTE_NRE],
                             &q->sf_symbols_m[j][i*q->cell.nof_prb*SRSLTE_NRE],
                             q->sample_offset / q->fft[j].symbol_sz);
        }
      }
    }
    return srslte_ue_dl_decode_estimate_mbsfn(q, sf_idx, cfi, SRSLTE_SF_NORM);
  } else {
    return SRSLTE_ERROR_INVALID_INPUTS;
  }
}
Ejemplo n.º 12
0
int srslte_chest_ul_estimate_pucch(srslte_chest_ul_t *q, cf_t *input, cf_t *ce, 
                                   srslte_pucch_format_t format, uint32_t n_pucch, uint32_t sf_idx, 
                                   uint8_t *pucch2_ack_bits) 
{
  if (!q->dmrs_signal_configured) {
    fprintf(stderr, "Error must call srslte_chest_ul_set_cfg() before using the UL estimator\n");
    return SRSLTE_ERROR; 
  }
    
  int n_rs = srslte_refsignal_dmrs_N_rs(format, q->cell.cp);
  if (!n_rs) {
    fprintf(stderr, "Error computing N_rs\n");
    return SRSLTE_ERROR; 
  }
  int nrefs_sf = SRSLTE_NRE*n_rs*2; 
  
  /* Get references from the input signal */
  srslte_refsignal_dmrs_pucch_get(&q->dmrs_signal, format, n_pucch, input, q->pilot_recv_signal);
  
  /* Generate known pilots */
  uint8_t pucch2_bits[2] = {0, 0};
  if (format == SRSLTE_PUCCH_FORMAT_2A || format == SRSLTE_PUCCH_FORMAT_2B) {
    float max = -1e9;
    int i_max = 0; 
    
    int m = 0; 
    if (format == SRSLTE_PUCCH_FORMAT_2A) {
      m = 2; 
    } else {
      m = 4; 
    }
    
    for (int i=0;i<m;i++) {
      pucch2_bits[0] = i%2;
      pucch2_bits[1] = i/2;
      srslte_refsignal_dmrs_pucch_gen(&q->dmrs_signal, format, n_pucch, sf_idx, pucch2_bits, q->pilot_known_signal);
      srslte_vec_prod_conj_ccc(q->pilot_recv_signal, q->pilot_known_signal, q->pilot_estimates_tmp[i], nrefs_sf);
      float x = cabsf(srslte_vec_acc_cc(q->pilot_estimates_tmp[i], nrefs_sf));
      if (x >= max) {
        max = x; 
        i_max = i; 
      }      
    }
    memcpy(q->pilot_estimates, q->pilot_estimates_tmp[i_max], nrefs_sf*sizeof(cf_t));
    pucch2_ack_bits[0] = i_max%2;
    pucch2_ack_bits[1] = i_max/2;
  } else {
    srslte_refsignal_dmrs_pucch_gen(&q->dmrs_signal, format, n_pucch, sf_idx, pucch2_bits, q->pilot_known_signal);
    /* Use the known DMRS signal to compute Least-squares estimates */
    srslte_vec_prod_conj_ccc(q->pilot_recv_signal, q->pilot_known_signal, q->pilot_estimates, nrefs_sf);
  }
  
  if (ce != NULL) {
    /* FIXME: Currently averaging entire slot, performance good enough? */
    for (int ns=0;ns<2;ns++) {
      // Average all slot 
      for (int i=1;i<n_rs;i++) {
        srslte_vec_sum_ccc(&q->pilot_estimates[ns*n_rs*SRSLTE_NRE], &q->pilot_estimates[(i+ns*n_rs)*SRSLTE_NRE], 
                           &q->pilot_estimates[ns*n_rs*SRSLTE_NRE], 
                           SRSLTE_NRE);
      }
      srslte_vec_sc_prod_ccc(&q->pilot_estimates[ns*n_rs*SRSLTE_NRE], (float) 1.0/n_rs, 
                             &q->pilot_estimates[ns*n_rs*SRSLTE_NRE], 
                             SRSLTE_NRE);
      
      // Average in freq domain
      srslte_chest_average_pilots(&q->pilot_estimates[ns*n_rs*SRSLTE_NRE], &q->pilot_recv_signal[ns*n_rs*SRSLTE_NRE], 
                                  q->smooth_filter, SRSLTE_NRE, 1, q->smooth_filter_len);
      
      // Determine n_prb
      uint32_t n_prb = srslte_pucch_n_prb(&q->dmrs_signal.pucch_cfg, format, n_pucch, q->cell.nof_prb, q->cell.cp, ns); 

      // copy estimates to slot 
      for (int i=0;i<SRSLTE_CP_NSYMB(q->cell.cp);i++) {
        memcpy(&ce[SRSLTE_RE_IDX(q->cell.nof_prb, i+ns*SRSLTE_CP_NSYMB(q->cell.cp), n_prb*SRSLTE_NRE)], 
               &q->pilot_recv_signal[ns*n_rs*SRSLTE_NRE], sizeof(cf_t)*SRSLTE_NRE);
      }
    }
  }
  
  return 0;
}
Ejemplo n.º 13
0
/* the gateway function */
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
{
  int i; 
  srslte_cell_t cell; 
  srslte_pdsch_t pdsch;
  srslte_chest_dl_t chest; 
  srslte_ofdm_t fft; 
  cf_t *input_fft, *input_signal;
  int nof_re; 
  srslte_pdsch_cfg_t cfg;
  srslte_softbuffer_rx_t softbuffer; 
  uint32_t rnti32;
  uint32_t cfi; 

  if (nrhs < NOF_INPUTS) {
    help();
    return;
  }

  bzero(&cfg, sizeof(srslte_pdsch_cfg_t));

  if (mexutils_read_cell(ENBCFG, &cell)) {
    help();
    return;
  }
  
  if (mexutils_read_uint32_struct(PDSCHCFG, "RNTI", &rnti32)) {
    mexErrMsgTxt("Field RNTI not found in pdsch config\n");
    return;
  }
  
  if (mexutils_read_uint32_struct(ENBCFG, "CFI", &cfi)) {
    help();
    return;
  }
  if (mexutils_read_uint32_struct(ENBCFG, "NSubframe", &cfg.sf_idx)) {
    help();
    return;
  }

  if (srslte_pdsch_init(&pdsch, cell)) {
    mexErrMsgTxt("Error initiating PDSCH\n");
    return;
  }
  srslte_pdsch_set_rnti(&pdsch, (uint16_t) (rnti32 & 0xffff));

  if (srslte_softbuffer_rx_init(&softbuffer, cell)) {
    mexErrMsgTxt("Error initiating soft buffer\n");
    return;
  }
  
  if (srslte_chest_dl_init(&chest, cell)) {
    mexErrMsgTxt("Error initializing equalizer\n");
    return;
  }

  if (srslte_ofdm_rx_init(&fft, cell.cp, cell.nof_prb)) {
    mexErrMsgTxt("Error initializing FFT\n");
    return;
  }
  
  nof_re = 2 * SRSLTE_CP_NORM_NSYMB * cell.nof_prb * SRSLTE_NRE;

  cfg.grant.mcs.tbs = mxGetScalar(TBS);
  if (cfg.grant.mcs.tbs == 0) {
    mexErrMsgTxt("Error trblklen is zero\n");
    return;
  }
  if (srslte_cbsegm(&cfg.cb_segm, cfg.grant.mcs.tbs)) {
    mexErrMsgTxt("Error computing CB segmentation\n");
    return; 
  }

  if (mexutils_read_uint32_struct(PDSCHCFG, "RV", &cfg.rv)) {
    mexErrMsgTxt("Field RV not found in pdsch config\n");
    return;
  }
  
  char *mod_str = mexutils_get_char_struct(PDSCHCFG, "Modulation");
  
  if (!strcmp(mod_str, "QPSK")) {
    cfg.grant.mcs.mod = SRSLTE_MOD_QPSK;
  } else if (!strcmp(mod_str, "16QAM")) {
    cfg.grant.mcs.mod = SRSLTE_MOD_16QAM;
  } else if (!strcmp(mod_str, "64QAM")) {
    cfg.grant.mcs.mod = SRSLTE_MOD_64QAM;
  } else {
   mexErrMsgTxt("Unknown modulation\n");
   return;
  }

  mxFree(mod_str);
  
  float *prbset; 
  mxArray *p; 
  p = mxGetField(PDSCHCFG, 0, "PRBSet");
  if (!p) {
    mexErrMsgTxt("Error field PRBSet not found\n");
    return;
  } 
  
  // Only localized PRB supported 
  cfg.grant.nof_prb = mexutils_read_f(p, &prbset);

  for (i=0;i<cell.nof_prb;i++) {
    cfg.grant.prb_idx[0][i] = false; 
    for (int j=0;j<cfg.grant.nof_prb && !cfg.grant.prb_idx[0][i];j++) {
      if ((int) prbset[j] == i) {
        cfg.grant.prb_idx[0][i] = true;
      }
    }
  }
  memcpy(&cfg.grant.prb_idx[1], &cfg.grant.prb_idx[0], SRSLTE_MAX_PRB*sizeof(bool));

  free(prbset);
  
  srslte_dl_dci_to_grant_nof_re(&cfg.grant, cell, cfg.sf_idx, cell.nof_prb<10?(cfi+1):cfi);
  
  // Fill rest of grant structure 
  cfg.grant.lstart = cell.nof_prb<10?(cfi+1):cfi;
  cfg.grant.nof_symb = 2*SRSLTE_CP_NSYMB(cell.cp)-cfg.grant.lstart;
  cfg.grant.Qm = srslte_mod_bits_x_symbol(cfg.grant.mcs.mod);
  cfg.grant.nof_bits = cfg.grant.nof_re * cfg.grant.Qm;     
    
  /** Allocate input buffers */
  if (mexutils_read_cf(INPUT, &input_signal) < 0) {
    mexErrMsgTxt("Error reading input signal\n");
    return; 
  }
  input_fft = srslte_vec_malloc(SRSLTE_SF_LEN_RE(cell.nof_prb, cell.cp) * sizeof(cf_t));
  
  cf_t *ce[SRSLTE_MAX_PORTS];
  for (i=0;i<cell.nof_ports;i++) {
    ce[i] = srslte_vec_malloc(SRSLTE_SF_LEN_RE(cell.nof_prb, cell.cp) * sizeof(cf_t));
  }
  
  srslte_ofdm_rx_sf(&fft, input_signal, input_fft);

  if (nrhs > NOF_INPUTS) {
    cf_t *cearray = NULL; 
    nof_re = mexutils_read_cf(prhs[NOF_INPUTS], &cearray);
    cf_t *cearray_ptr = cearray; 
    for (i=0;i<cell.nof_ports;i++) {
      for (int j=0;j<nof_re/cell.nof_ports;j++) {
        ce[i][j] = *cearray;
        cearray++;
      }
    }    
    if (cearray_ptr)
      free(cearray_ptr);
  } else {
    srslte_chest_dl_estimate(&chest, input_fft, ce, cfg.sf_idx);    
  }
  float noise_power;
  if (nrhs > NOF_INPUTS + 1) {
    noise_power = mxGetScalar(prhs[NOF_INPUTS+1]);
  } else {
    noise_power = srslte_chest_dl_get_noise_estimate(&chest);
  }
  
  uint8_t *data = malloc(sizeof(uint8_t) * cfg.grant.mcs.tbs);
  if (!data) {
    return;
  }

  int r = srslte_pdsch_decode(&pdsch, &cfg, &softbuffer, input_fft, ce, noise_power, data);

  
  if (nlhs >= 1) { 
    plhs[0] = mxCreateLogicalScalar(r == 0);
  }
  if (nlhs >= 2) {
    mexutils_write_uint8(data, &plhs[1], cfg.grant.mcs.tbs, 1);  
  }
  if (nlhs >= 3) {
    mexutils_write_cf(pdsch.symbols[0], &plhs[2], cfg.grant.nof_re, 1);  
  }
  if (nlhs >= 4) {
    mexutils_write_cf(pdsch.d, &plhs[3], cfg.grant.nof_re, 1);  
  }
  if (nlhs >= 5) {
    mexutils_write_f(pdsch.e, &plhs[4], cfg.grant.nof_bits, 1);  
  }
  
  srslte_chest_dl_free(&chest);
  srslte_ofdm_rx_free(&fft);
  srslte_pdsch_free(&pdsch);
  
  for (i=0;i<cell.nof_ports;i++) {
    free(ce[i]);
  }
  free(data);
  free(input_signal);
  free(input_fft);
  
  return;
}
Ejemplo n.º 14
0
Archivo: pss.c Proyecto: srsLTE/srsLTE
void srslte_pss_get_slot(cf_t *slot, cf_t *pss_signal, uint32_t nof_prb, srslte_cp_t cp) {
  int k;
  k = (SRSLTE_CP_NSYMB(cp) - 1) * nof_prb * SRSLTE_NRE + nof_prb * SRSLTE_NRE / 2 - 31;
  memcpy(pss_signal, &slot[k], SRSLTE_PSS_LEN * sizeof(cf_t));
}
Ejemplo n.º 15
0
int srslte_pdsch_cp(srslte_pdsch_t *q, cf_t *input, cf_t *output, srslte_ra_dl_grant_t *grant, uint32_t lstart_grant, uint32_t nsubframe, bool put)
{
    uint32_t s, n, l, lp, lstart, lend, nof_refs;
    bool is_pbch, is_sss;
    cf_t *in_ptr = input, *out_ptr = output;
    uint32_t offset = 0;

#ifdef DEBUG_IDX
    indices_ptr = 0;
    if (put) {
        offset_original = output;
    } else {
        offset_original = input;
    }
#endif

    if (q->cell.nof_ports == 1) {
        nof_refs = 2;
    } else {
        nof_refs = 4;
    }

    for (s = 0; s < 2; s++) {
        for (l = 0; l < SRSLTE_CP_NSYMB(q->cell.cp); l++) {
            for (n = 0; n < q->cell.nof_prb; n++) {

                // If this PRB is assigned
                if (grant->prb_idx[s][n]) {
                    if (s == 0) {
                        lstart = lstart_grant;
                    } else {
                        lstart = 0;
                    }
                    lend = SRSLTE_CP_NSYMB(q->cell.cp);
                    is_pbch = is_sss = false;

                    // Skip PSS/SSS signals
                    if (s == 0 && (nsubframe == 0 || nsubframe == 5)) {
                        if (n >= q->cell.nof_prb / 2 - 3
                                && n < q->cell.nof_prb / 2 + 3 + (q->cell.nof_prb%2)) {
                            lend = SRSLTE_CP_NSYMB(q->cell.cp) - 2;
                            is_sss = true;
                        }
                    }
                    // Skip PBCH
                    if (s == 1 && nsubframe == 0) {
                        if (n >= q->cell.nof_prb / 2 - 3
                                && n < q->cell.nof_prb / 2 + 3 + (q->cell.nof_prb%2)) {
                            lstart = 4;
                            is_pbch = true;
                        }
                    }
                    lp = l + s * SRSLTE_CP_NSYMB(q->cell.cp);
                    if (put) {
                        out_ptr = &output[(lp * q->cell.nof_prb + n)
                                          * SRSLTE_NRE];
                    } else {
                        in_ptr = &input[(lp * q->cell.nof_prb + n)
                                        * SRSLTE_NRE];
                    }
                    // This is a symbol in a normal PRB with or without references
                    if (l >= lstart && l < lend) {
                        if (SRSLTE_SYMBOL_HAS_REF(l, q->cell.cp, q->cell.nof_ports)) {
                            if (nof_refs == 2) {
                                if (l == 0) {
                                    offset = q->cell.id % 6;
                                } else {
                                    offset = (q->cell.id + 3) % 6;
                                }
                            } else {
                                offset = q->cell.id % 3;
                            }
                            prb_cp_ref(&in_ptr, &out_ptr, offset, nof_refs, nof_refs, put);
                        } else {
                            prb_cp(&in_ptr, &out_ptr, 1);
                        }
                    }
                    // This is a symbol in a PRB with PBCH or Synch signals (SS).
                    // If the number or total PRB is odd, half of the the PBCH or SS will fall into the symbol
                    if ((q->cell.nof_prb % 2) && ((is_pbch && l < lstart) || (is_sss && l >= lend))) {
                        if (n == q->cell.nof_prb / 2 - 3) {
                            if (SRSLTE_SYMBOL_HAS_REF(l, q->cell.cp, q->cell.nof_ports)) {
                                prb_cp_ref(&in_ptr, &out_ptr, offset, nof_refs, nof_refs/2, put);
                            } else {
                                prb_cp_half(&in_ptr, &out_ptr, 1);
                            }
                        } else if (n == q->cell.nof_prb / 2 + 3) {
                            if (put) {
                                out_ptr += 6;
                            } else {
                                in_ptr += 6;
                            }
                            if (SRSLTE_SYMBOL_HAS_REF(l, q->cell.cp, q->cell.nof_ports)) {
                                prb_cp_ref(&in_ptr, &out_ptr, offset, nof_refs, nof_refs/2, put);
                            } else {
                                prb_cp_half(&in_ptr, &out_ptr, 1);
                            }
                        }
                    }
                }
            }
        }
    }

    int r;
    if (put) {
        r = abs((int) (input - in_ptr));
    } else {
        r = abs((int) (output - out_ptr));
    }

    return r;
}
Ejemplo n.º 16
0
static void compute_nof_re(srslte_pusch_grant_t* grant, srslte_cp_t cp, uint32_t N_srs)
{
  grant->nof_symb    = 2 * (SRSLTE_CP_NSYMB(cp) - 1) - N_srs;
  grant->nof_re      = grant->nof_symb * grant->L_prb * SRSLTE_NRE;
  grant->tb.nof_bits = grant->nof_re * srslte_mod_bits_x_symbol(grant->tb.mod);
}
Ejemplo n.º 17
0
/* the gateway function */
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
{

  int i;
  srslte_cell_t cell; 
  srslte_chest_dl_t chest;
  srslte_precoding_t cheq; 
  cf_t *input_signal = NULL, *output_signal[SRSLTE_MAX_LAYERS]; 
  cf_t *output_signal2 = NULL;
  cf_t *ce[SRSLTE_MAX_PORTS]; 
  double *outr0=NULL, *outi0=NULL;
  double *outr1=NULL, *outi1=NULL;
  double *outr2=NULL, *outi2=NULL;
  
  if (!mxIsDouble(CELLID) && mxGetN(CELLID) != 1 && 
      !mxIsDouble(PORTS) && mxGetN(PORTS) != 1 && 
      mxGetM(CELLID) != 1) {
    help();
    return;
  }

  cell.id = (uint32_t) *((double*) mxGetPr(CELLID));
  cell.nof_prb = mxGetM(INPUT)/SRSLTE_NRE;
  cell.nof_ports = (uint32_t) *((double*) mxGetPr(PORTS)); 
  if ((mxGetN(INPUT)%14) == 0) {
    cell.cp = SRSLTE_CP_NORM;    
  } else if ((mxGetN(INPUT)%12)!=0) {
    cell.cp = SRSLTE_CP_EXT;
  } else {
    mexErrMsgTxt("Invalid number of symbols\n");
    help();
    return;
  }
  
  if (srslte_chest_dl_init(&chest, cell)) {
    mexErrMsgTxt("Error initiating channel estimator\n");
    return;
  }
  
  int nsubframes;
  if (cell.cp == SRSLTE_CP_NORM) {
    nsubframes = mxGetN(INPUT)/14;
  } else {
    nsubframes = mxGetN(INPUT)/12;
  }
  
  uint32_t sf_idx=0; 
  if (nsubframes == 1) {
    if (nrhs != NOF_INPUTS+1) {
      mexErrMsgTxt("Received 1 subframe. Need to provide subframe index.\n");
      help();
      return;
    }
    sf_idx = (uint32_t) *((double*) mxGetPr(SFIDX));
  } 
  
  if (nrhs > 5) {
    uint32_t filter_len = 0;
    float *filter; 
    double *f; 
    
    filter_len = mxGetNumberOfElements(FREQ_FILTER);
    filter = malloc(sizeof(float) * filter_len);
    f = (double*) mxGetPr(FREQ_FILTER);
    for (i=0;i<filter_len;i++) {
      filter[i] = (float) f[i];
    }

    srslte_chest_dl_set_filter_freq(&chest, filter, filter_len);

    filter_len = mxGetNumberOfElements(TIME_FILTER);
    filter = malloc(sizeof(float) * filter_len);
    f = (double*) mxGetPr(TIME_FILTER);
    for (i=0;i<filter_len;i++) {
      filter[i] = (float) f[i];
    }
    srslte_chest_dl_set_filter_time(&chest, filter, filter_len);
  }  


  double *inr=(double *)mxGetPr(INPUT);
  double *ini=(double *)mxGetPi(INPUT);
  
  /** Allocate input buffers */
  int nof_re = 2*SRSLTE_CP_NSYMB(cell.cp)*cell.nof_prb*SRSLTE_NRE;
  for (i=0;i<SRSLTE_MAX_PORTS;i++) {
    ce[i] = srslte_vec_malloc(nof_re * sizeof(cf_t));
  }
  input_signal = srslte_vec_malloc(nof_re * sizeof(cf_t));
  for (i=0;i<SRSLTE_MAX_PORTS;i++) {
    output_signal[i] = srslte_vec_malloc(nof_re * sizeof(cf_t));
  }
  output_signal2 = srslte_vec_malloc(nof_re * sizeof(cf_t));
  
  srslte_precoding_init(&cheq, nof_re);
  
  /* Create output values */
  if (nlhs >= 1) {
    plhs[0] = mxCreateDoubleMatrix(nof_re * nsubframes, cell.nof_ports, mxCOMPLEX);
    outr0 = mxGetPr(plhs[0]);
    outi0 = mxGetPi(plhs[0]);
  }  
  if (nlhs >= 2) {
    plhs[1] = mxCreateDoubleMatrix(SRSLTE_REFSIGNAL_MAX_NUM_SF(cell.nof_prb)*nsubframes, cell.nof_ports, mxCOMPLEX);
    outr1 = mxGetPr(plhs[1]);
    outi1 = mxGetPi(plhs[1]);
  }
  if (nlhs >= 3) {
    plhs[2] = mxCreateDoubleMatrix(nof_re * nsubframes, 1,  mxCOMPLEX);
    outr2 = mxGetPr(plhs[2]);
    outi2 = mxGetPi(plhs[2]);
  }
    
  for (int sf=0;sf<nsubframes;sf++) {
    /* Convert input to C complex type */
    for (i=0;i<nof_re;i++) {
      __real__ input_signal[i] = (float) *inr;
      if (ini) {
        __imag__ input_signal[i] = (float) *ini;
      }
      inr++;
      ini++;
    }
    
    if (nsubframes != 1) {
      sf_idx = sf%10;
    }
    
    if (srslte_chest_dl_estimate(&chest, input_signal, ce, sf_idx)) {
      mexErrMsgTxt("Error running channel estimator\n");
      return;
    }    
       
    if (cell.nof_ports == 1) {
      srslte_predecoding_single(input_signal, ce[0], output_signal2, nof_re, srslte_chest_dl_get_noise_estimate(&chest));            
    } else {
      srslte_predecoding_diversity(&cheq, input_signal, ce, output_signal, cell.nof_ports, nof_re, srslte_chest_dl_get_noise_estimate(&chest));
      srslte_layerdemap_diversity(output_signal, output_signal2, cell.nof_ports, nof_re/cell.nof_ports);
    }
    
    if (nlhs >= 1) { 
      for (int j=0;j<cell.nof_ports;j++) {
        for (i=0;i<nof_re;i++) {      
          *outr0 = (double) crealf(ce[j][i]);
          if (outi0) {
            *outi0 = (double) cimagf(ce[j][i]);
          }
          outr0++;
          outi0++;
        } 
      }
    }
    if (nlhs >= 2) {    
      for (int j=0;j<cell.nof_ports;j++) {
        for (i=0;i<SRSLTE_REFSIGNAL_NUM_SF(cell.nof_prb,j);i++) {
          *outr1 = (double) crealf(chest.pilot_estimates_average[j][i]);
          if (outi1) {
            *outi1 = (double) cimagf(chest.pilot_estimates_average[j][i]);
          }
          outr1++;
          outi1++;
        }
      }    
    }
    if (nlhs >= 3) {
      for (i=0;i<nof_re;i++) {      
        *outr2 = (double) crealf(output_signal2[i]);
        if (outi2) {
          *outi2 = (double) cimagf(output_signal2[i]);
        }
        outr2++;
        outi2++;
      }
    }
  }

  if (nlhs >= 4) {
    plhs[3] = mxCreateDoubleScalar(srslte_chest_dl_get_noise_estimate(&chest));
  }
  if (nlhs >= 5) {
    plhs[4] = mxCreateDoubleScalar(srslte_chest_dl_get_rsrp(&chest));
  }
  
  srslte_chest_dl_free(&chest);
  srslte_precoding_free(&cheq);

  return;
}
Ejemplo n.º 18
0
int main(int argc, char **argv) {
  srslte_pusch_t pusch;
  uint8_t *data = NULL;
  cf_t *sf_symbols = NULL;
  cf_t *ce = NULL; 
  int ret = -1;
  struct timeval t[3];
  srslte_pusch_cfg_t cfg; 
  srslte_softbuffer_tx_t softbuffer_tx;
  srslte_softbuffer_rx_t softbuffer_rx; 
  
  parse_args(argc,argv);

  bzero(&cfg, sizeof(srslte_pusch_cfg_t));

  srslte_ra_ul_dci_t dci;
  dci.freq_hop_fl = freq_hop;
  if (riv < 0) {
    dci.type2_alloc.L_crb = L_prb; 
    dci.type2_alloc.RB_start = n_prb;    
  } else {
    dci.type2_alloc.riv = riv;
  }
  dci.mcs_idx = mcs_idx;
  
  srslte_ra_ul_grant_t grant; 
  if (srslte_ra_ul_dci_to_grant(&dci, cell.nof_prb, 0, &grant, 0)) {
    fprintf(stderr, "Error computing resource allocation\n");
    return ret;
  }
      
  srslte_pusch_hopping_cfg_t ul_hopping; 
  ul_hopping.n_sb = 1; 
  ul_hopping.hopping_offset = 0;
  ul_hopping.hop_mode = SRSLTE_PUSCH_HOP_MODE_INTER_SF;
  
  if (srslte_pusch_init(&pusch, cell)) {
    fprintf(stderr, "Error creating PDSCH object\n");
    goto quit;
  }
  
  /* Configure PUSCH */
    
  printf("Encoding rv_idx=%d\n",rv_idx);
  
  srslte_uci_cfg_t uci_cfg; 
  uci_cfg.I_offset_cqi = 6; 
  uci_cfg.I_offset_ri = 2; 
  uci_cfg.I_offset_ack = 4; 

  if (srslte_pusch_cfg(&pusch, &cfg, &grant, &uci_cfg, &ul_hopping, NULL, subframe, 0, 0)) {
    fprintf(stderr, "Error configuring PDSCH\n");
    exit(-1);
  }
  
  srslte_pusch_set_rnti(&pusch, 1234);
  
  srslte_uci_data_t uci_data_tx; 
  srslte_uci_data_t uci_data_rx; 
  bzero(&uci_data_tx, sizeof(srslte_uci_data_t));
  uci_data_tx.uci_cqi_len = 4; 
  uci_data_tx.uci_ri_len = 0; 
  uci_data_tx.uci_ack_len = 0; 
  memcpy(&uci_data_rx, &uci_data_tx, sizeof(srslte_uci_data_t));
    
  for (uint32_t i=0;i<20;i++) {
    uci_data_tx.uci_cqi [i] = 1;
  }
  uci_data_tx.uci_ri = 1; 
  uci_data_tx.uci_ack = 1; 

  uint32_t nof_re = SRSLTE_NRE*cell.nof_prb*2*SRSLTE_CP_NSYMB(cell.cp);
  sf_symbols = srslte_vec_malloc(sizeof(cf_t) * nof_re);
  if (!sf_symbols) {
    perror("malloc");
    exit(-1);
  }
  
  data = srslte_vec_malloc(sizeof(uint8_t) * cfg.grant.mcs.tbs);
  if (!data) {
    perror("malloc");
    exit(-1);
  }
  
  for (uint32_t i=0;i<cfg.grant.mcs.tbs/8;i++) {
    data[i] = 1;
  }

  if (srslte_softbuffer_tx_init(&softbuffer_tx, 100)) {
    fprintf(stderr, "Error initiating soft buffer\n");
    goto quit;
  }
  if (srslte_softbuffer_rx_init(&softbuffer_rx, 100)) {
    fprintf(stderr, "Error initiating soft buffer\n");
    goto quit;
  }
  
  uint32_t ntrials = 100; 

  if (srslte_pusch_uci_encode(&pusch, &cfg, &softbuffer_tx, data, uci_data_tx, sf_symbols)) {
    fprintf(stderr, "Error encoding TB\n");
    exit(-1);
  }
  if (rv_idx > 0) {
    cfg.rv = rv_idx; 
    if (srslte_pusch_uci_encode(&pusch, &cfg, &softbuffer_tx, data, uci_data_tx, sf_symbols)) {
      fprintf(stderr, "Error encoding TB\n");
      exit(-1);
    }
  }

  ce = srslte_vec_malloc(sizeof(cf_t) * SRSLTE_SF_LEN_RE(cell.nof_prb, cell.cp));
  if (!ce) {
    perror("srslte_vec_malloc");
    goto quit;
  }
  for (int j=0;j<SRSLTE_SF_LEN_RE(cell.nof_prb, cell.cp);j++) {
    ce[j] = 1;
  }
  
  gettimeofday(&t[1], NULL);
  int r = srslte_pusch_uci_decode(&pusch, &cfg, &softbuffer_rx, sf_symbols, ce, 0, data, &uci_data_rx);
  gettimeofday(&t[2], NULL);
  get_time_interval(t);
  if (r) {
    printf("Error decoding\n");
    ret = -1;
  } else {
    ret = 0;
    printf("DECODED OK in %d:%d (TBS: %d bits, TX: %.2f Mbps, Processing: %.2f Mbps)\n", (int) t[0].tv_sec, 
           (int) t[0].tv_usec/ntrials, 
           cfg.grant.mcs.tbs,
           (float) cfg.grant.mcs.tbs/1000,
           (float) cfg.grant.mcs.tbs/t[0].tv_usec*ntrials);    
  }
  if (uci_data_tx.uci_ack_len) {
    if (uci_data_tx.uci_ack != uci_data_rx.uci_ack) {
      printf("UCI ACK bit error: %d != %d\n", uci_data_tx.uci_ack, uci_data_rx.uci_ack);
    }
  }
  if (uci_data_tx.uci_ri_len) {
    if (uci_data_tx.uci_ri != uci_data_rx.uci_ri) {
      printf("UCI RI bit error: %d != %d\n", uci_data_tx.uci_ri, uci_data_rx.uci_ri);
    }
  }
  if (uci_data_tx.uci_cqi_len) {
    printf("cqi_tx=");
    srslte_vec_fprint_b(stdout, uci_data_tx.uci_cqi, uci_data_tx.uci_cqi_len);
    printf("cqi_rx=");
    srslte_vec_fprint_b(stdout, uci_data_rx.uci_cqi, uci_data_rx.uci_cqi_len);
  }

quit:
  srslte_pusch_free(&pusch);
  srslte_softbuffer_tx_free(&softbuffer_tx);
  
  if (sf_symbols) {
    free(sf_symbols);
  }
  if (data) {
    free(data);
  }
  if (ce) {
    free(ce);
  }
  if (ret) {
    printf("Error\n");
  } else {
    printf("Ok\n");
  }
  exit(ret);
}
Ejemplo n.º 19
0
/* the gateway function */
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
{
  srslte_sch_t ulsch;
  
  srslte_pusch_cfg_t cfg;
  srslte_softbuffer_tx_t softbuffer; 
  srslte_uci_data_t uci_data; 
  bzero(&uci_data, sizeof(srslte_uci_data_t));
  uint32_t rv; 
  
  if (nrhs < NOF_INPUTS) {
    help();
    return;
  }
  bzero(&cfg, sizeof(srslte_pusch_cfg_t));
  
  if (srslte_sch_init(&ulsch)) {
    mexErrMsgTxt("Error initiating ULSCH\n");
    return;
  }
  srslte_cell_t cell;
  cell.nof_prb = 100;
  cell.id=1;
  cell.cp=SRSLTE_CP_NORM;

  if (srslte_softbuffer_tx_init(&softbuffer, cell.nof_prb)) {
    mexErrMsgTxt("Error initiating HARQ\n");
    return;
  }

  uint8_t *trblkin_bits = NULL;
  cfg.grant.mcs.tbs = mexutils_read_uint8(TRBLKIN, &trblkin_bits);

  uint8_t *trblkin = srslte_vec_malloc(cfg.grant.mcs.tbs/8);
  srslte_bit_unpack_vector(trblkin_bits, trblkin, cfg.grant.mcs.tbs);
  free(trblkin_bits);

  
  uint8_t *tmp; 
  uci_data.uci_cqi_len = mexutils_read_uint8(CQI, &tmp);
  memcpy(uci_data.uci_cqi, tmp, uci_data.uci_cqi_len);
  free(tmp);  
  uci_data.uci_ri_len = mexutils_read_uint8(RI, &tmp);
  if (uci_data.uci_ri_len > 0) {
    uci_data.uci_ri = *tmp;
  }
  free(tmp);
  uci_data.uci_ack_len = mexutils_read_uint8(ACK, &tmp);
  if (uci_data.uci_ack_len > 0) {
    uci_data.uci_ack = *tmp;
  }
  free(tmp);
  
  mexPrintf("TRBL_len: %d, CQI_len: %d, ACK_len: %d, RI_len: %d\n", cfg.grant.mcs.tbs, 
            uci_data.uci_cqi_len, uci_data.uci_ack_len, uci_data.uci_ri_len);
  
  if (mexutils_read_uint32_struct(PUSCHCFG, "RV", &rv)) {
    mexErrMsgTxt("Field RV not found in pdsch config\n");
    return;
  }

  float beta; 
  if (mexutils_read_float_struct(PUSCHCFG, "BetaCQI", &beta)) {
    cfg.uci_cfg.I_offset_cqi = 7; 
  } else {
    cfg.uci_cfg.I_offset_cqi = srslte_sch_find_Ioffset_cqi(beta);
  }
  if (mexutils_read_float_struct(PUSCHCFG, "BetaRI", &beta)) {
    cfg.uci_cfg.I_offset_ri = 2; 
  } else {
    cfg.uci_cfg.I_offset_ri = srslte_sch_find_Ioffset_ri(beta);
  }
  if (mexutils_read_float_struct(PUSCHCFG, "BetaACK", &beta)) {
    cfg.uci_cfg.I_offset_ack = 0; 
  } else {
    cfg.uci_cfg.I_offset_ack = srslte_sch_find_Ioffset_ack(beta);
  }
  
  char *mod_str = mexutils_get_char_struct(PUSCHCFG, "Modulation");
  
  if (!strcmp(mod_str, "QPSK")) {
    cfg.grant.mcs.mod = SRSLTE_MOD_QPSK;
  } else if (!strcmp(mod_str, "16QAM")) {
    cfg.grant.mcs.mod = SRSLTE_MOD_16QAM;
  } else if (!strcmp(mod_str, "64QAM")) {
    cfg.grant.mcs.mod = SRSLTE_MOD_64QAM;
  } else {
   mexErrMsgTxt("Unknown modulation\n");
   return;
  }

  mxFree(mod_str);
  
  float *prbset; 
  mxArray *p; 
  p = mxGetField(PUSCHCFG, 0, "PRBSet");
  if (!p) {
    mexErrMsgTxt("Error field PRBSet not found\n");
    return;
  } 
  
  uint32_t N_srs = 0; 
  mexutils_read_uint32_struct(PUSCHCFG, "Shortened", &N_srs);
  
  
  cfg.grant.L_prb = mexutils_read_f(p, &prbset);
  cfg.grant.n_prb[0] = prbset[0];
  cfg.grant.n_prb[1] = prbset[0];
  free(prbset);
  cfg.grant.L_prb = mexutils_read_f(p, &prbset);
  cfg.grant.n_prb[0] = prbset[0];
  cfg.grant.n_prb[1] = prbset[0];
  cfg.nbits.lstart = 0;
  cfg.nbits.nof_symb = 2*(SRSLTE_CP_NSYMB(cell.cp)-1) - N_srs; 
  cfg.grant.M_sc = cfg.grant.L_prb*SRSLTE_NRE;
  cfg.grant.M_sc_init = cfg.grant.M_sc; // FIXME: What should M_sc_init be? 
  cfg.nbits.nof_re = cfg.nbits.nof_symb*cfg.grant.M_sc;
  cfg.grant.Qm = srslte_mod_bits_x_symbol(cfg.grant.mcs.mod);
  cfg.nbits.nof_bits = cfg.nbits.nof_re * cfg.grant.Qm;

  mexPrintf("Q_m: %d, NPRB: %d, RV: %d, Nsrs=%d\n", srslte_mod_bits_x_symbol(cfg.grant.mcs.mod), cfg.grant.L_prb, cfg.rv, N_srs);

  mexPrintf("I_cqi: %d, I_ri: %d, I_ack=%d\n", cfg.uci_cfg.I_offset_cqi, cfg.uci_cfg.I_offset_ri, cfg.uci_cfg.I_offset_ack);

  if (srslte_cbsegm(&cfg.cb_segm, cfg.grant.mcs.tbs)) {
    mexErrMsgTxt("Error configuring HARQ process\n");
    return;
  }
    
  uint8_t *q_bits = srslte_vec_malloc(cfg.nbits.nof_bits * sizeof(uint8_t));
  if (!q_bits) {
    return;
  }
  uint8_t *g_bits = srslte_vec_malloc(cfg.nbits.nof_bits * sizeof(uint8_t));
  if (!g_bits) {
    return;
  }

  if (srslte_ulsch_uci_encode(&ulsch, &cfg, &softbuffer, trblkin, uci_data, g_bits, q_bits)) 
  {
    mexErrMsgTxt("Error encoding TB\n");
    return;
  }    
  if (rv > 0) {
    cfg.rv = rv; 
    if (srslte_ulsch_uci_encode(&ulsch, &cfg, &softbuffer, trblkin, uci_data, g_bits, q_bits)) {
      mexErrMsgTxt("Error encoding TB\n");
      return;
    }    
  }
  
  if (nlhs >= 1) {
    mexutils_write_uint8(q_bits, &plhs[0], cfg.nbits.nof_bits, 1);  
  }
  
  srslte_sch_free(&ulsch);  
  srslte_softbuffer_tx_free(&softbuffer);
  
  free(trblkin);
  free(g_bits);    
  free(q_bits);    
  
  
  return;
}