diff --git a/cmake/modules/FindVolk.cmake b/cmake/modules/FindVolk.cmake index d9e90e9e4..7a3660f18 100644 --- a/cmake/modules/FindVolk.cmake +++ b/cmake/modules/FindVolk.cmake @@ -31,11 +31,13 @@ CHECK_FUNCTION_EXISTS_MATH(volk_32f_accumulator_s32f HAVE_VOLK_ACC_FUNCTION) CHECK_FUNCTION_EXISTS_MATH(volk_32fc_s32fc_multiply_32fc HAVE_VOLK_MULT_FUNCTION) CHECK_FUNCTION_EXISTS_MATH(volk_32fc_conjugate_32fc HAVE_VOLK_CONJ_FUNCTION) CHECK_FUNCTION_EXISTS_MATH(volk_32fc_x2_multiply_32fc HAVE_VOLK_MULT2_FUNCTION) +CHECK_FUNCTION_EXISTS_MATH(volk_32fc_x2_multiply_conjugate_32fc HAVE_VOLK_MULT2_CONJ_FUNCTION) CHECK_FUNCTION_EXISTS_MATH(volk_32fc_32f_multiply_32fc HAVE_VOLK_MULT_REAL_FUNCTION) CHECK_FUNCTION_EXISTS_MATH(volk_32f_s32f_multiply_32f HAVE_VOLK_MULT_FLOAT_FUNCTION) CHECK_FUNCTION_EXISTS_MATH(volk_32fc_magnitude_32f HAVE_VOLK_MAG_FUNCTION) CHECK_FUNCTION_EXISTS_MATH(volk_32f_x2_divide_32f HAVE_VOLK_DIVIDE_FUNCTION) CHECK_FUNCTION_EXISTS_MATH(volk_32fc_32f_dot_prod_32fc HAVE_VOLK_DOTPROD_FC_FUNCTION) +CHECK_FUNCTION_EXISTS_MATH(volk_32fc_x2_conjugate_dot_prod_32fc HAVE_VOLK_DOTPROD_CONJ_FC_FUNCTION) CHECK_FUNCTION_EXISTS_MATH(volk_32f_x2_dot_prod_32f HAVE_VOLK_DOTPROD_F_FUNCTION) CHECK_FUNCTION_EXISTS_MATH(volk_32fc_s32f_atan2_32f HAVE_VOLK_ATAN_FUNCTION) CHECK_FUNCTION_EXISTS_MATH(volk_32f_s32f_convert_16i HAVE_VOLK_CONVERT_FI_FUNCTION) @@ -45,9 +47,15 @@ CHECK_FUNCTION_EXISTS_MATH(volk_32f_x2_subtract_32f HAVE_VOLK_SUB_FLOAT_FUNCTION SET(VOLK_DEFINITIONS "HAVE_VOLK") +IF(${HAVE_VOLK_DOTPROD_CONJ_FC_FUNCTION}) + SET(VOLK_DEFINITIONS "${VOLK_DEFINITIONS}; HAVE_VOLK_DOTPROD_CONJ_FC_FUNCTION") +ENDIF() IF(${HAVE_VOLK_SUB_FLOAT_FUNCTION}) SET(VOLK_DEFINITIONS "${VOLK_DEFINITIONS}; HAVE_VOLK_SUB_FLOAT_FUNCTION") ENDIF() +IF(${HAVE_VOLK_MULT2_CONJ_FUNCTION}) + SET(VOLK_DEFINITIONS "${VOLK_DEFINITIONS}; HAVE_VOLK_MULT2_CONJ_FUNCTION") +ENDIF() IF(${HAVE_VOLK_DEINTERLEAVE_FUNCTION}) SET(VOLK_DEFINITIONS "${VOLK_DEFINITIONS}; HAVE_VOLK_DEINTERLEAVE_FUNCTION") ENDIF() diff --git a/lte/phy/examples/pdsch_ue.c b/lte/phy/examples/pdsch_ue.c index 70b6cb121..75d497fe7 100644 --- a/lte/phy/examples/pdsch_ue.c +++ b/lte/phy/examples/pdsch_ue.c @@ -58,7 +58,6 @@ typedef struct { uint16_t rnti; int nof_subframes; bool disable_plots; - bool pbch_only; iodev_cfg_t io_config; }prog_args_t; @@ -68,7 +67,6 @@ void args_default(prog_args_t *args) { args->rnti = SIRNTI; args->nof_subframes = -1; args->disable_plots = false; - args->pbch_only = false; args->io_config.find_threshold = -1.0; args->io_config.input_file_name = NULL; args->io_config.uhd_args = ""; @@ -121,10 +119,7 @@ void parse_args(prog_args_t *args, int argc, char **argv) { case 'f': args->io_config.uhd_freq = atof(argv[optind]); break; - case 'b': - args->pbch_only = true; - break; - case 't': + case 't': args->io_config.find_threshold = atof(argv[optind]); break; case 'n': @@ -151,6 +146,9 @@ void sigintHandler(int x) { go_exit = 1; } +/* TODO: Do something with the output data */ +char data[10000]; + int main(int argc, char **argv) { int ret; cf_t *sf_buffer; @@ -162,6 +160,8 @@ int main(int argc, char **argv) { int64_t sf_cnt; uint32_t sf_idx; pbch_mib_t mib; + bool printed_sib = false; + uint32_t rlen; parse_args(&prog_args, argc, argv); @@ -215,14 +215,21 @@ int main(int argc, char **argv) { if (iodev_isUSRP(&iodev)) { sf_idx = ue_sync_get_sfidx(&iodev.sframe); } - if (ue_dl_process(&ue_dl, sf_buffer, sf_idx, ue_sync_get_mib(&iodev.sframe).sfn, prog_args.rnti)) { + rlen = ue_dl_receive(&ue_dl, sf_buffer, data, sf_idx, ue_sync_get_mib(&iodev.sframe).sfn, prog_args.rnti); + if (rlen < 0) { fprintf(stderr, "\nError running receiver\n");fflush(stdout); exit(-1); } + if (prog_args.rnti == SIRNTI && !printed_sib && rlen > 0) { + printf("\n\nDecoded SIB1 Message: "); + vec_fprint_hex(stdout, data, rlen); + printf("\n");fflush(stdout); + printed_sib = true; + } if (!(sf_cnt % 10)) { - printf("Cell ID: %3d, CFO: %+.4f KHz, SFO: %+.4f Khz, TimeOffset: %4d, Errors: %4d/%4d/%d, BLER: %.1e\r", - cell.id, iodev.sframe.cur_cfo * 15, iodev.sframe.mean_time_offset / 5, iodev.sframe.peak_idx, - (int) ue_dl.pkt_errors, (int) ue_dl.pkts_total, (int) ue_dl.nof_trials, (float) ue_dl.pkt_errors / ue_dl.pkts_total); + printf("Cell ID: %3d, RSSI: %+.2f dBm, CFO: %+.4f KHz, SFO: %+.4f Khz, TimeOffset: %4d, Errors: %4d/%4d, BLER: %.1e\r", + cell.id, 20*log10f(agc_get_rssi(&iodev.sframe.agc)), iodev.sframe.cur_cfo * 15, iodev.sframe.mean_time_offset / 5, iodev.sframe.peak_idx, + (int) ue_dl.pkt_errors, (int) ue_dl.pkts_total, (float) ue_dl.pkt_errors / ue_dl.pkts_total); fflush(stdout); if (VERBOSE_ISINFO()) { printf("\n"); @@ -277,24 +284,24 @@ void init_plots() { 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_setYAxisScale(&poutfft, -30, 20); 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, Ip, -3, 3); + plot_complex_setYAxisScale(&pce, Q, -3, 3); + plot_complex_setYAxisScale(&pce, Magnitude, 0, 4); 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_setXAxisScale(&pscatrecv, -4, 4); + plot_scatter_setYAxisScale(&pscatrecv, -4, 4); plot_scatter_init(&pscatequal); plot_scatter_setTitle(&pscatequal, "Equalized Symbols"); - plot_scatter_setXAxisScale(&pscatequal, -1, 1); - plot_scatter_setYAxisScale(&pscatequal, -1, 1); + plot_scatter_setXAxisScale(&pscatequal, -2, 2); + plot_scatter_setYAxisScale(&pscatequal, -2, 2); } void do_plots(ue_dl_t *q, uint32_t sf_idx) { diff --git a/lte/phy/examples/scan_mib.c b/lte/phy/examples/scan_mib.c index 94782c308..d92b06aea 100644 --- a/lte/phy/examples/scan_mib.c +++ b/lte/phy/examples/scan_mib.c @@ -442,7 +442,7 @@ int main(int argc, char **argv) { case FIND: /* find peak in all frame */ ret = sync_find(&ssync, &input_buffer[FLEN], &find_idx); - DEBUG("[%3d/%d]: PAR=%.2f\n", freq, nof_bands, sync_get_peak_to_avg(&ssync)); + DEBUG("[%3d/%d]: PAR=%.2f\n", freq, nof_bands, sync_get_peak_value(&ssync)); if (ret == 1) { /* if found peak, go to track and set lower threshold */ frame_cnt = -1; @@ -453,7 +453,7 @@ int main(int argc, char **argv) { state = TRACK; INFO("[%3d/%d]: EARFCN %d Freq. %.2f MHz PSS found PAR %.2f dB\n", freq, nof_bands, channels[freq].id, channels[freq].fd, - 10*log10f(sync_get_peak_to_avg(&ssync))); + 10*log10f(sync_get_peak_value(&ssync))); } else { if (frame_cnt >= nof_frames_find) { state = INIT; @@ -465,7 +465,7 @@ int main(int argc, char **argv) { INFO("Tracking PSS find_idx %d offset %d\n", find_idx, find_idx - track_len); ret = sync_track(&ssync, input_buffer, FLEN + find_idx - track_len, &track_idx); - p2a_v[frame_cnt] = sync_get_peak_to_avg(&ssync); + p2a_v[frame_cnt] = sync_get_peak_value(&ssync); /* save cell id for the best peak-to-avg */ if (p2a_v[frame_cnt] > max_peak_to_avg) { diff --git a/lte/phy/examples/scan_pss.c b/lte/phy/examples/scan_pss.c index e6e052cd6..0e0868b2e 100644 --- a/lte/phy/examples/scan_pss.c +++ b/lte/phy/examples/scan_pss.c @@ -356,7 +356,7 @@ int main(int argc, char **argv) { case FIND: /* find peak in all frame */ ret = sync_find(&sfind, &input_buffer[FLEN], &find_idx); - DEBUG("[%3d/%d]: PAR=%.2f\n", freq, nof_bands, sync_get_peak_to_avg(&sfind)); + DEBUG("[%3d/%d]: PAR=%.2f\n", freq, nof_bands, sync_get_peak_value(&sfind)); if (ret == 1) { /* if found peak, go to track and set lower threshold */ frame_cnt = -1; @@ -364,7 +364,7 @@ int main(int argc, char **argv) { state = TRACK; INFO("[%3d/%d]: EARFCN %d Freq. %.2f MHz PSS found PAR %.2f dB\n", freq, nof_bands, channels[freq].id, channels[freq].fd, - 10*log10f(sync_get_peak_to_avg(&sfind))); + 10*log10f(sync_get_peak_value(&sfind))); } else { if (frame_cnt >= nof_frames_find) { state = INIT; @@ -383,7 +383,7 @@ int main(int argc, char **argv) { filesink_write(&fs, &input_buffer[FLEN+find_idx+track_len], track_len); ret = sync_find(&strack, &input_buffer[FLEN + find_idx - track_len], &track_idx); - p2a_v[frame_cnt] = sync_get_peak_to_avg(&strack); + p2a_v[frame_cnt] = sync_get_peak_value(&strack); /* save cell id for the best peak-to-avg */ if (p2a_v[frame_cnt] > max_peak_to_avg) { diff --git a/lte/phy/include/liblte/phy/agc/agc.h b/lte/phy/include/liblte/phy/agc/agc.h new file mode 100644 index 000000000..f28e7a09b --- /dev/null +++ b/lte/phy/include/liblte/phy/agc/agc.h @@ -0,0 +1,69 @@ +/** + * + * \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 AGC_ +#define AGC_ + +#include +#include +#include + +#include "liblte/config.h" + +/* Automatic Gain Control + * + */ +typedef _Complex float cf_t; + +#define AGC_DEFAULT_BW (1e-2f) + +typedef struct LIBLTE_API{ + float bandwidth; + float gain; + float y_out; + bool lock; +} agc_t; + +LIBLTE_API int agc_init (agc_t *q); + +LIBLTE_API void agc_free(agc_t *q); + +LIBLTE_API void agc_set_bandwidth(agc_t *q, + float bandwidth); + +LIBLTE_API float agc_get_rssi(agc_t *q); + +LIBLTE_API void agc_lock(agc_t *q, bool enable); + +LIBLTE_API void agc_push(agc_t *q, + cf_t *input, + cf_t *output, + uint32_t len); + +#endif // AGC_ diff --git a/lte/phy/include/liblte/phy/phch/ue_dl.h b/lte/phy/include/liblte/phy/phch/ue_dl.h index b6ca44bab..22ecd718d 100644 --- a/lte/phy/include/liblte/phy/phch/ue_dl.h +++ b/lte/phy/include/liblte/phy/phch/ue_dl.h @@ -86,8 +86,9 @@ LIBLTE_API int ue_dl_init(ue_dl_t *q, LIBLTE_API void ue_dl_free(ue_dl_t *q); -LIBLTE_API int ue_dl_process(ue_dl_t *q, +LIBLTE_API int ue_dl_receive(ue_dl_t *q, cf_t *sf_buffer, + char *data, uint32_t sf_idx, uint32_t sfn, uint16_t rnti); diff --git a/lte/phy/include/liblte/phy/phch/ue_sync.h b/lte/phy/include/liblte/phy/phch/ue_sync.h index cf1e2f7a2..dc374e238 100644 --- a/lte/phy/include/liblte/phy/phch/ue_sync.h +++ b/lte/phy/include/liblte/phy/phch/ue_sync.h @@ -36,6 +36,7 @@ #include "liblte/phy/ch_estimation/chest.h" #include "liblte/phy/phch/pbch.h" #include "liblte/phy/common/fft.h" +#include "liblte/phy/agc/agc.h" /************************************************************** * @@ -66,7 +67,7 @@ typedef enum LIBLTE_API { SF_FIND, SF_TRACK} ue_sync_state_t; #define SYNC_PBCH_NOF_PORTS 2 #define TRACK_MAX_LOST 10 -#define PAR_THRESHOLD_FIND 20 +#define PSS_THRESHOLD 1 #define NOF_MIB_DECODES 10 @@ -82,6 +83,7 @@ typedef struct LIBLTE_API { ue_sync_state_t state; cf_t *input_buffer; + cf_t *receive_buffer; cf_t *sf_symbols; cf_t *ce[SYNC_PBCH_NOF_PORTS]; @@ -100,6 +102,7 @@ typedef struct LIBLTE_API { float cur_cfo; /* Variables for PBCH decoding */ + agc_t agc; pbch_mib_t mib; lte_fft_t fft; chest_t chest; diff --git a/lte/phy/include/liblte/phy/sync/sync.h b/lte/phy/include/liblte/phy/sync/sync.h index 6f40777dd..8dddbc7b5 100644 --- a/lte/phy/include/liblte/phy/sync/sync.h +++ b/lte/phy/include/liblte/phy/sync/sync.h @@ -60,7 +60,7 @@ typedef struct LIBLTE_API { enum sync_pss_det pss_mode; float find_threshold; float track_threshold; - float peak_to_avg; + float peak_value; uint32_t N_id_2; uint32_t N_id_1; uint32_t slot_id; @@ -113,7 +113,7 @@ LIBLTE_API void sync_pss_det_peak_to_avg(sync_t *q); LIBLTE_API uint32_t sync_get_slot_id(sync_t *q); /* Gets the last peak-to-average ratio */ -LIBLTE_API float sync_get_peak_to_avg(sync_t *q); +LIBLTE_API float sync_get_peak_value(sync_t *q); /* Gets the N_id_2 from the last call to synch_run() */ LIBLTE_API uint32_t sync_get_N_id_2(sync_t *q); diff --git a/lte/phy/include/liblte/phy/utils/vector.h b/lte/phy/include/liblte/phy/utils/vector.h index 1b0547cb9..369428fb9 100644 --- a/lte/phy/include/liblte/phy/utils/vector.h +++ b/lte/phy/include/liblte/phy/utils/vector.h @@ -76,7 +76,12 @@ LIBLTE_API void vec_prod_ccc(cf_t *x, cf_t *y, cf_t *z, uint32_t len); /* vector product (element-wise) */ LIBLTE_API void vec_prod_cfc(cf_t *x, float *y, cf_t *z, uint32_t len); +/* conjugate vector product (element-wise) */ +LIBLTE_API void vec_prod_conj_ccc(cf_t *x, cf_t *y, cf_t *z, uint32_t len); + +/* Dot-product */ LIBLTE_API cf_t vec_dot_prod_ccc(cf_t *x, cf_t *y, uint32_t len); +LIBLTE_API cf_t vec_dot_prod_conj_ccc(cf_t *x, cf_t *y, uint32_t len); LIBLTE_API float vec_dot_prod_fff(float *x, float *y, uint32_t len); /* z=x/y vector division (element-wise) */ diff --git a/lte/phy/lib/agc/src/agc.c b/lte/phy/lib/agc/src/agc.c new file mode 100644 index 000000000..e377ac1be --- /dev/null +++ b/lte/phy/lib/agc/src/agc.c @@ -0,0 +1,79 @@ +/** + * + * \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 "liblte/phy/utils/debug.h" + +#include "liblte/phy/agc/agc.h" +#include "liblte/phy/utils/vector.h" +#include "liblte/phy/utils/debug.h" + + +int agc_init (agc_t *q) { + bzero(q, sizeof(agc_t)); + q->bandwidth = AGC_DEFAULT_BW; + q->lock = false; + q->gain = 1.0; + q->y_out = 1.0; + return LIBLTE_SUCCESS; +} + +void agc_free(agc_t *q) { + bzero(q, sizeof(agc_t)); +} + +void agc_set_bandwidth(agc_t *q, float bandwidth) { + q->bandwidth = bandwidth; +} + +float agc_get_rssi(agc_t *q) { + return 1.0/q->gain; +} + +void agc_lock(agc_t *q, bool enable) { + q->lock = enable; +} + +void agc_push(agc_t *q, cf_t *input, cf_t *output, uint32_t len) { + + // Apply current gain to input signal + vec_sc_prod_cfc(input, q->gain, output, len); + + // compute output energy estimate + float y = sqrtf(crealf(vec_dot_prod_conj_ccc(output, output, len))/len); + + q->y_out = (1-q->bandwidth) * q->y_out + q->bandwidth * y; + if (!q->lock) { + q->gain *= expf(-0.5*q->bandwidth*logf(q->y_out)); + } +} diff --git a/lte/phy/lib/phch/src/ue_dl.c b/lte/phy/lib/phch/src/ue_dl.c index 707f89917..e48b28f62 100644 --- a/lte/phy/lib/phch/src/ue_dl.c +++ b/lte/phy/lib/phch/src/ue_dl.c @@ -53,6 +53,7 @@ int ue_dl_init(ue_dl_t *q, q->user_rnti = user_rnti; q->pkt_errors = 0; q->pkts_total = 0; + q->nof_trials = 0; if (lte_fft_init(&q->fft, q->cell.cp, q->cell.nof_prb)) { fprintf(stderr, "Error initiating FFT\n"); @@ -135,10 +136,7 @@ void ue_dl_free(ue_dl_t *q) { } } -/* 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) +int ue_dl_receive(ue_dl_t *q, cf_t *input, char *data, uint32_t sf_idx, uint32_t sfn, uint16_t rnti) { uint32_t cfi, cfi_distance, i; ra_pdsch_t ra_dl; @@ -185,11 +183,11 @@ int ue_dl_process(ue_dl_t *q, cf_t *input, uint32_t sf_idx, uint32_t sfn, uint16 for (i=0;ipdcch, q->sf_symbols, q->ce, locations[i], sf_idx, cfi)) { fprintf(stderr, "Error extracting LLRs\n"); - return -1; + return LIBLTE_ERROR; } if (pdcch_decode_msg(&q->pdcch, &dci_msg, format, &crc_rem)) { fprintf(stderr, "Error decoding DCI msg\n"); - return -1; + return LIBLTE_ERROR; } INFO("Decoded DCI message RNTI: 0x%x\n", crc_rem); } @@ -198,7 +196,7 @@ int ue_dl_process(ue_dl_t *q, cf_t *input, uint32_t sf_idx, uint32_t sfn, uint16 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; + return LIBLTE_ERROR; } uint32_t rvidx; @@ -224,7 +222,7 @@ int ue_dl_process(ue_dl_t *q, cf_t *input, uint32_t sf_idx, uint32_t sfn, uint16 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; + return LIBLTE_ERROR; } } if (q->harq_process[0].mcs.mod > 0) { @@ -251,5 +249,9 @@ int ue_dl_process(ue_dl_t *q, cf_t *input, uint32_t sf_idx, uint32_t sfn, uint16 } } - return 0; + if (crc_rem == rnti) { + return ra_dl.mcs.tbs; + } else { + return 0; + } } diff --git a/lte/phy/lib/phch/src/ue_sync.c b/lte/phy/lib/phch/src/ue_sync.c index 7a73da125..bf19c5516 100644 --- a/lte/phy/lib/phch/src/ue_sync.c +++ b/lte/phy/lib/phch/src/ue_sync.c @@ -88,11 +88,15 @@ int ue_sync_init(ue_sync_t *q, INFO("Setting sampling frequency 1.92 MHz\n",0); q->set_rate_callback(q->stream, 1920000.0); + if (agc_init(&q->agc)) { + goto clean_exit; + } + if(sync_init(&q->s, CURRENT_SFLEN, CURRENT_FFTSIZE, CURRENT_FFTSIZE)) { goto clean_exit; } - sync_pss_det_peak_to_avg(&q->s); + sync_pss_det_absolute(&q->s); if (cfo_init(&q->cfocorr, MAXIMUM_SFLEN)) { fprintf(stderr, "Error initiating CFO\n"); @@ -104,6 +108,12 @@ int ue_sync_init(ue_sync_t *q, perror("malloc"); goto clean_exit; } + + q->receive_buffer = vec_malloc(3 * MAXIMUM_SFLEN * sizeof(cf_t)); + if (!q->receive_buffer) { + perror("malloc"); + goto clean_exit; + } q->sf_symbols = vec_malloc(MAXIMUM_SFLEN_RE * sizeof(cf_t)); if (!q->sf_symbols) { @@ -118,8 +128,7 @@ int ue_sync_init(ue_sync_t *q, } } - //float th = PAR_THRESHOLD_FIND * (1+(float) CURRENT_FFTSIZE/128/10); - sync_set_threshold(&q->s, PAR_THRESHOLD_FIND, PAR_THRESHOLD_FIND/4); + sync_set_threshold(&q->s, PSS_THRESHOLD, PSS_THRESHOLD); ret = LIBLTE_SUCCESS; } @@ -135,6 +144,9 @@ void ue_sync_free(ue_sync_t *q) { if (q->input_buffer) { free(q->input_buffer); } + if (q->receive_buffer) { + free(q->receive_buffer); + } if (q->sf_symbols) { free(q->sf_symbols); } @@ -146,6 +158,7 @@ void ue_sync_free(ue_sync_t *q) { mib_decoder_free(q); cfo_free(&q->cfocorr); sync_free(&q->s); + agc_free(&q->agc); } void ue_sync_set_threshold(ue_sync_t *q, float threshold) { @@ -398,10 +411,10 @@ static int receive_samples(ue_sync_t *q) { q->time_offset = -q->time_offset; } /* copy last part of the last subframe (use move since there could be overlapping) */ - memmove(q->input_buffer, &q->input_buffer[CURRENT_SFLEN-q->time_offset], q->time_offset*sizeof(cf_t)); + memcpy(q->receive_buffer, &q->input_buffer[CURRENT_SFLEN-q->time_offset], q->time_offset*sizeof(cf_t)); /* Get 1 subframe from the USRP getting more samples and keeping the previous samples, if any */ - if (q->recv_callback(q->stream, &q->input_buffer[q->time_offset], CURRENT_SFLEN - q->time_offset) < 0) { + if (q->recv_callback(q->stream, &q->receive_buffer[q->time_offset], CURRENT_SFLEN - q->time_offset) < 0) { return LIBLTE_ERROR; } @@ -426,6 +439,8 @@ int ue_sync_get_buffer(ue_sync_t *q, cf_t **sf_symbols) { return -1; } + agc_push(&q->agc, q->receive_buffer, q->input_buffer, CURRENT_SFLEN); + switch (q->state) { case SF_FIND: q->s.sss_en = true; @@ -437,7 +452,7 @@ int ue_sync_get_buffer(ue_sync_t *q, cf_t **sf_symbols) { return -1; } - DEBUG("Find PAR=%.2f\n", sync_get_peak_to_avg(&q->s)); + DEBUG("Find PAR=%.2f\n", sync_get_peak_value(&q->s)); if (ret == 1) { ret = find_peak_ok(q); diff --git a/lte/phy/lib/sync/src/pss.c b/lte/phy/lib/sync/src/pss.c index 4c8da1a26..29ca1608c 100644 --- a/lte/phy/lib/sync/src/pss.c +++ b/lte/phy/lib/sync/src/pss.c @@ -262,7 +262,7 @@ int pss_synch_find_pss(pss_synch_t *q, cf_t *input, vec_abs_cf(q->conv_output, q->conv_abs, conv_output_len); corr_peak_pos = vec_max_fi(q->conv_abs, conv_output_len); if (corr_peak_value) { - *corr_peak_value = q->conv_abs[corr_peak_pos]; + *corr_peak_value = q->conv_abs[corr_peak_pos] / conv_output_len; } if (corr_mean_value) { *corr_mean_value = vec_acc_ff(q->conv_abs, conv_output_len) diff --git a/lte/phy/lib/sync/src/sync.c b/lte/phy/lib/sync/src/sync.c index 28333e06a..bb62a806f 100644 --- a/lte/phy/lib/sync/src/sync.c +++ b/lte/phy/lib/sync/src/sync.c @@ -176,8 +176,8 @@ float sync_get_cfo(sync_t *q) { return q->cfo; } -float sync_get_peak_to_avg(sync_t *q) { - return q->peak_to_avg; +float sync_get_peak_value(sync_t *q) { + return q->peak_value; } void sync_cp_en(sync_t *q, bool enabled) { @@ -278,7 +278,6 @@ int sync_track(sync_t *q, cf_t *input, uint32_t offset, uint32_t *peak_position) fft_size_isvalid(q->fft_size)) { float peak_value, mean_value, *mean_ptr; - bool peak_detected; uint32_t peak_pos; pss_synch_set_N_id_2(&q->pss_track, q->N_id_2); @@ -291,20 +290,16 @@ int sync_track(sync_t *q, cf_t *input, uint32_t offset, uint32_t *peak_position) peak_pos = pss_synch_find_pss(&q->pss_track, &input[offset], &peak_value, mean_ptr); - peak_detected = false; if (q->pss_mode == ABSOLUTE) { - if (peak_value > q->track_threshold) { - peak_detected = true; - } + q->peak_value = peak_value; } else { - q->peak_to_avg = peak_value / mean_value; - if (q->peak_to_avg > q->track_threshold) { - peak_detected = true; - } + q->peak_value = peak_value / mean_value; } - DEBUG("PSS possible tracking peak pos=%d peak=%.2f par=%.2f threshold=%.2f\n", - peak_pos, peak_value, q->peak_to_avg, q->track_threshold); - if (peak_detected) { + + DEBUG("PSS possible tracking peak pos=%d peak=%.2f threshold=%.2f\n", + peak_pos, peak_value, q->track_threshold); + + if (peak_value > q->track_threshold) { q->cfo = pss_synch_cfo_compute(&q->pss_track, &input[offset+peak_pos-q->fft_size]); if (q->sss_en) { @@ -332,11 +327,16 @@ int sync_find(sync_t *q, cf_t *input, uint32_t *peak_position) { float max=-999; uint32_t i; int ret; - bool peak_detected; - + float *mean_ptr; + for (N_id_2=0;N_id_2<3;N_id_2++) { + if (q->pss_mode == ABSOLUTE) { + mean_ptr = NULL; + } else { + mean_ptr = &mean_value[N_id_2]; + } pss_synch_set_N_id_2(&q->pss_find, N_id_2); - ret = pss_synch_find_pss(&q->pss_find, input, &peak_value[N_id_2], &mean_value[N_id_2]); + ret = pss_synch_find_pss(&q->pss_find, input, &peak_value[N_id_2], mean_ptr); if (ret < 0) { fprintf(stderr, "Error finding PSS for N_id_2=%d\n", N_id_2); return LIBLTE_ERROR; @@ -351,32 +351,25 @@ int sync_find(sync_t *q, cf_t *input, uint32_t *peak_position) { } } - q->peak_to_avg = peak_value[N_id_2] / mean_value[N_id_2]; - - DEBUG("PSS possible peak N_id_2=%d, pos=%d peak=%.2f par=%.2f threshold=%.2f\n", - N_id_2, peak_pos[N_id_2], peak_value[N_id_2], q->peak_to_avg, q->find_threshold); - - /* If peak detected */ - peak_detected = false; if (peak_pos[N_id_2] > q->fft_size) { if (q->pss_mode == ABSOLUTE) { - if (peak_value[N_id_2] > q->find_threshold) { - peak_detected = true; - } + q->peak_value = peak_value[N_id_2]; } else { - if (q->peak_to_avg > q->find_threshold) { - peak_detected = true; - } + q->peak_value = peak_value[N_id_2] / mean_value[N_id_2]; } } - if (peak_detected) { + DEBUG("PSS possible peak N_id_2=%d, pos=%d peak=%.2f threshold=%.2f\n", + N_id_2, peak_pos[N_id_2], peak_value[N_id_2], q->find_threshold); + + /* If peak detected */ + if (q->peak_value > q->find_threshold) { q->N_id_2 = N_id_2; pss_synch_set_N_id_2(&q->pss_find, q->N_id_2); q->cfo = pss_synch_cfo_compute(&q->pss_find, &input[peak_pos[N_id_2]-q->fft_size]); DEBUG("PSS peak detected N_id_2=%d, pos=%d peak=%.2f par=%.2f th=%.2f cfo=%.4f\n", N_id_2, - peak_pos[N_id_2], peak_value[N_id_2], q->peak_to_avg, q->find_threshold, q->cfo); + peak_pos[N_id_2], peak_value[N_id_2], q->peak_value, q->find_threshold, q->cfo); if (q->sss_en) { if (sync_sss(q, input, peak_pos[q->N_id_2], q->detect_cp) < 0) { diff --git a/lte/phy/lib/utils/src/vector.c b/lte/phy/lib/utils/src/vector.c index 61ba4313c..1c7ad6275 100644 --- a/lte/phy/lib/utils/src/vector.c +++ b/lte/phy/lib/utils/src/vector.c @@ -281,6 +281,18 @@ void vec_prod_ccc(cf_t *x,cf_t *y, cf_t *z, uint32_t len) { #endif } + +void vec_prod_conj_ccc(cf_t *x,cf_t *y, cf_t *z, uint32_t len) { +#ifndef HAVE_VOLK_MULT2_CONJ_FUNCTION + int i; + for (i=0;i