/** * * \section COPYRIGHT * * Copyright 2013-2014 The libLTE Developers. See the * COPYRIGHT file at the top-level directory of this distribution. * * \section LICENSE * * This file is part of the libLTE library. * * libLTE is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation, either version 3 of * the License, or (at your option) any later version. * * libLTE is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * A copy of the GNU Lesser General Public License can be found in * the LICENSE file in the top-level directory of this distribution * and at http://www.gnu.org/licenses/. * */ #include #include #include #include #include #include #include #include #include #include #include "lte.h" #ifndef DISABLE_UHD #include "cuhd.h" void *uhd; #endif #ifndef DISABLE_GRAPHICS #include "plot.h" plot_real_t poutfft; plot_complex_t pce; plot_scatter_t pscatrecv, pscatequal; #endif #define MHZ 1000000 #define SAMP_FREQ 1920000 #define FLEN 9600 #define FLEN_PERIOD 0.005 #define NOF_PORTS 2 float find_threshold = 30.0, track_threshold = 10.0; int max_track_lost = 20, nof_slots = -1; int track_len=300; char *input_file_name = NULL; int disable_plots = 0; int go_exit=0; float uhd_freq = 2600000000.0, uhd_gain = 20.0; char *uhd_args = ""; filesource_t fsrc; cf_t *input_buffer, *fft_buffer, *ce[MAX_PORTS_CTRL]; pbch_t pbch; lte_fft_t fft; chest_t chest; sync_t sfind, strack; cfo_t cfocorr; enum sync_state {FIND, TRACK}; void usage(char *prog) { printf("Usage: %s [iagfndvp]\n", prog); printf("\t-i input_file [Default use USRP]\n"); #ifndef DISABLE_UHD printf("\t-a UHD args [Default %s]\n", uhd_args); printf("\t-g UHD RX gain [Default %.2f dB]\n", uhd_gain); printf("\t-f UHD RX frequency [Default %.1f MHz]\n", uhd_freq/1000000); #else printf("\t UHD is disabled. CUHD library not available\n"); #endif printf("\t-n nof_frames [Default %d]\n", nof_slots); printf("\t-p PSS threshold [Default %f]\n", find_threshold); #ifndef DISABLE_GRAPHICS printf("\t-d disable plots [Default enabled]\n"); #else printf("\t plots are disabled. Graphics library not available\n"); #endif printf("\t-v [set verbose to debug, default none]\n"); } void parse_args(int argc, char **argv) { int opt; while ((opt = getopt(argc, argv, "iagfndvp")) != -1) { switch(opt) { case 'i': input_file_name = argv[optind]; break; case 'a': uhd_args = argv[optind]; break; case 'g': uhd_gain = atof(argv[optind]); break; case 'f': uhd_freq = atof(argv[optind]); break; case 'p': find_threshold = atof(argv[optind]); break; case 'n': nof_slots = atoi(argv[optind]); break; case 'd': disable_plots = 1; break; case 'v': verbose++; break; default: usage(argv[0]); exit(-1); } } } #ifndef DISABLE_GRAPHICS void init_plots() { plot_init(); plot_real_init(&poutfft); plot_real_setTitle(&poutfft, "Output FFT - Magnitude"); plot_real_setLabels(&poutfft, "Index", "dB"); plot_real_setYAxisScale(&poutfft, -60, 0); plot_real_setXAxisScale(&poutfft, 1, 504); plot_complex_init(&pce); plot_complex_setTitle(&pce, "Channel Estimates"); plot_complex_setYAxisScale(&pce, Ip, -0.01, 0.01); plot_complex_setYAxisScale(&pce, Q, -0.01, 0.01); plot_complex_setYAxisScale(&pce, Magnitude, 0, 0.01); plot_complex_setYAxisScale(&pce, Phase, -M_PI, M_PI); plot_scatter_init(&pscatrecv); plot_scatter_setTitle(&pscatrecv, "Received Symbols"); plot_scatter_setXAxisScale(&pscatrecv, -0.01, 0.01); plot_scatter_setYAxisScale(&pscatrecv, -0.01, 0.01); plot_scatter_init(&pscatequal); plot_scatter_setTitle(&pscatequal, "Equalized Symbols"); plot_scatter_setXAxisScale(&pscatequal, -1, 1); plot_scatter_setYAxisScale(&pscatequal, -1, 1); } #endif int base_init(int frame_length) { int i; #ifndef DISABLE_GRAPHICS if (!disable_plots) { init_plots(); } #else printf("-- PLOTS are disabled. Graphics library not available --\n\n"); #endif if (input_file_name) { if (filesource_init(&fsrc, input_file_name, COMPLEX_FLOAT_BIN)) { return -1; } } else { /* open UHD device */ #ifndef DISABLE_UHD printf("Opening UHD device...\n"); if (cuhd_open(uhd_args,&uhd)) { fprintf(stderr, "Error opening uhd\n"); return -1; } #else printf("Error UHD not available. Select an input file\n"); return -1; #endif } input_buffer = (cf_t*) malloc(frame_length * sizeof(cf_t)); if (!input_buffer) { perror("malloc"); return -1; } fft_buffer = (cf_t*) malloc(CPNORM_NSYMB * 72 * sizeof(cf_t)); if (!fft_buffer) { perror("malloc"); return -1; } for (i=0;i max_track_lost) { INFO("%d frames lost. Going back to FIND", frame_cnt - last_found); printf("\r\n"); fflush(stdout); printf("\r\n"); state = FIND; } // Correct CFO INFO("Correcting CFO=%.4f\n", cfo); cfo_correct(&cfocorr, input_buffer, -cfo/128); if (nslot == 0 && find_idx + 960 < FLEN) { INFO("Finding MIB at idx %d\n", find_idx); if (mib_decoder_run(&input_buffer[find_idx], &mib)) { INFO("MIB detected attempt=%d\n", frame_cnt); if (verbose == VERBOSE_NONE) { if (!nof_found_mib) { printf("\r\n"); fflush(stdout); printf("\r\n"); pbch_mib_fprint(stdout, &mib); } } nof_found_mib++; } else { INFO("MIB not found attempt %d\n",frame_cnt); } if (frame_cnt) { printf("SFN: %4d, CFO: %+.4f KHz, SFO: %+.4f Khz, TimeOffset: %4d, Errors: %4d/%4d, ErrorRate: %.1e\r", mib.sfn, cfo*15, timeoffset/5, find_idx, frame_cnt-2*(nof_found_mib-1), frame_cnt, (float) (frame_cnt-2*(nof_found_mib-1))/frame_cnt); fflush(stdout); } } if (input_file_name) { usleep(5000); } nslot = (nslot+10)%20; break; } frame_cnt++; } base_free(); printf("\nBye\n"); exit(0); }