Added AGC module

This commit is contained in:
ismagom 2014-07-21 17:54:25 +02:00
parent d99e4f5988
commit ecb30a9014
15 changed files with 286 additions and 76 deletions

View File

@ -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()

View File

@ -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) {

View File

@ -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) {

View File

@ -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) {

View File

@ -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 <stdbool.h>
#include <stdint.h>
#include <complex.h>
#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_

View File

@ -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);

View File

@ -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;

View File

@ -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);

View File

@ -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) */

79
lte/phy/lib/agc/src/agc.c Normal file
View File

@ -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 <string.h>
#include <strings.h>
#include <stdlib.h>
#include <math.h>
#include <complex.h>
#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));
}
}

View File

@ -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;i<nof_locations && crc_rem != rnti;i++) {
if (pdcch_extract_llr(&q->pdcch, 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;
}
}

View File

@ -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);

View File

@ -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)

View File

@ -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) {

View File

@ -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<len;i++) {
z[i] = x[i]*conjf(y[i]);
}
#else
volk_32fc_x2_multiply_conjugate_32fc(z,x,y,len);
#endif
}
void vec_div_ccc(cf_t *x, cf_t *y, cf_t *z, uint32_t len) {
int i;
for (i=0;i<len;i++) {
@ -314,6 +326,22 @@ cf_t vec_dot_prod_ccc(cf_t *x, cf_t *y, uint32_t len) {
#endif
}
cf_t vec_dot_prod_conj_ccc(cf_t *x, cf_t *y, uint32_t len) {
#ifdef HAVE_VOLK_DOTPROD_CONJ_FC_FUNCTION
cf_t res;
volk_32fc_x2_conjugate_dot_prod_32fc(&res, x, y, len);
return res;
#else
uint32_t i;
cf_t res = 0;
for (i=0;i<len;i++) {
res += x[i]*conjf(y[i]);
}
return res;
#endif
}
float vec_dot_prod_fff(float *x, float *y, uint32_t len) {
#ifdef HAVE_VOLK_DOTPROD_F_FUNCTION
float res;