Using short correlation for peak tracking

This commit is contained in:
ismagom 2014-12-11 09:06:58 +00:00
parent ecbd3dda2c
commit 5a032c4316
11 changed files with 113 additions and 64 deletions

View File

@ -48,7 +48,7 @@ float gain_offset = B210_DEFAULT_GAIN_CORREC;
cell_detect_cfg_t cell_detect_config = {
100, // nof_frames_total
3.0 // early-stops cell detection if mean PSR is above this value
6.0 // early-stops cell detection if mean PSR is above this value
};
/**********************************************************************
@ -149,16 +149,11 @@ int main(int argc, char **argv) {
uint8_t bch_payload[BCH_PAYLOAD_LEN], bch_payload_unpacked[BCH_PAYLOAD_LEN];
uint32_t sfn_offset;
float rssi_utra=0,rssi=0, rsrp=0, rsrq=0, snr=0;
cf_t *nullce[MAX_PORTS];
uint32_t si_window_length;
scheduling_info_t sinfo[MAX_SINFO];
scheduling_info_t *sinfo_sib4 = NULL;
uint32_t neighbour_cell_ids[MAX_NEIGHBOUR_CELLS];
for (int i=0;i<MAX_PORTS;i++) {
nullce[i] = NULL;
}
cf_t *ce[MAX_PORTS];
parse_args(&prog_args, argc, argv);
@ -174,6 +169,10 @@ int main(int argc, char **argv) {
cuhd_set_rx_freq(uhd, (double) prog_args.uhd_freq);
cuhd_rx_wait_lo_locked(uhd);
printf("Tunning receiver to %.3f MHz\n", (double ) prog_args.uhd_freq/1000000);
if (detect_and_decode_cell(&cell_detect_config, uhd, prog_args.force_N_id_2, &cell)) {
fprintf(stderr, "Cell not found\n");
@ -215,12 +214,17 @@ int main(int argc, char **argv) {
int sf_re = SF_LEN_RE(cell.nof_prb, cell.cp);
cf_t *sf_symbols = vec_malloc(sf_re * sizeof(cf_t));
for (int i=0;i<MAX_PORTS;i++) {
ce[i] = vec_malloc(sizeof(cf_t) * sf_re);
}
cuhd_start_rx_stream(uhd);
bool sib4_window_start = false;
uint32_t sib4_window_cnt = 0;
/* Main loop */
while (sf_cnt < prog_args.nof_subframes || prog_args.nof_subframes == -1) {
@ -307,9 +311,7 @@ int main(int argc, char **argv) {
/* We are looking for SI Blocks, search only in appropiate places */
if (sib4_window_start && !(ue_sync_get_sfidx(&ue_sync) == 5 && (sfn%2)==0))
{
/* printf("[%d/%d]: Trying SIB4 in SF: %d, SFN: %d\n", sib4_window_cnt, si_window_length,
ue_sync_get_sfidx(&ue_sync), sfn);
*/ n = ue_dl_decode_sib(&ue_dl, sf_buffer, data, ue_sync_get_sfidx(&ue_sync),
n = ue_dl_decode_sib(&ue_dl, sf_buffer, data, ue_sync_get_sfidx(&ue_sync),
((int) ceilf((float)3*sib4_window_cnt/2))%4);
if (n < 0) {
fprintf(stderr, "Error decoding UE DL\n");fflush(stdout);
@ -340,7 +342,7 @@ int main(int argc, char **argv) {
/* Run FFT for all subframe data */
lte_fft_run_sf(&fft, sf_buffer, sf_symbols);
chest_dl_estimate(&chest, sf_symbols, nullce, ue_sync_get_sfidx(&ue_sync));
chest_dl_estimate(&chest, sf_symbols, ce, ue_sync_get_sfidx(&ue_sync));
rssi = VEC_CMA(vec_avg_power_cf(sf_buffer,SF_LEN(lte_symbol_sz(cell.nof_prb))),rssi,nframes);
rssi_utra = VEC_CMA(chest_dl_get_rssi(&chest),rssi_utra,nframes);
@ -357,7 +359,10 @@ int main(int argc, char **argv) {
10*log10(rssi*1000)-gain_offset,
10*log10(rssi_utra*1000)-gain_offset,
10*log10(rsrp*1000)-gain_offset,
10*log10(rsrq), 10*log10(snr));
10*log10(rsrq), 10*log10(snr));
if (verbose != VERBOSE_NONE) {
printf("\n");
}
}
break;
}

View File

@ -43,7 +43,7 @@
#ifndef DISABLE_GRAPHICS
void init_plots();
void do_plots(ue_dl_t *q, uint32_t sf_idx);
void do_plots(ue_dl_t *q, uint32_t sf_idx, ue_sync_t *qs);
#endif
@ -175,12 +175,6 @@ int main(int argc, char **argv) {
uint32_t sfn_offset;
parse_args(&prog_args, argc, argv);
#ifndef DISABLE_GRAPHICS
if (!prog_args.disable_plots) {
init_plots();
}
#endif
printf("Opening UHD device...\n");
if (cuhd_open(prog_args.uhd_args, &uhd)) {
fprintf(stderr, "Error opening uhd\n");
@ -225,11 +219,19 @@ int main(int argc, char **argv) {
// Register Ctrl+C handler
signal(SIGINT, sig_int_handler);
#ifndef DISABLE_GRAPHICS
if (!prog_args.disable_plots) {
init_plots();
}
#endif
cuhd_start_rx_stream(uhd);
// Variables for measurements
uint32_t nframes=0;
float rsrp=0, rsrq=0, snr=0;
float rsrp=1.0, rsrq=1.0, snr=1.0;
/* Main loop */
while (!go_exit && (sf_cnt < prog_args.nof_subframes || prog_args.nof_subframes == -1)) {
@ -276,6 +278,10 @@ int main(int argc, char **argv) {
rsrp = VEC_CMA(chest_dl_get_rsrp(&ue_dl.chest),rsrp,nframes);
snr = VEC_CMA(chest_dl_get_snr(&ue_dl.chest),snr,nframes);
nframes++;
if (isnan(rsrq)) {
rsrq = 0;
}
// Plot and Printf
if (ue_sync_get_sfidx(&ue_sync) == 0) {
@ -298,7 +304,7 @@ int main(int argc, char **argv) {
}
#ifndef DISABLE_GRAPHICS
if (!prog_args.disable_plots && ue_sync_get_sfidx(&ue_sync) == 5) {
do_plots(&ue_dl, 5);
do_plots(&ue_dl, 5, &ue_sync);
}
#endif
} else if (ret == 0) {
@ -332,12 +338,13 @@ int main(int argc, char **argv) {
#include "liblte/graphics/plot.h"
plot_real_t poutfft;
plot_real_t poutfft, p_sync;
plot_real_t pce;
plot_scatter_t pscatrecv, pscatequal, pscatequal_pdcch;
plot_scatter_t pscatequal, pscatequal_pdcch;
float tmp_plot[SLOT_LEN_RE(MAX_PRB, CPNORM)];
float tmp_plot2[SLOT_LEN_RE(MAX_PRB, CPNORM)];
float tmp_plot3[SLOT_LEN_RE(MAX_PRB, CPNORM)];
void init_plots() {
plot_init();
@ -351,10 +358,9 @@ void init_plots() {
plot_real_setLabels(&pce, "Index", "dB");
plot_real_setYAxisScale(&pce, -60, 0);
plot_scatter_init(&pscatrecv);
plot_scatter_setTitle(&pscatrecv, "Received Symbols");
plot_scatter_setXAxisScale(&pscatrecv, -4, 4);
plot_scatter_setYAxisScale(&pscatrecv, -4, 4);
plot_real_init(&p_sync);
plot_real_setTitle(&p_sync, "PSS Cross-Corr abs value");
plot_real_setYAxisScale(&p_sync, 0, 1);
plot_scatter_init(&pscatequal);
plot_scatter_setTitle(&pscatequal, "PDSCH - Equalized Symbols");
@ -368,7 +374,7 @@ void init_plots() {
}
void do_plots(ue_dl_t *q, uint32_t sf_idx) {
void do_plots(ue_dl_t *q, uint32_t sf_idx, ue_sync_t *qs) {
int i;
uint32_t nof_re = SLOT_LEN_RE(q->cell.nof_prb, q->cell.cp);
uint32_t nof_symbols = q->harq_process[0].prb_alloc.re_sf[sf_idx];
@ -386,7 +392,10 @@ void do_plots(ue_dl_t *q, uint32_t sf_idx) {
}
plot_real_setNewData(&poutfft, tmp_plot, nof_re);
plot_real_setNewData(&pce, tmp_plot2, REFSIGNAL_NUM_SF(q->cell.nof_prb,0));
plot_scatter_setNewData(&pscatrecv, q->pdsch.pdsch_symbols[0], nof_symbols);
int max = vec_max_fi(qs->strack.pss.conv_output_avg, qs->strack.pss.frame_size+qs->strack.pss.fft_size-1);
vec_sc_prod_fff(qs->strack.pss.conv_output_avg, 1/qs->strack.pss.conv_output_avg[max], tmp_plot2, qs->strack.pss.frame_size+qs->strack.pss.fft_size-1);
plot_real_setNewData(&p_sync, tmp_plot2, qs->strack.pss.frame_size);
plot_scatter_setNewData(&pscatequal, q->pdsch.pdsch_d, nof_symbols);
plot_scatter_setNewData(&pscatequal_pdcch, q->pdcch.pdcch_d, 36*q->pdcch.nof_cce);
}

View File

@ -39,8 +39,6 @@
typedef _Complex float cf_t; /* this is only a shortcut */
#define CONVOLUTION_FFT
#define DEFAULT_CORRELATION_TH 10000
#define DEFAULT_NOSYNC_TIMEOUT 5
#define PSS_LEN 62
#define PSS_RE 6*12

View File

@ -37,6 +37,7 @@ typedef _Complex float cf_t;
#define MAX(a,b) ((a)>(b)?(a):(b))
#define MIN(a,b) ((a)<(b)?(a):(b))
// Cumulative moving average
#define VEC_CMA(data, average, n) ((average) + ((data) - (average)) / ((n)+1))

View File

@ -373,6 +373,7 @@ float chest_dl_get_rssi(chest_dl_t *q) {
*/
float chest_dl_get_rsrq(chest_dl_t *q) {
return q->cell.nof_prb*q->rsrp[0] / q->rssi[0];
}
float chest_dl_get_rsrp(chest_dl_t *q) {

View File

@ -290,20 +290,27 @@ int pss_synch_find_pss(pss_synch_t *q, cf_t *input, float *corr_peak_value)
memcpy(q->tmp_input, input, q->frame_size * sizeof(cf_t));
/* Correlate input with PSS sequence */
#ifdef CONVOLUTION_FFT
conv_output_len = conv_fft_cc_run(&q->conv_fft, q->tmp_input,
q->pss_signal_freq[q->N_id_2], q->conv_output);
#else
conv_output_len = conv_cc(input, q->pss_signal_freq[q->N_id_2], q->conv_output, q->frame_size, q->fft_size);
#endif
if (q->frame_size >= q->fft_size) {
#ifdef CONVOLUTION_FFT
conv_output_len = conv_fft_cc_run(&q->conv_fft, q->tmp_input,
q->pss_signal_freq[q->N_id_2], q->conv_output);
#else
conv_output_len = conv_cc(input, q->pss_signal_freq[q->N_id_2], q->conv_output, q->frame_size, q->fft_size);
#endif
} else {
for (int i=0;i<q->frame_size;i++) {
q->conv_output[i] = vec_dot_prod_ccc(q->pss_signal_freq[q->N_id_2], &input[i], q->fft_size);
}
conv_output_len = q->frame_size;
}
#ifdef PSS_ABS_SQUARE
vec_abs_square_cf(q->conv_output, q->conv_output_abs, conv_output_len-1);
#else
vec_abs_cf(q->conv_output, q->conv_output_abs, conv_output_len-1);
#endif
#ifdef PSS_ABS_SQUARE
vec_abs_square_cf(q->conv_output, q->conv_output_abs, conv_output_len-1);
#else
vec_abs_cf(q->conv_output, q->conv_output_abs, conv_output_len-1);
#endif
vec_sc_prod_fff(q->conv_output_abs, q->ema_alpha, q->conv_output_abs, conv_output_len-1);
vec_sc_prod_fff(q->conv_output_avg, 1-q->ema_alpha, q->conv_output_avg, conv_output_len-1);
@ -321,16 +328,35 @@ int pss_synch_find_pss(pss_synch_t *q, cf_t *input, float *corr_peak_value)
pl_ub ++;
}
// Find end of peak lobe to the left
int pl_lb = corr_peak_pos-1;
while(q->conv_output_avg[pl_lb-1] <= q->conv_output_avg[pl_lb] && pl_lb > 1) {
pl_lb --;
int pl_lb;
if (corr_peak_pos > 0) {
pl_lb = corr_peak_pos-1;
while(q->conv_output_avg[pl_lb-1] <= q->conv_output_avg[pl_lb] && pl_lb > 1) {
pl_lb --;
}
} else {
pl_lb = 0;
}
int sl_distance_right = conv_output_len-1-pl_ub;
if (sl_distance_right < 0) {
sl_distance_right = 0;
}
int sl_distance_left = pl_lb;
int sl_right = pl_ub+vec_max_fi(&q->conv_output_avg[pl_ub], conv_output_len-1 - pl_ub);
int sl_left = vec_max_fi(q->conv_output_avg, pl_lb);
int sl_right = pl_ub+vec_max_fi(&q->conv_output_avg[pl_ub], sl_distance_right);
int sl_left = vec_max_fi(q->conv_output_avg, sl_distance_left);
float side_lobe_value = MAX(q->conv_output_avg[sl_right], q->conv_output_avg[sl_left]);
if (corr_peak_value) {
*corr_peak_value = q->conv_output_avg[corr_peak_pos]/side_lobe_value;
if (*corr_peak_value < 2.0) {
INFO("pl_ub=%d, pl_lb=%d, sl_right: %d (%.2f), sl_left: %d (%.2f), PSR: %.2f/%.2f=%.2f\n", pl_ub, pl_lb,
sl_right, 1000000*q->conv_output_avg[sl_right],
sl_left, 1000000*q->conv_output_avg[sl_left],
1000000*q->conv_output_avg[corr_peak_pos], 1000000*side_lobe_value,*corr_peak_value
);
}
}
#else
if (corr_peak_value) {

View File

@ -52,7 +52,6 @@ int sync_init(sync_t *q, uint32_t frame_size, uint32_t fft_size) {
int ret = LIBLTE_ERROR_INVALID_INPUTS;
if (q != NULL &&
frame_size >= fft_size &&
frame_size <= 307200 &&
fft_size_isvalid(fft_size))
{

View File

@ -53,14 +53,16 @@ float uhd_gain=40.0, uhd_freq=-1.0;
int nof_frames = -1;
uint32_t fft_size=64;
float threshold = 0.4;
int N_id_2_sync = -1;
int N_id_2_sync = -1;
lte_cp_t cp=CPNORM;
void usage(char *prog) {
printf("Usage: %s [adgtvnp] -f rx_frequency_hz -i cell_id\n", prog);
printf("Usage: %s [aedgtvnp] -f rx_frequency_hz -i cell_id\n", prog);
printf("\t-a UHD args [Default %s]\n", uhd_args);
printf("\t-g UHD Gain [Default %.2f dB]\n", uhd_gain);
printf("\t-n nof_frames [Default %d]\n", nof_frames);
printf("\t-l N_id_2 to sync [Default use cell_id]\n");
printf("\t-e Extended CP [Default Normal]\n", fft_size);
printf("\t-s symbol_sz [Default %d]\n", fft_size);
printf("\t-t threshold [Default %.2f]\n", threshold);
#ifndef DISABLE_GRAPHICS
@ -73,7 +75,7 @@ void usage(char *prog) {
void parse_args(int argc, char **argv) {
int opt;
while ((opt = getopt(argc, argv, "adgtvsfil")) != -1) {
while ((opt = getopt(argc, argv, "adgetvsfil")) != -1) {
switch (opt) {
case 'a':
uhd_args = argv[optind];
@ -87,6 +89,9 @@ void parse_args(int argc, char **argv) {
case 't':
threshold = atof(argv[optind]);
break;
case 'e':
cp = CPEXT;
break;
case 'i':
cell_id = atoi(argv[optind]);
break;
@ -154,6 +159,7 @@ int main(int argc, char **argv) {
fprintf(stderr, "Error initiating PSS\n");
exit(-1);
}
if (pss_synch_set_N_id_2(&pss, N_id_2_sync)) {
fprintf(stderr, "Error setting N_id_2=%d\n",N_id_2_sync);
exit(-1);
@ -233,7 +239,7 @@ int main(int argc, char **argv) {
}
// Find SSS
int sss_idx = peak_idx-2*fft_size-CP(fft_size, CPNORM_LEN);
int sss_idx = peak_idx-2*fft_size-(CP_ISNORM(cp)?CP(fft_size, CPNORM_LEN):CP(fft_size, CPEXT_LEN));
if (sss_idx >= 0 && sss_idx < flen-fft_size) {
sss_synch_m0m1_partial(&sss, &buffer[sss_idx], 3, NULL, &m0, &m0_value, &m1, &m1_value);
if (sss_synch_N_id_1(&sss, m0, m1) != N_id_1) {

View File

@ -75,6 +75,7 @@ int ue_celldetect_init_max(ue_celldetect_t * q, uint32_t max_frames_total) {
sync_set_threshold(&q->sfind, 1.0);
sync_sss_en(&q->sfind, true);
sync_set_sss_algorithm(&q->sfind, SSS_PARTIAL_3);
sync_set_em_alpha(&q->sfind, 0.01);
q->max_frames_total = max_frames_total;
q->nof_frames_total = CS_DEFAULT_NOFFRAMES_TOTAL;

View File

@ -49,6 +49,7 @@ cf_t dummy[MAX_TIME_OFFSET];
#define FIND_THRESHOLD 4.0
#define TRACK_THRESHOLD 2.0
#define TRACK_MAX_LOST 10
#define TRACK_FRAME_SIZE 32
int ue_sync_init(ue_sync_t *q,
@ -76,7 +77,7 @@ int ue_sync_init(ue_sync_t *q,
fprintf(stderr, "Error initiating sync find\n");
goto clean_exit;
}
if(sync_init(&q->strack, CURRENT_FFTSIZE, CURRENT_FFTSIZE)) {
if(sync_init(&q->strack, TRACK_FRAME_SIZE, CURRENT_FFTSIZE)) {
fprintf(stderr, "Error initiating sync track\n");
goto clean_exit;
}
@ -190,7 +191,7 @@ int track_peak_ok(ue_sync_t *q, uint32_t track_idx) {
q->sf_idx = sync_get_sf_idx(&q->strack);
}
} else {
q->time_offset = ((int) track_idx - (int) CURRENT_FFTSIZE);
q->time_offset = ((int) track_idx - (int) q->strack.frame_size/2);
/* If the PSS peak is beyond the frame (we sample too slowly),
discard the offseted samples to align next frame */
@ -305,7 +306,7 @@ int ue_sync_get_buffer(ue_sync_t *q, cf_t **sf_symbols) {
track_idx = 0;
/* track pss around the middle of the subframe, where the PSS is */
ret = sync_find(&q->strack, q->input_buffer, CURRENT_SFLEN/2-CURRENT_FFTSIZE, &track_idx);
ret = sync_find(&q->strack, q->input_buffer, CURRENT_SFLEN/2-CURRENT_FFTSIZE-q->strack.frame_size/2, &track_idx);
if (ret < 0) {
fprintf(stderr, "Error tracking correlation peak\n");
return LIBLTE_ERROR;

View File

@ -91,15 +91,17 @@ uint32_t conv_fft_cc_run(conv_fft_cc_t *q, cf_t *input, cf_t *filter, cf_t *outp
}
uint32_t conv_cc(cf_t *input, cf_t *filter, cf_t *output, uint32_t input_len, uint32_t filter_len) {
uint32_t i,j;
uint32_t output_len;
output_len=input_len+filter_len-1;
for (i=0;i<input_len;i++) {
for (j=0;j<filter_len;j++) {
output[i+j]+=input[i]*filter[j];
}
uint32_t i;
uint32_t M = filter_len;
uint32_t N = input_len;
for (i=0;i<M;i++) {
output[i]=vec_dot_prod_ccc(&input[i],&filter[i],i);
}
return output_len;
for (;i<M+N-1;i++) {
output[i] = vec_dot_prod_ccc(&input[i-M], filter, M);
}
return M+N-1;
}
/* Centered convolution. Returns the same number of input elements. Equivalent to conv(x,h,'same') in matlab.