Integrated new synchronization

master
ismagom 9 years ago
parent 64515eb602
commit c57441d3f7

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

@ -449,6 +449,8 @@ int main(int argc, char **argv) {
fprintf(stderr, "Error calling srslte_ue_sync_work()\n"); 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 */ /* srslte_ue_sync_get_buffer returns 1 if successfully read 1 aligned subframe */
if (ret == 1) { if (ret == 1) {
switch (state) { switch (state) {
@ -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 (!prog_args.input_file_name) {
if (plot_track) { if (plot_track) {
@ -708,7 +710,7 @@ void *plot_thread_run(void *arg) {
for (i = 0; i < 12*ue_dl.cell.nof_prb; i++) { for (i = 0; i < 12*ue_dl.cell.nof_prb; i++) {
tmp_plot2[i] = cargf(ue_dl.ce[0][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 #endif
plot_scatter_setNewData(&pscatequal_pdcch, ue_dl.pdcch.d, 36*ue_dl.pdcch.nof_cce); 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/ra.h"
#include "srslte/phch/regs.h" #include "srslte/phch/regs.h"
#include "srslte/sync/cfo.h"
#include "srslte/utils/vector.h" #include "srslte/utils/vector.h"
#include "srslte/utils/debug.h" #include "srslte/utils/debug.h"
@ -67,6 +69,8 @@ typedef struct SRSLTE_API {
srslte_ofdm_t fft; srslte_ofdm_t fft;
srslte_chest_dl_t chest; srslte_chest_dl_t chest;
srslte_cfo_t sfo_correct;
srslte_pdsch_cfg_t pdsch_cfg; srslte_pdsch_cfg_t pdsch_cfg;
srslte_softbuffer_rx_t softbuffer; srslte_softbuffer_rx_t softbuffer;
srslte_ra_dl_dci_t dl_dci; srslte_ra_dl_dci_t dl_dci;
@ -87,6 +91,8 @@ typedef struct SRSLTE_API {
srslte_dci_msg_t pending_ul_dci_msg; srslte_dci_msg_t pending_ul_dci_msg;
uint16_t pending_ul_dci_rnti; uint16_t pending_ul_dci_rnti;
float sample_offset;
}srslte_ue_dl_t; }srslte_ue_dl_t;
/* This function shall be called just after the initial synchronization */ /* 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 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, SRSLTE_API int srslte_ue_dl_decode(srslte_ue_dl_t * q,
cf_t *input, cf_t *input,
uint8_t *data, uint8_t *data,

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

@ -240,11 +240,19 @@ 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)); fprintf(stderr, "Failed to set samplerate = %u: %s\n", (uint32_t) freq, bladerf_strerror(status));
return -1; return -1;
} }
if (handler->rx_rate < 2000000) {
status = bladerf_set_bandwidth(handler->dev, BLADERF_MODULE_RX, handler->rx_rate, &bw); status = bladerf_set_bandwidth(handler->dev, BLADERF_MODULE_RX, handler->rx_rate, &bw);
if (status != 0) { if (status != 0) {
fprintf(stderr, "Failed to set bandwidth = %u: %s\n", handler->rx_rate, bladerf_strerror(status)); fprintf(stderr, "Failed to set bandwidth = %u: %s\n", handler->rx_rate, bladerf_strerror(status));
return -1; 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); 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; 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 */ /* Correlate input with PSS sequence */
if (q->frame_size >= q->fft_size) { if (q->frame_size > 2*q->fft_size) {
#ifdef CONVOLUTION_FFT #ifdef CONVOLUTION_FFT
memcpy(q->tmp_input, input, q->frame_size * sizeof(cf_t)); 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->fft_size = fft_size;
q->frame_size = frame_size; q->frame_size = frame_size;
q->max_offset = max_offset; q->max_offset = max_offset;
q->sss_alg = SSS_DIFF; q->sss_alg = SSS_FULL;
q->enable_cfo_corr = true; q->enable_cfo_corr = true;
for (int i=0;i<2;i++) { for (int i=0;i<2;i++) {
@ -228,8 +228,12 @@ srslte_cp_t srslte_sync_get_cp(srslte_sync_t *q) {
void srslte_sync_set_cp(srslte_sync_t *q, srslte_cp_t cp) { void srslte_sync_set_cp(srslte_sync_t *q, srslte_cp_t cp) {
q->cp = 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->cp_len = SRSLTE_CP_ISNORM(q->cp)?SRSLTE_CP_LEN_NORM(1,q->fft_size):SRSLTE_CP_LEN_EXT(q->fft_size);
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; 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) { void srslte_sync_set_sss_algorithm(srslte_sync_t *q, sss_alg_t alg) {
q->sss_alg = alg; q->sss_alg = alg;
@ -354,10 +358,12 @@ int srslte_sync_find(srslte_sync_t *q, cf_t *input, uint32_t find_offset, uint32
*peak_position = 0; *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; uint32_t cp_offset = 0;
if (q->enable_cfo_corr) { 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); cf_t cp_corr_max = srslte_cp_synch_corr_output(&q->cp_synch, cp_offset);
float cfo = -carg(cp_corr_max) / M_PI / 2; 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); 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) { if (q->find_cfo_i && q->enable_cfo_corr) {
float peak_value; float peak_value;
float max_peak_value = -99; float max_peak_value = -99;
@ -435,8 +442,9 @@ int srslte_sync_find(srslte_sync_t *q, cf_t *input, uint32_t find_offset, uint32
ret = 0; 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", 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, peak_pos, q->peak_value, q->threshold, q->sf_idx, 15*(q->cfo_i+q->mean_cfo)); 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)) { } else if (srslte_N_id_2_isvalid(q->N_id_2)) {
fprintf(stderr, "Must call srslte_sync_set_N_id_2() first!\n"); fprintf(stderr, "Must call srslte_sync_set_N_id_2() first!\n");

@ -40,7 +40,7 @@
#ifndef DISABLE_GRAPHICS #ifndef DISABLE_GRAPHICS
void init_plots(); 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); void do_plots_sss(float *corr_m0, float *corr_m1);
#endif #endif
@ -134,6 +134,7 @@ int main(int argc, char **argv) {
float mean_peak; float mean_peak;
uint32_t nof_det, nof_nodet, nof_nopeak, nof_nopeakdet; uint32_t nof_det, nof_nodet, nof_nopeak, nof_nopeakdet;
cf_t ce[SRSLTE_PSS_LEN]; cf_t ce[SRSLTE_PSS_LEN];
float sfo = 0;
parse_args(argc, argv); parse_args(argc, argv);
@ -190,7 +191,7 @@ int main(int argc, char **argv) {
if (srslte_sss_synch_init(&sss, fft_size)) { if (srslte_sss_synch_init(&sss, fft_size)) {
fprintf(stderr, "Error initializing SSS object\n"); fprintf(stderr, "Error initializing SSS object\n");
return SRSLTE_ERROR; exit(-1);
} }
srslte_sss_synch_set_N_id_2(&sss, N_id_2); srslte_sss_synch_set_N_id_2(&sss, N_id_2);
@ -217,6 +218,11 @@ int main(int argc, char **argv) {
bzero(&ssync, sizeof(srslte_sync_t)); bzero(&ssync, sizeof(srslte_sync_t));
ssync.fft_size = fft_size; 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) { while(frame_cnt < nof_frames || nof_frames == -1) {
n = srslte_rf_recv(&rf, buffer, flen - peak_offset, 1); n = srslte_rf_recv(&rf, buffer, flen - peak_offset, 1);
if (n < 0) { if (n < 0) {
@ -253,7 +259,7 @@ int main(int argc, char **argv) {
// Find SSS // 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)); 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) { 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) { if (srslte_sss_synch_N_id_1(&sss, m0, m1) != N_id_1) {
sss_error2++; sss_error2++;
} }
@ -294,6 +300,18 @@ int main(int argc, char **argv) {
nof_nodet++; 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 (frame_cnt > 100) {
if (abs(last_peak-peak_idx) > 4) { if (abs(last_peak-peak_idx) > 4) {
if (peak_value >= threshold) { if (peak_value >= threshold) {
@ -301,37 +319,47 @@ int main(int argc, char **argv) {
} }
nof_nopeak++; 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++; 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()) { if (SRSLTE_VERBOSE_ISINFO()) {
printf("\n"); printf("\n");
} }
#ifndef DISABLE_GRAPHICS #ifndef DISABLE_GRAPHICS
if (!disable_plots) if (!disable_plots) {
do_plots(pss.conv_output_avg, pss.conv_output_avg[peak_idx], pss.fft_size+pss.frame_size-1, ce); do_plots_pss(pss.conv_output_avg, pss.conv_output_avg[peak_idx], pss.fft_size+pss.frame_size-1);
}
#endif #endif
last_peak = peak_idx; last_peak = peak_idx;
} }
srslte_sss_synch_free(&sss);
srslte_pss_synch_free(&pss); srslte_pss_synch_free(&pss);
free(buffer); free(buffer);
srslte_rf_close(&rf); srslte_rf_close(&rf);
printf("Ok\n"); printf("Ok\n");
exit(0); exit(0);
} }
@ -349,7 +377,7 @@ extern cf_t *tmp2;
plot_real_t pssout; plot_real_t pssout;
//plot_complex_t pce; //plot_complex_t pce;
plot_real_t psss1;//, psss2; plot_real_t psss1;
float tmp[1000000]; float tmp[1000000];
cf_t tmpce[SRSLTE_PSS_LEN]; cf_t tmpce[SRSLTE_PSS_LEN];
@ -375,35 +403,18 @@ void init_plots() {
plot_real_setTitle(&psss1, "SSS xCorr m0"); plot_real_setTitle(&psss1, "SSS xCorr m0");
plot_real_setLabels(&psss1, "Index", "Absolute value"); plot_real_setLabels(&psss1, "Index", "Absolute value");
plot_real_setYAxisScale(&psss1, 0, 1); 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]) { void do_plots_pss(float *corr, float peak, uint32_t size) {
srslte_vec_sc_prod_fff(corr,1./energy,tmp, size); srslte_vec_sc_prod_fff(corr,1./peak,tmp, size);
plot_real_setNewData(&pssout, 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_sss(float *corr_m0, float *corr_m1) { void do_plots_sss(float *corr_m0, float *corr_m1) {
if (m0_value > 0) if (m0_value > 0)
srslte_vec_sc_prod_fff(corr_m0,1./m0_value,corr_m0, SRSLTE_SSS_N); srslte_vec_sc_prod_fff(corr_m0,1./m0_value,corr_m0, SRSLTE_SSS_N);
plot_real_setNewData(&psss1, 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);
} }
#endif #endif

@ -97,6 +97,10 @@ int srslte_ue_dl_init(srslte_ue_dl_t *q,
fprintf(stderr, "Error initiating soft buffer\n"); fprintf(stderr, "Error initiating soft buffer\n");
goto clean_exit; 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)); q->sf_symbols = srslte_vec_malloc(CURRENT_SFLEN_RE * sizeof(cf_t));
if (!q->sf_symbols) { if (!q->sf_symbols) {
perror("malloc"); perror("malloc");
@ -132,6 +136,7 @@ void srslte_ue_dl_free(srslte_ue_dl_t *q) {
srslte_phich_free(&q->phich); srslte_phich_free(&q->phich);
srslte_pdcch_free(&q->pdcch); srslte_pdcch_free(&q->pdcch);
srslte_pdsch_free(&q->pdsch); srslte_pdsch_free(&q->pdsch);
srslte_cfo_free(&q->sfo_correct);
srslte_softbuffer_rx_free(&q->softbuffer); srslte_softbuffer_rx_free(&q->softbuffer);
if (q->sf_symbols) { if (q->sf_symbols) {
free(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)); 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: /** Applies the following operations to a subframe of synchronized samples:
* - OFDM demodulation * - OFDM demodulation
* - Channel estimation * - 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 */ /* Run FFT for all subframe data */
srslte_ofdm_rx_sf(&q->fft, input, q->sf_symbols); 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); return srslte_ue_dl_decode_estimate(q, sf_idx, cfi);
} else { } else {
return SRSLTE_ERROR_INVALID_INPUTS; return SRSLTE_ERROR_INVALID_INPUTS;

@ -41,9 +41,10 @@
#define MAX_TIME_OFFSET 128 #define MAX_TIME_OFFSET 128
cf_t dummy[MAX_TIME_OFFSET]; cf_t dummy[MAX_TIME_OFFSET];
#define TRACK_MAX_LOST 4 #define TRACK_MAX_LOST 10
#define TRACK_FRAME_SIZE 16 #define TRACK_FRAME_SIZE 16
#define FIND_NOF_AVG_FRAMES 2 #define FIND_NOF_AVG_FRAMES 2
#define SAMPLE_OFFSET_MEAN_LEN 100
cf_t dummy_offset_buffer[1024*1024]; cf_t dummy_offset_buffer[1024*1024];
@ -153,10 +154,17 @@ int srslte_ue_sync_init(srslte_ue_sync_t *q,
fprintf(stderr, "Error initiating sync find\n"); fprintf(stderr, "Error initiating sync find\n");
goto clean_exit; goto clean_exit;
} }
if (cell.id == 1000) {
if(srslte_sync_init(&q->strack, q->frame_len, TRACK_FRAME_SIZE, q->fft_size)) { if(srslte_sync_init(&q->strack, q->frame_len, TRACK_FRAME_SIZE, q->fft_size)) {
fprintf(stderr, "Error initiating sync track\n"); fprintf(stderr, "Error initiating sync track\n");
goto clean_exit; 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) { if (cell.id == 1000) {
/* If the cell id is unknown, enable CP detection on find */ /* If the cell id is unknown, enable CP detection on find */
@ -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->sfind, 0.9);
srslte_sync_set_cfo_ema_alpha(&q->strack, 0.2); 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->sfind, false);
srslte_sync_cfo_i_detec_en(&q->strack, true); srslte_sync_cfo_i_detec_en(&q->strack, false);
srslte_sync_set_threshold(&q->sfind, 1.5); srslte_sync_set_threshold(&q->sfind, 1.5);
q->nof_avg_find_frames = FIND_NOF_AVG_FRAMES; 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->sfind, false);
srslte_sync_cp_en(&q->strack, false); srslte_sync_cp_en(&q->strack, false);
srslte_sync_cfo_i_detec_en(&q->sfind, true); srslte_sync_cfo_i_detec_en(&q->sfind, false);
srslte_sync_cfo_i_detec_en(&q->strack, true); 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->sfind, 0.7);
srslte_sync_set_cfo_ema_alpha(&q->strack, 0.01); 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_em_alpha(&q->sfind, 1);
srslte_sync_set_threshold(&q->sfind, 4.0); srslte_sync_set_threshold(&q->sfind, 4.0);
srslte_sync_set_em_alpha(&q->strack, 0.1); srslte_sync_set_em_alpha(&q->strack, 1.3);
srslte_sync_set_threshold(&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) { 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) { void srslte_ue_sync_decode_sss_on_track(srslte_ue_sync_t *q, bool enabled) {
@ -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_no_cnt = 0;
q->frame_total_cnt = 0; q->frame_total_cnt = 0;
q->frame_find_cnt = 0; q->frame_find_cnt = 0;
q->mean_time_offset = 0; q->mean_sample_offset = 0;
/* Goto Tracking state */ /* Goto Tracking state */
q->state = SF_TRACK; 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->sf_idx = srslte_sync_get_sf_idx(&q->strack);
q->frame_no_cnt++; q->frame_no_cnt++;
if (q->frame_no_cnt >= TRACK_MAX_LOST) { 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; q->state = SF_FIND;
} }
} else { } else {
@ -347,27 +356,47 @@ static int track_peak_ok(srslte_ue_sync_t *q, uint32_t track_idx) {
} }
// Adjust time offset // Adjust time offset
q->time_offset = ((int) track_idx - (int) q->strack.max_offset/2 - (int) q->strack.fft_size); 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);
if (q->time_offset) { /* compute cumulative moving average time offset */
INFO("Time offset adjustment: %d samples\n", q->time_offset); 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);
/* compute cumulative moving average time offset */ printf("\n\nTime offset adjustment: %d samples (%d-%d), mean SFO: %f\n",
q->mean_time_offset = (float) SRSLTE_VEC_CMA((float) q->time_offset, q->mean_time_offset, q->frame_total_cnt); 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), /* If the PSS peak is beyond the frame (we sample too slowly),
discard the offseted samples to align next frame */ discard the offseted samples to align next frame */
if (q->time_offset > 0 && q->time_offset < MAX_TIME_OFFSET) { if (q->next_rf_sample_offset > 0 && q->next_rf_sample_offset < MAX_TIME_OFFSET) {
DEBUG("Positive time offset %d samples. Mean time offset %f.\n", q->time_offset, q->mean_time_offset); DEBUG("Positive time offset %d samples.\n", q->next_rf_sample_offset);
if (q->recv_callback(q->stream, dummy, (uint32_t) q->time_offset, &q->last_timestamp) < 0) { 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"); fprintf(stderr, "Error receiving from USRP\n");
return SRSLTE_ERROR; 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++; q->frame_ok_cnt++;
return 1; 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 */ /* if we missed too many PSS go back to FIND and consider this frame unsynchronized */
q->frame_no_cnt++; q->frame_no_cnt++;
if (q->frame_no_cnt >= TRACK_MAX_LOST) { 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; q->state = SF_FIND;
return 0; return 0;
} else { } 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, /* A negative time offset means there are samples in our buffer for the next subframe,
because we are sampling too fast. because we are sampling too fast.
*/ */
if (q->time_offset < 0) { if (q->next_rf_sample_offset < 0) {
q->time_offset = -q->time_offset; 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 */ /* 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; return SRSLTE_ERROR;
} }
/* reset time offset */ /* reset time offset */
q->time_offset = 0; q->next_rf_sample_offset = 0;
return SRSLTE_SUCCESS; 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_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, ret = srslte_sync_find(&q->strack, input_buffer,
q->frame_len - q->sf_len/2 - q->fft_size - q->strack.max_offset/2, q->frame_len - q->sf_len/2 - q->fft_size - q->strack.max_offset/2,
&track_idx); &track_idx);
@ -557,8 +588,9 @@ void srslte_ue_sync_reset(srslte_ue_sync_t *q) {
q->frame_ok_cnt = 0; q->frame_ok_cnt = 0;
q->frame_no_cnt = 0; q->frame_no_cnt = 0;
q->frame_total_cnt = 0; q->frame_total_cnt = 0;
q->mean_time_offset = 0.0; q->mean_sample_offset = 0.0;
q->time_offset = 0; q->mean_sfo = 0;
q->next_rf_sample_offset = 0;
q->frame_find_cnt = 0; q->frame_find_cnt = 0;
#ifdef MEASURE_EXEC_TIME #ifdef MEASURE_EXEC_TIME
q->mean_exec_time = 0; q->mean_exec_time = 0;

Loading…
Cancel
Save