From f31922f5f56da1eb9bf8ad84ffd8905a7fd20364 Mon Sep 17 00:00:00 2001 From: ismagom Date: Wed, 23 Mar 2016 10:24:27 +0100 Subject: [PATCH] Added matlab files to test synchronization --- matlab/sync/find_pss.m | 13 +- matlab/sync/find_pss_ac.m | 7 + matlab/tests/pdsch_bler_equal.m | 159 ++++++++++++++++++ matlab/tests/pdsch_decode_signal.m | 66 ++++++++ matlab/tests/pdsch_test_verify_unrm.m | 39 +++++ matlab/tests/sync_test.m | 83 ++++++--- .../include/srslte/ch_estimation/chest_dl.h | 4 + srslte/include/srslte/ue/ue_dl.h | 4 + srslte/lib/ch_estimation/src/chest_dl.c | 15 ++ srslte/lib/sync/src/pss.c | 14 +- srslte/lib/sync/src/sync.c | 8 +- srslte/lib/sync/test/pss_mex.c | 15 +- srslte/lib/ue/src/ue_dl.c | 12 +- srslte/lib/ue/src/ue_sync.c | 47 ++++-- 14 files changed, 427 insertions(+), 59 deletions(-) create mode 100644 matlab/sync/find_pss_ac.m create mode 100644 matlab/tests/pdsch_bler_equal.m create mode 100644 matlab/tests/pdsch_decode_signal.m create mode 100644 matlab/tests/pdsch_test_verify_unrm.m diff --git a/matlab/sync/find_pss.m b/matlab/sync/find_pss.m index 139173dab..1dbd4a4fb 100644 --- a/matlab/sync/find_pss.m +++ b/matlab/sync/find_pss.m @@ -7,12 +7,13 @@ function [ fs, cfo, p_m, w2] = find_pss( x, N_id_2) w2=conv(x,ccf); [m, fs]=max(abs(w2)); - y=ccf.*x(fs-128:fs-1); - y0=y(1:64); - y1=y(65:length(y)); + if (fs > 128 && fs < length(x)) + y=ccf.*x(fs-128:fs-1); + y0=y(1:64); + y1=y(65:length(y)); - cfo=angle(conj(sum(y0))*sum(y1))/pi; - p_m = m/mean(abs(w2)); - + cfo=angle(conj(sum(y0))*sum(y1))/pi; + p_m = m/mean(abs(w2)); + end end diff --git a/matlab/sync/find_pss_ac.m b/matlab/sync/find_pss_ac.m new file mode 100644 index 000000000..0bff75866 --- /dev/null +++ b/matlab/sync/find_pss_ac.m @@ -0,0 +1,7 @@ +function fs = find_pss_ac( x) + + w2=xcorr(x,x); + [m, fs]=max(abs(w2)); + fs=fs-1920; +end + diff --git a/matlab/tests/pdsch_bler_equal.m b/matlab/tests/pdsch_bler_equal.m new file mode 100644 index 000000000..b9bda08ba --- /dev/null +++ b/matlab/tests/pdsch_bler_equal.m @@ -0,0 +1,159 @@ + +%% PDSCH decoding based on RMC channels + +%% Cell-Wide Settings +% A structure |enbConfig| is used to configure the eNodeB. +%clear12 + +recordedSignal=[]; + +Npackets = 20; +SNR_values = linspace(2,6,10); + +Lp=12; +N=256; +K=180; +rstart=(N-K)/2; +P=K/6; +Rhphp=zeros(P,P); +Rhhp=zeros(K,P); +Rhh=zeros(K,K); + +t=0:Lp-1; +alfa=log(2*Lp)/Lp; +c_l=exp(-t*alfa); +c_l=c_l/sum(c_l); +C_l=diag(1./c_l); +prows=rstart+(1:6:K); + +F=dftmtx(N); +F_p=F(prows,1:Lp); +F_l=F((rstart+1):(K+rstart),1:Lp); +Wi=(F_p'*F_p+C_l*0.01)^(-1); +W2=F_l*Wi*F_p'; +w2=reshape(transpose(W2),1,[]); + + +%% Choose RMC +[waveform,rgrid,rmccFgOut] = lteRMCDLTool('R.0',[1;0;0;1]); +waveform = sum(waveform,2); + +if ~isempty(recordedSignal) + rmccFgOut = struct('CellRefP',1,'NDLRB',100,'DuplexMode','FDD','CyclicPrefix','Normal'); + rmccFgOut.PDSCH.RNTI = 1234; + rmccFgOut.PDSCH.PRBSet = repmat(transpose(0:rmccFgOut.NDLRB-1),1,2); + rmccFgOut.PDSCH.TxScheme = 'Port0'; + rmccFgOut.PDSCH.NLayers = 1; + rmccFgOut.PDSCH.NTurboDecIts = 5; + rmccFgOut.PDSCH.Modulation = {'64QAM'}; + trblklen=75376; + rmccFgOut.PDSCH.TrBlkSizes = trblklen*ones(10,1); + rmccFgOut.PDSCH.RV = 0; +end + +flen=rmccFgOut.SamplingRate/1000; + +Nsf = 9; + +%% Setup Fading channel model +cfg.Seed = 0; % Random channel seed +cfg.NRxAnts = 1; % 1 receive antenna +cfg.DelayProfile = 'EPA'; % EVA delay spread +cfg.DopplerFreq = 5; % 120Hz Doppler frequency +cfg.MIMOCorrelation = 'Low'; % Low (no) MIMO correlation +cfg.InitTime = 0; % Initialize at time zero +cfg.NTerms = 16; % Oscillators used in fading model +cfg.ModelType = 'GMEDS'; % Rayleigh fading model type +cfg.InitPhase = 'Random'; % Random initial phases +cfg.NormalizePathGains = 'On'; % Normalize delay profile power +cfg.NormalizeTxAnts = 'On'; % Normalize for transmit antennas +cfg.SamplingRate = rmccFgOut.SamplingRate; + +% Setup channel equalizer +cec.PilotAverage = 'UserDefined'; % Type of pilot averaging +cec.FreqWindow = 9; % Frequency window size +cec.TimeWindow = 9; % Time window size +cec.InterpType = 'linear'; % 2D interpolation type +cec.InterpWindow = 'Causal'; % Interpolation window type +cec.InterpWinSize = 1; % Interpolation window size + +addpath('../../build/srslte/lib/phch/test') + +decoded = zeros(size(SNR_values)); +decoded_srslte = zeros(size(SNR_values)); + +for snr_idx=1:length(SNR_values) + SNRdB = SNR_values(snr_idx); + SNR = 10^(SNRdB/10); % Linear SNR + N0 = 1/(sqrt(2.0*rmccFgOut.CellRefP*double(rmccFgOut.Nfft))*SNR); + + Rhphp=zeros(30,30); + Rhhp=zeros(180,30); + + for i=1:Npackets + + if isempty(recordedSignal) + + %% Fading + %rxWaveform = lteFadingChannel(cfg,waveform); + rxWaveform = waveform; + + %% Noise Addition + noise = N0*complex(randn(size(rxWaveform)), randn(size(rxWaveform))); % Generate noise + rxWaveform = rxWaveform + noise; + else + rxWaveform = recordedSignal; + end + + %% Demodulate + frame_rx = lteOFDMDemodulate(rmccFgOut, rxWaveform); + + for sf_idx=0:Nsf-1 + % sf_idx=9; + subframe_rx=frame_rx(:,sf_idx*14+1:(sf_idx+1)*14); + rmccFgOut.NSubframe=sf_idx; + rmccFgOut.TotSubframes=1; + + % Perform channel estimation + [hest, nest,estimates] = lteDLChannelEstimate2(rmccFgOut, cec, subframe_rx); + + [cws,symbols] = ltePDSCHDecode(rmccFgOut,rmccFgOut.PDSCH,subframe_rx,hest,nest); + [trblkout,blkcrc,dstate] = lteDLSCHDecode(rmccFgOut,rmccFgOut.PDSCH, ... + rmccFgOut.PDSCH.TrBlkSizes(sf_idx+1),cws); + + decoded(snr_idx) = decoded(snr_idx) + ~blkcrc; + + + %% Same with srsLTE + if (rmccFgOut.PDSCH.TrBlkSizes(sf_idx+1) > 0) + [dec2, data, pdschRx, pdschSymbols2, cws2] = srslte_pdsch(rmccFgOut, rmccFgOut.PDSCH, ... + rmccFgOut.PDSCH.TrBlkSizes(sf_idx+1), ... + subframe_rx); + else + dec2 = 1; + end + if (~dec2) + fprintf('Error in sf=%d\n',sf_idx); + end + decoded_srslte(snr_idx) = decoded_srslte(snr_idx)+dec2; + end + + if ~isempty(recordedSignal) + recordedSignal = recordedSignal(flen*10+1:end); + end + end + fprintf('SNR: %.1f. Decoded: %d-%d\n',SNRdB, decoded(snr_idx), decoded_srslte(snr_idx)) +end + +if (length(SNR_values)>1) + semilogy(SNR_values,1-decoded/Npackets/(Nsf),'bo-',... + SNR_values,1-decoded_srslte/Npackets/(Nsf), 'ro-') + grid on; + legend('Matlab','srsLTE') + xlabel('SNR (dB)') + ylabel('BLER') + axis([min(SNR_values) max(SNR_values) 1/Npackets/(Nsf+1) 1]) +else + fprintf('Matlab: %d OK\nsrsLTE: %d OK\n',decoded, decoded_srslte); +end + diff --git a/matlab/tests/pdsch_decode_signal.m b/matlab/tests/pdsch_decode_signal.m new file mode 100644 index 000000000..cc78cff53 --- /dev/null +++ b/matlab/tests/pdsch_decode_signal.m @@ -0,0 +1,66 @@ +enb=struct('NCellID',0,'NDLRB',100,'NSubframe',9,'CFI',1,'CyclicPrefix','Normal','CellRefP',1,'Ng','One','PHICHDuration','Normal','DuplexMode','FDD'); + +RNTI=73; + +addpath('../../build/srslte/lib/phch/test') + +cec.PilotAverage = 'UserDefined'; % Type of pilot averaging +cec.FreqWindow = 9; % Frequency window size +cec.TimeWindow = 9; % Time window size +cec.InterpType = 'linear'; % 2D interpolation type +cec.InterpWindow = 'Causal'; % Interpolation window type +cec.InterpWinSize = 1; % Interpolation window size + +%subframe_rx=lteOFDMDemodulate(enb,inputSignal); +subframe_rx=reshape(input,[],14); +[hest,nest] = lteDLChannelEstimate(enb, cec, subframe_rx); + +% Search PDCCH +pdcchIndices = ltePDCCHIndices(enb); +[pdcchRx, pdcchHest] = lteExtractResources(pdcchIndices, subframe_rx, hest); +[dciBits, pdcchSymbols] = ltePDCCHDecode(enb, pdcchRx, pdcchHest, nest); +pdcch = struct('RNTI', RNTI); +dci = ltePDCCHSearch(enb, pdcch, dciBits); % Search PDCCH for DCI + +if ~isempty(dci) + + dci = dci{1}; + disp(dci); + + % Get the PDSCH configuration from the DCI + [pdsch, trblklen] = hPDSCHConfiguration(enb, dci, pdcch.RNTI); + pdsch.NTurboDecIts = 10; + pdsch.Modulation = {'64QAM'}; + trblklen=75376; + fprintf('PDSCH settings after DCI decoding:\n'); + disp(pdsch); + + fprintf('Decoding PDSCH...\n\n'); + % Get PDSCH indices + [pdschIndices,pdschIndicesInfo] = ltePDSCHIndices(enb, pdsch, pdsch.PRBSet); + [pdschRx, pdschHest] = lteExtractResources(pdschIndices, subframe_rx, hest); + % Decode PDSCH + [dlschBits,pdschSymbols] = ltePDSCHDecode(enb, pdsch, d); + [sib1, crc] = lteDLSCHDecode(enb, pdsch, trblklen, dlschBits); + +% [dec2, data, pdschRx2, pdschSymbols2, e_bits, indices] = srslte_pdsch(enb, pdsch, ... +% trblklen, ... +% subframe_rx); + + + scatter(real(pdschSymbols{1}),imag(pdschSymbols{1})) + + if crc == 0 + fprintf('PDSCH OK.\n\n'); + else + fprintf('PDSCH ERROR.\n\n'); + end + + else + % indicate that DCI decoding failed + fprintf('DCI decoding failed.\n\n'); +end + +%indices=indices+1; +%plot(t,indices(t),t,pdschIndices(t)) + \ No newline at end of file diff --git a/matlab/tests/pdsch_test_verify_unrm.m b/matlab/tests/pdsch_test_verify_unrm.m new file mode 100644 index 000000000..3f32c7466 --- /dev/null +++ b/matlab/tests/pdsch_test_verify_unrm.m @@ -0,0 +1,39 @@ +clear + +% Run pdsch_test with -vv to generate files. Then run this script to check +% rate matching and demodulation +% Need to change soft demodulator output to +-10 + +enbConfig=struct('NCellID',0,'CyclicPrefix','Normal','CellRefP',1,'DuplexMode','FDD'); +pdschConfig=struct('Modulation','64QAM','RV',3,'TxScheme','Port0','NTurboDecIts',10,... + 'NSoftbits',0,'DuplexMode','FDD'); + +addpath('../../build/srslte/lib/phch/test') + +cbidx_v=0:12; +e_bits=90000; + +trblkin=read_uchar('../../build/data_in'); +[mat, info]=lteDLSCH(enbConfig,pdschConfig,e_bits,trblkin); +mat(mat==0)=-1; +mat=mat*10; +rec = lteRateRecoverTurbo(mat,length(trblkin),pdschConfig.RV,pdschConfig); + +rec2=cell(size(rec)); +srs=cell(size(rec)); +for cbidx=cbidx_v + rec2{cbidx+1} = reshape(reshape(rec{cbidx+1},[],3)',[],1); + srs{cbidx+1}=read_int16(sprintf('../../build/rmout_%d.dat',cbidx)); +end + + +subplot(2,1,1) +plot(abs(double(reshape(cell2mat(srs),1,[]))-double(reshape(cell2mat(rec2),1,[])))); + +subplot(2,1,2) +llr=read_int16('../../build/llr.dat'); +plot(abs(double(mat)-double(llr))) + +[data, crc,state] = lteDLSCHDecode(enbConfig, pdschConfig, length(trblkin), mat); +disp(crc) + diff --git a/matlab/tests/sync_test.m b/matlab/tests/sync_test.m index c1e33d782..733b3523b 100644 --- a/matlab/tests/sync_test.m +++ b/matlab/tests/sync_test.m @@ -1,44 +1,83 @@ -enb = lteTestModel('1.1','5MHz'); +clear +enb = lteTestModel('1.1','1.4MHz'); Ntrials = 1; -SNR_values =-20;%linspace(-18,-10,8); +SNR_values = 100;%linspace(0,10,6); +flen=1920; +fft_size=128; -tx_offset = randi(50,Ntrials,1); -diff=zeros(size(SNR_values)); -diff_lt=zeros(size(SNR_values)); +tx_offset = 0;%randi(50,1,Ntrials); +cfo_offset = 0;%2*rand(1,Ntrials)-1; tx_signal = lteTestModelTool(enb); -tx_power = mean(tx_signal.*conj(tx_signal)); +pss_idx = flen/2-fft_size+1:flen/2; +pss_signal=tx_signal(pss_idx); +tx_power = mean(pss_signal.*conj(pss_signal)); corrcfg.PSS='On'; corrcfg.SSS='On'; corrcfg.CellRS='Off'; -addpath('../../debug/lte/phy/lib/sync/test') +cfg.Seed = 0; % Random channel seed +cfg.NRxAnts = 1; % 1 receive antenna +cfg.DelayProfile = 'ETU'; % EVA delay spread +cfg.DopplerFreq = 120; % 120Hz Doppler frequency +cfg.MIMOCorrelation = 'Low'; % Low (no) MIMO correlation +cfg.InitTime = 0; % Initialize at time zero +cfg.NTerms = 16; % Oscillators used in fading model +cfg.ModelType = 'GMEDS'; % Rayleigh fading model type +cfg.InitPhase = 'Random'; % Random initial phases +cfg.NormalizePathGains = 'On'; % Normalize delay profile power +cfg.NormalizeTxAnts = 'On'; % Normalize for transmit antennas +cfg.SamplingRate = flen*1000; +addpath('../../build/srslte/lib/sync/test') +addpath('../sync/') + +t = (0:length(tx_signal)-1).'/fft_size; + +L=16; +M=3; +diff=zeros(length(SNR_values),M); for snr_idx=1:length(SNR_values) + fprintf('SNR=%.1f dB\n', SNR_values(snr_idx)); SNRdB = SNR_values(snr_idx); - rx_offset = zeros(size(tx_offset)); - rx_offset_lt = zeros(size(tx_offset)); + rx_offset = zeros(M,length(tx_offset)); for i=1:Ntrials + [rx_signal, chinfo] = lteFadingChannel(cfg,tx_signal); + % rx_signal = rx_signal.*exp(-1i*cfo_offset(i)*2*pi.*t); + %rx_signal = tx_signal; SNR = 10^(SNRdB/10); % Linear SNR - tx = [zeros(tx_offset(i),1); tx_signal]; + rx = [zeros(tx_offset(i),1); rx_signal]; N0 = tx_power/(sqrt(2.0)*SNR); - noise = N0*complex(randn(size(tx)), randn(size(tx))); % Generate noise - rx=noise+tx; - [rx_offset(i),corr] = lteDLFrameOffset(enb,rx,corrcfg); - [rx_offset_lt(i),corr_lt] = srslte_pss(enb,rx); + noise = N0*complex(randn(size(rx)), randn(size(rx))); % Generate noise + rx=noise+rx; + [rx_offset(1,i),corr_res] = lteDLFrameOffset(enb,rx(1:flen),corrcfg); + + % srsLTE in find mode + [rx_offset(2,i),corr_lt] = srslte_pss(enb,rx(1:flen)); + rx_offset(2,i) = rx_offset(2,i) - flen/2; + + % 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); end - diff(snr_idx)=sum(abs(rx_offset-tx_offset)); - diff_lt(snr_idx)=sum(abs(rx_offset_lt-tx_offset)); - disp(SNRdB) + diff(snr_idx,:)=mean(abs(rx_offset-repmat(tx_offset,M,1)),2); end if (Ntrials == 1) - len=1:length(corr)-rx_offset(i)-3840; - len2=rx_offset(i)+1+3840:length(corr); - plot(len,corr(len)/max(corr(len)),... - len,abs(corr_lt(len2))/max(abs(corr_lt(len2)))); + disp(diff) + %plot(1:flen,abs(corr_res(1:flen)),1:flen,abs(corr_lt(1:flen))); + t=940:1000; + plot(t,abs(corr_lt(t))); + %plot(1:L,abs(corr_lt_track),[L/2, L/2], [0 max(abs(corr_lt_track))]) + grid on + else - plot(SNR_values,diff,SNR_values,diff_lt); + plot(SNR_values,diff); + legend('Matlab','srs find','srs tracking 16','srs tracking 64') + grid on + xlabel('SNR (dB)') + ylabel('Avg time offset') end diff --git a/srslte/include/srslte/ch_estimation/chest_dl.h b/srslte/include/srslte/ch_estimation/chest_dl.h index 3e6668ad5..9aa4214fa 100644 --- a/srslte/include/srslte/ch_estimation/chest_dl.h +++ b/srslte/include/srslte/ch_estimation/chest_dl.h @@ -60,6 +60,10 @@ typedef struct { cf_t *pilot_recv_signal; cf_t *tmp_noise; +#ifdef FREQ_SEL_SNR + float snr_vector[12000]; + float pilot_power[12000]; +#endif uint32_t smooth_filter_len; float smooth_filter[SRSLTE_CHEST_DL_MAX_SMOOTH_FIL_LEN]; diff --git a/srslte/include/srslte/ue/ue_dl.h b/srslte/include/srslte/ue/ue_dl.h index e2f46c46c..ef9565b4d 100644 --- a/srslte/include/srslte/ue/ue_dl.h +++ b/srslte/include/srslte/ue/ue_dl.h @@ -100,6 +100,10 @@ SRSLTE_API int srslte_ue_dl_decode_fft_estimate(srslte_ue_dl_t *q, uint32_t sf_idx, uint32_t *cfi); +SRSLTE_API int srslte_ue_dl_decode_estimate(srslte_ue_dl_t *q, + uint32_t sf_idx, + uint32_t *cfi); + SRSLTE_API int srslte_ue_dl_cfg_grant(srslte_ue_dl_t *q, srslte_ra_dl_grant_t *grant, uint32_t cfi, diff --git a/srslte/lib/ch_estimation/src/chest_dl.c b/srslte/lib/ch_estimation/src/chest_dl.c index 389cf073e..2a760358d 100644 --- a/srslte/lib/ch_estimation/src/chest_dl.c +++ b/srslte/lib/ch_estimation/src/chest_dl.c @@ -168,6 +168,16 @@ static float estimate_noise_pilots(srslte_chest_dl_t *q, cf_t *ce, uint32_t port srslte_refsignal_cs_get_sf(q->cell, port_id, ce, q->tmp_noise); /* Substract noisy pilot estimates */ srslte_vec_sub_ccc(q->tmp_noise, q->pilot_estimates, q->tmp_noise, nref); + +#ifdef FREQ_SEL_SNR + /* Compute frequency-selective SNR */ + srslte_vec_abs_square_cf(q->tmp_noise, q->snr_vector, nref); + srslte_vec_abs_square_cf(q->pilot_estimates, q->pilot_power, nref); + srslte_vec_div_fff(q->pilot_power, q->snr_vector, q->snr_vector, nref); + + srslte_vec_fprint_f(stdout, q->snr_vector, nref); +#endif + /* Compute average power */ float power = 2*q->cell.nof_ports*srslte_vec_avg_power_cf(q->tmp_noise, nref); return power; @@ -340,7 +350,12 @@ float srslte_chest_dl_get_noise_estimate(srslte_chest_dl_t *q) { } float srslte_chest_dl_get_snr(srslte_chest_dl_t *q) { +#ifdef FREQ_SEL_SNR + int nref=SRSLTE_REFSIGNAL_NUM_SF(q->cell.nof_prb, 0); + return srslte_vec_acc_ff(q->snr_vector, nref)/nref; +#else return srslte_chest_dl_get_rsrp(q)/srslte_chest_dl_get_noise_estimate(q); +#endif } float srslte_chest_dl_get_rssi(srslte_chest_dl_t *q) { diff --git a/srslte/lib/sync/src/pss.c b/srslte/lib/sync/src/pss.c index 76ab9534e..d0c37e512 100644 --- a/srslte/lib/sync/src/pss.c +++ b/srslte/lib/sync/src/pss.c @@ -325,11 +325,14 @@ int srslte_pss_synch_find_pss(srslte_pss_synch_t *q, cf_t *input, float *corr_pe srslte_vec_abs_cf(q->conv_output, q->conv_output_abs, conv_output_len-1); #endif - srslte_vec_sc_prod_fff(q->conv_output_abs, q->ema_alpha, q->conv_output_abs, conv_output_len-1); - srslte_vec_sc_prod_fff(q->conv_output_avg, 1-q->ema_alpha, q->conv_output_avg, conv_output_len-1); + if (q->ema_alpha < 1.0 && q->ema_alpha > 0.0) { + srslte_vec_sc_prod_fff(q->conv_output_abs, q->ema_alpha, q->conv_output_abs, conv_output_len-1); + srslte_vec_sc_prod_fff(q->conv_output_avg, 1-q->ema_alpha, q->conv_output_avg, conv_output_len-1); - srslte_vec_sum_fff(q->conv_output_abs, q->conv_output_avg, q->conv_output_avg, conv_output_len-1); - + srslte_vec_sum_fff(q->conv_output_abs, q->conv_output_avg, q->conv_output_avg, conv_output_len-1); + } else { + memcpy(q->conv_output_avg, q->conv_output_abs, sizeof(float)*(conv_output_len-1)); + } /* Find maximum of the absolute value of the correlation */ corr_peak_pos = srslte_vec_max_fi(q->conv_output_avg, conv_output_len-1); @@ -367,7 +370,8 @@ int srslte_pss_synch_find_pss(srslte_pss_synch_t *q, cf_t *input, float *corr_pe if (corr_peak_value) { *corr_peak_value = q->conv_output_avg[corr_peak_pos]/side_lobe_value; - DEBUG("peak_pos=%2d, pl_ub=%2d, pl_lb=%2d, sl_right: %2d, sl_left: %2d, PSR: %.2f/%.2f=%.2f\n", corr_peak_pos, pl_ub, pl_lb, + if (*corr_peak_value < 10) + DEBUG("peak_pos=%2d, pl_ub=%2d, pl_lb=%2d, sl_right: %2d, sl_left: %2d, PSR: %.2f/%.2f=%.2f\n", corr_peak_pos, pl_ub, pl_lb, sl_right,sl_left, q->conv_output_avg[corr_peak_pos], side_lobe_value,*corr_peak_value); } #else diff --git a/srslte/lib/sync/src/sync.c b/srslte/lib/sync/src/sync.c index a45164c1d..ac1f9d8b2 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_PARTIAL_3; + q->sss_alg = SSS_DIFF; q->enable_cfo_corr = true; for (int i=0;i<2;i++) { @@ -355,13 +355,14 @@ int srslte_sync_find(srslte_sync_t *q, cf_t *input, uint32_t find_offset, uint32 } /* Estimate CFO using CP */ + uint32_t cp_offset = 0; if (q->enable_cfo_corr) { - uint32_t 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->nof_symbols, 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; /* compute cumulative moving average CFO */ - INFO("cp_offset_pos=%d, abs=%f, cfo=%f, mean_cfo=%f, nof_symb=%d\n", + DEBUG("cp_offset_pos=%d, abs=%f, cfo=%f, mean_cfo=%f, nof_symb=%d\n", cp_offset, cabs(cp_corr_max), cfo, q->mean_cfo, q->nof_symbols); if (q->mean_cfo) { q->mean_cfo = SRSLTE_VEC_EMA(cfo, q->mean_cfo, q->cfo_ema_alpha); @@ -400,6 +401,7 @@ int srslte_sync_find(srslte_sync_t *q, cf_t *input, uint32_t find_offset, uint32 return SRSLTE_ERROR; } } + q->mean_peak_value = SRSLTE_VEC_EMA(q->peak_value, q->mean_peak_value, MEANPEAK_EMA_ALPHA); if (peak_position) { diff --git a/srslte/lib/sync/test/pss_mex.c b/srslte/lib/sync/test/pss_mex.c index 4b86385c9..77922a020 100644 --- a/srslte/lib/sync/test/pss_mex.c +++ b/srslte/lib/sync/test/pss_mex.c @@ -51,23 +51,29 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) cf_t *input_symbols; int frame_len; - if (nrhs != NOF_INPUTS) { + if (nrhs < NOF_INPUTS) { help(); return; } + srslte_use_standard_symbol_size(true); + if (mexutils_read_cell(ENBCFG, &cell)) { help(); return; } - /** Allocate input buffers */ + /* Allocate input buffers */ frame_len = mexutils_read_cf(INPUT, &input_symbols); if (frame_len < 0) { mexErrMsgTxt("Error reading input symbols\n"); return; } + if (nrhs == NOF_INPUTS+1) { + frame_len = (int) mxGetScalar(prhs[NOF_INPUTS]); + } + if (srslte_pss_synch_init_fft(&pss, frame_len, srslte_symbol_sz(cell.nof_prb))) { fprintf(stderr, "Error initiating PSS\n"); exit(-1); @@ -76,11 +82,12 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) fprintf(stderr, "Error setting N_id_2=%d\n",cell.id%3); exit(-1); } + srslte_pss_synch_set_ema_alpha(&pss, 1.0); int peak_idx = srslte_pss_synch_find_pss(&pss, input_symbols, NULL); - + if (nlhs >= 1) { - plhs[0] = mxCreateLogicalScalar(peak_idx); + plhs[0] = mxCreateDoubleScalar(peak_idx); } if (nlhs >= 2) { mexutils_write_cf(pss.conv_output, &plhs[1], frame_len, 1); diff --git a/srslte/lib/ue/src/ue_dl.c b/srslte/lib/ue/src/ue_dl.c index e0d167064..f1d917af2 100644 --- a/srslte/lib/ue/src/ue_dl.c +++ b/srslte/lib/ue/src/ue_dl.c @@ -175,12 +175,21 @@ int srslte_ue_dl_decode_rnti(srslte_ue_dl_t *q, cf_t *input, uint8_t *data, uint } int srslte_ue_dl_decode_fft_estimate(srslte_ue_dl_t *q, cf_t *input, uint32_t sf_idx, uint32_t *cfi) { - float cfi_corr; if (input && q && cfi && sf_idx < SRSLTE_NSUBFRAMES_X_FRAME) { /* Run FFT for all subframe data */ srslte_ofdm_rx_sf(&q->fft, input, q->sf_symbols); + return srslte_ue_dl_decode_estimate(q, sf_idx, cfi); + } else { + return SRSLTE_ERROR_INVALID_INPUTS; + } +} + +int srslte_ue_dl_decode_estimate(srslte_ue_dl_t *q, uint32_t sf_idx, uint32_t *cfi) { + float cfi_corr; + if (q && cfi && sf_idx < SRSLTE_NSUBFRAMES_X_FRAME) { + /* Get channel estimates for each port */ srslte_chest_dl_estimate(&q->chest, q->sf_symbols, q->ce, sf_idx); @@ -204,6 +213,7 @@ int srslte_ue_dl_decode_fft_estimate(srslte_ue_dl_t *q, cf_t *input, uint32_t sf } } + int srslte_ue_dl_cfg_grant(srslte_ue_dl_t *q, srslte_ra_dl_grant_t *grant, uint32_t cfi, uint32_t sf_idx, uint32_t rvidx) { return srslte_pdsch_cfg(&q->pdsch_cfg, q->cell, grant, cfi, sf_idx, rvidx); diff --git a/srslte/lib/ue/src/ue_sync.c b/srslte/lib/ue/src/ue_sync.c index f98e2acc7..b1fab4885 100644 --- a/srslte/lib/ue/src/ue_sync.c +++ b/srslte/lib/ue/src/ue_sync.c @@ -42,10 +42,10 @@ cf_t dummy[MAX_TIME_OFFSET]; #define TRACK_MAX_LOST 4 -#define TRACK_FRAME_SIZE 32 +#define TRACK_FRAME_SIZE 16 #define FIND_NOF_AVG_FRAMES 2 -cf_t kk[1024*1024]; +cf_t dummy_offset_buffer[1024*1024]; int srslte_ue_sync_init_file(srslte_ue_sync_t *q, uint32_t nof_prb, char *file_name, int offset_time, float offset_freq) { int ret = SRSLTE_ERROR_INVALID_INPUTS; @@ -80,7 +80,7 @@ int srslte_ue_sync_init_file(srslte_ue_sync_t *q, uint32_t nof_prb, char *file_n INFO("Offseting input file by %d samples and %.1f KHz\n", offset_time, offset_freq/1000); - srslte_filesource_read(&q->file_source, kk, offset_time); + srslte_filesource_read(&q->file_source, dummy_offset_buffer, offset_time); srslte_ue_sync_reset(q); ret = SRSLTE_SUCCESS; @@ -164,7 +164,7 @@ int srslte_ue_sync_init(srslte_ue_sync_t *q, srslte_sync_cp_en(&q->strack, true); srslte_sync_set_cfo_ema_alpha(&q->sfind, 0.9); - srslte_sync_set_cfo_ema_alpha(&q->strack, 0.4); + 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); @@ -183,9 +183,9 @@ int srslte_ue_sync_init(srslte_ue_sync_t *q, srslte_sync_cfo_i_detec_en(&q->sfind, true); srslte_sync_cfo_i_detec_en(&q->strack, true); - - srslte_sync_set_cfo_ema_alpha(&q->sfind, 0.9); - srslte_sync_set_cfo_ema_alpha(&q->strack, 0.1); + + srslte_sync_set_cfo_ema_alpha(&q->sfind, 0.7); + srslte_sync_set_cfo_ema_alpha(&q->strack, 0.01); /* In find phase and if the cell is known, do not average pss correlation * because we only capture 1 subframe and do not know where the peak is. @@ -302,7 +302,7 @@ static int find_peak_ok(srslte_ue_sync_t *q, cf_t *input_buffer) { srslte_sync_get_last_peak_value(&q->sfind), q->cell.id, srslte_cp_string(q->cell.cp)); if (q->frame_find_cnt >= q->nof_avg_find_frames || q->peak_idx < 2*q->fft_size) { - DEBUG("Realigning frame, reading %d samples\n", q->peak_idx+q->sf_len/2); + 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*/ if (q->recv_callback(q->stream, input_buffer, q->peak_idx+q->sf_len/2, &q->last_timestamp) < 0) { return SRSLTE_ERROR; @@ -330,17 +330,27 @@ static int find_peak_ok(srslte_ue_sync_t *q, cf_t *input_buffer) { static int track_peak_ok(srslte_ue_sync_t *q, uint32_t track_idx) { /* Make sure subframe idx is what we expect */ - if ((q->sf_idx != srslte_sync_get_sf_idx(&q->strack)) && q->decode_sss_on_track && srslte_sync_sss_detected(&q->sfind)) { - DEBUG("Warning: Expected SF idx %d but got %d!\n", - q->sf_idx, srslte_sync_get_sf_idx(&q->strack)); - q->sf_idx = srslte_sync_get_sf_idx(&q->strack); + if ((q->sf_idx != srslte_sync_get_sf_idx(&q->strack)) && + q->decode_sss_on_track && + srslte_sync_sss_detected(&q->strack)) + { + INFO("Warning: Expected SF idx %d but got %d! (%d frames)\n", + q->sf_idx, srslte_sync_get_sf_idx(&q->strack), q->frame_no_cnt); + 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); + q->state = SF_FIND; + } + } else { + q->frame_no_cnt = 0; } // Adjust time offset q->time_offset = ((int) track_idx - (int) q->strack.max_offset/2 - (int) q->strack.fft_size); if (q->time_offset) { - DEBUG("Time offset adjustment: %d samples\n", q->time_offset); + INFO("Time offset adjustment: %d samples\n", q->time_offset); } /* compute cumulative moving average time offset */ @@ -359,24 +369,24 @@ static int track_peak_ok(srslte_ue_sync_t *q, uint32_t track_idx) { q->peak_idx = q->sf_len/2 + q->time_offset; q->frame_ok_cnt++; - q->frame_no_cnt = 0; return 1; } static int track_peak_no(srslte_ue_sync_t *q) { - /* if we missed too many PSS go back to FIND */ + /* 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) { - DEBUG("\n%d frames lost. Going back to FIND\n", (int) q->frame_no_cnt); + INFO("\n%d frames lost. Going back to FIND\n", (int) q->frame_no_cnt); q->state = SF_FIND; + return 0; } else { - DEBUG("Tracking peak not found. Peak %.3f, %d lost\n", + INFO("Tracking peak not found. Peak %.3f, %d lost\n", srslte_sync_get_last_peak_value(&q->strack), (int) q->frame_no_cnt); + return 1; } - return 1; } static int receive_samples(srslte_ue_sync_t *q, cf_t *input_buffer) { @@ -410,6 +420,7 @@ int srslte_ue_sync_get_buffer(srslte_ue_sync_t *q, cf_t **sf_symbols) { } +/* Returns 1 if the subframe is synchronized in time, 0 otherwise */ int srslte_ue_sync_zerocopy(srslte_ue_sync_t *q, cf_t *input_buffer) { int ret = SRSLTE_ERROR_INVALID_INPUTS; uint32_t track_idx;