static int srslte_pdsch_codeword_encode(srslte_pdsch_t *q, srslte_pdsch_cfg_t *cfg, srslte_softbuffer_tx_t *softbuffer, uint16_t rnti, uint8_t *data, uint32_t codeword_idx, uint32_t tb_idx) { srslte_ra_nbits_t *nbits = &cfg->nbits[tb_idx]; srslte_ra_mcs_t *mcs = &cfg->grant.mcs[tb_idx]; uint32_t rv = cfg->rv[tb_idx]; bool valid_inputs = true; if (!softbuffer) { ERROR("Error encoding (TB%d -> CW%d), softbuffer=NULL", tb_idx, codeword_idx); valid_inputs = false; } if (nbits->nof_bits && valid_inputs) { INFO("Encoding PDSCH SF: %d (TB%d -> CW%d), Mod %s, NofBits: %d, NofSymbols: %d, NofBitsE: %d, rv_idx: %d\n", cfg->sf_idx, tb_idx, codeword_idx, srslte_mod_string(mcs->mod), mcs->tbs, nbits->nof_re, nbits->nof_bits, rv); /* Channel coding */ if (srslte_dlsch_encode2(&q->dl_sch, cfg, softbuffer, data, q->e[codeword_idx], tb_idx)) { ERROR("Error encoding (TB%d -> CW%d)", tb_idx, codeword_idx); return SRSLTE_ERROR; } /* Select scrambling sequence */ srslte_sequence_t *seq = get_user_sequence(q, rnti, codeword_idx, cfg->sf_idx, nbits->nof_bits); /* Bit scrambling */ srslte_scrambling_bytes(seq, (uint8_t *) q->e[codeword_idx], nbits->nof_bits); /* Bit mapping */ srslte_mod_modulate_bytes(&q->mod[mcs->mod], (uint8_t *) q->e[codeword_idx], q->d[codeword_idx], nbits->nof_bits); } else { return SRSLTE_ERROR_INVALID_INPUTS; } return SRSLTE_SUCCESS; }
int srslte_pmch_encode(srslte_pmch_t *q, srslte_pdsch_cfg_t *cfg, srslte_softbuffer_tx_t *softbuffer, uint8_t *data, uint16_t area_id, cf_t *sf_symbols[SRSLTE_MAX_PORTS]) { int i; /* Set pointers for layermapping & precoding */ cf_t *x[SRSLTE_MAX_LAYERS]; int ret = SRSLTE_ERROR_INVALID_INPUTS; if (q != NULL && cfg != NULL) { for (i=0;i<q->cell.nof_ports;i++) { if (sf_symbols[i] == NULL) { return SRSLTE_ERROR_INVALID_INPUTS; } } if (cfg->grant.mcs[0].tbs == 0) { return SRSLTE_ERROR_INVALID_INPUTS; } if (cfg->nbits[0].nof_re > q->max_re) { fprintf(stderr, "Error too many RE per subframe (%d). PMCH configured for %d RE (%d PRB)\n", cfg->nbits[0].nof_re, q->max_re, q->cell.nof_prb); return SRSLTE_ERROR_INVALID_INPUTS; } INFO("Encoding PMCH SF: %d, Mod %s, NofBits: %d, NofSymbols: %d, NofBitsE: %d, rv_idx: %d\n", cfg->sf_idx, srslte_mod_string(cfg->grant.mcs[0].mod), cfg->grant.mcs[0].tbs, cfg->nbits[0].nof_re, cfg->nbits[0].nof_bits, 0); /* 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)); // TODO: use tb_encode directly if (srslte_dlsch_encode(&q->dl_sch, cfg, softbuffer, data, q->e)) { fprintf(stderr, "Error encoding TB\n"); return SRSLTE_ERROR; } /* scramble */ srslte_scrambling_bytes(&q->seqs[area_id]->seq[cfg->sf_idx], (uint8_t*) q->e, cfg->nbits[0].nof_bits); srslte_mod_modulate_bytes(&q->mod[cfg->grant.mcs[0].mod], (uint8_t*) q->e, q->d, cfg->nbits[0].nof_bits); /* No tx diversity in MBSFN */ memcpy(q->symbols[0], q->d, cfg->nbits[0].nof_re * sizeof(cf_t)); /* mapping to resource elements */ for (i = 0; i < q->cell.nof_ports; i++) { srslte_pmch_put(q, q->symbols[i], sf_symbols[i], cfg->nbits[0].lstart); } ret = SRSLTE_SUCCESS; } return ret; }
int main(int argc, char **argv) { int i; srslte_modem_table_t mod; uint8_t *input, *input_bytes, *output; cf_t *symbols, *symbols_bytes; float *llr, *llr2; parse_args(argc, argv); /* initialize objects */ if (srslte_modem_table_lte(&mod, modulation)) { fprintf(stderr, "Error initializing modem table\n"); exit(-1); } srslte_modem_table_bytes(&mod); /* check that num_bits is multiple of num_bits x symbol */ if (num_bits % mod.nbits_x_symbol) { fprintf(stderr, "Error num_bits must be multiple of %d\n", mod.nbits_x_symbol); exit(-1); } /* allocate buffers */ input = srslte_vec_malloc(sizeof(uint8_t) * num_bits); if (!input) { perror("malloc"); exit(-1); } input_bytes = srslte_vec_malloc(sizeof(uint8_t) * num_bits/8); if (!input_bytes) { perror("malloc"); exit(-1); } output = srslte_vec_malloc(sizeof(uint8_t) * num_bits); if (!output) { perror("malloc"); exit(-1); } symbols = srslte_vec_malloc(sizeof(cf_t) * num_bits / mod.nbits_x_symbol); if (!symbols) { perror("malloc"); exit(-1); } symbols_bytes = srslte_vec_malloc(sizeof(cf_t) * num_bits / mod.nbits_x_symbol); if (!symbols_bytes) { perror("malloc"); exit(-1); } llr = srslte_vec_malloc(sizeof(float) * num_bits); if (!llr) { perror("malloc"); exit(-1); } llr2 = srslte_vec_malloc(sizeof(float) * num_bits); if (!llr2) { perror("malloc"); exit(-1); } /* generate random data */ for (i=0;i<num_bits;i++) { input[i] = rand()%2; } /* modulate */ struct timeval t[3]; gettimeofday(&t[1], NULL); int ntrials = 100; for (int i=0;i<ntrials;i++) { srslte_mod_modulate(&mod, input, symbols, num_bits); } gettimeofday(&t[2], NULL); get_time_interval(t); printf("Bit: %d us\n", t[0].tv_usec); /* Test packed implementation */ srslte_bit_pack_vector(input, input_bytes, num_bits); gettimeofday(&t[1], NULL); for (int i=0;i<ntrials;i++) { srslte_mod_modulate_bytes(&mod, input_bytes, symbols_bytes, num_bits); } gettimeofday(&t[2], NULL); get_time_interval(t); printf("Byte: %d us\n", t[0].tv_usec); for (int i=0;i<num_bits/mod.nbits_x_symbol;i++) { if (symbols[i] != symbols_bytes[i]) { printf("error in symbol %d\n", i); exit(-1); } } printf("Symbols OK\n"); /* demodulate */ gettimeofday(&x, NULL); srslte_demod_soft_demodulate(modulation, symbols, llr, num_bits / mod.nbits_x_symbol); gettimeofday(&y, NULL); printf("\nElapsed time [ns]: %d\n", (int) y.tv_usec - (int) x.tv_usec); for (i=0;i<num_bits;i++) { output[i] = llr[i]>=0 ? 1 : 0; } /* check errors */ for (i=0;i<num_bits;i++) { if (input[i] != output[i]) { fprintf(stderr, "Error in bit %d\n", i); exit(-1); } } free(llr); free(symbols); free(symbols_bytes); free(output); free(input); free(input_bytes); srslte_modem_table_free(&mod); printf("Ok\n"); exit(0); }
/** Converts the PDSCH data bits to symbols mapped to the slot ready for transmission */ int srslte_pdsch_encode_rnti(srslte_pdsch_t *q, srslte_pdsch_cfg_t *cfg, srslte_softbuffer_tx_t *softbuffer, uint8_t *data, uint16_t rnti, cf_t *sf_symbols[SRSLTE_MAX_PORTS]) { int i; /* Set pointers for layermapping & precoding */ cf_t *x[SRSLTE_MAX_LAYERS]; int ret = SRSLTE_ERROR_INVALID_INPUTS; if (q != NULL && data != NULL && cfg != NULL) { for (i=0; i<q->cell.nof_ports; i++) { if (sf_symbols[i] == NULL) { return SRSLTE_ERROR_INVALID_INPUTS; } } if (cfg->grant.mcs.tbs == 0) { return SRSLTE_ERROR_INVALID_INPUTS; } if (cfg->nbits.nof_re > q->max_re) { fprintf(stderr, "Error too many RE per subframe (%d). PDSCH configured for %d RE (%d PRB)\n", cfg->nbits.nof_re, q->max_re, q->cell.nof_prb); return SRSLTE_ERROR_INVALID_INPUTS; } INFO("Encoding PDSCH SF: %d, Mod %s, NofBits: %d, NofSymbols: %d, NofBitsE: %d, rv_idx: %d\n", cfg->sf_idx, srslte_mod_string(cfg->grant.mcs.mod), cfg->grant.mcs.tbs, cfg->nbits.nof_re, cfg->nbits.nof_bits, cfg->rv); /* 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)); if (srslte_dlsch_encode(&q->dl_sch, cfg, softbuffer, data, q->e)) { fprintf(stderr, "Error encoding TB\n"); return SRSLTE_ERROR; } 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_bytes_offset(&seq, (uint8_t*) q->e, 0, cfg->nbits.nof_bits); srslte_sequence_free(&seq); } else { srslte_scrambling_bytes_offset(&q->seq[cfg->sf_idx], (uint8_t*) q->e, 0, cfg->nbits.nof_bits); } srslte_mod_modulate_bytes(&q->mod[cfg->grant.mcs.mod], (uint8_t*) q->e, q->d, cfg->nbits.nof_bits); /* TODO: only diversity supported */ if (q->cell.nof_ports > 1) { srslte_layermap_diversity(q->d, x, q->cell.nof_ports, cfg->nbits.nof_re); srslte_precoding_diversity(&q->precoding, x, q->symbols, q->cell.nof_ports, cfg->nbits.nof_re / q->cell.nof_ports); } else { memcpy(q->symbols[0], q->d, cfg->nbits.nof_re * sizeof(cf_t)); } /* mapping to resource elements */ for (i = 0; i < q->cell.nof_ports; i++) { srslte_pdsch_put(q, q->symbols[i], sf_symbols[i], &cfg->grant, cfg->nbits.lstart, cfg->sf_idx); } ret = SRSLTE_SUCCESS; } return ret; }