/** * * \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 "liblte/phy/phy.h" int cell_id = -1, offset = 0; lte_cp_t cp = CPNORM; uint32_t nof_prb=6; #define FLEN SF_LEN(fft_size) void usage(char *prog) { printf("Usage: %s [cpoev]\n", prog); printf("\t-c cell_id [Default check for all]\n"); printf("\t-p nof_prb [Default %d]\n", nof_prb); printf("\t-o offset [Default %d]\n", offset); printf("\t-e extended CP [Default normal]\n"); printf("\t-v verbose\n"); } void parse_args(int argc, char **argv) { int opt; while ((opt = getopt(argc, argv, "cpoev")) != -1) { switch (opt) { case 'c': cell_id = atoi(argv[optind]); break; case 'p': nof_prb = atoi(argv[optind]); break; case 'o': offset = atoi(argv[optind]); break; case 'e': cp = CPEXT; break; case 'v': verbose++; break; default: usage(argv[0]); exit(-1); } } } int main(int argc, char **argv) { int N_id_2, ns, find_ns; cf_t *buffer, *fft_buffer; cf_t pss_signal[PSS_LEN]; float sss_signal0[SSS_LEN]; // for subframe 0 float sss_signal5[SSS_LEN]; // for subframe 5 int cid, max_cid; uint32_t find_idx; sync_t sync; lte_fft_t ifft; int fft_size; parse_args(argc, argv); fft_size = lte_symbol_sz(nof_prb); if (fft_size < 0) { fprintf(stderr, "Invalid nof_prb=%d\n", nof_prb); exit(-1); } buffer = malloc(sizeof(cf_t) * FLEN); if (!buffer) { perror("malloc"); exit(-1); } fft_buffer = malloc(sizeof(cf_t) * FLEN); if (!fft_buffer) { perror("malloc"); exit(-1); } if (lte_ifft_init(&ifft, cp, nof_prb)) { fprintf(stderr, "Error creating iFFT object\n"); exit(-1); } if (sync_init(&sync, FLEN, fft_size)) { fprintf(stderr, "Error initiating PSS/SSS\n"); return -1; } /* Set a very high threshold to make sure the correlation is ok */ sync_set_threshold(&sync, 5.0); sync_set_sss_algorithm(&sync, SSS_PARTIAL_3); if (cell_id == -1) { cid = 0; max_cid = 49; } else { cid = cell_id; max_cid = cell_id; } while(cid <= max_cid) { N_id_2 = cid%3; /* Generate PSS/SSS signals */ pss_generate(pss_signal, N_id_2); sss_generate(sss_signal0, sss_signal5, cid); sync_set_N_id_2(&sync, N_id_2); for (ns=0;ns<2;ns++) { memset(buffer, 0, sizeof(cf_t) * FLEN); pss_put_slot(pss_signal, buffer, nof_prb, cp); sss_put_slot(ns?sss_signal5:sss_signal0, buffer, nof_prb, cp); /* Transform to OFDM symbols */ memset(fft_buffer, 0, sizeof(cf_t) * FLEN); lte_ifft_run_slot(&ifft, buffer, &fft_buffer[offset]); if (sync_find(&sync, fft_buffer, 0, &find_idx) < 0) { fprintf(stderr, "Error running sync_find\n"); exit(-1); } find_ns = 2*sync_get_sf_idx(&sync); printf("cell_id: %d find: %d, offset: %d, ns=%d find_ns=%d\n", cid, find_idx, offset, ns, find_ns); if (find_idx != offset + FLEN/2) { printf("offset != find_offset: %d != %d\n", find_idx, offset + FLEN/2); exit(-1); } if (ns*10 != find_ns) { printf("ns != find_ns\n", 10 * ns, find_ns); exit(-1); } if (sync_get_cp(&sync) != cp) { printf("Detected CP should be %s\n", CP_ISNORM(cp)?"Normal":"Extended"); exit(-1); } } cid++; } free(fft_buffer); free(buffer); sync_free(&sync); lte_ifft_free(&ifft); printf("Ok\n"); exit(0); }