/** * * \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 "lte.h" #include "cuhd.h" #define MHZ 1000000 #define SAMP_FREQ 1920000 #define RSSI_FS 1000000 #define FLEN 9600 #define FLEN_PERIOD 0.005 #define RSSI_DECIM 20 #define IS_SIGNAL(i) (10*log10f(rssi[i]) + 30 > rssi_threshold) int band, earfcn=-1; float find_threshold = 40.0, track_threshold = 8.0; int earfcn_start=-1, earfcn_end = -1; float rssi_threshold = -30.0; int max_track_lost=9; int nof_frames_find=8, nof_frames_track=100, nof_samples_rssi=50000; int track_len=500; cf_t *input_buffer; float *cfo_v; int *idx_v, *idx_valid, *t; float *p2a_v; void *uhd; int nof_bands; float uhd_gain = 20.0; #define MAX_EARFCN 1000 lte_earfcn_t channels[MAX_EARFCN]; float rssi[MAX_EARFCN]; float rssi_d[MAX_EARFCN/RSSI_DECIM]; float freqs[MAX_EARFCN]; float cfo[MAX_EARFCN]; float p2a[MAX_EARFCN]; enum sync_state {INIT, FIND, TRACK, DONE}; void print_to_matlab(); void usage(char *prog) { printf("Usage: %s [seRrFfTtgv] -b band\n", prog); printf("\t-s earfcn_start [Default All]\n"); printf("\t-e earfcn_end [Default All]\n"); printf("\t-R rssi_nof_samples [Default %d]\n", nof_samples_rssi); printf("\t-r rssi_threshold [Default %.2f dBm]\n", rssi_threshold); printf("\t-F pss_find_nof_frames [Default %d]\n", nof_frames_find); printf("\t-f pss_find_threshold [Default %.2f]\n", find_threshold); printf("\t-T pss_track_nof_frames [Default %d]\n", nof_frames_track); printf("\t-t pss_track_threshold [Default %.2f]\n", track_threshold); printf("\t-l pss_track_len [Default %d]\n", track_len); printf("\t-g gain [Default %.2f dB]\n", uhd_gain); printf("\t-v [set verbose to debug, default none]\n"); } void parse_args(int argc, char **argv) { int opt; while ((opt = getopt(argc, argv, "bseRrFfTtgv")) != -1) { switch(opt) { case 'b': band = atoi(argv[optind]); break; case 's': earfcn_start = atoi(argv[optind]); break; case 'e': earfcn_end = atoi(argv[optind]); break; case 'R': nof_samples_rssi = atoi(argv[optind]); break; case 'r': rssi_threshold = -atof(argv[optind]); break; case 'F': nof_frames_find = atoi(argv[optind]); break; case 'f': find_threshold = atof(argv[optind]); break; case 'T': nof_frames_track = atoi(argv[optind]); break; case 't': track_threshold = atof(argv[optind]); break; case 'g': uhd_gain = atof(argv[optind]); break; case 'v': verbose++; break; default: usage(argv[0]); exit(-1); } } } int base_init(int frame_length) { input_buffer = malloc(2 * frame_length * sizeof(cf_t)); if (!input_buffer) { perror("malloc"); exit(-1); } idx_v = malloc(nof_frames_track * sizeof(int)); if (!idx_v) { perror("malloc"); exit(-1); } idx_valid = malloc(nof_frames_track * sizeof(int)); if (!idx_valid) { perror("malloc"); exit(-1); } t = malloc(nof_frames_track * sizeof(int)); if (!t) { perror("malloc"); exit(-1); } cfo_v = malloc(nof_frames_track * sizeof(float)); if (!cfo_v) { perror("malloc"); exit(-1); } p2a_v = malloc(nof_frames_track * sizeof(float)); if (!p2a_v) { perror("malloc"); exit(-1); } bzero(cfo, sizeof(float) * MAX_EARFCN); bzero(p2a, sizeof(float) * MAX_EARFCN); /* open UHD device */ printf("Opening UHD device...\n"); if (cuhd_open("",&uhd)) { fprintf(stderr, "Error opening uhd\n"); exit(-1); } return 0; } void base_free() { cuhd_close(&uhd); free(input_buffer); free(idx_v); free(idx_valid); free(t); free(cfo_v); free(p2a_v); } float mean_valid(int *idx_v, float *x, int nof_frames) { int i; float mean = 0; int n = 0; for (i=0;i 0) { return mean/n; } else { return 0.0; } } int preprocess_idx(int *in, int *out, int *period, int len) { int i, n; n=0; for (i=0;i 100) { /* scan every Mhz, that is 10 freqs */ for (i=0;i= nof_frames_find) { state = INIT; printf("[%3d/%d]: EARFCN %d Freq. %.2f MHz No PSS found\r", freq, nof_bands, channels[freq].id, channels[freq].fd, frame_cnt - last_found); if (VERBOSE_ISINFO()) { printf("\n"); } freq++; } } break; case TRACK: INFO("Tracking PSS find_idx %d offset %d\n", find_idx, find_idx + track_len); filesink_write(&fs, &input_buffer[FLEN+find_idx+track_len], track_len); track_idx = sync_run(&strack, &input_buffer[FLEN + find_idx - track_len]); p2a_v[frame_cnt] = sync_get_peak_to_avg(&strack); /* save cell id for the best peak-to-avg */ if (p2a_v[frame_cnt] > max_peak_to_avg) { max_peak_to_avg = p2a_v[frame_cnt]; cell_id = sync_get_cell_id(&strack); } if (track_idx != -1) { cfo_v[frame_cnt] = sync_get_cfo(&strack); last_found = frame_cnt; find_idx += track_idx - track_len; idx_v[frame_cnt] = find_idx; } else { idx_v[frame_cnt] = -1; cfo_v[frame_cnt] = 0.0; } /* if we missed to many PSS it is not a cell, next freq */ if (frame_cnt - last_found > max_track_lost) { INFO("\n[%3d/%d]: EARFCN %d Freq. %.2f MHz %d frames lost\n", freq, nof_bands, channels[freq].id, channels[freq].fd, frame_cnt - last_found); state = INIT; freq++; } else if (frame_cnt >= nof_frames_track) { state = DONE; } break; case DONE: cfo[freq] = mean_valid(idx_v, cfo_v, frame_cnt); p2a[freq] = mean_valid(idx_v, p2a_v, frame_cnt); valid_frames = preprocess_idx(idx_v, idx_valid, t, frame_cnt); sfo = sfo_estimate_period(idx_valid, t, valid_frames, FLEN_PERIOD); printf("\n[%3d/%d]: FOUND EARFCN %d Freq. %.2f MHz. " "PAR %2.2f dB, CFO=%+.2f KHz, SFO=%+2.3f KHz, CELL_ID=%3d\n", freq, nof_bands, channels[freq].id, channels[freq].fd, 10*log10f(p2a[freq]), cfo[freq] * 15, sfo / 1000, cell_id); state = INIT; freq++; break; } if (state == TRACK || (state == FIND && frame_cnt)) { memcpy(input_buffer, &input_buffer[FLEN], FLEN * sizeof(cf_t)); } frame_cnt++; } } print_to_matlab(); sync_free(&sfind); base_free(); printf("\n\nDone\n"); exit(0); } void print_to_matlab() { int i; FILE *f = fopen("output.m", "w"); if (!f) { perror("fopen"); exit(-1); } fprintf(f, "fd=["); for (i=0;i