void srslte_pdsch_free(srslte_pdsch_t *q) { int i; if (q->e) { free(q->e); } if (q->d) { free(q->d); } for (i = 0; i < q->cell.nof_ports; i++) { if (q->ce[i]) { free(q->ce[i]); } if (q->x[i]) { free(q->x[i]); } if (q->symbols[i]) { free(q->symbols[i]); } } for (i = 0; i < SRSLTE_NSUBFRAMES_X_FRAME; i++) { srslte_sequence_free(&q->seq[i]); } for (i = 0; i < 4; i++) { srslte_modem_table_free(&q->mod[i]); } srslte_precoding_free(&q->precoding); srslte_sch_free(&q->dl_sch); bzero(q, sizeof(srslte_pdsch_t)); }
void srslte_pcfich_free(srslte_pcfich_t *q) { for (int ns = 0; ns < SRSLTE_NSUBFRAMES_X_FRAME; ns++) { srslte_sequence_free(&q->seq[ns]); } srslte_modem_table_free(&q->mod); bzero(q, sizeof(srslte_pcfich_t)); }
void srslte_pucch_free(srslte_pucch_t *q) { if (q->rnti_is_set) { for (uint32_t sf_idx=0;sf_idx<SRSLTE_NSUBFRAMES_X_FRAME;sf_idx++) { srslte_sequence_free(&q->seq_f2[sf_idx]); } } srslte_modem_table_free(&q->mod); bzero(q, sizeof(srslte_pucch_t)); }
void srslte_pdsch_free(srslte_pdsch_t *q) { for (int i = 0; i < SRSLTE_MAX_CODEWORDS; i++) { if (q->e[i]) { free(q->e[i]); } if (q->d[i]) { free(q->d[i]); } if (q->csi[i]) { free(q->csi[i]); } } /* Free sch objects */ srslte_sch_free(&q->dl_sch); for (int i = 0; i < SRSLTE_MAX_PORTS; i++) { if (q->x[i]) { free(q->x[i]); } if (q->symbols[i]) { free(q->symbols[i]); } if (q->is_ue) { for (int j = 0; j < SRSLTE_MAX_PORTS; j++) { if (q->ce[i][j]) { free(q->ce[i][j]); } } } } if (q->users) { if (q->is_ue) { srslte_pdsch_free_rnti(q, 0); } else { for (int u=0;u<=SRSLTE_SIRNTI;u++) { if (q->users[u]) { srslte_pdsch_free_rnti(q, u); } } } free(q->users); } srslte_sequence_free(&q->tmp_seq); for (int i = 0; i < 4; i++) { srslte_modem_table_free(&q->mod[i]); } bzero(q, sizeof(srslte_pdsch_t)); }
void srslte_pmch_free_area_id(srslte_pmch_t* q, uint16_t area_id) { if (q->seqs[area_id]) { for (int i = 0; i < SRSLTE_NSUBFRAMES_X_FRAME; i++) { srslte_sequence_free(&q->seqs[area_id]->seq[i]); } free(q->seqs[area_id]); q->seqs[area_id] = NULL; } }
void srslte_pdsch_free_rnti(srslte_pdsch_t* q, uint16_t rnti) { uint32_t rnti_idx = q->is_ue?0:rnti; if (q->users[rnti_idx]) { for (int i = 0; i < SRSLTE_NSUBFRAMES_X_FRAME; i++) { for (int j = 0; j < SRSLTE_MAX_CODEWORDS; j++) { srslte_sequence_free(&q->users[rnti_idx]->seq[j][i]); } } free(q->users[rnti_idx]); q->users[rnti_idx] = NULL; q->ue_rnti = 0; } }
/** Computes sequence-group pattern f_gh according to 5.5.1.3 of 36.211 */ int srslte_group_hopping_f_gh(uint32_t f_gh[SRSLTE_NSLOTS_X_FRAME], uint32_t cell_id) { srslte_sequence_t seq; bzero(&seq, sizeof(srslte_sequence_t)); if (srslte_sequence_LTE_pr(&seq, 160, cell_id / 30)) { return SRSLTE_ERROR; } for (uint32_t ns=0;ns<SRSLTE_NSLOTS_X_FRAME;ns++) { f_gh[ns] = 0; for (int i = 0; i < 8; i++) { f_gh[ns] += (((uint32_t) seq.c[8 * ns + i]) << i); } } srslte_sequence_free(&seq); return SRSLTE_SUCCESS; }
/* 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; }
int main(int argc, char **argv) { int i; srslte_sequence_t seq; uint8_t *input_b, *scrambled_b; float *input_f, *scrambled_f; struct timeval t[3]; parse_args(argc, argv); if (init_sequence(&seq, srslte_sequence_name) == -1) { fprintf(stderr, "Error initiating sequence %s\n", srslte_sequence_name); exit(-1); } if (!do_floats) { input_b = malloc(sizeof(uint8_t) * seq.len); if (!input_b) { perror("malloc"); exit(-1); } scrambled_b = malloc(sizeof(uint8_t) * seq.len); if (!scrambled_b) { perror("malloc"); exit(-1); } for (i=0;i<seq.len;i++) { input_b[i] = rand()%2; scrambled_b[i] = input_b[i]; } gettimeofday(&t[1], NULL); srslte_scrambling_b(&seq, scrambled_b); gettimeofday(&t[2], NULL); srslte_scrambling_b(&seq, scrambled_b); get_time_interval(t); printf("Texec=%d us for %d bits\n", t[0].tv_usec, seq.len); for (i=0;i<seq.len;i++) { if (scrambled_b[i] != input_b[i]) { printf("Error in %d\n", i); exit(-1); } } free(input_b); free(scrambled_b); } else { input_f = malloc(sizeof(float) * seq.len); if (!input_f) { perror("malloc"); exit(-1); } scrambled_f = malloc(sizeof(float) * seq.len); if (!scrambled_f) { perror("malloc"); exit(-1); } for (i=0;i<seq.len;i++) { input_f[i] = 100*(rand()/RAND_MAX); scrambled_f[i] = input_f[i]; } gettimeofday(&t[1], NULL); srslte_scrambling_f(&seq, scrambled_f); gettimeofday(&t[2], NULL); srslte_scrambling_f(&seq, scrambled_f); get_time_interval(t); printf("Texec=%d us for %d bits\n", t[0].tv_usec, seq.len); for (i=0;i<seq.len;i++) { if (scrambled_f[i] != input_f[i]) { printf("Error in %d\n", i); exit(-1); } } free(input_f); free(scrambled_f); } printf("Ok\n"); srslte_sequence_free(&seq); 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; }
/** 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; } }
void srslte_ra_ul_pusch_hopping_free(srslte_ra_ul_pusch_hopping_t* q) { srslte_sequence_free(&q->seq_type2_fo); }