Integrated new synchronization

master
ismagom 9 years ago
parent 64515eb602
commit c57441d3f7

@ -1,11 +1,12 @@
clear
enb = lteTestModel('1.1','1.4MHz');
Ntrials = 100;
SNR_values = linspace(-8,0,6);
Ntrials = 1;
SNR_values = 100;%linspace(-8,0,6);
flen=1920;
fft_size=128;
fading_enabled = true;
tx_offset = randi(50,1,Ntrials);
tx_offset = 10;%randi(50,1,Ntrials);
tx_signal = lteTestModelTool(enb);
pss_idx = flen/2-fft_size+1:flen/2;
@ -34,7 +35,7 @@ addpath('../sync/')
t = (0:length(tx_signal)-1).'/fft_size;
L=16;
L=fft_size;
M=4;
diff=zeros(length(SNR_values),M);
for snr_idx=1:length(SNR_values)
@ -42,8 +43,11 @@ for snr_idx=1:length(SNR_values)
SNRdB = SNR_values(snr_idx);
rx_offset = zeros(M,length(tx_offset));
for i=1:Ntrials
[rx_signal, chinfo] = lteFadingChannel(cfg,tx_signal);
%rx_signal = tx_signal;
if fading_enabled
[rx_signal, chinfo] = lteFadingChannel(cfg,tx_signal);
else
rx_signal = tx_signal;
end
SNR = 10^(SNRdB/10); % Linear SNR
rx = [zeros(tx_offset(i),1); rx_signal];
N0 = tx_power/(sqrt(2.0)*SNR);
@ -58,20 +62,26 @@ for snr_idx=1:length(SNR_values)
% srsLTE in tracking mode
track_offset=2+rx_offset(2,i)+flen/2-fft_size-L/2;
[rx_offset(3,i),corr_lt_track] = srslte_pss(enb,rx(track_offset:end),L);
rx_offset(3,i) = rx_offset(2,i) + (rx_offset(3,i) - fft_size - L/2) + 1;
rx_offset(3,i) = rx_offset(2,i) + (rx_offset(3,i) - L/2) + 1;
% CP based
[rx_offset(4,i), corr_lt_cp] = srslte_cp_synch(enb, rx);
end
diff(snr_idx,:)=mean(abs(rx_offset-repmat(tx_offset,M,1) - chinfo.ChannelFilterDelay),2);
if fading_enabled
ch_delay = chinfo.ChannelFilterDelay;
else
ch_delay = 0;
end
diff(snr_idx,:)=mean(abs(rx_offset-repmat(tx_offset,M,1) - ch_delay),2);
end
if (Ntrials == 1)
disp(rx_offset)
disp(diff)
%plot(1:flen,abs(corr_res(1:flen)),1:flen,abs(corr_lt(1:flen)));
t=1:fft_size;
plot(t,abs(corr_lt_cp(t)));
t=1:L;
plot(t,abs(corr_lt_track(t)));
%plot(lambda)
%plot(1:L,abs(corr_lt_track),[L/2, L/2], [0 max(abs(corr_lt_track))])
grid on

