Exemple #1
0
/* Decode a transport block according to 36.212 5.3.2
 *
 */
static int decode_tb(srslte_sch_t *q, 
                     srslte_softbuffer_rx_t *softbuffer, srslte_cbsegm_t *cb_segm, 
                     uint32_t Qm, uint32_t rv, uint32_t nof_e_bits, 
                     float *e_bits, uint8_t *data) 
{
  uint8_t parity[24];
  uint8_t *p_parity = parity;
  uint32_t par_rx, par_tx;
  uint32_t i;
  uint32_t cb_len, rp, wp, rlen, F, n_e;
  
  if (q            != NULL && 
      data         != NULL &&       
      softbuffer   != NULL &&
      e_bits       != NULL &&
      cb_segm      != NULL)
  {

    if (cb_segm->tbs == 0 || cb_segm->C == 0) {
      return SRSLTE_SUCCESS;
    }
    
    rp = 0;
    rp = 0;
    wp = 0;
    uint32_t Gp = nof_e_bits / Qm;
    uint32_t gamma=Gp;

    if (cb_segm->C>0) {
      gamma = Gp%cb_segm->C;
    }
    
    bool early_stop = true;
    for (i = 0; i < cb_segm->C && early_stop; i++) {

      /* Get read/write 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;
      } else {
        rlen = cb_len - 24;
      }
      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);
      
      /* Rate Unmatching */
      if (srslte_rm_turbo_rx(softbuffer->buffer_f[i], softbuffer->buff_size,  
                  &e_bits[rp], n_e, 
                  (float*) q->cb_out, 3 * cb_len + 12, rv, F)) {
        fprintf(stderr, "Error in rate matching\n");
        return SRSLTE_ERROR;
      }

      if (SRSLTE_VERBOSE_ISDEBUG()) {
        DEBUG("CB#%d RMOUT: ", i);
        srslte_vec_fprint_f(stdout, q->cb_out, 3*cb_len+12);
      }

      /* Turbo Decoding with CRC-based early stopping */
      q->nof_iterations = 0; 
      uint32_t len_crc; 
      uint8_t *cb_in_ptr; 
      srslte_crc_t *crc_ptr; 
      early_stop = false; 

      srslte_tdec_reset(&q->decoder, cb_len);
            
      do {
        srslte_tdec_iteration(&q->decoder, (float*) q->cb_out, cb_len); 
        q->nof_iterations++;
        
        if (cb_segm->C > 1) {
          len_crc = cb_len; 
          cb_in_ptr = q->cb_in; 
          crc_ptr = &q->crc_cb; 
        } else {
          len_crc = cb_segm->tbs+24; 
          cb_in_ptr = &q->cb_in[F];
          crc_ptr = &q->crc_tb; 
        }

        srslte_tdec_decision(&q->decoder, q->cb_in, cb_len);
  
        /* Check Codeblock CRC and stop early if incorrect */
        if (!srslte_crc_checksum(crc_ptr, cb_in_ptr, len_crc)) {
          early_stop = true;           
        }
        
      } while (q->nof_iterations < SRSLTE_PDSCH_MAX_TDEC_ITERS && !early_stop);
      q->average_nof_iterations = SRSLTE_VEC_EMA((float) q->nof_iterations, q->average_nof_iterations, 0.2);

      if (SRSLTE_VERBOSE_ISDEBUG()) {
        DEBUG("CB#%d IN: ", i);
        srslte_vec_fprint_b(stdout, q->cb_in, cb_len);
      }
            
      // If CB CRC is not correct, early_stop will be false and wont continue with rest of CBs

      /* Copy data to another buffer, removing the Codeblock CRC */
      if (i < cb_segm->C - 1) {
        memcpy(&data[wp], &q->cb_in[F], (rlen - F) * sizeof(uint8_t));
      } else {
        DEBUG("Last CB, appending parity: %d to %d from %d and 24 from %d\n",
            rlen - F - 24, wp, F, rlen - 24);
        
        /* Append Transport Block parity bits to the last CB */
        memcpy(&data[wp], &q->cb_in[F], (rlen - F - 24) * sizeof(uint8_t));
        memcpy(parity, &q->cb_in[rlen - 24], 24 * sizeof(uint8_t));
      }

      /* Set read/write pointers */
      wp += (rlen - F);
      rp += n_e;
    }

    if (!early_stop) {
      INFO("CB %d failed. TB is erroneous.\n",i-1);
      return SRSLTE_ERROR; 
    } else {
      INFO("END CB#%d: wp: %d, rp: %d\n", i, wp, rp);

      // Compute transport block CRC
      par_rx = srslte_crc_checksum(&q->crc_tb, data, cb_segm->tbs);

      // check parity bits
      par_tx = srslte_bit_unpack(&p_parity, 24);

      if (!par_rx) {
        INFO("\n\tCAUTION!! Received all-zero transport block\n\n", 0);
      }

      if (par_rx == par_tx) {
        INFO("TB decoded OK\n",i);
        return SRSLTE_SUCCESS;
      } else {
        INFO("Error in TB parity\n",i);
        return SRSLTE_ERROR;
      }
      
    }
  } else {
    return SRSLTE_ERROR_INVALID_INPUTS;
  }
}
Exemple #2
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);
}