From d99e4f5988fde8ad9fc6517d3debd2226c9e3986 Mon Sep 17 00:00:00 2001 From: ismagom Date: Mon, 21 Jul 2014 16:19:50 +0200 Subject: [PATCH] ue_dl --- lte/phy/examples/iodev.c | 167 ++++++++++++ lte/phy/examples/iodev.h | 90 ++++++ lte/phy/include/liblte/phy/phch/ue_dl.h | 95 +++++++ lte/phy/lib/phch/src/ue_dl.c | 255 +++++++++++++++++ lte/phy/lib/phch/test/ue_sync_usrp.c | 257 ++++++++++++++++++ .../lib/resampling/test/interp_test_volk.c | 92 +++++++ matlab/sync/find_pss2.m | 18 ++ 7 files changed, 974 insertions(+) create mode 100644 lte/phy/examples/iodev.c create mode 100644 lte/phy/examples/iodev.h create mode 100644 lte/phy/include/liblte/phy/phch/ue_dl.h create mode 100644 lte/phy/lib/phch/src/ue_dl.c create mode 100644 lte/phy/lib/phch/test/ue_sync_usrp.c create mode 100644 lte/phy/lib/resampling/test/interp_test_volk.c create mode 100644 matlab/sync/find_pss2.m diff --git a/lte/phy/examples/iodev.c b/lte/phy/examples/iodev.c new file mode 100644 index 000000000..056c64f16 --- /dev/null +++ b/lte/phy/examples/iodev.c @@ -0,0 +1,167 @@ +/** + * + * \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 "iodev.h" + +#include "liblte/phy/io/filesource.h" +#include "liblte/phy/phch/ue_sync.h" +#include "liblte/phy/utils/debug.h" +#include "liblte/phy/utils/vector.h" + +#ifndef DISABLE_UHD +#include "liblte/cuhd/cuhd.h" +#endif + + +int cuhd_recv_wrapper(void *h, void *data, uint32_t nsamples) { + DEBUG(" ---- Receive %d samples ---- \n", nsamples); + return cuhd_recv(h, data, nsamples, 1); +} + +/* Setup USRP or input file */ +int iodev_init(iodev_t *q, iodev_cfg_t *config) { + + if (config->input_file_name) { + if (filesource_init(&q->fsrc, config->input_file_name, COMPLEX_FLOAT_BIN)) { + return LIBLTE_ERROR; + } + q->input_buffer_file = vec_malloc(SF_LEN_MAX * sizeof(cf_t)); + if (!q->input_buffer_file) { + perror("malloc"); + return LIBLTE_ERROR; + } + + q->mode = FILESOURCE; + q->sf_len = 1920; + + } else { +#ifndef DISABLE_UHD + printf("Opening UHD device...\n"); + if (cuhd_open(config->uhd_args, &q->uhd)) { + fprintf(stderr, "Error opening uhd\n"); + return LIBLTE_ERROR; + } + + /* set uhd_freq */ + cuhd_set_rx_gain(q->uhd, config->uhd_gain); + cuhd_set_rx_freq(q->uhd, (double) config->uhd_freq); + + cuhd_rx_wait_lo_locked(q->uhd); + DEBUG("Set uhd_freq to %.3f MHz\n", (double ) config->uhd_freq); + + DEBUG("Starting receiver...\n", 0); + cuhd_start_rx_stream(q->uhd); + + if (config->find_threshold > 0.0) { + ue_sync_set_threshold(&q->sframe, config->find_threshold); + } + + ue_sync_init(&q->sframe, cuhd_set_rx_srate, cuhd_recv_wrapper, q->uhd); + + // Here, the subframe length and input buffer is managed by ue_sync + q->mode = UHD; + +#else + printf("Error UHD not available. Select an input file\n"); + return LIBLTE_ERROR; +#endif + } + + memcpy(&q->config, config, sizeof(iodev_cfg_t)); + + return LIBLTE_SUCCESS; +} + + + +void iodev_free(iodev_t *q) { + + if (q->mode == FILESOURCE) { + filesource_free(&q->fsrc); + } else { +#ifndef DISABLE_UHD + cuhd_close(q->uhd); +#endif + } +} +/* Receive samples from the USRP or read from file */ +int iodev_receive(iodev_t *q, cf_t **buffer) { + int n; + if (q->mode == FILESOURCE) { + DEBUG(" ----- READING %d SAMPLES ---- \n", q->sf_len); + n = filesource_read(&q->fsrc, q->input_buffer_file, q->sf_len); + *buffer = q->input_buffer_file; + if (n == -1) { + fprintf(stderr, "Error reading file\n"); + /* wrap file if arrive to end */ + } else if (n < q->sf_len) { + DEBUG("Read %d from file. Seeking to 0\n",n); + filesource_seek(&q->fsrc, 0); + n = filesource_read(&q->fsrc, q->input_buffer_file, q->sf_len); + if (n == -1) { + fprintf(stderr, "Error reading file\n"); + /* wrap file if arrive to end */ + } else { + n = 1; + } + } else { + n = 1; + } + } else { + /* Use ue_sync_work which returns a synchronized buffer of subframe samples */ +#ifndef DISABLE_UHD + n = ue_sync_get_buffer(&q->sframe, buffer); + if (n < 0) { + fprintf(stderr, "Error calling ue_sync_work()\n"); + } +#endif + } + return n; +} + +void* iodev_get_cuhd(iodev_t *q) { + if (q->mode == UHD) { + return q->uhd; + } else { + return NULL; + } +} + +bool iodev_isfile(iodev_t *q) { + return q->mode == FILESOURCE; +} + +bool iodev_isUSRP(iodev_t *q) { + return q->mode == UHD; +} + + diff --git a/lte/phy/examples/iodev.h b/lte/phy/examples/iodev.h new file mode 100644 index 000000000..87264eda6 --- /dev/null +++ b/lte/phy/examples/iodev.h @@ -0,0 +1,90 @@ +/** + * + * \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/. + * + */ + +#ifndef IODEF_H +#define IODEF_H + +#include "liblte/config.h" + +#include "liblte/phy/phch/ue_sync.h" +#include "liblte/phy/io/filesource.h" + +#ifndef DISABLE_UHD +#include "liblte/cuhd/cuhd.h" +#endif + +/********* + * + * This component is a wrapper to the cuhd or filesource modules. It uses + * sync_frame_t to read aligned subframes from the USRP or filesource to read + * subframes from a file. + * + * When created, it starts receiving/reading at 1.92 MHz. The sampling frequency + * can then be changed using iodev_set_srate() + */ + + +typedef enum LIBLTE_API {FILESOURCE, UHD} iodev_mode_t; + +typedef _Complex float cf_t; + +typedef struct LIBLTE_API { + char *input_file_name; + float uhd_freq; + float uhd_gain; + char *uhd_args; + float find_threshold; +} iodev_cfg_t; + +typedef struct LIBLTE_API { + #ifndef DISABLE_UHD + void *uhd; + ue_sync_t sframe; + #endif + uint32_t sf_len; + cf_t *input_buffer_file; // for UHD mode, the input buffer is managed by sync_frame_t + filesource_t fsrc; + iodev_cfg_t config; + iodev_mode_t mode; +} iodev_t; + + +LIBLTE_API int iodev_init(iodev_t *q, + iodev_cfg_t *config); + +LIBLTE_API void iodev_free(iodev_t *q); + +LIBLTE_API int iodev_receive(iodev_t *q, + cf_t **buffer); + +LIBLTE_API void* iodev_get_cuhd(iodev_t *q); + +LIBLTE_API bool iodev_isfile(iodev_t *q); + +LIBLTE_API bool iodev_isUSRP(iodev_t *q); + +#endif \ No newline at end of file diff --git a/lte/phy/include/liblte/phy/phch/ue_dl.h b/lte/phy/include/liblte/phy/phch/ue_dl.h new file mode 100644 index 000000000..b6ca44bab --- /dev/null +++ b/lte/phy/include/liblte/phy/phch/ue_dl.h @@ -0,0 +1,95 @@ +/** + * + * \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/. + * + */ + +#ifndef UEDL_H +#define UEDL_H + +/******************************************************* + * + * This module is a frontend to all the data and control channels processing + * modules. + ********************************************************/ + + + +#include "liblte/phy/ch_estimation/chest.h" +#include "liblte/phy/common/fft.h" +#include "liblte/phy/common/phy_common.h" + +#include "liblte/phy/phch/dci.h" +#include "liblte/phy/phch/pbch.h" +#include "liblte/phy/phch/pcfich.h" +#include "liblte/phy/phch/pdcch.h" +#include "liblte/phy/phch/pdsch.h" +#include "liblte/phy/phch/phich.h" +#include "liblte/phy/phch/ra.h" +#include "liblte/phy/phch/regs.h" + +#include "liblte/phy/utils/vector.h" +#include "liblte/phy/utils/debug.h" + +#include "liblte/config.h" + +#define NOF_HARQ_PROCESSES 8 + +typedef struct LIBLTE_API { + pcfich_t pcfich; + pdcch_t pdcch; + pdsch_t pdsch; + pdsch_harq_t harq_process[NOF_HARQ_PROCESSES]; + regs_t regs; + lte_fft_t fft; + chest_t chest; + + lte_cell_t cell; + + cf_t *sf_symbols; + cf_t *ce[MAX_PORTS]; + + uint64_t pkt_errors; + uint64_t pkts_total; + uint64_t nof_trials; + + uint16_t user_rnti; +}ue_dl_t; + +/* This function shall be called just after the initial synchronization */ +LIBLTE_API int ue_dl_init(ue_dl_t *q, + lte_cell_t cell, + phich_resources_t phich_resources, + phich_length_t phich_length, + uint16_t user_rnti); + +LIBLTE_API void ue_dl_free(ue_dl_t *q); + +LIBLTE_API int ue_dl_process(ue_dl_t *q, + cf_t *sf_buffer, + uint32_t sf_idx, + uint32_t sfn, + uint16_t rnti); + +#endif \ No newline at end of file diff --git a/lte/phy/lib/phch/src/ue_dl.c b/lte/phy/lib/phch/src/ue_dl.c new file mode 100644 index 000000000..707f89917 --- /dev/null +++ b/lte/phy/lib/phch/src/ue_dl.c @@ -0,0 +1,255 @@ +/** + * + * \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 "liblte/phy/phch/ue_dl.h" + + +#define EXPAVERAGE(data, average, nframes) ((data + average * nframes) / (nframes + 1)) + +#define CURRENT_FFTSIZE lte_symbol_sz(q->cell.nof_prb) +#define CURRENT_SFLEN SF_LEN(CURRENT_FFTSIZE, q->cell.cp) + +#define CURRENT_SLOTLEN_RE SLOT_LEN_RE(q->cell.nof_prb, q->cell.cp) +#define CURRENT_SFLEN_RE SF_LEN_RE(q->cell.nof_prb, q->cell.cp) + + +int ue_dl_init(ue_dl_t *q, + lte_cell_t cell, + phich_resources_t phich_resources, phich_length_t phich_length, + uint16_t user_rnti) +{ + int ret = LIBLTE_ERROR_INVALID_INPUTS; + + if (q != NULL && + lte_cell_isvalid(&cell)) + { + ret = LIBLTE_ERROR; + + q->cell = cell; + q->user_rnti = user_rnti; + q->pkt_errors = 0; + q->pkts_total = 0; + + if (lte_fft_init(&q->fft, q->cell.cp, q->cell.nof_prb)) { + fprintf(stderr, "Error initiating FFT\n"); + goto clean_exit; + } + if (chest_init_LTEDL(&q->chest, cell)) { + fprintf(stderr, "Error initiating channel estimator\n"); + goto clean_exit; + } + if (regs_init(&q->regs, phich_resources, phich_length, q->cell)) { + fprintf(stderr, "Error initiating REGs\n"); + goto clean_exit; + } + + if (pcfich_init(&q->pcfich, &q->regs, q->cell)) { + fprintf(stderr, "Error creating PCFICH object\n"); + goto clean_exit; + } + + if (pdcch_init(&q->pdcch, &q->regs, q->cell)) { + fprintf(stderr, "Error creating PDCCH object\n"); + goto clean_exit; + } + + if (pdsch_init(&q->pdsch, q->cell)) { + fprintf(stderr, "Error creating PDSCH object\n"); + goto clean_exit; + } + for (uint32_t i=0;iharq_process[i], &q->pdsch)) { + fprintf(stderr, "Error initiating HARQ process\n"); + goto clean_exit; + } + } + q->sf_symbols = vec_malloc(CURRENT_SFLEN_RE * sizeof(cf_t)); + if (!q->sf_symbols) { + perror("malloc"); + goto clean_exit; + } + for (uint32_t i=0;icell.nof_ports;i++) { + q->ce[i] = vec_malloc(CURRENT_SFLEN_RE * sizeof(cf_t)); + if (!q->ce[i]) { + perror("malloc"); + goto clean_exit; + } + } + + ret = LIBLTE_SUCCESS; + } else { + fprintf(stderr, "Invalid cell properties: Id=%d, Ports=%d, PRBs=%d\n", + cell.id, cell.nof_ports, cell.nof_prb); + } + +clean_exit: + if (ret == LIBLTE_ERROR) { + ue_dl_free(q); + } + return ret; +} + +void ue_dl_free(ue_dl_t *q) { + if (q) { + lte_fft_free(&q->fft); + chest_free(&q->chest); + regs_free(&q->regs); + pcfich_free(&q->pcfich); + pdcch_free(&q->pdcch); + pdsch_free(&q->pdsch); + for (uint32_t i=0;iharq_process[i]); + } + if (q->sf_symbols) { + free(q->sf_symbols); + } + for (uint32_t i=0;icell.nof_ports;i++) { + if (q->ce[i]) { + free(q->ce[i]); + } + } + } +} + +/* TODO: Do something with the output data */ +char data[10000]; + +int ue_dl_process(ue_dl_t *q, cf_t *input, uint32_t sf_idx, uint32_t sfn, uint16_t rnti) +{ + uint32_t cfi, cfi_distance, i; + ra_pdsch_t ra_dl; + dci_location_t locations[10]; + dci_msg_t dci_msg; + uint32_t nof_locations; + uint16_t crc_rem; + dci_format_t format; + + /* If we are looking for SI Blocks, search only in appropiate places */ + if ((rnti == SIRNTI && (sfn % 2) == 0 && sf_idx == 5) || + rnti != SIRNTI) + { + + /* Run FFT for all subframe data */ + lte_fft_run_sf(&q->fft, input, q->sf_symbols); + + /* Get channel estimates for each port */ + chest_ce_sf(&q->chest, q->sf_symbols, q->ce, sf_idx); + + /* First decode PCFICH and obtain CFI */ + if (pcfich_decode(&q->pcfich, q->sf_symbols, q->ce, sf_idx, &cfi, &cfi_distance)<0) { + fprintf(stderr, "Error decoding PCFICH\n"); + return LIBLTE_ERROR; + } + + INFO("Decoded CFI=%d with distance %d\n", cfi, cfi_distance); + + if (regs_set_cfi(&q->regs, cfi)) { + fprintf(stderr, "Error setting CFI\n"); + return LIBLTE_ERROR; + } + + /* Generate PDCCH candidates */ + if (rnti == SIRNTI) { + nof_locations = pdcch_common_locations(&q->pdcch, locations, 10, cfi); + format = Format1A; + } else { + nof_locations = pdcch_ue_locations(&q->pdcch, locations, 10, sf_idx, cfi, q->user_rnti); + format = Format1; + } + + crc_rem = 0; + for (i=0;ipdcch, q->sf_symbols, q->ce, locations[i], sf_idx, cfi)) { + fprintf(stderr, "Error extracting LLRs\n"); + return -1; + } + if (pdcch_decode_msg(&q->pdcch, &dci_msg, format, &crc_rem)) { + fprintf(stderr, "Error decoding DCI msg\n"); + return -1; + } + INFO("Decoded DCI message RNTI: 0x%x\n", crc_rem); + } + + + if (crc_rem == rnti) { + if (dci_msg_to_ra_dl(&dci_msg, rnti, q->user_rnti, q->cell, cfi, &ra_dl)) { + fprintf(stderr, "Error unpacking PDSCH scheduling DCI message\n"); + return -1; + } + + uint32_t rvidx; + if (rnti == SIRNTI) { + switch((sfn%8)/2) { + case 0: + rvidx = 0; + break; + case 1: + rvidx = 2; + break; + case 2: + rvidx = 3; + break; + case 3: + rvidx = 1; + break; + } + } else { + rvidx = ra_dl.rv_idx; + } + + if (rvidx == 0) { + if (pdsch_harq_setup(&q->harq_process[0], ra_dl.mcs, &ra_dl.prb_alloc)) { + fprintf(stderr, "Error configuring HARQ process\n"); + return -1; + } + } + if (q->harq_process[0].mcs.mod > 0) { + if (pdsch_decode(&q->pdsch, q->sf_symbols, q->ce, data, sf_idx, + &q->harq_process[0], rvidx)) { + if (rnti == SIRNTI && rvidx == 1) { + q->pkt_errors++; + } else { + q->pkt_errors++; + } + } else { + if (VERBOSE_ISINFO()) { + INFO("Decoded Message: ", 0); + vec_fprint_hex(stdout, data, ra_dl.mcs.tbs); + } + } + if (rnti == SIRNTI && rvidx == 1) { + q->pkts_total++; + } + } + } + if (rnti == SIRNTI && (sfn%8) == 0) { + q->nof_trials++; + } + } + + return 0; +} diff --git a/lte/phy/lib/phch/test/ue_sync_usrp.c b/lte/phy/lib/phch/test/ue_sync_usrp.c new file mode 100644 index 000000000..752c4d236 --- /dev/null +++ b/lte/phy/lib/phch/test/ue_sync_usrp.c @@ -0,0 +1,257 @@ +/** + * + * \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 + +#include "liblte/phy/phy.h" + +#include "liblte/cuhd/cuhd.h" +void *uhd; + +#ifndef DISABLE_GRAPHICS +#include "liblte/graphics/plot.h" +plot_real_t poutfft; +#endif + +int nof_frames = -1; +float threshold = -1.0; + +float uhd_freq = 0.0, uhd_gain = 20.0; +char *uhd_args = ""; +int disable_plots = 0; + +void usage(char *prog) { + printf("Usage: %s [agntdv] -f uhd_freq\n", prog); + printf("\t-a UHD args [Default %s]\n", uhd_args); + printf("\t-g UHD RX gain [Default %.2f dB]\n", uhd_gain); + printf("\t-n nof_frames [Default infinite]\n"); + printf("\t-t threshold [Default %.2f]\n",threshold); + +#ifndef DISABLE_GRAPHICS + printf("\t-d disable plots [Default enabled]\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, "agntdvf")) != -1) { + switch (opt) { + case 'n': + nof_frames = atoi(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 't': + threshold = atof(argv[optind]); + break; + case 'd': + disable_plots = 1; + break; + case 'v': + verbose++; + break; + default: + usage(argv[0]); + exit(-1); + } + } + if (uhd_freq == 0.0) { + usage(argv[0]); + exit(-1); + } +} + +void input_init() { + + printf("Opening UHD device...\n"); + if (cuhd_open(uhd_args, &uhd)) { + fprintf(stderr, "Error opening uhd\n"); + exit(-1); + } + cuhd_set_rx_gain(uhd, uhd_gain); + + /* set uhd_freq */ + cuhd_set_rx_freq(uhd, (double) uhd_freq); + cuhd_rx_wait_lo_locked(uhd); + DEBUG("Set uhd_freq to %.3f MHz\n", (double ) uhd_freq/1000000); + + DEBUG("Starting receiver...\n", 0); + cuhd_start_rx_stream(uhd); + +} + +int cuhd_recv_wrapper(void *h, void *data, uint32_t nsamples) { + DEBUG(" ---- Receive %d samples ---- \n", nsamples); + return cuhd_recv(h, data, nsamples, 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); + +} + +#endif + +float tmp_plot[100000]; + +int main(int argc, char **argv) { + cf_t *input_buffer, *sf_symbols = NULL; + int frame_cnt; + ue_sync_t s; + int pos; + pss_synch_t pss; + float peak; + struct timeval t[3]; + float mean_ce_time=0; + bool signal_detected; + lte_fft_t fft; + lte_cell_t cell; + + bzero(&cell, sizeof(lte_cell_t)); + + parse_args(argc, argv); + + #ifndef DISABLE_GRAPHICS + if (!disable_plots) { + init_plots(); + } + #endif + + input_init(); + + if (ue_sync_init(&s, cuhd_set_rx_srate, cuhd_recv_wrapper, uhd)) { + fprintf(stderr, "Error initiating UE sync module\n"); + exit(-1); + } + + if (threshold > 0.0) { + ue_sync_set_threshold(&s, threshold); + } + + ue_sync_pbch_enable(&s, true); +// ue_sync_pbch_always(&s, true); +// ue_sync_decode_sss_on_track(&s, true); + + signal_detected = true; + frame_cnt = 0; + mean_ce_time=0; + uint32_t valid_frames=0; + //uint32_t unaligned = 0; + while (frame_cnt < nof_frames || nof_frames == -1) { + + int n = ue_sync_get_buffer(&s, &input_buffer); + if (n < 0) { + fprintf(stderr, "Error calling sync work()\n"); + exit(-1); + } + + if (n == 1 && ue_sync_get_sfidx(&s) == 0) { + + if (signal_detected) { + cell = ue_sync_get_cell(&s); + pss_synch_init_fft(&pss, + SF_LEN(lte_symbol_sz(cell.nof_prb), cell.cp), + lte_symbol_sz(cell.nof_prb)); + pss_synch_set_N_id_2(&pss, cell.id%3); + + sf_symbols = vec_malloc(SLOT_LEN_RE(cell.nof_prb, cell.cp) * sizeof(cf_t)); + if (!sf_symbols) { + perror("malloc"); + exit(-1); + } + lte_fft_init(&fft, cell.cp, cell.nof_prb); + signal_detected = false; + } + + mean_ce_time = (float) (mean_ce_time + (float) t[0].tv_usec * valid_frames) / (valid_frames+1); + valid_frames++; + + #ifndef DISABLE_GRAPHICS + if (!disable_plots && !(valid_frames % 5) && sf_symbols) { + + /* Run FFT for the second slot */ + lte_fft_run_slot(&fft, input_buffer, sf_symbols); + + int i; + int nof_re = SLOT_LEN_RE(cell.nof_prb, cell.cp); + for (i = 0; i < nof_re; i++) { + tmp_plot[i] = 10 * log10f(cabsf(sf_symbols[i])); + if (isinf(tmp_plot[i])) { + tmp_plot[i] = -80; + } + } + plot_real_setNewData(&poutfft, tmp_plot, nof_re); + } + #endif + + pos = pss_synch_find_pss(&pss, input_buffer, &peak, NULL); + /*if (pos > 962 || pos < 958) { + unaligned++; + } + */ + printf("CELL_ID: %3d CFO: %+.4f KHz, SFO: %+.4f Khz, TimeOffset: %4d, Exec: %3.2f\r", + cell.id, ue_sync_get_cfo(&s)/1000, ue_sync_get_sfo(&s)/1000, pos, + s.mean_exec_time); + fflush(stdout); + if (VERBOSE_ISINFO()) { + printf("\n"); + } + } + + frame_cnt++; + } + + printf("\nBye\n"); + exit(0); +} + + diff --git a/lte/phy/lib/resampling/test/interp_test_volk.c b/lte/phy/lib/resampling/test/interp_test_volk.c new file mode 100644 index 000000000..cc97f3cef --- /dev/null +++ b/lte/phy/lib/resampling/test/interp_test_volk.c @@ -0,0 +1,92 @@ +#include +#include +#include +#include +#include +#include + +#include "liblte/phy/phy.h" + +typedef _Complex float cf_t; + +int main(int argc, char **argv) { + uint32_t N = 1000; // Number of sinwave samples + interp_t interp; + struct timeval t[3]; + + if (argc < 3) { + printf("usage: %s upsampling_rate nof_trials\n", argv[0]); + exit(-1); + } + + uint32_t M = atoi(argv[1]); + uint32_t nof_trials = atoi(argv[2]); + + if (interp_init(&interp, LINEAR, N, M)) { + exit(-1); + } + + cf_t *in = vec_malloc(N*sizeof(cf_t)); + if(!in) { + perror("malloc"); + exit(-1); + } + cf_t *out = vec_malloc(M * N*sizeof(cf_t)); + if(!out) { + perror("malloc"); + exit(-1); + } + cf_t *out_volk = vec_malloc(M * N*sizeof(cf_t)); + if(!out_volk) { + perror("malloc"); + exit(-1); + } + + srand(time(NULL)); + for(uint32_t i=0;i