Added matlab files to test synchronization

master
ismagom 9 years ago
parent dd396c0562
commit f31922f5f5

@ -7,12 +7,13 @@ function [ fs, cfo, p_m, w2] = find_pss( x, N_id_2)
w2=conv(x,ccf); w2=conv(x,ccf);
[m, fs]=max(abs(w2)); [m, fs]=max(abs(w2));
y=ccf.*x(fs-128:fs-1); if (fs > 128 && fs < length(x))
y0=y(1:64); y=ccf.*x(fs-128:fs-1);
y1=y(65:length(y)); 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 end

@ -0,0 +1,7 @@
function fs = find_pss_ac( x)
w2=xcorr(x,x);
[m, fs]=max(abs(w2));
fs=fs-1920;
end

@ -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

@ -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))

@ -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)

@ -1,44 +1,83 @@
enb = lteTestModel('1.1','5MHz'); clear
enb = lteTestModel('1.1','1.4MHz');
Ntrials = 1; 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); tx_offset = 0;%randi(50,1,Ntrials);
diff=zeros(size(SNR_values)); cfo_offset = 0;%2*rand(1,Ntrials)-1;
diff_lt=zeros(size(SNR_values));
tx_signal = lteTestModelTool(enb); 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.PSS='On';
corrcfg.SSS='On'; corrcfg.SSS='On';
corrcfg.CellRS='Off'; 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) for snr_idx=1:length(SNR_values)
fprintf('SNR=%.1f dB\n', SNR_values(snr_idx));
SNRdB = SNR_values(snr_idx); SNRdB = SNR_values(snr_idx);
rx_offset = zeros(size(tx_offset)); rx_offset = zeros(M,length(tx_offset));
rx_offset_lt = zeros(size(tx_offset));
for i=1:Ntrials 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 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); N0 = tx_power/(sqrt(2.0)*SNR);
noise = N0*complex(randn(size(tx)), randn(size(tx))); % Generate noise noise = N0*complex(randn(size(rx)), randn(size(rx))); % Generate noise
rx=noise+tx; rx=noise+rx;
[rx_offset(i),corr] = lteDLFrameOffset(enb,rx,corrcfg); [rx_offset(1,i),corr_res] = lteDLFrameOffset(enb,rx(1:flen),corrcfg);
[rx_offset_lt(i),corr_lt] = srslte_pss(enb,rx);
% 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 end
diff(snr_idx)=sum(abs(rx_offset-tx_offset)); diff(snr_idx,:)=mean(abs(rx_offset-repmat(tx_offset,M,1)),2);
diff_lt(snr_idx)=sum(abs(rx_offset_lt-tx_offset));
disp(SNRdB)
end end
if (Ntrials == 1) if (Ntrials == 1)
len=1:length(corr)-rx_offset(i)-3840; disp(diff)
len2=rx_offset(i)+1+3840:length(corr); %plot(1:flen,abs(corr_res(1:flen)),1:flen,abs(corr_lt(1:flen)));
plot(len,corr(len)/max(corr(len)),... t=940:1000;
len,abs(corr_lt(len2))/max(abs(corr_lt(len2)))); 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 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 end

