Example #1
0
int main(int argc, char **argv) {

  parse_args(argc, argv);
  
  srslte_tcod_gentable();

  srslte_tcod_t tcod;
  srslte_tcod_init(&tcod, 6144);

  uint32_t st=0, end=187;
  if (long_cb) {
    st=srslte_cbsegm_cbindex(long_cb);
    end=st;
  }
  
  for (uint32_t len=st;len<=end;len++) {
    long_cb = srslte_cbsegm_cbsize(len); 
    printf("Checking long_cb=%d\n", long_cb);
    for (int i=0;i<long_cb/8;i++) {
      input_bytes[i] = rand()%256;
    }
    
    srslte_bit_unpack_vector(input_bytes, input_bits, long_cb);

    if (SRSLTE_VERBOSE_ISINFO()) {
      printf("Input bits:\n");
      for (int i=0;i<long_cb/8;i++) {
        srslte_vec_fprint_b(stdout, &input_bits[i*8], 8);
      }
    }

    srslte_tcod_encode(&tcod, input_bits, output_bits, long_cb);
    srslte_tcod_encode_lut(&tcod, input_bytes, parity, len);

    srslte_bit_unpack_vector(parity, parity_bits, 2*(long_cb+4));
    
    for (int i=0;i<long_cb;i++) {
      output_bits2[3*i] = input_bits[i];
      output_bits2[3*i+1] = parity_bits[i];
      output_bits2[3*i+2] = parity_bits[i+long_cb+4];
    }

    if (SRSLTE_VERBOSE_ISINFO()) {
      srslte_vec_fprint_b(stdout, output_bits2, 3*long_cb); 
      srslte_vec_fprint_b(stdout, output_bits, 3*long_cb);       
      printf("\n");
    }  
    for (int i=0;i<2*long_cb;i++) {
      if (output_bits2[long_cb+i] != output_bits[long_cb+i]) {
        printf("error in bit %d, len=%d\n", i, len);
        exit(-1);
      }
    }
  }
  
  srslte_tcod_free(&tcod);
  printf("Done\n");
  exit(0);
}
Example #2
0
void srslte_scrambling_bytes(srslte_sequence_t *s, uint8_t *data, int len) {
  scrambling_b_word(s->c_bytes, data, len/8);  
  // Scramble last bits
  if (len%8) {
    uint8_t tmp_bits[8];
    srslte_bit_unpack_vector(&data[len/8], tmp_bits, len%8);
    scrambling_b(&s->c[8*(len/8)], tmp_bits, len%8);
    srslte_bit_pack_vector(tmp_bits, &data[len/8], len%8);
  }    
}
Example #3
0
int main(int argc, char **argv) {

  parse_args(argc, argv);
  
  srslte_tcod_gentable();

  srslte_tcod_t tcod;
  srslte_tcod_init(&tcod, 6144);

  uint32_t st=0, end=187;
  if (long_cb) {
    st=srslte_cbsegm_cbindex(long_cb);
    end=st;
  }
  
  for (uint32_t len=st;len<=end;len++) {
    long_cb = srslte_cbsegm_cbsize(len); 
    printf("Checking long_cb=%d\n", long_cb);
    for (int i=0;i<long_cb/8;i++) {
      input_bytes[i] = rand()%256;
    }
    
    srslte_bit_unpack_vector(input_bytes, input_bits, long_cb);

    if (SRSLTE_VERBOSE_ISINFO()) {
      printf("Input bits:\n");
      for (int i=0;i<long_cb/8;i++) {
        srslte_vec_fprint_b(stdout, &input_bits[i*8], 8);
      }
    }

    srslte_tcod_encode(&tcod, input_bits, output_bits, long_cb);
    srslte_tcod_encode_lut(&tcod, input_bytes, output_bytes, long_cb);
    
    srslte_bit_unpack_vector(output_bytes, output_bits2, 2*long_cb+12);

    /* de-Interleace bits for comparison */
    for (int i=0;i<long_cb;i++) {
      for (int j=0;j<2;j++) {
        output_bits3[j*long_cb+i] = output_bits[3*i+j+1]; 
      }
    }
    // copy tail 
    memcpy(&output_bits3[2*long_cb], &output_bits[3*long_cb], 12);

    if (SRSLTE_VERBOSE_ISINFO()) {
      printf("1st encoder\n");
      srslte_vec_fprint_b(stdout, output_bits2, long_cb); 
      srslte_vec_fprint_b(stdout, output_bits3, long_cb); 
      
      printf("2nd encoder\n");
      srslte_vec_fprint_b(stdout, &output_bits2[long_cb], long_cb); 
      srslte_vec_fprint_b(stdout, &output_bits3[long_cb], long_cb); 

      printf("tail\n");
      srslte_vec_fprint_b(stdout, &output_bits2[2*long_cb], 12); 
      srslte_vec_fprint_b(stdout, &output_bits3[2*long_cb], 12); 
      printf("\n");
    }  
    for (int i=0;i<2*long_cb+12;i++) {
      if (output_bits2[i] != output_bits3[i]) {
        printf("error in bit %d, len=%d\n", i, len);
        exit(-1);
      }
    }
  }
  
  srslte_tcod_free(&tcod);
  printf("Done\n");
  exit(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;
}
Example #5
0
/* Encode a transport block according to 36.212 5.3.2
 *
 */
static int encode_tb(srslte_sch_t *q, 
                     srslte_softbuffer_tx_t *soft_buffer, srslte_cbsegm_t *cb_segm, 
                     uint32_t Qm, uint32_t rv, uint32_t nof_e_bits,  
                     uint8_t *data, uint8_t *e_bits) 
{
  uint8_t parity[3] = {0, 0, 0};
  uint32_t par;
  uint32_t i;
  uint32_t cb_len, rp, wp, rlen, F, n_e;
  int ret = SRSLTE_ERROR_INVALID_INPUTS; 
  
  if (q            != NULL &&
      e_bits       != NULL &&
      cb_segm      != NULL &&
      soft_buffer  != NULL)
  {
  
    uint32_t Gp = nof_e_bits / Qm;
    
    uint32_t gamma = Gp;
    if (cb_segm->C > 0) {
      gamma = Gp%cb_segm->C;
    }

    if (data) {

      /* Compute transport block CRC */
      par = srslte_crc_checksum_byte(&q->crc_tb, data, cb_segm->tbs);

      /* parity bits will be appended later */
      parity[0] = (par&(0xff<<16))>>16;
      parity[1] = (par&(0xff<<8))>>8;
      parity[2] = par&0xff;

      if (SRSLTE_VERBOSE_ISDEBUG()) {
        DEBUG("DATA: ", 0);
        srslte_vec_fprint_byte(stdout, data, cb_segm->tbs/8);
        DEBUG("PARITY: ", 0);
        srslte_vec_fprint_byte(stdout, parity, 3);
      }      
    }
    
    wp = 0;
    rp = 0;
    for (i = 0; i < cb_segm->C; i++) {

      /* Get read lengths */
      if (i < cb_segm->C2) {
        cb_len = cb_segm->K2;
      } else {
        cb_len = cb_segm->K1;
      }
      if (cb_segm->C > 1) {
        rlen = cb_len - 24;
      } else {
        rlen = cb_len;
      }
      if (i == 0) {
        F = cb_segm->F;
      } else {
        F = 0;
      }
      if (i <= cb_segm->C - gamma - 1) {
        n_e = Qm * (Gp/cb_segm->C);
      } else {
        n_e = Qm * ((uint32_t) ceilf((float) Gp/cb_segm->C));
      }

      INFO("CB#%d: cb_len: %d, rlen: %d, wp: %d, rp: %d, F: %d, E: %d\n", i,
          cb_len, rlen - F, wp, rp, F, n_e);

      if (data) {

        /* Copy data to another buffer, making space for the Codeblock CRC */
        if (i < cb_segm->C - 1) {
          // Copy data 
          memcpy(&q->cb_in[F/8], &data[rp/8], (rlen - F) * sizeof(uint8_t)/8);
        } else {
          INFO("Last CB, appending parity: %d from %d and 24 to %d\n",
              rlen - F - 24, rp, rlen - 24);
          
          /* Append Transport Block parity bits to the last CB */
          memcpy(&q->cb_in[F/8], &data[rp/8], (rlen - 24 - F) * sizeof(uint8_t)/8);
          memcpy(&q->cb_in[(rlen - 24)/8], parity, 3 * sizeof(uint8_t));
        }        
        
        /* Filler bits are treated like zeros for the CB CRC calculation */
        for (int j = 0; j < F/8; j++) {
          q->cb_in[j] = 0;
        }
        
        /* Attach Codeblock CRC */
        if (cb_segm->C > 1) {
          srslte_crc_attach_byte(&q->crc_cb, q->cb_in, rlen);
        }
        
        /* pack bits to temporal buffer for encoding */
        srslte_bit_unpack_vector(q->cb_in, q->cb_temp, cb_len);

        /* Set the filler bits to <NULL> */
        for (int j = 0; j < F; j++) {
          q->cb_temp[j] = SRSLTE_TX_NULL;
        }
        
        if (SRSLTE_VERBOSE_ISDEBUG()) {
          DEBUG("CB#%d: ", i);
          srslte_vec_fprint_hex(stdout, q->cb_temp, cb_len);
        }
        
        /* Turbo Encoding */
        srslte_tcod_encode(&q->encoder, q->cb_temp, (uint8_t*) q->cb_out, cb_len);

        if (SRSLTE_VERBOSE_ISDEBUG()) {
          DEBUG("CB#%d encoded: ", i);
          srslte_vec_fprint_b(stdout, q->cb_out, 3*cb_len+12);
        }
      }
      
      /* Rate matching */
      if (srslte_rm_turbo_tx(soft_buffer->buffer_b[i], soft_buffer->buff_size, 
                  (uint8_t*) q->cb_out, 3 * cb_len + 12,
                  &e_bits[wp], n_e, rv))
      {
        fprintf(stderr, "Error in rate matching\n");
        return SRSLTE_ERROR;
      }

      /* Set read/write pointers */
      rp += (rlen - F);
      wp += n_e;
    }
    INFO("END CB#%d: wp: %d, rp: %d\n", i, wp, rp);
   
    ret = SRSLTE_SUCCESS;      
  } 
Example #6
0
/* the gateway function */
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
{
  int i; 
  srslte_cell_t cell; 
  srslte_ofdm_t ofdm_rx; 
  srslte_pdsch_t pdsch;
  srslte_chest_dl_t chest; 
  cf_t *input_fft;
  srslte_pdsch_cfg_t cfg;
  srslte_softbuffer_rx_t softbuffer; 
  uint32_t rnti32;
  uint32_t cfi; 

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

  srslte_verbose = SRSLTE_VERBOSE_DEBUG;
  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_ofdm_rx_init(&ofdm_rx, cell.cp, cell.nof_prb)) {
    fprintf(stderr, "Error initializing FFT\n");
    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.nof_prb)) {
    mexErrMsgTxt("Error initiating soft buffer\n");
    return;
  }
  
  if (srslte_chest_dl_init(&chest, cell)) {
    mexErrMsgTxt("Error initializing equalizer\n");
    return;
  }

  srslte_ra_dl_grant_t grant; 
  grant.mcs.tbs = mxGetScalar(TBS);
  if (grant.mcs.tbs == 0) {
    mexErrMsgTxt("Error trblklen is zero\n");
    return;
  }
  if (srslte_cbsegm(&cfg.cb_segm, 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;
  }

  uint32_t max_iterations = 5;
  mexutils_read_uint32_struct(PDSCHCFG, "NTurboDecIts", &max_iterations);
  
  char *mod_str = mexutils_get_char_struct(PDSCHCFG, "Modulation");
  
  if (!strcmp(mod_str, "QPSK")) {
    grant.mcs.mod = SRSLTE_MOD_QPSK;
  } else if (!strcmp(mod_str, "16QAM")) {
    grant.mcs.mod = SRSLTE_MOD_16QAM;
  } else if (!strcmp(mod_str, "64QAM")) {
    grant.mcs.mod = SRSLTE_MOD_64QAM;
  } else {
   mexErrMsgTxt("Unknown modulation\n");
   return;
  }

  mxFree(mod_str);
  
  mxArray *p; 
  p = mxGetField(PDSCHCFG, 0, "PRBSet");
  if (!p) {
    mexErrMsgTxt("Error field PRBSet not found\n");
    return;
  } 
  
  float *prbset_f;
  uint64_t *prbset;
  if (mxGetClassID(p) == mxDOUBLE_CLASS) {
    grant.nof_prb = mexutils_read_f(p, &prbset_f);
    prbset = malloc(sizeof(uint64_t)*grant.nof_prb);
    for (i=0;i<grant.nof_prb;i++) {
      prbset[i] = (uint64_t) prbset_f[i];
    }
  } else {
    grant.nof_prb = mexutils_read_uint64(p, &prbset);
  }
  
  for (i=0;i<cell.nof_prb;i++) {
    grant.prb_idx[0][i] = false; 
    for (int j=0;j<grant.nof_prb && !grant.prb_idx[0][i];j++) {
      if ((int) prbset[j] == i) {
        grant.prb_idx[0][i] = true;
      }
    }
    grant.prb_idx[1][i] = grant.prb_idx[0][i];
  }
  
  free(prbset);
  
  /* Configure rest of pdsch_cfg parameters */
  grant.Qm = srslte_mod_bits_x_symbol(grant.mcs.mod);
  if (srslte_pdsch_cfg(&cfg, cell, &grant, cfi, cfg.sf_idx, cfg.rv)) {
    fprintf(stderr, "Error configuring PDSCH\n");
    exit(-1);
  }
      
  /** Allocate input buffers */
  int nof_retx=1; 
  if (mexutils_isCell(INPUT)) {
    nof_retx = mexutils_getLength(INPUT);
  } 
  
  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));
  }

  uint8_t *data_bytes = srslte_vec_malloc(sizeof(uint8_t) * grant.mcs.tbs/8);
  if (!data_bytes) {
    return;
  }
  srslte_sch_set_max_noi(&pdsch.dl_sch, max_iterations);

  input_fft = NULL; 
  int r=-1;
  for (int rvIdx=0;rvIdx<nof_retx && r != 0;rvIdx++) {
    
    mxArray *tmp = (mxArray*) INPUT; 
    if (mexutils_isCell(INPUT)) {
      tmp = mexutils_getCellArray(INPUT, rvIdx);
      if (nof_retx > 1) {
        cfg.rv = rv_seq[rvIdx%4];
      }
    } 
    
    // Read input signal 
    cf_t *input_signal = NULL; 
    int insignal_len = mexutils_read_cf(tmp, &input_signal);
    if (insignal_len < 0) {
      mexErrMsgTxt("Error reading input signal\n");
      return; 
    }
    if (insignal_len == SRSLTE_SF_LEN_RE(cell.nof_prb, cell.cp)) {
      input_fft = input_signal; 
    } else {
      input_fft = srslte_vec_malloc(SRSLTE_SF_LEN_RE(cell.nof_prb, cell.cp) * sizeof(cf_t));  
      srslte_ofdm_rx_sf(&ofdm_rx, input_signal, input_fft);
      free(input_signal);
    }
    
    if (nrhs > NOF_INPUTS) {
      cf_t *cearray = NULL; 
      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<SRSLTE_SF_LEN_RE(cell.nof_prb, cell.cp);j++) {
          ce[i][j] = *cearray_ptr;
          cearray_ptr++;
        }
      }    
      if (cearray)
        free(cearray);
    } 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 if (nrhs > NOF_INPUTS) {
      noise_power = 0; 
    } else {
      noise_power = srslte_chest_dl_get_noise_estimate(&chest);
    }

    r = srslte_pdsch_decode(&pdsch, &cfg, &softbuffer, input_fft, ce, noise_power, data_bytes);
  }
  
  uint8_t *data = malloc(grant.mcs.tbs);
  srslte_bit_unpack_vector(data_bytes, data, grant.mcs.tbs);
  
  if (nlhs >= 1) { 
    plhs[0] = mxCreateLogicalScalar(r == 0);
  }
  if (nlhs >= 2) {
    mexutils_write_uint8(data, &plhs[1], grant.mcs.tbs, 1);  
  }
  if (nlhs >= 3) {
    mexutils_write_cf(pdsch.symbols[0], &plhs[2], cfg.nbits.nof_re, 1);  
  }
  if (nlhs >= 4) {
    mexutils_write_cf(pdsch.d, &plhs[3], cfg.nbits.nof_re, 1);  
  }
  if (nlhs >= 5) {
    mexutils_write_s(pdsch.e, &plhs[4], cfg.nbits.nof_bits, 1);  
  }
  
  srslte_softbuffer_rx_free(&softbuffer);
  srslte_chest_dl_free(&chest);
  srslte_pdsch_free(&pdsch);
  srslte_ofdm_rx_free(&ofdm_rx);
  
  for (i=0;i<cell.nof_ports;i++) {
    free(ce[i]);
  }
  free(data_bytes);
  free(data);
  if (input_fft) {
    free(input_fft); 
  }
  
  return;
}
Example #7
0
int main(int argc, char **argv) {
  int i;
  uint8_t *rm_bits, *rm_bits2, *rm_bits2_bytes;
  short *rm_bits_s; 
  float *rm_bits_f; 
  
  parse_args(argc, argv);
  
  srslte_rm_turbo_gentables();

  rm_bits_s = srslte_vec_malloc(sizeof(short) * nof_e_bits);
  if (!rm_bits_s) {
    perror("malloc");
    exit(-1);
  }
  rm_bits_f = srslte_vec_malloc(sizeof(float) * nof_e_bits);
  if (!rm_bits_f) {
    perror("malloc");
    exit(-1);
  }
  rm_bits = srslte_vec_malloc(sizeof(uint8_t) * nof_e_bits);
  if (!rm_bits) {
    perror("malloc");
    exit(-1);
  }
  rm_bits2 = malloc(sizeof(uint8_t) * nof_e_bits);
  if (!rm_bits2) {
    perror("malloc");
    exit(-1);
  }
  rm_bits2_bytes = malloc(sizeof(uint8_t) * nof_e_bits/8 + 1);
  if (!rm_bits2_bytes) {
    perror("malloc");
    exit(-1);
  }

  uint32_t st=0, end=188;
  if (cb_idx != -1) {
    st=cb_idx;
    end=cb_idx+1;
  }
  uint32_t rv_st=0, rv_end=4;
  if (rv_idx != -1) {
    rv_st=rv_idx;
    rv_end=rv_idx+1;
  }
  
  for (cb_idx=st;cb_idx<end;cb_idx++) {
    for (rv_idx=rv_st;rv_idx<rv_end;rv_idx++) {
      uint32_t long_cb_enc = 3*srslte_cbsegm_cbsize(cb_idx)+12;
      
      printf("checking cb_idx=%3d rv_idx=%d...", cb_idx, rv_idx);
      
      for (i = 0; i < long_cb_enc; i++) {
        bits[i] = rand() % 2;
      }
      
      bzero(buff_b, BUFFSZ * sizeof(uint8_t));
      
      srslte_rm_turbo_tx(buff_b, BUFFSZ, bits, long_cb_enc, rm_bits, nof_e_bits, 0);

      if (rv_idx > 0) {
        srslte_rm_turbo_tx(buff_b, BUFFSZ, bits, long_cb_enc, rm_bits, nof_e_bits, rv_idx);
      }

      for (int i=0;i<long_cb_enc/3;i++) {
        systematic[i] = bits[3*i];
        parity[i] = bits[3*i+1];
        parity[i+long_cb_enc/3] = bits[3*i+2];
      }
      
      srslte_bit_pack_vector(systematic, systematic_bytes, long_cb_enc/3);
      srslte_bit_pack_vector(parity, parity_bytes, 2*long_cb_enc/3);
      
      bzero(buff_b, BUFFSZ * sizeof(uint8_t));

      bzero(rm_bits2_bytes, nof_e_bits/8);
      srslte_rm_turbo_tx_lut(buff_b, systematic_bytes, parity_bytes, rm_bits2_bytes, cb_idx, nof_e_bits, 0, 0);
      if (rv_idx > 0) {
        bzero(rm_bits2_bytes, nof_e_bits/8);
        srslte_rm_turbo_tx_lut(buff_b, systematic_bytes, parity_bytes, rm_bits2_bytes, cb_idx, nof_e_bits, 0, rv_idx);
      }

      srslte_bit_unpack_vector(rm_bits2_bytes, rm_bits2, nof_e_bits);

      for (int i=0;i<nof_e_bits;i++) {
        if (rm_bits2[i] != rm_bits[i]) {
          printf("Error in TX bit %d\n", i);
          exit(-1);
        }
      }
      
      printf("OK TX...");
      
      for (int i=0;i<nof_e_bits;i++) {
        rm_bits_f[i] = rand()%10-5;
        rm_bits_s[i] = (short) rm_bits_f[i];
      }

      bzero(buff_f, BUFFSZ*sizeof(float));
      srslte_rm_turbo_rx(buff_f, BUFFSZ, rm_bits_f, nof_e_bits, bits_f, long_cb_enc, rv_idx, 0);

      bzero(bits2_s, long_cb_enc*sizeof(short));
      srslte_rm_turbo_rx_lut(rm_bits_s, bits2_s, nof_e_bits, cb_idx, rv_idx);

      for (int i=0;i<long_cb_enc;i++) {
        if (bits_f[i] != bits2_s[i]) {
          printf("error RX in bit %d %f!=%d\n", i, bits_f[i], bits2_s[i]);
          exit(-1);
        }
      }
    
      printf("OK RX\n");

    }
  }

  free(rm_bits);
  free(rm_bits2);
  free(rm_bits2_bytes);
  
  exit(0);
}
int main(int argc, char **argv) {
  uint32_t frame_cnt;
  float *llr;
  short *llr_s;
  uint8_t *llr_c;
  uint8_t *data_tx, *data_rx, *data_rx_bytes, *symbols;
  uint32_t i, j;
  float var[SNR_POINTS];
  uint32_t snr_points;
  uint32_t errors;
  uint32_t coded_length;
  struct timeval tdata[3];
  float mean_usec;
  srslte_tdec_t tdec;
  srslte_tcod_t tcod;
  
  parse_args(argc, argv);

  if (!seed) {
    seed = time(NULL);
  }
  srand(seed);

  if (test_known_data) {
    frame_length = KNOWN_DATA_LEN;
  } else {
    frame_length = srslte_cbsegm_cbsize(srslte_cbsegm_cbindex(frame_length));
  }

  coded_length = 3 * (frame_length) + SRSLTE_TCOD_TOTALTAIL;

  printf("  Frame length: %d\n", frame_length);
  if (ebno_db < 100.0) {
    printf("  EbNo: %.2f\n", ebno_db);
  }

  data_tx = srslte_vec_malloc(frame_length * sizeof(uint8_t));
  if (!data_tx) {
    perror("malloc");
    exit(-1);
  }

  data_rx = srslte_vec_malloc(frame_length * sizeof(uint8_t));
  if (!data_rx) {
    perror("malloc");
    exit(-1);
  }
  data_rx_bytes = srslte_vec_malloc(frame_length * sizeof(uint8_t));
  if (!data_rx_bytes) {
    perror("malloc");
    exit(-1);
  }

  symbols = srslte_vec_malloc(coded_length * sizeof(uint8_t));
  if (!symbols) {
    perror("malloc");
    exit(-1);
  }
  llr = srslte_vec_malloc(coded_length * sizeof(float));
  if (!llr) {
    perror("malloc");
    exit(-1);
  }
  llr_s = srslte_vec_malloc(coded_length * sizeof(short));
  if (!llr_s) {
    perror("malloc");
    exit(-1);
  }
  llr_c = srslte_vec_malloc(coded_length * sizeof(uint8_t));
  if (!llr_c) {
    perror("malloc");
    exit(-1);
  }

  if (srslte_tcod_init(&tcod, frame_length)) {
    fprintf(stderr, "Error initiating Turbo coder\n");
    exit(-1);
  }

  if (srslte_tdec_init_manual(&tdec, frame_length, tdec_type)) {
    fprintf(stderr, "Error initiating Turbo decoder\n");
    exit(-1);
  }

  srslte_tdec_force_not_sb(&tdec);

  float ebno_inc, esno_db;
  ebno_inc = (SNR_MAX - SNR_MIN) / SNR_POINTS;
  if (ebno_db == 100.0) {
    snr_points = SNR_POINTS;
    for (i = 0; i < snr_points; i++) {
      ebno_db = SNR_MIN + i * ebno_inc;
      esno_db = ebno_db + 10 * log10((double) 1 / 3);
      var[i] = sqrt(1 / (pow(10, esno_db / 10)));
    }
  } else {
    esno_db = ebno_db + 10 * log10((double) 1 / 3);
    var[0] = sqrt(1 / (pow(10, esno_db / 10)));
    snr_points = 1;
  }
  for (i = 0; i < snr_points; i++) {

    mean_usec = 0;
    errors = 0; 
    frame_cnt = 0;
    while (frame_cnt < nof_frames) {
      /* generate data_tx */
      for (j = 0; j < frame_length; j++) {
        if (test_known_data) {
          data_tx[j] = known_data[j];
        } else {
          data_tx[j] = rand() % 2;
        }
      }

      /* coded BER */
      if (test_known_data) {
        for (j = 0; j < coded_length; j++) {
          symbols[j] = known_data_encoded[j];
        }
      } else {
        srslte_tcod_encode(&tcod, data_tx, symbols, frame_length);
      }

      for (j = 0; j < coded_length; j++) {
        llr[j] = symbols[j] ? 1 : -1;
      }
      srslte_ch_awgn_f(llr, llr, var[i], coded_length);

      for (j=0;j<coded_length;j++) {
        llr_s[j] = (int16_t) (100*llr[j]);
      }

      /* decoder */
      srslte_tdec_new_cb(&tdec, frame_length);

      uint32_t t;
      if (nof_iterations == -1) {
        t = MAX_ITERATIONS;
      } else {
        t = nof_iterations;
      }

      gettimeofday(&tdata[1], NULL); 
      for (int k=0;k<nof_repetitions;k++) { 
        srslte_tdec_run_all(&tdec, llr_s, data_rx_bytes, t, frame_length);
      }
      gettimeofday(&tdata[2], NULL);
      get_time_interval(tdata);
      mean_usec = (tdata[0].tv_sec*1e6+tdata[0].tv_usec)/nof_repetitions;
      
      frame_cnt++;
      uint32_t errors_this = 0; 
      srslte_bit_unpack_vector(data_rx_bytes, data_rx, frame_length);

      errors_this=srslte_bit_diff(data_tx, data_rx, frame_length);
      //printf("error[%d]=%d\n", cb, errors_this);
      errors += errors_this;
      printf("Eb/No: %2.2f %10d/%d   ", SNR_MIN + i * ebno_inc, frame_cnt, nof_frames);
      printf("BER: %.2e  ", (float) errors / (nof_cb*frame_cnt * frame_length));
      printf("%3.1f Mbps (%6.2f usec)", (float) (nof_cb*frame_length) / mean_usec, mean_usec);
      printf("\r");        

    }    
    printf("\n");
  }

  printf("\n");
  if (snr_points == 1) {
    if (errors) {
      printf("%d Errors\n", errors/nof_cb);
    }
  }

  if (data_rx_bytes) {
    free(data_rx_bytes);
  }
  free(data_tx);
  free(symbols);
  free(llr);
  free(llr_c);
  free(llr_s);
  free(data_rx);

  srslte_tdec_free(&tdec);
  srslte_tcod_free(&tcod);

  printf("\n");
  printf("Done\n");
  exit(0);
}
Example #9
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.nof_prb)) {
    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;

  srslte_ra_dl_grant_t grant; 
  grant.mcs.tbs = mxGetScalar(TBS);
  if (grant.mcs.tbs == 0) {
    mexErrMsgTxt("Error trblklen is zero\n");
    return;
  }
  if (srslte_cbsegm(&cfg.cb_segm, 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")) {
    grant.mcs.mod = SRSLTE_MOD_QPSK;
  } else if (!strcmp(mod_str, "16QAM")) {
    grant.mcs.mod = SRSLTE_MOD_16QAM;
  } else if (!strcmp(mod_str, "64QAM")) {
    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 
  grant.nof_prb = mexutils_read_f(p, &prbset);

  for (i=0;i<cell.nof_prb;i++) {
    grant.prb_idx[0][i] = false; 
    for (int j=0;j<grant.nof_prb && !grant.prb_idx[0][i];j++) {
      if ((int) prbset[j] == i) {
        grant.prb_idx[0][i] = true;
      }
    }
    grant.prb_idx[1][i] = grant.prb_idx[0][i];
  }

  free(prbset);
  
  /* Configure rest of pdsch_cfg parameters */
  grant.Qm = srslte_mod_bits_x_symbol(grant.mcs.mod);
  if (srslte_pdsch_cfg(&cfg, cell, &grant, cfi, cfg.sf_idx, (uint16_t) (rnti32 & 0xffff), cfg.rv)) {
    fprintf(stderr, "Error configuring PDSCH\n");
    exit(-1);
  }
      
  /** 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_bytes = srslte_vec_malloc(sizeof(uint8_t) * grant.mcs.tbs/8);
  if (!data_bytes) {
    return;
  }

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

  free(data_bytes);
  
  uint8_t *data = malloc(grant.mcs.tbs);
  srslte_bit_unpack_vector(data_bytes, data, grant.mcs.tbs);
  
  if (nlhs >= 1) { 
    plhs[0] = mxCreateLogicalScalar(r == 0);
  }
  if (nlhs >= 2) {
    mexutils_write_uint8(data, &plhs[1], grant.mcs.tbs, 1);  
  }
  if (nlhs >= 3) {
    mexutils_write_cf(pdsch.symbols[0], &plhs[2], cfg.nbits.nof_re, 1);  
  }
  if (nlhs >= 4) {
    mexutils_write_cf(pdsch.d, &plhs[3], cfg.nbits.nof_re, 1);  
  }
  if (nlhs >= 5) {
    mexutils_write_f(pdsch.e, &plhs[4], cfg.nbits.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;
}