@ -448,7 +448,9 @@ int main(int argc, char **argv) {
if (ret < 0) {
fprintf(stderr, "Error calling srslte_ue_sync_work()\n");
}
srslte_ue_dl_set_sample_offset(&ue_dl, srslte_ue_sync_get_sfo(&ue_sync));
/* srslte_ue_sync_get_buffer returns 1 if successfully read 1 aligned subframe */
if (ret == 1) {
switch (state) {
@ -482,7 +484,7 @@ int main(int argc, char **argv) {
}
if (decode_pdsch) {
if (prog_args.rnti != SRSLTE_SIRNTI) {
if (prog_args.rnti != SRSLTE_SIRNTI) {
n = srslte_ue_dl_decode(&ue_dl, &sf_buffer[prog_args.time_offset], data, srslte_ue_sync_get_sfidx(&ue_sync));
} else {
// RV for SIB1 is predefined
@ -682,7 +684,7 @@ void *plot_thread_run(void *arg) {
}
}
plot_real_setNewData(&pce, tmp_plot2, 12*ue_dl.cell.nof_prb);
plot_real_setNewData(&pce, tmp_plot2, i);
if (!prog_args.input_file_name) {
if (plot_track) {
@ -708,7 +710,7 @@ void *plot_thread_run(void *arg) {
for (i = 0; i < 12*ue_dl.cell.nof_prb; i++) {
tmp_plot2[i] = cargf(ue_dl.ce[0][i]);
}
plot_real_setNewData(&pce_arg, tmp_plot2, 12*ue_dl.cell.nof_prb);
plot_real_setNewData(&pce_arg, tmp_plot2, i);
#endif
plot_scatter_setNewData(&pscatequal_pdcch, ue_dl.pdcch.d, 36*ue_dl.pdcch.nof_cce);

@ -53,6 +53,8 @@
#include "srslte/phch/ra.h"
#include "srslte/phch/regs.h"
#include "srslte/sync/cfo.h"
#include "srslte/utils/vector.h"
#include "srslte/utils/debug.h"
@ -67,6 +69,8 @@ typedef struct SRSLTE_API {
srslte_ofdm_t fft;
srslte_chest_dl_t chest;
srslte_cfo_t sfo_correct;
srslte_pdsch_cfg_t pdsch_cfg;
srslte_softbuffer_rx_t softbuffer;
srslte_ra_dl_dci_t dl_dci;
@ -87,6 +91,8 @@ typedef struct SRSLTE_API {
srslte_dci_msg_t pending_ul_dci_msg;
uint16_t pending_ul_dci_rnti;
float sample_offset;
}srslte_ue_dl_t;
/* This function shall be called just after the initial synchronization */
@ -131,6 +137,9 @@ SRSLTE_API int srslte_ue_dl_find_dl_dci_type(srslte_ue_dl_t *q,
SRSLTE_API uint32_t srslte_ue_dl_get_ncce(srslte_ue_dl_t *q);
SRSLTE_API void srslte_ue_dl_set_sample_offset(srslte_ue_dl_t * q,
float sample_offset);
SRSLTE_API int srslte_ue_dl_decode(srslte_ue_dl_t * q,
cf_t *input,
uint8_t *data,

@ -109,8 +109,13 @@ typedef struct SRSLTE_API {
bool correct_cfo;
uint32_t peak_idx;
int time_offset;
float mean_time_offset;
int next_rf_sample_offset;
int last_sample_offset;
int max_sample_offset;
int min_sample_offset;
float mean_sample_offset;
float mean_sfo;
#ifdef MEASURE_EXEC_TIME
float mean_exec_time;

@ -240,10 +240,18 @@ double rf_blade_set_rx_srate(void *h, double freq)
fprintf(stderr, "Failed to set samplerate = %u: %s\n", (uint32_t) freq, bladerf_strerror(status));
return -1;
}
status = bladerf_set_bandwidth(handler->dev, BLADERF_MODULE_RX, handler->rx_rate, &bw);
if (status != 0) {
fprintf(stderr, "Failed to set bandwidth = %u: %s\n", handler->rx_rate, bladerf_strerror(status));
return -1;
if (handler->rx_rate < 2000000) {
status = bladerf_set_bandwidth(handler->dev, BLADERF_MODULE_RX, handler->rx_rate, &bw);
if (status != 0) {
fprintf(stderr, "Failed to set bandwidth = %u: %s\n", handler->rx_rate, bladerf_strerror(status));
return -1;
}
} else {
status = bladerf_set_bandwidth(handler->dev, BLADERF_MODULE_RX, handler->rx_rate*0.8, &bw);
if (status != 0) {
fprintf(stderr, "Failed to set bandwidth = %u: %s\n", handler->rx_rate, bladerf_strerror(status));
return -1;
}
}
printf("Set RX sampling rate %.2f Mhz, filter BW: %.2f Mhz\n", (float) handler->rx_rate/1e6, (float) bw/1e6);
return (double) handler->rx_rate;

@ -303,7 +303,7 @@ int srslte_pss_synch_find_pss(srslte_pss_synch_t *q, cf_t *input, float *corr_pe
}
/* Correlate input with PSS sequence */
if (q->frame_size >= q->fft_size) {
if (q->frame_size > 2*q->fft_size) {
#ifdef CONVOLUTION_FFT
memcpy(q->tmp_input, input, q->frame_size * sizeof(cf_t));

@ -71,7 +71,7 @@ int srslte_sync_init(srslte_sync_t *q, uint32_t frame_size, uint32_t max_offset,
q->fft_size = fft_size;
q->frame_size = frame_size;
q->max_offset = max_offset;
q->sss_alg = SSS_DIFF;
q->sss_alg = SSS_FULL;
q->enable_cfo_corr = true;
for (int i=0;i<2;i++) {
@ -228,7 +228,11 @@ srslte_cp_t srslte_sync_get_cp(srslte_sync_t *q) {
void srslte_sync_set_cp(srslte_sync_t *q, srslte_cp_t cp) {
q->cp = cp;
q->cp_len = SRSLTE_CP_ISNORM(q->cp)?SRSLTE_CP_LEN_NORM(1,q->fft_size):SRSLTE_CP_LEN_EXT(q->fft_size);
q->nof_symbols = q->frame_size/(q->fft_size+q->cp_len)-1;
if (q->frame_size < q->fft_size) {
q->nof_symbols = 1;
} else {
q->nof_symbols = q->frame_size/(q->fft_size+q->cp_len)-1;
}
}
void srslte_sync_set_sss_algorithm(srslte_sync_t *q, sss_alg_t alg) {
@ -354,10 +358,12 @@ int srslte_sync_find(srslte_sync_t *q, cf_t *input, uint32_t find_offset, uint32
*peak_position = 0;
}
/* Estimate CFO using CP */
/* Estimate CFO using CP before computing the PSS correlation as in:
* Shoujun Huang, et al, "Joint Time and Frequency Offset Estimation in LTE Downlink"
*/
uint32_t cp_offset = 0;
if (q->enable_cfo_corr) {
cp_offset = srslte_cp_synch(&q->cp_synch, input, q->nof_symbols, q->nof_symbols, SRSLTE_CP_LEN_NORM(1,q->fft_size));
cp_offset = srslte_cp_synch(&q->cp_synch, input, q->max_offset, q->nof_symbols, SRSLTE_CP_LEN_NORM(1,q->fft_size));
cf_t cp_corr_max = srslte_cp_synch_corr_output(&q->cp_synch, cp_offset);
float cfo = -carg(cp_corr_max) / M_PI / 2;
@ -374,6 +380,7 @@ int srslte_sync_find(srslte_sync_t *q, cf_t *input, uint32_t find_offset, uint32
srslte_cfo_correct(&q->cfocorr, input, input, -q->mean_cfo / q->fft_size);
}
/* If integer CFO is enabled, find max PSS correlation for shifted +1/0/-1 integer versions */
if (q->find_cfo_i && q->enable_cfo_corr) {
float peak_value;
float max_peak_value = -99;
@ -393,7 +400,7 @@ int srslte_sync_find(srslte_sync_t *q, cf_t *input, uint32_t find_offset, uint32
srslte_vec_prod_ccc(input, q->cfo_i_corr[q->cfo_i<0?0:1], input, q->frame_size);
INFO("Compensating cfo_i=%d\n", q->cfo_i);
}
} else {
} else {
srslte_pss_synch_set_N_id_2(&q->pss, q->N_id_2);
peak_pos = srslte_pss_synch_find_pss(&q->pss, &input[find_offset], &q->peak_value);
if (peak_pos < 0) {
@ -435,8 +442,9 @@ int srslte_sync_find(srslte_sync_t *q, cf_t *input, uint32_t find_offset, uint32
ret = 0;
}
DEBUG("SYNC ret=%d N_id_2=%d find_offset=%d pos=%d peak=%.2f threshold=%.2f sf_idx=%d, CFO=%.3f KHz\n",
ret, q->N_id_2, find_offset, peak_pos, q->peak_value, q->threshold, q->sf_idx, 15*(q->cfo_i+q->mean_cfo));
DEBUG("SYNC ret=%d N_id_2=%d find_offset=%d frame_len=%d, pos=%d peak=%.2f threshold=%.2f sf_idx=%d, CFO=%.3f KHz\n",
ret, q->N_id_2, find_offset, q->frame_size, peak_pos, q->peak_value,
q->threshold, q->sf_idx, 15*(q->cfo_i+q->mean_cfo));
} else if (srslte_N_id_2_isvalid(q->N_id_2)) {
fprintf(stderr, "Must call srslte_sync_set_N_id_2() first!\n");

@ -40,7 +40,7 @@
#ifndef DISABLE_GRAPHICS
void init_plots();
void do_plots(float *corr, float energy, uint32_t size, cf_t ce[SRSLTE_PSS_LEN]);
void do_plots_pss(float *corr, float energy, uint32_t size);
void do_plots_sss(float *corr_m0, float *corr_m1);
#endif
@ -134,6 +134,7 @@ int main(int argc, char **argv) {
float mean_peak;
uint32_t nof_det, nof_nodet, nof_nopeak, nof_nopeakdet;
cf_t ce[SRSLTE_PSS_LEN];
float sfo = 0;
parse_args(argc, argv);
@ -190,9 +191,9 @@ int main(int argc, char **argv) {
if (srslte_sss_synch_init(&sss, fft_size)) {
fprintf(stderr, "Error initializing SSS object\n");
return SRSLTE_ERROR;
exit(-1);
}
srslte_sss_synch_set_N_id_2(&sss, N_id_2);
printf("N_id_2: %d\n", N_id_2);
@ -217,6 +218,11 @@ int main(int argc, char **argv) {
bzero(&ssync, sizeof(srslte_sync_t));
ssync.fft_size = fft_size;
uint32_t max_peak = 0;
uint32_t max_peak_ = 0;
uint32_t min_peak = fft_size;
uint32_t min_peak_ = fft_size;
while(frame_cnt < nof_frames || nof_frames == -1) {
n = srslte_rf_recv(&rf, buffer, flen - peak_offset, 1);
if (n < 0) {
@ -229,7 +235,7 @@ int main(int argc, char **argv) {
fprintf(stderr, "Error finding PSS peak\n");
exit(-1);
}
mean_peak = SRSLTE_VEC_CMA(peak_value, mean_peak, frame_cnt);
if (peak_value >= threshold) {
@ -253,7 +259,7 @@ int main(int argc, char **argv) {
// Find SSS
int sss_idx = peak_idx-2*fft_size-(SRSLTE_CP_ISNORM(cp)?SRSLTE_CP_LEN(fft_size, SRSLTE_CP_NORM_LEN):SRSLTE_CP_LEN(fft_size, SRSLTE_CP_EXT_LEN));
if (sss_idx >= 0 && sss_idx < flen-fft_size) {
srslte_sss_synch_m0m1_partial(&sss, &buffer[sss_idx], 3, NULL, &m0, &m0_value, &m1, &m1_value);
srslte_sss_synch_m0m1_partial(&sss, &buffer[sss_idx], 1, ce, &m0, &m0_value, &m1, &m1_value);
if (srslte_sss_synch_N_id_1(&sss, m0, m1) != N_id_1) {
sss_error2++;
}
@ -294,6 +300,18 @@ int main(int argc, char **argv) {
nof_nodet++;
}
printf("[%5d]: Pos: %5d (%d-%d), PSR: %4.1f (~%4.1f) Pdet: %4.2f, "
"FA: %4.2f, CFO: %+4.1f KHz, SFO: %+.2f Hz SSSmiss: %4.2f/%4.2f/%4.2f CPNorm: %.0f%%\r",
frame_cnt,
peak_idx, min_peak_, max_peak_,
peak_value, mean_peak,
(float) nof_det/frame_cnt,
(float) nof_nopeakdet/frame_cnt, mean_cfo*15, sfo,
(float) sss_error1/nof_det,(float) sss_error2/nof_det,(float) sss_error3/nof_det,
(float) cp_is_norm/nof_det * 100);
if (frame_cnt > 100) {
if (abs(last_peak-peak_idx) > 4) {
if (peak_value >= threshold) {
@ -301,37 +319,47 @@ int main(int argc, char **argv) {
}
nof_nopeak++;
}
sfo = SRSLTE_VEC_CMA((peak_idx - last_peak)/5e-3, sfo, frame_cnt);
int frame_idx = frame_cnt % 200;
uint32_t peak_offset_symbol = peak_idx%fft_size;
if (peak_offset_symbol > max_peak) {
max_peak = peak_offset_symbol;
}
if (peak_offset_symbol < min_peak) {
min_peak = peak_offset_symbol;
}
if (!frame_idx) {
max_peak_ = max_peak;
min_peak_ = min_peak;
max_peak = 0;
min_peak = fft_size;
}
}
frame_cnt++;
printf("[%5d]: Pos: %5d, PSR: %4.1f (~%4.1f) Pdet: %4.2f, "
"FA: %4.2f, CFO: %+4.1f KHz SSSmiss: %4.2f/%4.2f/%4.2f CPNorm: %.0f%%\r",
frame_cnt,
peak_idx,
peak_value, mean_peak,
(float) nof_det/frame_cnt,
(float) nof_nopeakdet/frame_cnt, mean_cfo*15,
(float) sss_error1/nof_det,(float) sss_error2/nof_det,(float) sss_error3/nof_det,
(float) cp_is_norm/nof_det * 100);
if (SRSLTE_VERBOSE_ISINFO()) {
printf("\n");
}
#ifndef DISABLE_GRAPHICS
if (!disable_plots)
do_plots(pss.conv_output_avg, pss.conv_output_avg[peak_idx], pss.fft_size+pss.frame_size-1, ce);
if (!disable_plots) {
do_plots_pss(pss.conv_output_avg, pss.conv_output_avg[peak_idx], pss.fft_size+pss.frame_size-1);
}
#endif
last_peak = peak_idx;
}
srslte_sss_synch_free(&sss);
srslte_pss_synch_free(&pss);
free(buffer);
srslte_rf_close(&rf);
printf("Ok\n");
exit(0);
}
@ -349,7 +377,7 @@ extern cf_t *tmp2;
plot_real_t pssout;
//plot_complex_t pce;
plot_real_t psss1;//, psss2;
plot_real_t psss1;
float tmp[1000000];
cf_t tmpce[SRSLTE_PSS_LEN];
@ -375,35 +403,18 @@ void init_plots() {
plot_real_setTitle(&psss1, "SSS xCorr m0");
plot_real_setLabels(&psss1, "Index", "Absolute value");
plot_real_setYAxisScale(&psss1, 0, 1);
/*
plot_real_init(&psss2);
plot_real_setTitle(&psss2, "SSS xCorr m1");
plot_real_setLabels(&psss2, "Index", "Absolute value");
plot_real_setYAxisScale(&psss2, 0, 1);
*/
}
void do_plots(float *corr, float energy, uint32_t size, cf_t ce[SRSLTE_PSS_LEN]) {
srslte_vec_sc_prod_fff(corr,1./energy,tmp, size);
plot_real_setNewData(&pssout, tmp, size);
// float norm = srslte_vec_avg_power_cf(ce, SRSLTE_PSS_LEN);
// srslte_vec_sc_prod_cfc(ce, 1.0/sqrt(norm), tmpce, SRSLTE_PSS_LEN);
//plot_complex_setNewData(&pce, tmpce, SRSLTE_PSS_LEN);
void do_plots_pss(float *corr, float peak, uint32_t size) {
srslte_vec_sc_prod_fff(corr,1./peak,tmp, size);
plot_real_setNewData(&pssout, tmp, size);
}
void do_plots_sss(float *corr_m0, float *corr_m1) {
if (m0_value > 0)
srslte_vec_sc_prod_fff(corr_m0,1./m0_value,corr_m0, SRSLTE_SSS_N);
plot_real_setNewData(&psss1, corr_m0, SRSLTE_SSS_N);
// if (m1_value > 0)
// srslte_vec_sc_prod_fff(corr_m1,1./m1_value,corr_m1, SRSLTE_SSS_N);
// plot_real_setNewData(&psss2, corr_m1, SRSLTE_SSS_N);
plot_real_setNewData(&psss1, corr_m0, SRSLTE_SSS_N);
}
#endif

@ -97,6 +97,10 @@ int srslte_ue_dl_init(srslte_ue_dl_t *q,
fprintf(stderr, "Error initiating soft buffer\n");
goto clean_exit;
}
if (srslte_cfo_init(&q->sfo_correct, q->cell.nof_prb*SRSLTE_NRE)) {
fprintf(stderr, "Error initiating SFO correct\n");
goto clean_exit;
}
q->sf_symbols = srslte_vec_malloc(CURRENT_SFLEN_RE * sizeof(cf_t));
if (!q->sf_symbols) {
perror("malloc");
@ -132,6 +136,7 @@ void srslte_ue_dl_free(srslte_ue_dl_t *q) {
srslte_phich_free(&q->phich);
srslte_pdcch_free(&q->pdcch);
srslte_pdsch_free(&q->pdsch);
srslte_cfo_free(&q->sfo_correct);
srslte_softbuffer_rx_free(&q->softbuffer);
if (q->sf_symbols) {
free(q->sf_symbols);
@ -159,6 +164,10 @@ void srslte_ue_dl_reset(srslte_ue_dl_t *q) {
bzero(&q->pdsch_cfg, sizeof(srslte_pdsch_cfg_t));
}
void srslte_ue_dl_set_sample_offset(srslte_ue_dl_t * q, float sample_offset) {
q->sample_offset = sample_offset;
}
/** Applies the following operations to a subframe of synchronized samples:
* - OFDM demodulation
* - Channel estimation
@ -180,6 +189,14 @@ int srslte_ue_dl_decode_fft_estimate(srslte_ue_dl_t *q, cf_t *input, uint32_t sf
/* Run FFT for all subframe data */
srslte_ofdm_rx_sf(&q->fft, input, q->sf_symbols);
/* Correct SFO multiplying by complex exponential in the time domain */
for (int i=0;i<2*SRSLTE_CP_NSYMB(q->cell.cp);i++) {
srslte_cfo_correct(&q->sfo_correct,
&q->sf_symbols[i*q->cell.nof_prb*SRSLTE_NRE],
&q->sf_symbols[i*q->cell.nof_prb*SRSLTE_NRE],
q->sample_offset / q->fft.symbol_sz);
}
return srslte_ue_dl_decode_estimate(q, sf_idx, cfi);
} else {
return SRSLTE_ERROR_INVALID_INPUTS;

@ -41,9 +41,10 @@
#define MAX_TIME_OFFSET 128
cf_t dummy[MAX_TIME_OFFSET];
#define TRACK_MAX_LOST 4
#define TRACK_MAX_LOST 10
#define TRACK_FRAME_SIZE 16
#define FIND_NOF_AVG_FRAMES 2
#define SAMPLE_OFFSET_MEAN_LEN 100
cf_t dummy_offset_buffer[1024*1024];
@ -153,9 +154,16 @@ int srslte_ue_sync_init(srslte_ue_sync_t *q,
fprintf(stderr, "Error initiating sync find\n");
goto clean_exit;
}
if(srslte_sync_init(&q->strack, q->frame_len, TRACK_FRAME_SIZE, q->fft_size)) {
fprintf(stderr, "Error initiating sync track\n");
goto clean_exit;
if (cell.id == 1000) {
if(srslte_sync_init(&q->strack, q->frame_len, TRACK_FRAME_SIZE, q->fft_size)) {
fprintf(stderr, "Error initiating sync track\n");
goto clean_exit;
}
} else {
if(srslte_sync_init(&q->strack, q->frame_len, 3*SRSLTE_CP_LEN_NORM(1,q->fft_size), q->fft_size)) {
fprintf(stderr, "Error initiating sync track\n");
goto clean_exit;
}
}
if (cell.id == 1000) {
@ -166,8 +174,8 @@ int srslte_ue_sync_init(srslte_ue_sync_t *q,
srslte_sync_set_cfo_ema_alpha(&q->sfind, 0.9);
srslte_sync_set_cfo_ema_alpha(&q->strack, 0.2);
srslte_sync_cfo_i_detec_en(&q->sfind, true);
srslte_sync_cfo_i_detec_en(&q->strack, true);
srslte_sync_cfo_i_detec_en(&q->sfind, false);
srslte_sync_cfo_i_detec_en(&q->strack, false);
srslte_sync_set_threshold(&q->sfind, 1.5);
q->nof_avg_find_frames = FIND_NOF_AVG_FRAMES;
@ -181,8 +189,8 @@ int srslte_ue_sync_init(srslte_ue_sync_t *q,
srslte_sync_cp_en(&q->sfind, false);
srslte_sync_cp_en(&q->strack, false);
srslte_sync_cfo_i_detec_en(&q->sfind, true);
srslte_sync_cfo_i_detec_en(&q->strack, true);
srslte_sync_cfo_i_detec_en(&q->sfind, false);
srslte_sync_cfo_i_detec_en(&q->strack, false);
srslte_sync_set_cfo_ema_alpha(&q->sfind, 0.7);
srslte_sync_set_cfo_ema_alpha(&q->strack, 0.01);
@ -194,8 +202,8 @@ int srslte_ue_sync_init(srslte_ue_sync_t *q,
srslte_sync_set_em_alpha(&q->sfind, 1);
srslte_sync_set_threshold(&q->sfind, 4.0);
srslte_sync_set_em_alpha(&q->strack, 0.1);
srslte_sync_set_threshold(&q->strack, 1.3);
srslte_sync_set_em_alpha(&q->strack, 1.3);
srslte_sync_set_threshold(&q->strack, 0.001);
}
@ -267,7 +275,8 @@ void srslte_ue_sync_set_cfo(srslte_ue_sync_t *q, float cfo) {
}
float srslte_ue_sync_get_sfo(srslte_ue_sync_t *q) {
return 5000*q->mean_time_offset;
//return 5000*q->mean_sample_offset;
return (float) q->last_sample_offset;
}
void srslte_ue_sync_decode_sss_on_track(srslte_ue_sync_t *q, bool enabled) {
@ -303,7 +312,7 @@ static int find_peak_ok(srslte_ue_sync_t *q, cf_t *input_buffer) {
if (q->frame_find_cnt >= q->nof_avg_find_frames || q->peak_idx < 2*q->fft_size) {
INFO("Realigning frame, reading %d samples\n", q->peak_idx+q->sf_len/2);
/* Receive the rest of the subframe so that we are subframe aligned*/
/* Receive the rest of the subframe so that we are subframe aligned */
if (q->recv_callback(q->stream, input_buffer, q->peak_idx+q->sf_len/2, &q->last_timestamp) < 0) {
return SRSLTE_ERROR;
}
@ -313,7 +322,7 @@ static int find_peak_ok(srslte_ue_sync_t *q, cf_t *input_buffer) {
q->frame_no_cnt = 0;
q->frame_total_cnt = 0;
q->frame_find_cnt = 0;
q->mean_time_offset = 0;
q->mean_sample_offset = 0;
/* Goto Tracking state */
q->state = SF_TRACK;
@ -339,7 +348,7 @@ static int track_peak_ok(srslte_ue_sync_t *q, uint32_t track_idx) {
q->sf_idx = srslte_sync_get_sf_idx(&q->strack);
q->frame_no_cnt++;
if (q->frame_no_cnt >= TRACK_MAX_LOST) {
INFO("\n%d frames lost. Going back to FIND\n", (int) q->frame_no_cnt);
printf("\n%d frames lost. Going back to FIND\n", (int) q->frame_no_cnt);
q->state = SF_FIND;
}
} else {
@ -347,27 +356,47 @@ static int track_peak_ok(srslte_ue_sync_t *q, uint32_t track_idx) {
}
// Adjust time offset
q->time_offset = ((int) track_idx - (int) q->strack.max_offset/2 - (int) q->strack.fft_size);
if (q->time_offset) {
INFO("Time offset adjustment: %d samples\n", q->time_offset);
}
uint32_t frame_idx = q->frame_ok_cnt%SAMPLE_OFFSET_MEAN_LEN;
q->last_sample_offset = ((int) track_idx - (int) q->strack.max_offset/2 - (int) q->strack.fft_size);
q->mean_sfo = SRSLTE_VEC_EMA(q->last_sample_offset, q->mean_sfo, 0.01);
/* compute cumulative moving average time offset */
q->mean_time_offset = (float) SRSLTE_VEC_CMA((float) q->time_offset, q->mean_time_offset, q->frame_total_cnt);
if (frame_idx) {
q->mean_sample_offset += (float) q->last_sample_offset/SAMPLE_OFFSET_MEAN_LEN;
if (q->last_sample_offset > q->max_sample_offset) {
q->max_sample_offset = q->last_sample_offset;
}
if (q->last_sample_offset < q->min_sample_offset) {
q->min_sample_offset = q->last_sample_offset;
}
DEBUG("idx=%d, offset=%d, mean=%f, sfo=%f\n", frame_idx, q->last_sample_offset, q->mean_sample_offset);
} else {
q->next_rf_sample_offset = (int) round(q->mean_sfo);
//q->mean_sfo = SRSLTE_VEC_EMA(q->mean_sample_offset, q->mean_sfo, 0.1);
printf("\n\nTime offset adjustment: %d samples (%d-%d), mean SFO: %f\n",
q->next_rf_sample_offset, q->min_sample_offset, q->max_sample_offset,
q->mean_sfo);
srslte_sync_reset(&q->strack);
q->mean_sample_offset = 0;
q->max_sample_offset = 0;
q->min_sample_offset = q->fft_size;
}
/* If the PSS peak is beyond the frame (we sample too slowly),
discard the offseted samples to align next frame */
if (q->time_offset > 0 && q->time_offset < MAX_TIME_OFFSET) {
DEBUG("Positive time offset %d samples. Mean time offset %f.\n", q->time_offset, q->mean_time_offset);
if (q->recv_callback(q->stream, dummy, (uint32_t) q->time_offset, &q->last_timestamp) < 0) {
if (q->next_rf_sample_offset > 0 && q->next_rf_sample_offset < MAX_TIME_OFFSET) {
DEBUG("Positive time offset %d samples.\n", q->next_rf_sample_offset);
if (q->recv_callback(q->stream, dummy, (uint32_t) q->next_rf_sample_offset, &q->last_timestamp) < 0) {
fprintf(stderr, "Error receiving from USRP\n");
return SRSLTE_ERROR;
}
q->time_offset = 0;
q->next_rf_sample_offset = 0;
}
q->peak_idx = q->sf_len/2 + q->time_offset;
q->peak_idx = q->sf_len/2 + q->last_sample_offset;
q->frame_ok_cnt++;
return 1;
@ -378,7 +407,7 @@ static int track_peak_no(srslte_ue_sync_t *q) {
/* if we missed too many PSS go back to FIND and consider this frame unsynchronized */
q->frame_no_cnt++;
if (q->frame_no_cnt >= TRACK_MAX_LOST) {
INFO("\n%d frames lost. Going back to FIND\n", (int) q->frame_no_cnt);
printf("\n%d frames lost. Going back to FIND\n", (int) q->frame_no_cnt);
q->state = SF_FIND;
return 0;
} else {
@ -394,17 +423,17 @@ static int receive_samples(srslte_ue_sync_t *q, cf_t *input_buffer) {
/* A negative time offset means there are samples in our buffer for the next subframe,
because we are sampling too fast.
*/
if (q->time_offset < 0) {
q->time_offset = -q->time_offset;
if (q->next_rf_sample_offset < 0) {
q->next_rf_sample_offset = -q->next_rf_sample_offset;
}
/* Get N subframes from the USRP getting more samples and keeping the previous samples, if any */
if (q->recv_callback(q->stream, &input_buffer[q->time_offset], q->frame_len - q->time_offset, &q->last_timestamp) < 0) {
if (q->recv_callback(q->stream, &input_buffer[q->next_rf_sample_offset], q->frame_len - q->next_rf_sample_offset, &q->last_timestamp) < 0) {
return SRSLTE_ERROR;
}
/* reset time offset */
q->time_offset = 0;
q->next_rf_sample_offset = 0;
return SRSLTE_SUCCESS;
}
@ -500,7 +529,9 @@ int srslte_ue_sync_zerocopy(srslte_ue_sync_t *q, cf_t *input_buffer) {
track_idx = 0;
/* track PSS/SSS around the expected PSS position */
/* Track PSS/SSS around the expected PSS position
* In tracking phase, the subframe carrying the PSS is always the last one of the frame
*/
ret = srslte_sync_find(&q->strack, input_buffer,
q->frame_len - q->sf_len/2 - q->fft_size - q->strack.max_offset/2,
&track_idx);
@ -557,8 +588,9 @@ void srslte_ue_sync_reset(srslte_ue_sync_t *q) {
q->frame_ok_cnt = 0;
q->frame_no_cnt = 0;
q->frame_total_cnt = 0;
q->mean_time_offset = 0.0;
q->time_offset = 0;
q->mean_sample_offset = 0.0;
q->mean_sfo = 0;
q->next_rf_sample_offset = 0;
q->frame_find_cnt = 0;
#ifdef MEASURE_EXEC_TIME
q->mean_exec_time = 0;

Loading…
Cancel
Save