@ -60,6 +60,10 @@ typedef struct {
cf_t *pilot_recv_signal; cf_t *pilot_recv_signal;
cf_t *tmp_noise; cf_t *tmp_noise;
#ifdef FREQ_SEL_SNR
float snr_vector[12000];
float pilot_power[12000];
#endif
uint32_t smooth_filter_len; uint32_t smooth_filter_len;
float smooth_filter[SRSLTE_CHEST_DL_MAX_SMOOTH_FIL_LEN]; float smooth_filter[SRSLTE_CHEST_DL_MAX_SMOOTH_FIL_LEN];

@ -100,6 +100,10 @@ SRSLTE_API int srslte_ue_dl_decode_fft_estimate(srslte_ue_dl_t *q,
uint32_t sf_idx, uint32_t sf_idx,
uint32_t *cfi); 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_API int srslte_ue_dl_cfg_grant(srslte_ue_dl_t *q,
srslte_ra_dl_grant_t *grant, srslte_ra_dl_grant_t *grant,
uint32_t cfi, uint32_t cfi,

@ -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); srslte_refsignal_cs_get_sf(q->cell, port_id, ce, q->tmp_noise);
/* Substract noisy pilot estimates */ /* Substract noisy pilot estimates */
srslte_vec_sub_ccc(q->tmp_noise, q->pilot_estimates, q->tmp_noise, nref); 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 */ /* Compute average power */
float power = 2*q->cell.nof_ports*srslte_vec_avg_power_cf(q->tmp_noise, nref); float power = 2*q->cell.nof_ports*srslte_vec_avg_power_cf(q->tmp_noise, nref);
return power; 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) { 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); 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) { float srslte_chest_dl_get_rssi(srslte_chest_dl_t *q) {

@ -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); srslte_vec_abs_cf(q->conv_output, q->conv_output_abs, conv_output_len-1);
#endif #endif
srslte_vec_sc_prod_fff(q->conv_output_abs, q->ema_alpha, q->conv_output_abs, conv_output_len-1); if (q->ema_alpha < 1.0 && q->ema_alpha > 0.0) {
srslte_vec_sc_prod_fff(q->conv_output_avg, 1-q->ema_alpha, q->conv_output_avg, conv_output_len-1); 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 */ /* Find maximum of the absolute value of the correlation */
corr_peak_pos = srslte_vec_max_fi(q->conv_output_avg, conv_output_len-1); 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) { if (corr_peak_value) {
*corr_peak_value = q->conv_output_avg[corr_peak_pos]/side_lobe_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); sl_right,sl_left, q->conv_output_avg[corr_peak_pos], side_lobe_value,*corr_peak_value);
} }
#else #else

