/** This function is simply a wrapper to the ue_cell_search module for rf devices * Return 1 if the MIB is decoded, 0 if not or -1 on error. */ int rf_mib_decoder(srslte_rf_t *rf, uint32_t nof_rx_antennas,cell_search_cfg_t *config, srslte_cell_t *cell, float *cfo) { int ret = SRSLTE_ERROR; srslte_ue_mib_sync_t ue_mib; uint8_t bch_payload[SRSLTE_BCH_PAYLOAD_LEN]; if (srslte_ue_mib_sync_init_multi(&ue_mib, srslte_rf_recv_wrapper_cs, nof_rx_antennas, (void*) rf)) { fprintf(stderr, "Error initiating srslte_ue_mib_sync\n"); goto clean_exit; } if (srslte_ue_mib_sync_set_cell(&ue_mib, cell->id, cell->cp)) { fprintf(stderr, "Error initiating srslte_ue_mib_sync\n"); goto clean_exit; } int srate = srslte_sampling_freq_hz(SRSLTE_UE_MIB_NOF_PRB); INFO("Setting sampling frequency %.2f MHz for PSS search\n", (float) srate/1000000); srslte_rf_set_rx_srate(rf, (float) srate); INFO("Starting receiver...\n"); srslte_rf_start_rx_stream(rf, false); // Copy CFO estimate if provided and disable CP estimation during find if (cfo) { ue_mib.ue_sync.cfo_current_value = *cfo/15000; ue_mib.ue_sync.cfo_is_copied = true; ue_mib.ue_sync.cfo_correct_enable_find = true; srslte_sync_set_cfo_cp_enable(&ue_mib.ue_sync.sfind, false, 0); } /* Find and decode MIB */ ret = srslte_ue_mib_sync_decode(&ue_mib, config->max_frames_pbch, bch_payload, &cell->nof_ports, NULL); if (ret < 0) { fprintf(stderr, "Error decoding MIB\n"); goto clean_exit; } if (ret == 1) { srslte_pbch_mib_unpack(bch_payload, cell, NULL); } // Save CFO if (cfo) { *cfo = srslte_ue_sync_get_cfo(&ue_mib.ue_sync); } clean_exit: srslte_rf_stop_rx_stream(rf); srslte_ue_mib_sync_free(&ue_mib); return ret; }
int rf_rssi_scan(srslte_rf_t *rf, float *freqs, float *rssi, int nof_bands, double fs, int nsamp) { int i, j; int ret = -1; cf_t *buffer; double f; buffer = calloc(nsamp, sizeof(cf_t)); if (!buffer) { goto free_and_exit; } srslte_rf_set_rx_gain(rf, 20.0); srslte_rf_set_rx_srate(rf, fs); for (i=0;i<nof_bands;i++) { srslte_rf_stop_rx_stream(rf); f = (double) freqs[i]; srslte_rf_set_rx_freq(rf, f); srslte_rf_rx_wait_lo_locked(rf); usleep(10000); srslte_rf_start_rx_stream(rf, false); /* discard first samples */ for (j=0;j<2;j++) { if (srslte_rf_recv(rf, buffer, nsamp, 1) != nsamp) { goto free_and_exit; } } rssi[i] = srslte_vec_avg_power_cf(buffer, nsamp); printf("[%3d]: Freq %4.1f Mhz - RSSI: %3.2f dBm\r", i, f/1000000, 10*log10f(rssi[i]) + 30); fflush(stdout); if (SRSLTE_VERBOSE_ISINFO()) { printf("\n"); } } srslte_rf_stop_rx_stream(rf); ret = 0; free_and_exit: free(buffer); return ret; }
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); }
/** This function is simply a wrapper to the ue_cell_search module for rf devices */ int rf_cell_search(srslte_rf_t *rf, uint32_t nof_rx_antennas, cell_search_cfg_t *config, int force_N_id_2, srslte_cell_t *cell, float *cfo) { int ret = SRSLTE_ERROR; srslte_ue_cellsearch_t cs; srslte_ue_cellsearch_result_t found_cells[3]; bzero(found_cells, 3*sizeof(srslte_ue_cellsearch_result_t)); if (srslte_ue_cellsearch_init_multi(&cs, config->max_frames_pss, srslte_rf_recv_wrapper_cs, nof_rx_antennas, (void*) rf)) { fprintf(stderr, "Error initiating UE cell detect\n"); return SRSLTE_ERROR; } if (config->nof_valid_pss_frames) { srslte_ue_cellsearch_set_nof_valid_frames(&cs, config->nof_valid_pss_frames); } INFO("Setting sampling frequency %.2f MHz for PSS search\n", SRSLTE_CS_SAMP_FREQ/1000000); srslte_rf_set_rx_srate(rf, SRSLTE_CS_SAMP_FREQ); INFO("Starting receiver...\n"); srslte_rf_start_rx_stream(rf, false); /* Find a cell in the given N_id_2 or go through the 3 of them to find the strongest */ uint32_t max_peak_cell = 0; if (force_N_id_2 >= 0) { ret = srslte_ue_cellsearch_scan_N_id_2(&cs, force_N_id_2, &found_cells[force_N_id_2]); max_peak_cell = force_N_id_2; } else { ret = srslte_ue_cellsearch_scan(&cs, found_cells, &max_peak_cell); } if (ret < 0) { srslte_rf_stop_rx_stream(rf); fprintf(stderr, "Error searching cell\n"); return SRSLTE_ERROR; } else if (ret == 0) { srslte_rf_stop_rx_stream(rf); fprintf(stderr, "Could not find any cell in this frequency\n"); return SRSLTE_SUCCESS; } for (int i=0;i<3;i++) { if (i == max_peak_cell) { printf("*"); } else { printf(" "); } printf("Found Cell_id: %3d CP: %s, DetectRatio=%2.0f%% PSR=%.2f, Power=%.1f dBm\n", found_cells[i].cell_id, srslte_cp_string(found_cells[i].cp), found_cells[i].mode*100, found_cells[i].psr, 20*log10(found_cells[i].peak*1000)); } // Save result if (cell) { cell->id = found_cells[max_peak_cell].cell_id; cell->cp = found_cells[max_peak_cell].cp; } // Save CFO if (cfo) { *cfo = found_cells[max_peak_cell].cfo; } srslte_rf_stop_rx_stream(rf); srslte_ue_cellsearch_free(&cs); return ret; }
int main(int argc, char **argv) { int ret; cf_t *sf_buffer; prog_args_t prog_args; srslte_cell_t cell; int64_t sf_cnt; srslte_ue_sync_t ue_sync; srslte_ue_mib_t ue_mib; srslte_rf_t rf; srslte_ue_dl_t ue_dl; srslte_ofdm_t fft; srslte_chest_dl_t chest; uint32_t nframes=0; uint32_t nof_trials = 0; uint32_t sfn = 0; // system frame number int n; uint8_t bch_payload[SRSLTE_BCH_PAYLOAD_LEN]; uint32_t sfn_offset; float rssi_utra=0,rssi=0, rsrp=0, rsrq=0, snr=0; cf_t *ce[SRSLTE_MAX_PORTS]; if (parse_args(&prog_args, argc, argv)) { exit(-1); } printf("Opening RF device...\n"); if (srslte_rf_open(&rf, prog_args.rf_args)) { fprintf(stderr, "Error opening rf\n"); exit(-1); } if (prog_args.rf_gain > 0) { srslte_rf_set_rx_gain(&rf, prog_args.rf_gain); } else { printf("Starting AGC thread...\n"); if (srslte_rf_start_gain_thread(&rf, false)) { fprintf(stderr, "Error opening rf\n"); exit(-1); } srslte_rf_set_rx_gain(&rf, 50); } sigset_t sigset; sigemptyset(&sigset); sigaddset(&sigset, SIGINT); sigprocmask(SIG_UNBLOCK, &sigset, NULL); signal(SIGINT, sig_int_handler); srslte_rf_set_master_clock_rate(&rf, 30.72e6); /* set receiver frequency */ srslte_rf_set_rx_freq(&rf, (double) prog_args.rf_freq); srslte_rf_rx_wait_lo_locked(&rf); printf("Tunning receiver to %.3f MHz\n", (double ) prog_args.rf_freq/1000000); cell_detect_config.init_agc = (prog_args.rf_gain<0); uint32_t ntrial=0; do { ret = rf_search_and_decode_mib(&rf, &cell_detect_config, prog_args.force_N_id_2, &cell); if (ret < 0) { fprintf(stderr, "Error searching for cell\n"); exit(-1); } else if (ret == 0 && !go_exit) { printf("Cell not found after %d trials. Trying again (Press Ctrl+C to exit)\n", ntrial++); } } while (ret == 0 && !go_exit); if (go_exit) { exit(0); } /* set sampling frequency */ int srate = srslte_sampling_freq_hz(cell.nof_prb); if (srate != -1) { if (srate < 10e6) { srslte_rf_set_master_clock_rate(&rf, 4*srate); } else { srslte_rf_set_master_clock_rate(&rf, srate); } printf("Setting sampling rate %.2f MHz\n", (float) srate/1000000); float srate_rf = srslte_rf_set_rx_srate(&rf, (double) srate); if (srate_rf != srate) { fprintf(stderr, "Could not set sampling rate\n"); exit(-1); } } else { fprintf(stderr, "Invalid number of PRB %d\n", cell.nof_prb); exit(-1); } INFO("Stopping RF and flushing buffer...\n",0); srslte_rf_stop_rx_stream(&rf); srslte_rf_flush_buffer(&rf); if (srslte_ue_sync_init(&ue_sync, cell, srslte_rf_recv_wrapper, (void*) &rf)) { fprintf(stderr, "Error initiating ue_sync\n"); return -1; } if (srslte_ue_dl_init(&ue_dl, cell)) { fprintf(stderr, "Error initiating UE downlink processing module\n"); return -1; } if (srslte_ue_mib_init(&ue_mib, cell)) { fprintf(stderr, "Error initaiting UE MIB decoder\n"); return -1; } /* Configure downlink receiver for the SI-RNTI since will be the only one we'll use */ srslte_ue_dl_set_rnti(&ue_dl, SRSLTE_SIRNTI); /* Initialize subframe counter */ sf_cnt = 0; if (srslte_ofdm_rx_init(&fft, cell.cp, cell.nof_prb)) { fprintf(stderr, "Error initiating FFT\n"); return -1; } if (srslte_chest_dl_init(&chest, cell)) { fprintf(stderr, "Error initiating channel estimator\n"); return -1; } int sf_re = SRSLTE_SF_LEN_RE(cell.nof_prb, cell.cp); cf_t *sf_symbols = srslte_vec_malloc(sf_re * sizeof(cf_t)); for (int i=0;i<SRSLTE_MAX_PORTS;i++) { ce[i] = srslte_vec_malloc(sizeof(cf_t) * sf_re); } srslte_rf_start_rx_stream(&rf); float rx_gain_offset = 0; /* Main loop */ while ((sf_cnt < prog_args.nof_subframes || prog_args.nof_subframes == -1) && !go_exit) { ret = srslte_ue_sync_get_buffer(&ue_sync, &sf_buffer); if (ret < 0) { fprintf(stderr, "Error calling srslte_ue_sync_work()\n"); } /* srslte_ue_sync_get_buffer returns 1 if successfully read 1 aligned subframe */ if (ret == 1) { switch (state) { case DECODE_MIB: if (srslte_ue_sync_get_sfidx(&ue_sync) == 0) { srslte_pbch_decode_reset(&ue_mib.pbch); n = srslte_ue_mib_decode(&ue_mib, sf_buffer, bch_payload, NULL, &sfn_offset); if (n < 0) { fprintf(stderr, "Error decoding UE MIB\n"); return -1; } else if (n == SRSLTE_UE_MIB_FOUND) { srslte_pbch_mib_unpack(bch_payload, &cell, &sfn); printf("Decoded MIB. SFN: %d, offset: %d\n", sfn, sfn_offset); sfn = (sfn + sfn_offset)%1024; state = DECODE_SIB; } } break; case DECODE_SIB: /* We are looking for SI Blocks, search only in appropiate places */ if ((srslte_ue_sync_get_sfidx(&ue_sync) == 5 && (sfn%2)==0)) { n = srslte_ue_dl_decode_rnti_rv(&ue_dl, sf_buffer, data, srslte_ue_sync_get_sfidx(&ue_sync), SRSLTE_SIRNTI, ((int) ceilf((float)3*(((sfn)/2)%4)/2))%4); if (n < 0) { fprintf(stderr, "Error decoding UE DL\n");fflush(stdout); return -1; } else if (n == 0) { printf("CFO: %+6.4f KHz, SFO: %+6.4f Khz, NOI: %.2f, PDCCH-Det: %.3f\r", srslte_ue_sync_get_cfo(&ue_sync)/1000, srslte_ue_sync_get_sfo(&ue_sync)/1000, srslte_sch_average_noi(&ue_dl.pdsch.dl_sch), (float) ue_dl.nof_detected/nof_trials); nof_trials++; } else { printf("Decoded SIB1. Payload: "); srslte_vec_fprint_byte(stdout, data, n/8);; state = MEASURE; } } break; case MEASURE: if (srslte_ue_sync_get_sfidx(&ue_sync) == 5) { /* Run FFT for all subframe data */ srslte_ofdm_rx_sf(&fft, sf_buffer, sf_symbols); srslte_chest_dl_estimate(&chest, sf_symbols, ce, srslte_ue_sync_get_sfidx(&ue_sync)); rssi = SRSLTE_VEC_EMA(srslte_vec_avg_power_cf(sf_buffer,SRSLTE_SF_LEN(srslte_symbol_sz(cell.nof_prb))),rssi,0.05); rssi_utra = SRSLTE_VEC_EMA(srslte_chest_dl_get_rssi(&chest),rssi_utra,0.05); rsrq = SRSLTE_VEC_EMA(srslte_chest_dl_get_rsrq(&chest),rsrq,0.05); rsrp = SRSLTE_VEC_EMA(srslte_chest_dl_get_rsrp(&chest),rsrp,0.05); snr = SRSLTE_VEC_EMA(srslte_chest_dl_get_snr(&chest),snr,0.05); nframes++; } if ((nframes%100) == 0 || rx_gain_offset == 0) { if (srslte_rf_has_rssi(&rf)) { rx_gain_offset = 10*log10(rssi)-srslte_rf_get_rssi(&rf); } else { rx_gain_offset = srslte_rf_get_rx_gain(&rf); } } // Plot and Printf if ((nframes%10) == 0) { printf("CFO: %+8.4f KHz, SFO: %+8.4f Khz, RSSI: %5.1f dBm, RSSI/ref-symbol: %+5.1f dBm, " "RSRP: %+5.1f dBm, RSRQ: %5.1f dB, SNR: %5.1f dB\r", srslte_ue_sync_get_cfo(&ue_sync)/1000, srslte_ue_sync_get_sfo(&ue_sync)/1000, 10*log10(rssi*1000) - rx_gain_offset, 10*log10(rssi_utra*1000)- rx_gain_offset, 10*log10(rsrp*1000) - rx_gain_offset, 10*log10(rsrq), 10*log10(snr)); if (srslte_verbose != SRSLTE_VERBOSE_NONE) { printf("\n"); } } break; } if (srslte_ue_sync_get_sfidx(&ue_sync) == 9) { sfn++; if (sfn == 1024) { sfn = 0; } } } else if (ret == 0) { printf("Finding PSS... Peak: %8.1f, FrameCnt: %d, State: %d\r", srslte_sync_get_peak_value(&ue_sync.sfind), ue_sync.frame_total_cnt, ue_sync.state); } sf_cnt++; } // Main loop srslte_ue_sync_free(&ue_sync); srslte_rf_close(&rf); printf("\nBye\n"); exit(0); }