static void pdsch_decode_debug(srslte_pdsch_t *q, srslte_pdsch_cfg_t *cfg, cf_t *sf_symbols[SRSLTE_MAX_PORTS], cf_t *ce[SRSLTE_MAX_PORTS][SRSLTE_MAX_PORTS]) { if (SRSLTE_VERBOSE_ISDEBUG()) { char filename[FILENAME_MAX]; for (int j = 0; j < q->nof_rx_antennas; j++) { if (snprintf(filename, FILENAME_MAX, "subframe_p%d.dat", j) < 0) { ERROR("Generating file name"); break; } DEBUG("SAVED FILE %s: received subframe symbols\n", filename); srslte_vec_save_file(filename, sf_symbols[j], SRSLTE_SF_LEN_RE(q->cell.nof_prb, q->cell.cp)*sizeof(cf_t)); for (int i = 0; i < q->cell.nof_ports; i++) { if (snprintf(filename, FILENAME_MAX, "hest_%d%d.dat", i, j) < 0) { ERROR("Generating file name"); break; } DEBUG("SAVED FILE %s: channel estimates for Tx %d and Rx %d\n", filename, j, i); srslte_vec_save_file(filename, ce[i][j], SRSLTE_SF_LEN_RE(q->cell.nof_prb, q->cell.cp)*sizeof(cf_t)); } } for (int i=0;i<cfg->nof_layers;i++) { if (snprintf(filename, FILENAME_MAX, "pdsch_symbols_%d.dat", i) < 0) { ERROR("Generating file name"); break; } DEBUG("SAVED FILE %s: symbols after equalization\n", filename); srslte_vec_save_file(filename, q->d[i], cfg->nbits[0].nof_re*sizeof(cf_t)); if (snprintf(filename, FILENAME_MAX, "llr_%d.dat", i) < 0) { ERROR("Generating file name"); break; } DEBUG("SAVED FILE %s: LLR estimates after demodulation and descrambling\n", filename); srslte_vec_save_file(filename, q->e[i], cfg->nbits[0].nof_bits*sizeof(int16_t)); } } }
void srslte_enb_dl_save_signal(srslte_enb_dl_t* q) { char tmpstr[64]; uint32_t tti = q->dl_sf.tti; snprintf(tmpstr, 64, "sf_symbols_%d", tti); srslte_vec_save_file(tmpstr, q->sf_symbols[0], SRSLTE_NOF_RE(q->cell) * sizeof(cf_t)); /* int cb_len = q->pdsch_cfg.cb_segm[0].K1; for (int i=0;i<q->pdsch_cfg.cb_segm[0].C;i++) { snprintf(tmpstr,64,"output/rmout_%d_%d",i,tti); srslte_bit_unpack_vector(softbuffer->buffer_b[i], q->tmp, (3*cb_len+12)); srslte_vec_save_file(tmpstr, q->tmp, (3*cb_len+12)*sizeof(uint8_t)); }*/ // printf("Saved files for tti=%d, sf=%d, cfi=%d, mcs=%d, tbs=%d, rv=%d, rnti=0x%x\n", tti, tti%10, cfi, // q->dci.mcs[0].idx, q->dci.mcs[0].tbs, rv_idx, rnti); }
/** Decodes the pmch from the received symbols */ int srslte_pmch_decode_multi(srslte_pmch_t *q, srslte_pdsch_cfg_t *cfg, srslte_softbuffer_rx_t *softbuffer, cf_t *sf_symbols[SRSLTE_MAX_PORTS], cf_t *ce[SRSLTE_MAX_PORTS][SRSLTE_MAX_PORTS], float noise_estimate, uint16_t area_id, 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 PMCH SF: %d, MBSFN area ID: 0x%x, Mod %s, TBS: %d, NofSymbols: %d, NofBitsE: %d, rv_idx: %d, C_prb=%d, cfi=%d\n", cfg->sf_idx, area_id, srslte_mod_string(cfg->grant.mcs[0].mod), cfg->grant.mcs[0].tbs, cfg->nbits[0].nof_re, cfg->nbits[0].nof_bits, 0, cfg->grant.nof_prb, cfg->nbits[0].lstart-1); /* 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)); for (int j=0;j<q->nof_rx_antennas;j++) { /* extract symbols */ n = srslte_pmch_get(q, sf_symbols[j], q->symbols[j], cfg->nbits[0].lstart); if (n != cfg->nbits[0].nof_re) { fprintf(stderr, "PMCH 1 extract symbols error expecting %d symbols but got %d, lstart %d\n", cfg->nbits[0].nof_re, n, cfg->nbits[0].lstart); return SRSLTE_ERROR; } /* extract channel estimates */ for (i = 0; i < q->cell.nof_ports; i++) { n = srslte_pmch_get(q, ce[i][j], q->ce[i][j], cfg->nbits[0].lstart); if (n != cfg->nbits[0].nof_re) { fprintf(stderr, "PMCH 2 extract chest error expecting %d symbols but got %d\n", cfg->nbits[0].nof_re, n); return SRSLTE_ERROR; } } } // No tx diversity in MBSFN srslte_predecoding_single_multi(q->symbols, q->ce[0], q->d, NULL, q->nof_rx_antennas, cfg->nbits[0].nof_re, 1.0f, noise_estimate); if (SRSLTE_VERBOSE_ISDEBUG()) { DEBUG("SAVED FILE subframe.dat: received subframe symbols\n"); srslte_vec_save_file("subframe.dat", sf_symbols, SRSLTE_SF_LEN_RE(q->cell.nof_prb, q->cell.cp)*sizeof(cf_t)); DEBUG("SAVED FILE hest0.dat: channel estimates for port 4\n"); srslte_vec_save_file("hest0.dat", ce[0], SRSLTE_SF_LEN_RE(q->cell.nof_prb, q->cell.cp)*sizeof(cf_t)); DEBUG("SAVED FILE pmch_symbols.dat: symbols after equalization\n"); srslte_vec_save_file("pmch_symbols.bin", q->d, cfg->nbits[0].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 thde LLRs normalization */ srslte_demod_soft_demodulate_s(cfg->grant.mcs[0].mod, q->d, q->e, cfg->nbits[0].nof_re); /* descramble */ srslte_scrambling_s_offset(&q->seqs[area_id]->seq[cfg->sf_idx], q->e, 0, cfg->nbits[0].nof_bits); if (SRSLTE_VERBOSE_ISDEBUG()) { DEBUG("SAVED FILE llr.dat: LLR estimates after demodulation and descrambling\n"); srslte_vec_save_file("llr.dat", q->e, cfg->nbits[0].nof_bits*sizeof(int16_t)); } return srslte_dlsch_decode(&q->dl_sch, cfg, softbuffer, q->e, data); } else { return SRSLTE_ERROR_INVALID_INPUTS; } }
/** 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; } }
int main(int argc, char **argv) { parse_args(argc, argv); uint32_t flen = srslte_sampling_freq_hz(nof_prb)/1000; cf_t *rx_buffer = malloc(sizeof(cf_t)*flen*nof_frames); if (!rx_buffer) { perror("malloc"); exit(-1); } cf_t *tx_buffer = malloc(sizeof(cf_t)*(flen+time_adv_samples)); if (!tx_buffer) { perror("malloc"); exit(-1); } bzero(tx_buffer, sizeof(cf_t)*(flen+time_adv_samples)); cf_t *zeros = calloc(sizeof(cf_t),flen); if (!zeros) { perror("calloc"); exit(-1); } float time_adv_sec = (float) time_adv_samples/srslte_sampling_freq_hz(nof_prb); // Send through RF srslte_rf_t rf; printf("Opening RF device...\n"); if (srslte_rf_open(&rf, rf_args)) { fprintf(stderr, "Error opening rf\n"); exit(-1); } srslte_rf_set_master_clock_rate(&rf, 30.72e6); int srate = srslte_sampling_freq_hz(nof_prb); if (srate < 10e6) { srslte_rf_set_master_clock_rate(&rf, 4*srate); } else { srslte_rf_set_master_clock_rate(&rf, srate); } srslte_rf_set_rx_srate(&rf, (double) srate); srslte_rf_set_tx_srate(&rf, (double) srate); printf("Subframe len: %d samples\n", flen); printf("Time advance: %f us\n",time_adv_sec*1e6); printf("Set TX/RX rate: %.2f MHz\n", (float) srate / 1000000); printf("Set RX gain: %.1f dB\n", srslte_rf_set_rx_gain(&rf, rf_rx_gain)); printf("Set TX gain: %.1f dB\n", srslte_rf_set_tx_gain(&rf, srslte_rf_tx_gain)); printf("Set TX/RX freq: %.2f MHz\n", srslte_rf_set_rx_freq(&rf, rf_freq) / 1000000); srslte_rf_set_tx_freq(&rf, rf_freq); sleep(1); if (input_filename) { srslte_vec_load_file(input_filename, &tx_buffer[time_adv_samples], flen*sizeof(cf_t)); } else { for (int i=0;i<flen-time_adv_samples;i++) { tx_buffer[i+time_adv_samples] = 0.3*cexpf(_Complex_I*2*M_PI*tone_offset_hz*((float) i/(float) srate)); } srslte_vec_save_file("srslte_rf_txrx_tone", tx_buffer, flen*sizeof(cf_t)); } srslte_timestamp_t tstamp; srslte_rf_start_rx_stream(&rf); uint32_t nframe=0; while(nframe<nof_frames) { printf("Rx subframe %d\n", nframe); srslte_rf_recv_with_time(&rf, &rx_buffer[flen*nframe], flen, true, &tstamp.full_secs, &tstamp.frac_secs); nframe++; if (nframe==9) { srslte_timestamp_add(&tstamp, 0, 2e-3-time_adv_sec); srslte_rf_send_timed2(&rf, tx_buffer, flen+time_adv_samples, tstamp.full_secs, tstamp.frac_secs, true, true); printf("Transmitting Signal\n"); } } srslte_vec_save_file(output_filename, &rx_buffer[10*flen], flen*sizeof(cf_t)); free(tx_buffer); free(rx_buffer); printf("Done\n"); exit(0); }
int main(int argc, char **argv) { parse_args(argc, argv); srslte_prach_t *p = (srslte_prach_t*)malloc(sizeof(srslte_prach_t)); bool high_speed_flag = false; cf_t preamble[MAX_LEN]; memset(preamble, 0, sizeof(cf_t)*MAX_LEN); srslte_prach_init(p, srslte_symbol_sz(nof_prb), preamble_format, root_seq_idx, high_speed_flag, zero_corr_zone); uint32_t flen = srslte_sampling_freq_hz(nof_prb)/1000; printf("Generating PRACH\n"); bzero(preamble, flen*sizeof(cf_t)); srslte_prach_gen(p, seq_idx, frequency_offset, preamble); uint32_t prach_len = p->N_seq; srslte_vec_save_file("generated",preamble,prach_len*sizeof(cf_t)); cf_t *buffer = malloc(sizeof(cf_t)*flen*nof_frames); // Send through UHD void *uhd; printf("Opening UHD device...\n"); if (cuhd_open(uhd_args, &uhd)) { fprintf(stderr, "Error opening uhd\n"); exit(-1); } printf("Subframe len: %d samples\n", flen); printf("Set TX/RX rate: %.2f MHz\n", cuhd_set_rx_srate(uhd, srslte_sampling_freq_hz(nof_prb)) / 1000000); printf("Set RX gain: %.1f dB\n", cuhd_set_rx_gain(uhd, uhd_gain)); printf("Set TX gain: %.1f dB\n", cuhd_set_tx_gain(uhd, uhd_gain)); printf("Set TX/RX freq: %.2f MHz\n", cuhd_set_rx_freq(uhd, uhd_freq) / 1000000); cuhd_set_tx_srate(uhd, srslte_sampling_freq_hz(nof_prb)); cuhd_set_tx_freq_offset(uhd, uhd_freq, 8e6); sleep(1); cf_t *zeros = calloc(sizeof(cf_t),flen); FILE *f = NULL; if (output_filename) { f = fopen(output_filename, "w"); } srslte_timestamp_t tstamp; cuhd_start_rx_stream(uhd); uint32_t nframe=0; while(nframe<nof_frames) { printf("Rx subframe %d\n", nframe); cuhd_recv_with_time(uhd, &buffer[flen*nframe], flen, true, &tstamp.full_secs, &tstamp.frac_secs); nframe++; if (nframe==9 || nframe==8) { srslte_timestamp_add(&tstamp, 0, 2e-3); if (nframe==8) { cuhd_send_timed2(uhd, zeros, flen, tstamp.full_secs, tstamp.frac_secs, true, false); printf("Transmitting zeros\n"); } else { cuhd_send_timed2(uhd, preamble, flen, tstamp.full_secs, tstamp.frac_secs, true, true); printf("Transmitting PRACH\n"); } } } if (f) { fwrite(&buffer[10*flen], flen*sizeof(cf_t), 1, f); } if (f) { fclose(f); } srslte_prach_free(p); free(p); printf("Done\n"); exit(0); }
void srslte_ue_dl_save_signal(srslte_ue_dl_t* q, srslte_dl_sf_cfg_t* sf, srslte_pdsch_cfg_t* pdsch_cfg) { uint32_t cfi = sf->cfi; uint32_t tti = sf->tti % 10; srslte_vec_save_file("sf_symbols", q->sf_symbols, SRSLTE_NOF_RE(q->cell) * sizeof(cf_t)); printf("%d samples\n", SRSLTE_NOF_RE(q->cell)); srslte_vec_save_file("ce0", q->chest_res.ce[0], SRSLTE_NOF_RE(q->cell) * sizeof(cf_t)); if (q->cell.nof_ports > 1) { srslte_vec_save_file("ce1", q->chest_res.ce[1], SRSLTE_NOF_RE(q->cell) * sizeof(cf_t)); } srslte_vec_save_file("pcfich_ce0", q->pcfich.ce[0], q->pcfich.nof_symbols * sizeof(cf_t)); srslte_vec_save_file("pcfich_ce1", q->pcfich.ce[1], q->pcfich.nof_symbols * sizeof(cf_t)); srslte_vec_save_file("pcfich_symbols", q->pcfich.symbols[0], q->pcfich.nof_symbols * sizeof(cf_t)); srslte_vec_save_file("pcfich_eq_symbols", q->pcfich.d, q->pcfich.nof_symbols * sizeof(cf_t)); srslte_vec_save_file("pcfich_llr", q->pcfich.data_f, PCFICH_CFI_LEN * sizeof(float)); srslte_vec_save_file("pdcch_ce0", q->pdcch.ce[0], q->pdcch.nof_cce[cfi - 1] * 36 * sizeof(cf_t)); srslte_vec_save_file("pdcch_ce1", q->pdcch.ce[1], q->pdcch.nof_cce[cfi - 1] * 36 * sizeof(cf_t)); srslte_vec_save_file("pdcch_symbols", q->pdcch.symbols[0], q->pdcch.nof_cce[cfi - 1] * 36 * sizeof(cf_t)); srslte_vec_save_file("pdcch_eq_symbols", q->pdcch.d, q->pdcch.nof_cce[cfi - 1] * 36 * sizeof(cf_t)); srslte_vec_save_file("pdcch_llr", q->pdcch.llr, q->pdcch.nof_cce[cfi - 1] * 72 * sizeof(float)); srslte_vec_save_file("pdsch_symbols", q->pdsch.d[0], pdsch_cfg->grant.nof_re * sizeof(cf_t)); srslte_vec_save_file("llr", q->pdsch.e[0], pdsch_cfg->grant.tb[0].nof_bits * sizeof(cf_t)); printf("Saved files for tti=%d, sf=%d, cfi=%d, tbs=%d, rv=%d\n", tti, tti % 10, cfi, pdsch_cfg->grant.tb[0].tbs, pdsch_cfg->grant.tb[0].rv); }
void srslte_ue_dl_save_signal(srslte_ue_dl_t *q, srslte_softbuffer_rx_t *softbuffer, uint32_t tti, uint32_t rv_idx) { srslte_vec_save_file("sf_symbols", q->sf_symbols, SRSLTE_SF_LEN_RE(q->cell.nof_prb, q->cell.cp)*sizeof(cf_t)); printf("%d samples\n", SRSLTE_SF_LEN_RE(q->cell.nof_prb, q->cell.cp)); srslte_vec_save_file("ce0", q->ce[0], SRSLTE_SF_LEN_RE(q->cell.nof_prb, q->cell.cp)*sizeof(cf_t)); if (q->cell.nof_ports > 1) { srslte_vec_save_file("ce1", q->ce[1], SRSLTE_SF_LEN_RE(q->cell.nof_prb, q->cell.cp)*sizeof(cf_t)); } srslte_vec_save_file("pcfich_ce0", q->pcfich.ce[0], q->pcfich.nof_symbols*sizeof(cf_t)); srslte_vec_save_file("pcfich_ce1", q->pcfich.ce[1], q->pcfich.nof_symbols*sizeof(cf_t)); srslte_vec_save_file("pcfich_symbols", q->pcfich.symbols[0], q->pcfich.nof_symbols*sizeof(cf_t)); srslte_vec_save_file("pcfich_eq_symbols", q->pcfich.d, q->pcfich.nof_symbols*sizeof(cf_t)); srslte_vec_save_file("pcfich_llr", q->pcfich.data_f, PCFICH_CFI_LEN*sizeof(float)); srslte_vec_save_file("pdcch_ce0", q->pdcch.ce[0], q->pdcch.nof_cce*36*sizeof(cf_t)); srslte_vec_save_file("pdcch_ce1", q->pdcch.ce[1], q->pdcch.nof_cce*36*sizeof(cf_t)); srslte_vec_save_file("pdcch_symbols", q->pdcch.symbols[0], q->pdcch.nof_cce*36*sizeof(cf_t)); srslte_vec_save_file("pdcch_eq_symbols", q->pdcch.d, q->pdcch.nof_cce*36*sizeof(cf_t)); srslte_vec_save_file("pdcch_llr", q->pdcch.llr, q->pdcch.nof_cce*72*sizeof(float)); srslte_vec_save_file("pdsch_symbols", q->pdsch.d, q->pdsch_cfg.nbits.nof_re*sizeof(cf_t)); srslte_vec_save_file("llr", q->pdsch.e, q->pdsch_cfg.nbits.nof_bits*sizeof(cf_t)); int cb_len = q->pdsch_cfg.cb_segm.K1; for (int i=0;i<q->pdsch_cfg.cb_segm.C;i++) { char tmpstr[64]; snprintf(tmpstr,64,"rmout_%d.dat",i); srslte_vec_save_file(tmpstr, softbuffer->buffer_f[i], (3*cb_len+12)*sizeof(int16_t)); } printf("Saved files for tti=%d, sf=%d, cfi=%d, mcs=%d, rv=%d, rnti=%d\n", tti, tti%10, q->cfi, q->pdsch_cfg.grant.mcs.idx, rv_idx, q->current_rnti); }