@ -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_PARTIAL_3; q->sss_alg = SSS_DIFF;
q->enable_cfo_corr = true; q->enable_cfo_corr = true;
for (int i=0;i<2;i++) { 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 */ /* Estimate CFO using CP */
uint32_t cp_offset = 0;
if (q->enable_cfo_corr) { 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); 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;
/* compute cumulative moving average CFO */ /* 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); cp_offset, cabs(cp_corr_max), cfo, q->mean_cfo, q->nof_symbols);
if (q->mean_cfo) { if (q->mean_cfo) {
q->mean_cfo = SRSLTE_VEC_EMA(cfo, q->mean_cfo, q->cfo_ema_alpha); 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; return SRSLTE_ERROR;
} }
} }
q->mean_peak_value = SRSLTE_VEC_EMA(q->peak_value, q->mean_peak_value, MEANPEAK_EMA_ALPHA); q->mean_peak_value = SRSLTE_VEC_EMA(q->peak_value, q->mean_peak_value, MEANPEAK_EMA_ALPHA);
if (peak_position) { if (peak_position) {

@ -51,23 +51,29 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
cf_t *input_symbols; cf_t *input_symbols;
int frame_len; int frame_len;
if (nrhs != NOF_INPUTS) { if (nrhs < NOF_INPUTS) {
help(); help();
return; return;
} }
srslte_use_standard_symbol_size(true);
if (mexutils_read_cell(ENBCFG, &cell)) { if (mexutils_read_cell(ENBCFG, &cell)) {
help(); help();
return; return;
} }
/** Allocate input buffers */ /* Allocate input buffers */
frame_len = mexutils_read_cf(INPUT, &input_symbols); frame_len = mexutils_read_cf(INPUT, &input_symbols);
if (frame_len < 0) { if (frame_len < 0) {
mexErrMsgTxt("Error reading input symbols\n"); mexErrMsgTxt("Error reading input symbols\n");
return; 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))) { if (srslte_pss_synch_init_fft(&pss, frame_len, srslte_symbol_sz(cell.nof_prb))) {
fprintf(stderr, "Error initiating PSS\n"); fprintf(stderr, "Error initiating PSS\n");
exit(-1); 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); fprintf(stderr, "Error setting N_id_2=%d\n",cell.id%3);
exit(-1); exit(-1);
} }
srslte_pss_synch_set_ema_alpha(&pss, 1.0);
int peak_idx = srslte_pss_synch_find_pss(&pss, input_symbols, NULL); int peak_idx = srslte_pss_synch_find_pss(&pss, input_symbols, NULL);
if (nlhs >= 1) { if (nlhs >= 1) {
plhs[0] = mxCreateLogicalScalar(peak_idx); plhs[0] = mxCreateDoubleScalar(peak_idx);
} }
if (nlhs >= 2) { if (nlhs >= 2) {
mexutils_write_cf(pss.conv_output, &plhs[1], frame_len, 1); mexutils_write_cf(pss.conv_output, &plhs[1], frame_len, 1);

@ -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) { 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) { if (input && q && cfi && sf_idx < SRSLTE_NSUBFRAMES_X_FRAME) {
/* 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);
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 */ /* Get channel estimates for each port */
srslte_chest_dl_estimate(&q->chest, q->sf_symbols, q->ce, sf_idx); 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) 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); return srslte_pdsch_cfg(&q->pdsch_cfg, q->cell, grant, cfi, sf_idx, rvidx);

@ -42,10 +42,10 @@
cf_t dummy[MAX_TIME_OFFSET]; cf_t dummy[MAX_TIME_OFFSET];
#define TRACK_MAX_LOST 4 #define TRACK_MAX_LOST 4
#define TRACK_FRAME_SIZE 32 #define TRACK_FRAME_SIZE 16
#define FIND_NOF_AVG_FRAMES 2 #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 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; 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); 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); srslte_ue_sync_reset(q);
ret = SRSLTE_SUCCESS; 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_cp_en(&q->strack, true);
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.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->sfind, true);
srslte_sync_cfo_i_detec_en(&q->strack, true); srslte_sync_cfo_i_detec_en(&q->strack, true);
@ -184,8 +184,8 @@ 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->sfind, true);
srslte_sync_cfo_i_detec_en(&q->strack, 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->sfind, 0.7);
srslte_sync_set_cfo_ema_alpha(&q->strack, 0.1); srslte_sync_set_cfo_ema_alpha(&q->strack, 0.01);
/* In find phase and if the cell is known, do not average pss correlation /* 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. * 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)); 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) { 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*/ /* 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) { if (q->recv_callback(q->stream, input_buffer, q->peak_idx+q->sf_len/2, &q->last_timestamp) < 0) {
return SRSLTE_ERROR; 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) { static int track_peak_ok(srslte_ue_sync_t *q, uint32_t track_idx) {
/* Make sure subframe idx is what we expect */ /* 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)) { if ((q->sf_idx != srslte_sync_get_sf_idx(&q->strack)) &&
DEBUG("Warning: Expected SF idx %d but got %d!\n", q->decode_sss_on_track &&
q->sf_idx, srslte_sync_get_sf_idx(&q->strack)); srslte_sync_sss_detected(&q->strack))
q->sf_idx = srslte_sync_get_sf_idx(&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 // Adjust time offset
q->time_offset = ((int) track_idx - (int) q->strack.max_offset/2 - (int) q->strack.fft_size); q->time_offset = ((int) track_idx - (int) q->strack.max_offset/2 - (int) q->strack.fft_size);
if (q->time_offset) { 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 */ /* 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->peak_idx = q->sf_len/2 + q->time_offset;
q->frame_ok_cnt++; q->frame_ok_cnt++;
q->frame_no_cnt = 0;
return 1; return 1;
} }
static int track_peak_no(srslte_ue_sync_t *q) { 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++; q->frame_no_cnt++;
if (q->frame_no_cnt >= TRACK_MAX_LOST) { 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; q->state = SF_FIND;
return 0;
} else { } 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); 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) { 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 srslte_ue_sync_zerocopy(srslte_ue_sync_t *q, cf_t *input_buffer) {
int ret = SRSLTE_ERROR_INVALID_INPUTS; int ret = SRSLTE_ERROR_INVALID_INPUTS;
uint32_t track_idx; uint32_t track_idx;

Loading…
Cancel
Save