From c57441d3f7baad195ff88b0397159000e8fd1cd2 Mon Sep 17 00:00:00 2001 From: ismagom Date: Thu, 24 Mar 2016 12:30:56 +0100 Subject: [PATCH] Integrated new synchronization --- matlab/tests/sync_test.m | 30 ++++++--- srslte/examples/pdsch_ue.c | 10 +-- srslte/include/srslte/ue/ue_dl.h | 9 +++ srslte/include/srslte/ue/ue_sync.h | 9 ++- srslte/lib/rf/src/rf_blade_imp.c | 16 +++-- srslte/lib/sync/src/pss.c | 2 +- srslte/lib/sync/src/sync.c | 22 ++++--- srslte/lib/sync/test/pss_usrp.c | 93 +++++++++++++++------------- srslte/lib/ue/src/ue_dl.c | 17 ++++++ srslte/lib/ue/src/ue_sync.c | 98 ++++++++++++++++++++---------- 10 files changed, 204 insertions(+), 102 deletions(-) diff --git a/matlab/tests/sync_test.m b/matlab/tests/sync_test.m index 029ac76a1..c71437aee 100644 --- a/matlab/tests/sync_test.m +++ b/matlab/tests/sync_test.m @@ -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 diff --git a/srslte/examples/pdsch_ue.c b/srslte/examples/pdsch_ue.c index 734d13d00..a00752dd8 100644 --- a/srslte/examples/pdsch_ue.c +++ b/srslte/examples/pdsch_ue.c @@ -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); diff --git a/srslte/include/srslte/ue/ue_dl.h b/srslte/include/srslte/ue/ue_dl.h index ef9565b4d..6af39645a 100644 --- a/srslte/include/srslte/ue/ue_dl.h +++ b/srslte/include/srslte/ue/ue_dl.h @@ -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, diff --git a/srslte/include/srslte/ue/ue_sync.h b/srslte/include/srslte/ue/ue_sync.h index 7900829e0..ccfcb123f 100644 --- a/srslte/include/srslte/ue/ue_sync.h +++ b/srslte/include/srslte/ue/ue_sync.h @@ -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; diff --git a/srslte/lib/rf/src/rf_blade_imp.c b/srslte/lib/rf/src/rf_blade_imp.c index cf9fc6e4b..ee7185c88 100644 --- a/srslte/lib/rf/src/rf_blade_imp.c +++ b/srslte/lib/rf/src/rf_blade_imp.c @@ -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; diff --git a/srslte/lib/sync/src/pss.c b/srslte/lib/sync/src/pss.c index d0c37e512..71304991f 100644 --- a/srslte/lib/sync/src/pss.c +++ b/srslte/lib/sync/src/pss.c @@ -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)); diff --git a/srslte/lib/sync/src/sync.c b/srslte/lib/sync/src/sync.c index ac1f9d8b2..4df16cc21 100644 --- a/srslte/lib/sync/src/sync.c +++ b/srslte/lib/sync/src/sync.c @@ -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"); diff --git a/srslte/lib/sync/test/pss_usrp.c b/srslte/lib/sync/test/pss_usrp.c index e96a4379c..3059970d7 100644 --- a/srslte/lib/sync/test/pss_usrp.c +++ b/srslte/lib/sync/test/pss_usrp.c @@ -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 diff --git a/srslte/lib/ue/src/ue_dl.c b/srslte/lib/ue/src/ue_dl.c index f1d917af2..f417df0ae 100644 --- a/srslte/lib/ue/src/ue_dl.c +++ b/srslte/lib/ue/src/ue_dl.c @@ -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; diff --git a/srslte/lib/ue/src/ue_sync.c b/srslte/lib/ue/src/ue_sync.c index b1fab4885..b39ee6ce3 100644 --- a/srslte/lib/ue/src/ue_sync.c +++ b/srslte/lib/ue/src/ue_sync.c @@ -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;