Merge branch 'improve_chest' into next

master
ismagom 9 years ago
commit e4ee073568

@ -0,0 +1,16 @@
function [ out ] = write_c_struct_complex( filename, varname, x)
[tidin msg]=fopen(filename,'wt');
if (tidin==-1)
fprintf('error opening %s: %s\n',filename, msg);
out=[];
return
end
fprintf(tidin, 'float %s[%d]={%.9g,%.9g',varname,2*length(x),real(x(1)),imag(x(1)));
for i=2:length(x)
fprintf(tidin, ',\n %.9g,%.9g',real(x(i)),imag(x(i)));
end
fprintf(tidin, '};\n');
fclose(tidin);
end

@ -1,25 +1,47 @@
clear clear
enbConfig=struct('NCellID',1,'CyclicPrefix','Normal','CellRefP',1); enbConfig=struct('NCellID',0,'CyclicPrefix','Normal','CellRefP',1);
pdschConfig=struct('Modulation','64QAM','RV',0,'TxScheme','Port0'); pdschConfig=struct('Modulation','64QAM','RV',1,'TxScheme','Port0','NTurboDecIts',10);
addpath('../../build/srslte/lib/phch/test') addpath('../../build/srslte/lib/phch/test')
TBs=36696; %TBs=18336;
e_bits=41400; i=1;
error=zeros(size(TBs)); e_bits=3450*6;
for i=1:length(TBs) %error=zeros(size(TBs));
trblkin=randi(2,TBs(i),1)-1; %for i=1:length(TBs)
%trblkin=randi(2,TBs(i),1)-1;
trblkin=read_uchar('../../build/data_in');
fprintf('e_bits=%d, trblkin=%d\n',e_bits,length(trblkin));
[mat, info]=lteDLSCH(enbConfig,pdschConfig,e_bits,trblkin); [mat, info]=lteDLSCH(enbConfig,pdschConfig,e_bits,trblkin);
lib=srslte_dlsch_encode(enbConfig,pdschConfig,e_bits,trblkin); lib=srslte_dlsch_encode(enbConfig,pdschConfig,e_bits,trblkin);
error(i)=mean(abs(double(mat)-double(lib))); error(i)=mean(abs(double(mat)-double(lib)));
end mat(mat==0)=-1;
mat=mat*10;
if (length(TBs) == 1)
%disp(info) rec = lteRateRecoverTurbo(mat,length(trblkin),pdschConfig.RV);
disp(error) rec2 = reshape(reshape(rec{1},[],3)',[],1);
n=1:length(mat); out = lteTurboDecode(rec{1});
plot(abs(double(mat)-double(lib)))
else x=read_int16('../../build/rmout_0.dat');
plot(error) subplot(2,1,1)
end plot(abs(double(x)-double(rec2)));
t=1:100;
%plot(t,double(x(t)),t,double(rec2(t)))
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)
%end
%
% if (length(TBs) == 1)
% %disp(info)
% disp(error)
% n=1:length(mat);
% plot(abs(double(mat)-double(lib)))
% else
% plot(error)
% end

@ -6,30 +6,35 @@ clear
plot_noise_estimation_only=false; plot_noise_estimation_only=false;
SNR_values_db=10;%linspace(0,30,8); SNR_values_db=30;%linspace(0,30,8);
Nrealizations=1 ; Nrealizations=1;
preEVM = zeros(length(SNR_values_db),Nrealizations); Lp=5;
postEVM_mmse = zeros(length(SNR_values_db),Nrealizations); N=512;
postEVM_mmse_lin = zeros(length(SNR_values_db),Nrealizations); enb.NDLRB = 25; % Number of resource blocks
postEVM_srslte = zeros(length(SNR_values_db),Nrealizations);
enb.NDLRB = 6; % Number of resource blocks
enb.CellRefP = 1; % One transmit antenna port enb.CellRefP = 1; % One transmit antenna port
enb.NCellID = 0; % Cell ID enb.NCellID = 0; % Cell ID
enb.CyclicPrefix = 'Normal'; % Normal cyclic prefix enb.CyclicPrefix = 'Normal'; % Normal cyclic prefix
enb.DuplexMode = 'FDD'; % FDD enb.DuplexMode = 'FDD'; % FDD
K=enb.NDLRB*12;
rstart=(N-K)/2;
P=K/6;
Rhphp=zeros(P,P);
Rhhp=zeros(K,P);
Rhh=zeros(K,K);
%% Channel Model Configuration %% Channel Model Configuration
rng(1); % Configure random number generators cfg.Seed = 0; % Random channel seed
cfg.InitTime = 0;
cfg.NRxAnts = 1; % 1 receive antenna
cfg.DelayProfile = 'EPA';
% doppler 5, 70 300
cfg.Seed = 2; % Random channel seed cfg.DopplerFreq = 5; % 120Hz Doppler frequency
cfg.NRxAnts = 2; % 1 receive antenna
cfg.DelayProfile = 'EVA'; % EVA delay spread
cfg.DopplerFreq = 120; % 120Hz Doppler frequency
cfg.MIMOCorrelation = 'Low'; % Low (no) MIMO correlation cfg.MIMOCorrelation = 'Low'; % Low (no) MIMO correlation
cfg.InitTime = 0; % Initialize at time zero
cfg.NTerms = 16; % Oscillators used in fading model cfg.NTerms = 16; % Oscillators used in fading model
cfg.ModelType = 'GMEDS'; % Rayleigh fading model type cfg.ModelType = 'GMEDS'; % Rayleigh fading model type
cfg.InitPhase = 'Random'; % Random initial phases cfg.InitPhase = 'Random'; % Random initial phases
@ -42,25 +47,42 @@ cec.PilotAverage = 'UserDefined'; % Type of pilot symbol averaging
cec.FreqWindow = 9; % Frequency window size cec.FreqWindow = 9; % Frequency window size
cec.TimeWindow = 9; % Time window size cec.TimeWindow = 9; % Time window size
cec.InterpType = 'Linear'; % 2D interpolation type cec.InterpType = 'Linear'; % 2D interpolation type
cec.InterpWindow = 'Centered'; % Interpolation window type cec.InterpWindow = 'Causal'; % Interpolation window type
cec.InterpWinSize = 1; % Interpolation window size cec.InterpWinSize = 1; % Interpolation window size
%% Subframe Resource Grid Size %% Subframe Resource Grid Size
gridsize = lteDLResourceGridSize(enb); gridsize = lteDLResourceGridSize(enb);
K = gridsize(1); % Number of subcarriers Ks = gridsize(1); % Number of subcarriers
L = gridsize(2); % Number of OFDM symbols in one subframe L = gridsize(2); % Number of OFDM symbols in one subframe
P = gridsize(3); % Number of transmit antenna ports Ports = gridsize(3); % Number of transmit antenna ports
%% Allocate memory
Ntests=4;
hest=cell(1,Ntests);
for i=1:Ntests
hest{i}=zeros(K,140);
end
hls=zeros(4,4*P*10);
MSE=zeros(Ntests,Nrealizations,length(SNR_values_db));
noiseEst=zeros(Ntests,Nrealizations,length(SNR_values_db));
legends={'matlab','ls.linear','mmse','r.smooth'};
colors={'bo-','rx-','m*-','k+-','c+-'};
colors2={'b-','r-','m-','k-','c-'};
addpath('../../build/srslte/lib/ch_estimation/test')
offset=-1;
for nreal=1:Nrealizations for nreal=1:Nrealizations
%% Transmit Resource Grid %% Transmit Resource Grid
txGrid = []; txGrid = [];
RSRP = [];
%% Payload Data Generation %% Payload Data Generation
% Number of bits needed is size of resource grid (K*L*P) * number of bits % Number of bits needed is size of resource grid (K*L*P) * number of bits
% per symbol (2 for QPSK) % per symbol (2 for QPSK)
numberOfBits = K*L*P*2; numberOfBits = Ks*L*Ports*2;
% Create random bit stream % Create random bit stream
inputBits = randi([0 1], numberOfBits, 1); inputBits = randi([0 1], numberOfBits, 1);
@ -104,7 +126,7 @@ for sf = 0:10
end end
txGrid([1:5 68:72],6:7) = zeros(10,2); txGrid([1:5 68:72],6:7) = ones(10,2);
%% OFDM Modulation %% OFDM Modulation
@ -112,19 +134,16 @@ txGrid([1:5 68:72],6:7) = zeros(10,2);
txGrid = txGrid(:,1:140); txGrid = txGrid(:,1:140);
%% SNR Configuration %% SNR Configuration
for snr_idx=1:length(SNR_values_db) for snr_idx=1:length(SNR_values_db)
SNRdB = SNR_values_db(snr_idx); % Desired SNR in dB SNRdB = SNR_values_db(snr_idx); % Desired SNR in dB
SNR = 10^(SNRdB/20); % Linear SNR SNR = 10^(SNRdB/20); % Linear SNR
fprintf('SNR=%.1f dB\n',SNRdB)
%% Fading Channel %% Fading Channel
cfg.SamplingRate = info.SamplingRate; cfg.SamplingRate = info.SamplingRate;
[rxWaveform, chinfo] = lteFadingChannel(cfg,txWaveform);
% Pass data through the fading channel model
%rxWaveform = lteFadingChannel(cfg,txWaveform);
rxWaveform = txWaveform;
%% Additive Noise %% Additive Noise
@ -134,91 +153,176 @@ N0 = 1/(sqrt(2.0*enb.CellRefP*double(info.Nfft))*SNR);
% Create additive white Gaussian noise % Create additive white Gaussian noise
noise = N0*complex(randn(size(rxWaveform)),randn(size(rxWaveform))); noise = N0*complex(randn(size(rxWaveform)),randn(size(rxWaveform)));
noiseTx(snr_idx) = N0;
% Add noise to the received time domain waveform % Add noise to the received time domain waveform
rxWaveform_nonoise = rxWaveform;
rxWaveform = rxWaveform + noise; rxWaveform = rxWaveform + noise;
%% Synchronization %% Synchronization
offset = lteDLFrameOffset(enb,rxWaveform); if (offset==-1)
rxWaveform = rxWaveform(1+offset+2:end,:); offset = lteDLFrameOffset(enb,rxWaveform);
end
rxWaveform = rxWaveform(1+offset:end,:);
rxWaveform_nonoise = rxWaveform_nonoise(1+offset:end,:);
%% OFDM Demodulation %% OFDM Demodulation
rxGrid = lteOFDMDemodulate(enb,rxWaveform); rxGrid = lteOFDMDemodulate(enb,rxWaveform);
rxGrid = rxGrid(:,1:140); rxGrid = rxGrid(:,1:140);
addpath('../../build/srslte/lib/ch_estimation/test') rxGrid_nonoise = lteOFDMDemodulate(enb,rxWaveform_nonoise);
rxGrid_nonoise = rxGrid_nonoise(:,1:140);
%% Channel Estimation % True channel
[estChannel, noiseEst(snr_idx)] = lteDLChannelEstimate(enb,cec,rxGrid); h=rxGrid_nonoise./(txGrid);
output=[];
snrest_srslte = zeros(10,1);
noise_srslte = zeros(10,1); %% Channel Estimation with Matlab
rsrp = zeros(1,10); tmpnoise=zeros(10,1);
for i=1:10
[d, ~, out] = srslte_chest(enb.NCellID,enb.CellRefP,rxGrid); enb.NSubframe=i-1;
output = [output out]; [hest{1}(:,(1:14)+(i-1)*14), tmpnoise(i), hls(:,(1:4*P)+(i-1)*4*P)] = ...
%RSRP = [RSRP rsrp]; lteDLChannelEstimate2(enb,cec,rxGrid(:,(i-1)*14+1:i*14));
%meanRSRP(snr_idx)=mean(rsrp);
%SNR_srslte(snr_idx)=mean(snrest_srslte);
%noiseEst_srslte(snr_idx)=mean(noise_srslte);
d=reshape(d, size(estChannel));
plot(1:288,real(reshape(estChannel(:,11:14),1,[])),'b-',...
1:288,real(reshape(d(:,11:14),1,[])),'r-')
% if ~plot_noise_estimation_only
%
% %% MMSE Equalization
% eqGrid_mmse = lteEqualizeMMSE(rxGrid, estChannel, noiseEst(snr_idx));
%
% eqGrid_srslte = reshape(output,size(eqGrid_mmse));
%
% % Analysis
%
% %Compute EVM across all input values EVM of pre-equalized receive signal
% preEqualisedEVM = lteEVM(txGrid,rxGrid);
% fprintf('%d-%d: Pre-EQ: %0.3f%%\n', ...
% snr_idx,nreal,preEqualisedEVM.RMS*100);
%
%
% %EVM of post-equalized receive signal
% postEqualisedEVM_mmse = lteEVM(txGrid,reshape(eqGrid_mmse,size(txGrid)));
% fprintf('%d-%d: MMSE: %0.3f%%\n', ...
% snr_idx,nreal,postEqualisedEVM_mmse.RMS*100);
%
% postEqualisedEVM_srslte = lteEVM(txGrid,reshape(eqGrid_srslte,size(txGrid)));
% fprintf('%d-%d: srslte: %0.3f%%\n', ...
% snr_idx,nreal,postEqualisedEVM_srslte.RMS*100);
%
% preEVM(snr_idx,nreal) = preEqualisedEVM.RMS;
% postEVM_mmse(snr_idx,nreal) = mean([postEqualisedEVM_mmse.RMS]);
% postEVM_srslte(snr_idx,nreal) = mean([postEqualisedEVM_srslte.RMS]);
% end
end end
noiseEst(1,nreal,snr_idx)=mean(tmpnoise)*sqrt(2)*enb.CellRefP;
%% LS-Linear estimation with srsLTE
[tmp, ~, ~, noiseEst(2,nreal,snr_idx)] = srslte_chest(enb.NCellID,enb.CellRefP,rxGrid);
hest{2}=reshape(tmp, size(hest{1}));
tmp_noise=zeros(2,1);
for sf=[0 5]
enb.NSubframe=sf;
pssSym = ltePSS(enb);
pssInd = ltePSSIndices(enb);
x=reshape(rxGrid(pssInd),[],1);
hh=reshape(hest{2}(pssInd),[],1);
y=hh.*pssSym;
tmp_noise(sf/5+1)=mean(abs(x-y).^2);
end
% noiseEst(2,nreal,snr_idx)=mean(tmp_noise);
%% MMSE estimation with srsLTE
% Compute Correlation matrices
M=40;
a=0.1;
hidx=zeros(M,1);
for i=1:M
if (mod(i,2)==1)
hx=floor((i-1)/2)*7+1;
else
hx=floor((i-1)/2)*7+5;
end
hidx(i)=hx;
hp=hest{1}(hls(1,(1:P)+P*(i-1)),hx);
Rhphp = (1-a)*Rhphp+a*(hp*hp');
Rhhp = (1-a)*Rhhp+a*(hest{1}(:,hx)*hp');
Rhh = (1-a)*Rhh+a*h(:,hx)*h(:,hx)';
end
snr_lin=10^(SNR_values_db(snr_idx)/10);
Wi=((Rhphp+(1/snr_lin)*eye(P)))^-1;
W = Rhhp*Wi;
w=reshape(transpose(W),1,[]);
[tmp, ~, ~, noiseEst(3,nreal,snr_idx)] = srslte_chest(enb.NCellID,enb.CellRefP,rxGrid,w);
hest{3}=reshape(tmp, size(hest{1}));
%% Low-pass filter smoother
prows=rstart+(1:6:K);
t=0:Lp-1;
alfa=log(2*Lp)/Lp;
c_l=exp(-t*alfa);
c_l2=[c_l zeros(1,N-Lp)];
C_l=diag(c_l2);
F=dftmtx(N);
R_hh=F*C_l*F';
R_hh=R_hh(prows,prows);
W3=R_hh*(R_hh+0.05*eye(P))^-1;
w3=reshape(transpose(W3),1,[]);
[tmp, pilot_avg, ~, noiseEst(4,nreal,snr_idx)] = srslte_chest(enb.NCellID,enb.CellRefP,rxGrid,w3);
hest{4}=reshape(tmp, size(hest{1}));
%% Compute MSE
for i=1:Ntests
MSE(i,nreal,snr_idx)=mean(mean(abs(h(:,hidx)-hest{i}(:,hidx)).^2));
fprintf('MSE test %d: %f\n',i, 10*log10(MSE(i,nreal,snr_idx)));
end
%% Plot a single realization
if (length(SNR_values_db) == 1)
subplot(2,1,1)
sym=1;
ref_idx=1:P;
ref_idx_x=[1:6:K];% (292:6:360)-216];% 577:6:648];
n=1:(K*length(sym));
for i=1:Ntests
plot(n,abs(reshape(hest{i}(:,sym),1,[])),colors2{i});
hold on;
end
plot(ref_idx_x,abs(hls(3,ref_idx)),'ro');
hold off;
tmp=cell(Ntests+1,1);
for i=1:Ntests
tmp{i}=legends{i};
end
tmp{Ntests+1}='LS';
legend(tmp)
xlabel('SNR (dB)')
ylabel('Channel Gain')
grid on;
fprintf('Mean MMSE Robust %.2f dB\n', 10*log10(MSE(4,nreal,snr_idx)))
fprintf('Mean MMSE matlab %.2f dB\n', 10*log10(MSE(1,nreal,snr_idx)))
subplot(2,1,2)
plot(1:P,abs(W3(P/2,:)))
end
end end
% end
% % subplot(1,2,1)
%
% if ~plot_noise_estimation_only %% Compute average MSE and noise estimation
% plot(SNR_values_db, mean(preEVM,2), ... mean_mse=mean(MSE,2);
% SNR_values_db, mean(postEVM_mmse,2), ... mean_snr=10*log10(1./mean(noiseEst,2));
% SNR_values_db, mean(postEVM_srslte,2))
% legend('No Eq','MMSE-lin','MMSE-srslte')
%% Plot average over all SNR values
if (length(SNR_values_db) > 1)
subplot(1,1,1)
for i=1:Ntests
plot(SNR_values_db, 10*log10(mean_mse(i,:)),colors{i})
hold on;
end
hold off;
legend(legends);
grid on
xlabel('SNR (dB)')
ylabel('MSE (dB)')
% subplot(1,2,2)
% plot(SNR_values_db, SNR_values_db,'k:')
% hold on;
% for i=1:Ntests
% plot(SNR_values_db, mean_snr(i,:), colors{i})
% end
% hold off
% tmp=cell(Ntests+1,1);
% tmp{1}='Theory';
% for i=2:Ntests+1
% tmp{i}=legends{i-1};
% end
% legend(tmp)
% grid on % grid on
% end % xlabel('SNR (dB)')
% % ylabel('Estimated SNR (dB)')
% % subplot(1,2,2) end
% if plot_noise_estimation_only
% SNR_matlab = 1./(noiseEst*sqrt(2.0)*enb.CellRefP);
%
% subplot(1,3,1)
% plot(SNR_values_db, SNR_values_db, SNR_values_db, 10*log10(SNR_srslte),SNR_values_db, 10*log10(SNR_matlab))
% legend('Theory','srsLTE','Matlab')
%
% subplot(1,3,2)
% plot(SNR_values_db, 10*log10(noiseTx), SNR_values_db, 10*log10(noiseEst_srslte),SNR_values_db, 10*log10(noiseEst))
% legend('Theory','srsLTE','Matlab')
%
% subplot(1,3,3)
% plot(1:10*length(SNR_values_db),RSRP,10*(1:length(SNR_values_db)),meanRSRP)
% end

@ -2,15 +2,39 @@
%% Cell-Wide Settings %% Cell-Wide Settings
% A structure |enbConfig| is used to configure the eNodeB. % A structure |enbConfig| is used to configure the eNodeB.
%clear %clear12
recordedSignal=[]; recordedSignal=[];
Npackets = 5; Npackets = 20;
SNR_values = linspace(18,25,5); 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 %% Choose RMC
[waveform,rgrid,rmccFgOut] = lteRMCDLTool('R.9',[1;0;0;1]); [waveform,rgrid,rmccFgOut] = lteRMCDLTool('R.0',[1;0;0;1]);
waveform = sum(waveform,2); waveform = sum(waveform,2);
if ~isempty(recordedSignal) if ~isempty(recordedSignal)
@ -28,12 +52,12 @@ end
flen=rmccFgOut.SamplingRate/1000; flen=rmccFgOut.SamplingRate/1000;
Nsf = 10; Nsf = 9;
%% Setup Fading channel model %% Setup Fading channel model
cfg.Seed = 8; % Random channel seed cfg.Seed = 0; % Random channel seed
cfg.NRxAnts = 1; % 1 receive antenna cfg.NRxAnts = 1; % 1 receive antenna
cfg.DelayProfile = 'EVA'; % EVA delay spread cfg.DelayProfile = 'EPA'; % EVA delay spread
cfg.DopplerFreq = 5; % 120Hz Doppler frequency cfg.DopplerFreq = 5; % 120Hz Doppler frequency
cfg.MIMOCorrelation = 'Low'; % Low (no) MIMO correlation cfg.MIMOCorrelation = 'Low'; % Low (no) MIMO correlation
cfg.InitTime = 0; % Initialize at time zero cfg.InitTime = 0; % Initialize at time zero
@ -49,7 +73,7 @@ cec.PilotAverage = 'UserDefined'; % Type of pilot averaging
cec.FreqWindow = 9; % Frequency window size cec.FreqWindow = 9; % Frequency window size
cec.TimeWindow = 9; % Time window size cec.TimeWindow = 9; % Time window size
cec.InterpType = 'linear'; % 2D interpolation type cec.InterpType = 'linear'; % 2D interpolation type
cec.InterpWindow = 'Centered'; % Interpolation window type cec.InterpWindow = 'Causal'; % Interpolation window type
cec.InterpWinSize = 1; % Interpolation window size cec.InterpWinSize = 1; % Interpolation window size
addpath('../../build/srslte/lib/phch/test') addpath('../../build/srslte/lib/phch/test')
@ -61,13 +85,17 @@ for snr_idx=1:length(SNR_values)
SNRdB = SNR_values(snr_idx); SNRdB = SNR_values(snr_idx);
SNR = 10^(SNRdB/10); % Linear SNR SNR = 10^(SNRdB/10); % Linear SNR
N0 = 1/(sqrt(2.0*rmccFgOut.CellRefP*double(rmccFgOut.Nfft))*SNR); N0 = 1/(sqrt(2.0*rmccFgOut.CellRefP*double(rmccFgOut.Nfft))*SNR);
Rhphp=zeros(30,30);
Rhhp=zeros(180,30);
for i=1:Npackets for i=1:Npackets
if isempty(recordedSignal) if isempty(recordedSignal)
%% Fading %% Fading
rxWaveform = lteFadingChannel(cfg,waveform); %rxWaveform = lteFadingChannel(cfg,waveform);
%rxWaveform = waveform; rxWaveform = waveform;
%% Noise Addition %% Noise Addition
noise = N0*complex(randn(size(rxWaveform)), randn(size(rxWaveform))); % Generate noise noise = N0*complex(randn(size(rxWaveform)), randn(size(rxWaveform))); % Generate noise
@ -86,7 +114,7 @@ for snr_idx=1:length(SNR_values)
rmccFgOut.TotSubframes=1; rmccFgOut.TotSubframes=1;
% Perform channel estimation % Perform channel estimation
[hest, nest] = lteDLChannelEstimate(rmccFgOut, cec, subframe_rx); [hest, nest,estimates] = lteDLChannelEstimate2(rmccFgOut, cec, subframe_rx);
[cws,symbols] = ltePDSCHDecode(rmccFgOut,rmccFgOut.PDSCH,subframe_rx,hest,nest); [cws,symbols] = ltePDSCHDecode(rmccFgOut,rmccFgOut.PDSCH,subframe_rx,hest,nest);
[trblkout,blkcrc,dstate] = lteDLSCHDecode(rmccFgOut,rmccFgOut.PDSCH, ... [trblkout,blkcrc,dstate] = lteDLSCHDecode(rmccFgOut,rmccFgOut.PDSCH, ...
@ -99,7 +127,7 @@ for snr_idx=1:length(SNR_values)
if (rmccFgOut.PDSCH.TrBlkSizes(sf_idx+1) > 0) if (rmccFgOut.PDSCH.TrBlkSizes(sf_idx+1) > 0)
[dec2, data, pdschRx, pdschSymbols2, cws2] = srslte_pdsch(rmccFgOut, rmccFgOut.PDSCH, ... [dec2, data, pdschRx, pdschSymbols2, cws2] = srslte_pdsch(rmccFgOut, rmccFgOut.PDSCH, ...
rmccFgOut.PDSCH.TrBlkSizes(sf_idx+1), ... rmccFgOut.PDSCH.TrBlkSizes(sf_idx+1), ...
subframe_rx, hest, nest); subframe_rx);
else else
dec2 = 1; dec2 = 1;
end end
@ -117,8 +145,8 @@ for snr_idx=1:length(SNR_values)
end end
if (length(SNR_values)>1) if (length(SNR_values)>1)
semilogy(SNR_values,1-decoded/Npackets/(Nsf+1),'bo-',... semilogy(SNR_values,1-decoded/Npackets/(Nsf),'bo-',...
SNR_values,1-decoded_srslte/Npackets/(Nsf+1), 'ro-') SNR_values,1-decoded_srslte/Npackets/(Nsf), 'ro-')
grid on; grid on;
legend('Matlab','srsLTE') legend('Matlab','srsLTE')
xlabel('SNR (dB)') xlabel('SNR (dB)')

File diff suppressed because one or more lines are too long

@ -39,7 +39,6 @@
#include "srslte/srslte.h" #include "srslte/srslte.h"
#ifndef DISABLE_RF #ifndef DISABLE_RF
#include "srslte/rf/rf.h" #include "srslte/rf/rf.h"
#include "srslte/rf/rf_utils.h" #include "srslte/rf/rf_utils.h"
@ -407,7 +406,7 @@ int main(int argc, char **argv) {
/* Configure downlink receiver for the SI-RNTI since will be the only one we'll use */ /* Configure downlink receiver for the SI-RNTI since will be the only one we'll use */
srslte_ue_dl_set_rnti(&ue_dl, prog_args.rnti); srslte_ue_dl_set_rnti(&ue_dl, prog_args.rnti);
/* Initialize subframe counter */ /* Initialize subframe counter */
sf_cnt = 0; sf_cnt = 0;
@ -519,9 +518,9 @@ int main(int argc, char **argv) {
nof_trials++; nof_trials++;
rsrq = SRSLTE_VEC_EMA(srslte_chest_dl_get_rsrq(&ue_dl.chest), rsrq, 0.05); rsrq = SRSLTE_VEC_EMA(srslte_chest_dl_get_rsrq(&ue_dl.chest), rsrq, 0.1);
rsrp = SRSLTE_VEC_EMA(srslte_chest_dl_get_rsrp(&ue_dl.chest), rsrp, 0.05); rsrp = SRSLTE_VEC_EMA(srslte_chest_dl_get_rsrp(&ue_dl.chest), rsrp, 0.1);
noise = SRSLTE_VEC_EMA(srslte_chest_dl_get_noise_estimate(&ue_dl.chest), noise, 0.05); noise = SRSLTE_VEC_EMA(srslte_chest_dl_get_noise_estimate(&ue_dl.chest), noise, 0.1);
nframes++; nframes++;
if (isnan(rsrq)) { if (isnan(rsrq)) {
rsrq = 0; rsrq = 0;
@ -541,11 +540,11 @@ int main(int argc, char **argv) {
gain = 10*log10(srslte_agc_get_gain(&ue_sync.agc)); gain = 10*log10(srslte_agc_get_gain(&ue_sync.agc));
} }
printf("CFO: %+6.2f KHz, " printf("CFO: %+6.2f KHz, "
"SNR: %4.1f dB, " "SNR: %4.1f dB, "
"PDCCH-Miss: %5.2f%%, PDSCH-BLER: %5.2f%%\r", "PDCCH-Miss: %5.2f%%, PDSCH-BLER: %5.2f%%\r",
srslte_ue_sync_get_cfo(&ue_sync)/1000, srslte_ue_sync_get_cfo(&ue_sync)/1000,
10*log10(srslte_chest_dl_get_snr(&ue_dl.chest)), 10*log10(rsrp/noise),
100*(1-(float) ue_dl.nof_detected/nof_trials), 100*(1-(float) ue_dl.nof_detected/nof_trials),
(float) 100*ue_dl.pkt_errors/ue_dl.pkts_total); (float) 100*ue_dl.pkt_errors/ue_dl.pkts_total);
} }

@ -48,26 +48,20 @@
#include "srslte/resampling/interp.h" #include "srslte/resampling/interp.h"
#include "srslte/ch_estimation/refsignal_dl.h" #include "srslte/ch_estimation/refsignal_dl.h"
#include "srslte/common/phy_common.h" #include "srslte/common/phy_common.h"
#include "srslte/sync/pss.h"
#define SRSLTE_CHEST_MAX_FILTER_FREQ_LEN 21 #define SRSLTE_CHEST_DL_MAX_SMOOTH_FIL_LEN 65
#define SRSLTE_CHEST_MAX_FILTER_TIME_LEN 40
typedef struct { typedef struct {
srslte_cell_t cell; srslte_cell_t cell;
srslte_refsignal_cs_t csr_signal; srslte_refsignal_cs_t csr_signal;
cf_t *pilot_estimates[SRSLTE_MAX_PORTS]; cf_t *pilot_estimates;
cf_t *pilot_estimates_average[SRSLTE_MAX_PORTS]; cf_t *pilot_estimates_average;
cf_t *pilot_recv_signal[SRSLTE_MAX_PORTS]; cf_t *pilot_recv_signal;
uint32_t filter_freq_len;
float filter_freq[SRSLTE_CHEST_MAX_FILTER_FREQ_LEN];
uint32_t filter_time_len;
float filter_time[SRSLTE_CHEST_MAX_FILTER_TIME_LEN];
cf_t *tmp_noise; cf_t *tmp_noise;
cf_t *tmp_freqavg;
cf_t *tmp_timeavg[SRSLTE_CHEST_MAX_FILTER_TIME_LEN]; uint32_t smooth_filter_len;
cf_t *tmp_timeavg_mult; float smooth_filter[SRSLTE_CHEST_DL_MAX_SMOOTH_FIL_LEN];
srslte_interp_linsrslte_vec_t srslte_interp_linvec; srslte_interp_linsrslte_vec_t srslte_interp_linvec;
srslte_interp_lin_t srslte_interp_lin; srslte_interp_lin_t srslte_interp_lin;
@ -75,7 +69,11 @@ typedef struct {
float rssi[SRSLTE_MAX_PORTS]; float rssi[SRSLTE_MAX_PORTS];
float rsrp[SRSLTE_MAX_PORTS]; float rsrp[SRSLTE_MAX_PORTS];
float noise_estimate[SRSLTE_MAX_PORTS]; float noise_estimate[SRSLTE_MAX_PORTS];
float filter_time_ema;
/* Use PSS for noise estimation in LS linear interpolation mode */
cf_t pss_signal[SRSLTE_PSS_LEN];
cf_t tmp_pss[SRSLTE_PSS_LEN];
cf_t tmp_pss_noisy[SRSLTE_PSS_LEN];
} srslte_chest_dl_t; } srslte_chest_dl_t;
@ -84,16 +82,9 @@ SRSLTE_API int srslte_chest_dl_init(srslte_chest_dl_t *q,
SRSLTE_API void srslte_chest_dl_free(srslte_chest_dl_t *q); SRSLTE_API void srslte_chest_dl_free(srslte_chest_dl_t *q);
SRSLTE_API int srslte_chest_dl_set_filter_freq(srslte_chest_dl_t *q, SRSLTE_API void srslte_chest_dl_set_smooth_filter(srslte_chest_dl_t *q,
float *filter, float *filter,
uint32_t filter_len); uint32_t filter_len);
SRSLTE_API int srslte_chest_dl_set_filter_time(srslte_chest_dl_t *q,
float *filter,
uint32_t filter_len);
SRSLTE_API void srslte_chest_dl_set_filter_time_ema(srslte_chest_dl_t *q,
float ema_coefficient);
SRSLTE_API int srslte_chest_dl_estimate(srslte_chest_dl_t *q, SRSLTE_API int srslte_chest_dl_estimate(srslte_chest_dl_t *q,
cf_t *input, cf_t *input,

@ -80,7 +80,12 @@ SRSLTE_API void srslte_interp_linear_vector(srslte_interp_linsrslte_vec_t *q,
cf_t *between, cf_t *between,
uint32_t M); uint32_t M);
SRSLTE_API void srslte_interp_linear_vector2(srslte_interp_linsrslte_vec_t *q,
cf_t *in0,
cf_t *in1,
cf_t *start,
cf_t *between,
uint32_t M);
/* Interpolation within a vector */ /* Interpolation within a vector */

@ -49,12 +49,8 @@ SRSLTE_API void srslte_scrambling_b_offset(srslte_sequence_t *s,
int len); int len);
SRSLTE_API void srslte_scrambling_bytes(srslte_sequence_t *s, SRSLTE_API void srslte_scrambling_bytes(srslte_sequence_t *s,
uint8_t *data); uint8_t *data,
int len);
SRSLTE_API void srslte_scrambling_bytes_offset(srslte_sequence_t *s,
uint8_t *data,
int offset,
int len);
SRSLTE_API void srslte_scrambling_f(srslte_sequence_t *s, SRSLTE_API void srslte_scrambling_f(srslte_sequence_t *s,
float *data); float *data);

@ -112,6 +112,11 @@ SRSLTE_API void srslte_pss_synch_reset(srslte_pss_synch_t *q);
SRSLTE_API int srslte_pss_generate(cf_t *signal, SRSLTE_API int srslte_pss_generate(cf_t *signal,
uint32_t N_id_2); uint32_t N_id_2);
SRSLTE_API void srslte_pss_get_slot(cf_t *slot,
cf_t *pss_signal,
uint32_t nof_prb,
srslte_cp_t cp);
SRSLTE_API void srslte_pss_put_slot(cf_t *pss_signal, SRSLTE_API void srslte_pss_put_slot(cf_t *pss_signal,
cf_t *slot, cf_t *slot,
uint32_t nof_prb, uint32_t nof_prb,

@ -39,31 +39,29 @@
#include "srslte/utils/vector.h" #include "srslte/utils/vector.h"
#include "srslte/utils/convolution.h" #include "srslte/utils/convolution.h"
#define NOISE_POWER_METHOD 1 // 0: Difference between noisy received and noiseless; 1: power of empty subcarriers #define ESTIMATE_NOISE_LS_PSS
#define DEFAULT_FILTER_FREQ_LEN 11 // Must be odd #define DEFAULT_FILTER_LEN 3
#define DEFAULT_FILTER_TIME_LEN 3
static void init_default_filters(srslte_chest_dl_t *q) { static void set_default_filter(srslte_chest_dl_t *q, int filter_len) {
float f[DEFAULT_FILTER_FREQ_LEN]; float fil[SRSLTE_CHEST_DL_MAX_SMOOTH_FIL_LEN];
float t[DEFAULT_FILTER_TIME_LEN];
for (int i=0;i<filter_len/2;i++) {
fil[i] = i+1;
fil[i+filter_len/2+1]=filter_len/2-i;
}
fil[filter_len/2]=filter_len/2+1;
for (int i=0;i<DEFAULT_FILTER_FREQ_LEN/2+1;i++) { float s=0;
f[i] = 1+i; for (int i=0;i<filter_len;i++) {
f[DEFAULT_FILTER_FREQ_LEN-i-1] = 1+i; s+=fil[i];
} }
float norm = srslte_vec_acc_ff(f, DEFAULT_FILTER_FREQ_LEN); for (int i=0;i<filter_len;i++) {
srslte_vec_sc_prod_fff(f, 1.0/norm, f, DEFAULT_FILTER_FREQ_LEN); fil[i]/=s;
srslte_chest_dl_set_filter_freq(q, f, DEFAULT_FILTER_FREQ_LEN);
for (int i=0;i<DEFAULT_FILTER_TIME_LEN/2+1;i++) {
t[i] = 1+i;
t[DEFAULT_FILTER_TIME_LEN-i-1] = 1+i;
} }
norm = srslte_vec_acc_ff(t, DEFAULT_FILTER_TIME_LEN);
srslte_vec_sc_prod_fff(t, 1.0/norm, t, DEFAULT_FILTER_TIME_LEN); srslte_chest_dl_set_smooth_filter(q, fil, filter_len);
srslte_chest_dl_set_filter_time(q, t, DEFAULT_FILTER_TIME_LEN);
} }
/** 3GPP LTE Downlink channel estimator and equalizer. /** 3GPP LTE Downlink channel estimator and equalizer.
@ -89,33 +87,25 @@ int srslte_chest_dl_init(srslte_chest_dl_t *q, srslte_cell_t cell)
goto clean_exit; goto clean_exit;
} }
q->tmp_freqavg = srslte_vec_malloc(sizeof(cf_t) * SRSLTE_SF_LEN_RE(cell.nof_prb, cell.cp)); q->tmp_noise = srslte_vec_malloc(sizeof(cf_t) * SRSLTE_REFSIGNAL_MAX_NUM_SF(cell.nof_prb));
if (!q->tmp_freqavg) { if (!q->tmp_noise) {
perror("malloc"); perror("malloc");
goto clean_exit; goto clean_exit;
} }
q->tmp_noise = srslte_vec_malloc(sizeof(cf_t) * SRSLTE_SF_LEN_RE(cell.nof_prb, cell.cp)); q->pilot_estimates = srslte_vec_malloc(sizeof(cf_t) * SRSLTE_REFSIGNAL_MAX_NUM_SF(cell.nof_prb));
if (!q->tmp_noise) { if (!q->pilot_estimates) {
perror("malloc"); perror("malloc");
goto clean_exit; goto clean_exit;
} }
q->tmp_timeavg_mult = srslte_vec_malloc(sizeof(cf_t) * 12*cell.nof_prb); q->pilot_estimates_average = srslte_vec_malloc(sizeof(cf_t) * SRSLTE_REFSIGNAL_MAX_NUM_SF(cell.nof_prb));
if (!q->tmp_timeavg_mult) { if (!q->pilot_estimates_average) {
perror("malloc");
goto clean_exit;
}
q->pilot_recv_signal = srslte_vec_malloc(sizeof(cf_t) * SRSLTE_REFSIGNAL_MAX_NUM_SF(cell.nof_prb));
if (!q->pilot_recv_signal) {
perror("malloc"); perror("malloc");
goto clean_exit; goto clean_exit;
}
for (int i=0;i<cell.nof_ports;i++) {
q->pilot_estimates[i] = srslte_vec_malloc(2*sizeof(cf_t) * SRSLTE_REFSIGNAL_NUM_SF(cell.nof_prb, i));
if (!q->pilot_estimates[i]) {
perror("malloc");
goto clean_exit;
}
q->pilot_recv_signal[i] = srslte_vec_malloc(sizeof(cf_t) * SRSLTE_REFSIGNAL_NUM_SF(cell.nof_prb, i));
if (!q->pilot_recv_signal[i]) {
perror("malloc");
goto clean_exit;
}
} }
if (srslte_interp_linear_vector_init(&q->srslte_interp_linvec, SRSLTE_NRE*cell.nof_prb)) { if (srslte_interp_linear_vector_init(&q->srslte_interp_linvec, SRSLTE_NRE*cell.nof_prb)) {
@ -128,7 +118,14 @@ int srslte_chest_dl_init(srslte_chest_dl_t *q, srslte_cell_t cell)
goto clean_exit; goto clean_exit;
} }
init_default_filters(q); if (srslte_pss_generate(q->pss_signal, cell.id%3)) {
fprintf(stderr, "Error initializing PSS signal for noise estimation\n");
goto clean_exit;
}
q->smooth_filter_len = 0;
set_default_filter(q, DEFAULT_FILTER_LEN);
q->cell = cell; q->cell = cell;
} }
@ -145,72 +142,62 @@ void srslte_chest_dl_free(srslte_chest_dl_t *q)
{ {
srslte_refsignal_cs_free(&q->csr_signal); srslte_refsignal_cs_free(&q->csr_signal);
if (q->tmp_freqavg) {
free(q->tmp_freqavg);
}
if (q->tmp_noise) { if (q->tmp_noise) {
free(q->tmp_noise); free(q->tmp_noise);
} }
if (q->tmp_timeavg_mult) {
free(q->tmp_timeavg_mult);
}
srslte_interp_linear_vector_free(&q->srslte_interp_linvec); srslte_interp_linear_vector_free(&q->srslte_interp_linvec);
srslte_interp_linear_free(&q->srslte_interp_lin); srslte_interp_linear_free(&q->srslte_interp_lin);
for (int i=0;i<SRSLTE_MAX_PORTS;i++) { if (q->pilot_estimates) {
if (q->pilot_estimates[i]) { free(q->pilot_estimates);
free(q->pilot_estimates[i]); }
} if (q->pilot_estimates_average) {
if (q->pilot_recv_signal[i]) { free(q->pilot_estimates_average);
free(q->pilot_recv_signal[i]); }
} if (q->pilot_recv_signal) {
free(q->pilot_recv_signal);
} }
bzero(q, sizeof(srslte_chest_dl_t)); bzero(q, sizeof(srslte_chest_dl_t));
} }
int srslte_chest_dl_set_filter_freq(srslte_chest_dl_t *q, float *filter, uint32_t filter_len) { /* Uses the difference between the averaged and non-averaged pilot estimates */
if (filter_len <= SRSLTE_CHEST_MAX_FILTER_FREQ_LEN) { static float estimate_noise_pilots(srslte_chest_dl_t *q, cf_t *ce, uint32_t port_id)
q->filter_freq_len = filter_len; {
for (int i=0;i<filter_len;i++) { int nref=SRSLTE_REFSIGNAL_NUM_SF(q->cell.nof_prb, port_id);
q->filter_freq[i] = filter[i]; /* Get averaged pilots from channel estimates */
} srslte_refsignal_cs_get_sf(q->cell, port_id, ce, q->tmp_noise);
return SRSLTE_SUCCESS; /* Substract noisy pilot estimates */
} else { srslte_vec_sub_ccc(q->tmp_noise, q->pilot_estimates, q->tmp_noise, nref);
return SRSLTE_ERROR; /* Compute average power */
} float power = sqrt(2)*q->cell.nof_ports*srslte_vec_avg_power_cf(q->tmp_noise, nref);
} return power;
void srslte_chest_dl_set_filter_time_ema(srslte_chest_dl_t *q, float ema_coefficient) {
q->filter_time_ema = ema_coefficient;
}
int srslte_chest_dl_set_filter_time(srslte_chest_dl_t *q, float *filter, uint32_t filter_len) {
if (filter_len <= SRSLTE_CHEST_MAX_FILTER_TIME_LEN) {
q->filter_time_len = filter_len;
for (int i=0;i<filter_len;i++) {
q->filter_time[i] = filter[i];
}
return SRSLTE_SUCCESS;
} else {
return SRSLTE_ERROR;
}
} }
#ifdef ESTIMATE_NOISE_LS_PSS
static float estimate_noise_pss(srslte_chest_dl_t *q, cf_t *input, cf_t *ce)
{
/* Get PSS from received signal */
srslte_pss_get_slot(input, q->tmp_pss, q->cell.nof_prb, q->cell.cp);
/* Get channel estimates for PSS position */
srslte_pss_get_slot(ce, q->tmp_pss_noisy, q->cell.nof_prb, q->cell.cp);
/* Multiply known PSS by channel estimates */
srslte_vec_prod_ccc(q->tmp_pss_noisy, q->pss_signal, q->tmp_pss_noisy, SRSLTE_PSS_LEN);
#if NOISE_POWER_METHOD==0 /* Substract received signal */
/* Uses the difference between the averaged and non-averaged pilot estimates */ srslte_vec_sub_ccc(q->tmp_pss_noisy, q->tmp_pss, q->tmp_pss_noisy, SRSLTE_PSS_LEN);
static float estimate_noise_port(srslte_chest_dl_t *q, cf_t *average, cf_t *ce, uint32_t len) {
/* Use difference between averaged and noisy LS pilot estimates */ /* Compute average power */
srslte_vec_sub_ccc(average, ce, q->tmp_noise, len); float power = 2*q->cell.nof_ports*srslte_vec_avg_power_cf(q->tmp_pss_noisy, SRSLTE_PSS_LEN);
return srslte_vec_avg_power_cf(q->tmp_noise, len); return power;
} }
#endif
#if NOISE_POWER_METHOD==1
#else
/* Uses the 5 empty transmitted SC before and after the SSS and PSS sequences for noise estimation */ /* Uses the 5 empty transmitted SC before and after the SSS and PSS sequences for noise estimation */
static float estimate_noise_port(srslte_chest_dl_t *q, cf_t *input) { static float estimate_noise_empty_sc(srslte_chest_dl_t *q, cf_t *input) {
int k_sss = (SRSLTE_CP_NSYMB(q->cell.cp) - 2) * q->cell.nof_prb * SRSLTE_NRE + q->cell.nof_prb * SRSLTE_NRE / 2 - 31; int k_sss = (SRSLTE_CP_NSYMB(q->cell.cp) - 2) * q->cell.nof_prb * SRSLTE_NRE + q->cell.nof_prb * SRSLTE_NRE / 2 - 31;
float noise_power = 0; float noise_power = 0;
noise_power += srslte_vec_avg_power_cf(&input[k_sss-5], 5); // 5 empty SC before SSS noise_power += srslte_vec_avg_power_cf(&input[k_sss-5], 5); // 5 empty SC before SSS
@ -224,48 +211,6 @@ static float estimate_noise_port(srslte_chest_dl_t *q, cf_t *input) {
#endif #endif
static void average_estimates(srslte_chest_dl_t *q, cf_t *ce, uint32_t port_id)
{
int nref=12*q->cell.nof_prb;
uint32_t l, i;
/* For each symbol with pilots in a slot */
for (l=0;l<SRSLTE_CP_NSYMB(q->cell.cp);l++) {
if (q->filter_freq_len > 0) {
/* Filter pilot estimates in frequency */
srslte_conv_same_cf(&ce[l*12*q->cell.nof_prb], q->filter_freq, &q->tmp_freqavg[l*12*q->cell.nof_prb], nref, q->filter_freq_len);
} else {
memcpy(&q->tmp_freqavg[l*12*q->cell.nof_prb], &ce[l*12*q->cell.nof_prb], nref * sizeof(cf_t));
}
}
#if NOISE_POWER_METHOD==0
q->noise_estimate[port_id] = estimate_noise_port(q, q->tmp_freqavg, ce,
SRSLTE_SF_LEN_RE(q->cell.nof_prb, q->cell.cp));
#endif
/* Filter with FIR or don't filter */
for (l=0;l<SRSLTE_CP_NSYMB(q->cell.cp);l++) {
/* Filter in time domain. */
if (q->filter_time_len > 0) {
/* Multiply symbols by filter and add them */
bzero(&ce[l*12*q->cell.nof_prb], nref * sizeof(cf_t));
for (i=0;i<q->filter_time_len;i++) {
if (l+i-q->filter_time_len/2 < SRSLTE_CP_NSYMB(q->cell.cp) && l+i-q->filter_time_len/2 > 0) {
srslte_vec_sc_prod_cfc(&q->tmp_freqavg[(l+i-q->filter_time_len/2)*12*q->cell.nof_prb], q->filter_time[i], q->tmp_timeavg_mult, nref);
srslte_vec_sum_ccc(q->tmp_timeavg_mult, &ce[l*12*q->cell.nof_prb], &ce[l*12*q->cell.nof_prb], nref);
} else {
srslte_vec_sc_prod_cfc(&q->tmp_freqavg[l*12*q->cell.nof_prb], q->filter_time[i], q->tmp_timeavg_mult, nref);
srslte_vec_sum_ccc(q->tmp_timeavg_mult, &ce[l*12*q->cell.nof_prb], &ce[l*12*q->cell.nof_prb], nref);
}
}
} else {
memcpy(&ce[l*12*q->cell.nof_prb], &q->tmp_freqavg[l*12*q->cell.nof_prb], nref * sizeof(cf_t));
}
}
}
#define cesymb(i) ce[SRSLTE_RE_IDX(q->cell.nof_prb,i,0)] #define cesymb(i) ce[SRSLTE_RE_IDX(q->cell.nof_prb,i,0)]
static void interpolate_pilots(srslte_chest_dl_t *q, cf_t *pilot_estimates, cf_t *ce, uint32_t port_id) static void interpolate_pilots(srslte_chest_dl_t *q, cf_t *pilot_estimates, cf_t *ce, uint32_t port_id)
@ -285,10 +230,10 @@ static void interpolate_pilots(srslte_chest_dl_t *q, cf_t *pilot_estimates, cf_t
/* Now interpolate in the time domain between symbols */ /* Now interpolate in the time domain between symbols */
if (SRSLTE_CP_ISNORM(q->cell.cp)) { if (SRSLTE_CP_ISNORM(q->cell.cp)) {
if (nsymbols == 4) { if (nsymbols == 4) {
srslte_interp_linear_vector(&q->srslte_interp_linvec, &cesymb(0), &cesymb(4), &cesymb(1), 3); srslte_interp_linear_vector(&q->srslte_interp_linvec, &cesymb(0), &cesymb(4), &cesymb(1), 3);
srslte_interp_linear_vector(&q->srslte_interp_linvec, &cesymb(4), &cesymb(7), &cesymb(5), 2); srslte_interp_linear_vector(&q->srslte_interp_linvec, &cesymb(4), &cesymb(7), &cesymb(5), 2);
srslte_interp_linear_vector(&q->srslte_interp_linvec, &cesymb(7), &cesymb(11), &cesymb(8), 3); srslte_interp_linear_vector(&q->srslte_interp_linvec, &cesymb(7), &cesymb(11), &cesymb(8), 3);
srslte_interp_linear_vector(&q->srslte_interp_linvec, &cesymb(7), &cesymb(11), &cesymb(12), 2); srslte_interp_linear_vector2(&q->srslte_interp_linvec, &cesymb(7), &cesymb(11), &cesymb(11), &cesymb(12), 2);
} else { } else {
srslte_interp_linear_vector(&q->srslte_interp_linvec, &cesymb(8), &cesymb(1), &cesymb(0), 1); srslte_interp_linear_vector(&q->srslte_interp_linvec, &cesymb(8), &cesymb(1), &cesymb(0), 1);
srslte_interp_linear_vector(&q->srslte_interp_linvec, &cesymb(1), &cesymb(8), &cesymb(2), 6); srslte_interp_linear_vector(&q->srslte_interp_linvec, &cesymb(1), &cesymb(8), &cesymb(2), 6);
@ -299,7 +244,7 @@ static void interpolate_pilots(srslte_chest_dl_t *q, cf_t *pilot_estimates, cf_t
srslte_interp_linear_vector(&q->srslte_interp_linvec, &cesymb(0), &cesymb(3), &cesymb(1), 2); srslte_interp_linear_vector(&q->srslte_interp_linvec, &cesymb(0), &cesymb(3), &cesymb(1), 2);
srslte_interp_linear_vector(&q->srslte_interp_linvec, &cesymb(3), &cesymb(6), &cesymb(4), 2); srslte_interp_linear_vector(&q->srslte_interp_linvec, &cesymb(3), &cesymb(6), &cesymb(4), 2);
srslte_interp_linear_vector(&q->srslte_interp_linvec, &cesymb(6), &cesymb(9), &cesymb(7), 2); srslte_interp_linear_vector(&q->srslte_interp_linvec, &cesymb(6), &cesymb(9), &cesymb(7), 2);
srslte_interp_linear_vector(&q->srslte_interp_linvec, &cesymb(6), &cesymb(9), &cesymb(9), 2); srslte_interp_linear_vector2(&q->srslte_interp_linvec, &cesymb(6), &cesymb(9), &cesymb(9), &cesymb(10), 2);
} else { } else {
srslte_interp_linear_vector(&q->srslte_interp_linvec, &cesymb(7), &cesymb(1), &cesymb(0), 1); srslte_interp_linear_vector(&q->srslte_interp_linvec, &cesymb(7), &cesymb(1), &cesymb(0), 1);
srslte_interp_linear_vector(&q->srslte_interp_linvec, &cesymb(1), &cesymb(7), &cesymb(2), 5); srslte_interp_linear_vector(&q->srslte_interp_linvec, &cesymb(1), &cesymb(7), &cesymb(2), 5);
@ -308,6 +253,25 @@ static void interpolate_pilots(srslte_chest_dl_t *q, cf_t *pilot_estimates, cf_t
} }
} }
void srslte_chest_dl_set_smooth_filter(srslte_chest_dl_t *q, float *filter, uint32_t filter_len) {
if (filter_len < SRSLTE_CHEST_DL_MAX_SMOOTH_FIL_LEN) {
memcpy(q->smooth_filter, filter, filter_len*sizeof(float));
q->smooth_filter_len = filter_len;
} else {
fprintf(stderr, "Error setting smoothing filter: filter len exceeds maximum (%d>%d)\n",
filter_len, SRSLTE_CHEST_DL_MAX_SMOOTH_FIL_LEN);
}
}
static void average_pilots(srslte_chest_dl_t *q, cf_t *input, cf_t *output, uint32_t port_id) {
uint32_t nsymbols = srslte_refsignal_cs_nof_symbols(port_id);
uint32_t nref = 2*q->cell.nof_prb;
for (int l=0;l<nsymbols;l++) {
srslte_conv_same_cf(&input[l*nref], q->smooth_filter, &output[l*nref], nref, q->smooth_filter_len);
}
}
float srslte_chest_dl_rssi(srslte_chest_dl_t *q, cf_t *input, uint32_t port_id) { float srslte_chest_dl_rssi(srslte_chest_dl_t *q, cf_t *input, uint32_t port_id) {
uint32_t l; uint32_t l;
@ -320,43 +284,39 @@ float srslte_chest_dl_rssi(srslte_chest_dl_t *q, cf_t *input, uint32_t port_id)
return rssi/nsymbols; return rssi/nsymbols;
} }
#define RSRP_FROM_ESTIMATES
float srslte_chest_dl_rsrp(srslte_chest_dl_t *q, uint32_t port_id) {
#ifdef RSRP_FROM_ESTIMATES
return srslte_vec_avg_power_cf(q->pilot_estimates[port_id],
SRSLTE_REFSIGNAL_NUM_SF(q->cell.nof_prb, port_id));
#else
return srslte_vec_avg_power_cf(q->pilot_estimates_average[port_id],
SRSLTE_REFSIGNAL_NUM_SF(q->cell.nof_prb, port_id));
#endif
}
int srslte_chest_dl_estimate_port(srslte_chest_dl_t *q, cf_t *input, cf_t *ce, uint32_t sf_idx, uint32_t port_id) int srslte_chest_dl_estimate_port(srslte_chest_dl_t *q, cf_t *input, cf_t *ce, uint32_t sf_idx, uint32_t port_id)
{ {
/* Get references from the input signal */ /* Get references from the input signal */
srslte_refsignal_cs_get_sf(q->cell, port_id, input, q->pilot_recv_signal[port_id]); srslte_refsignal_cs_get_sf(q->cell, port_id, input, q->pilot_recv_signal);
/* Use the known CSR signal to compute Least-squares estimates */ /* Use the known CSR signal to compute Least-squares estimates */
srslte_vec_prod_conj_ccc(q->pilot_recv_signal[port_id], q->csr_signal.pilots[port_id/2][sf_idx], srslte_vec_prod_conj_ccc(q->pilot_recv_signal, q->csr_signal.pilots[port_id/2][sf_idx],
q->pilot_estimates[port_id], SRSLTE_REFSIGNAL_NUM_SF(q->cell.nof_prb, port_id)); q->pilot_estimates, SRSLTE_REFSIGNAL_NUM_SF(q->cell.nof_prb, port_id));
if (ce != NULL) { if (ce != NULL) {
/* Interpolate to create channel estimates for all resource grid */ if (q->smooth_filter_len > 0) {
interpolate_pilots(q, q->pilot_estimates[port_id], ce, port_id); average_pilots(q, q->pilot_estimates, q->pilot_estimates_average, port_id);
interpolate_pilots(q, q->pilot_estimates_average, ce, port_id);
/* Average channel estimates */
average_estimates(q, ce, port_id); /* If averaging, compute noise from difference between received and averaged estimates */
} if (sf_idx == 0 || sf_idx == 5) {
q->noise_estimate[port_id] = estimate_noise_pilots(q, ce, port_id);
#if NOISE_POWER_METHOD==1 }
if (sf_idx == 0 || sf_idx == 5) { } else {
q->noise_estimate[port_id] = estimate_noise_port(q, input); interpolate_pilots(q, q->pilot_estimates, ce, port_id);
/* If not averaging, compute noise from empty subcarriers */
if (sf_idx == 0 || sf_idx == 5) {
#ifdef ESTIMATE_NOISE_LS_PSS
q->noise_estimate[port_id] = estimate_noise_pss(q, input, ce);
#else
q->noise_estimate[port_id] = estimate_noise_empty_sc(q, input);
#endif
}
}
} }
#endif
/* Compute RSRP for the channel estimates in this port */ /* Compute RSRP for the channel estimates in this port */
q->rsrp[port_id] = srslte_chest_dl_rsrp(q, port_id); q->rsrp[port_id] = srslte_vec_avg_power_cf(q->pilot_recv_signal, SRSLTE_REFSIGNAL_NUM_SF(q->cell.nof_prb, port_id));
if (port_id == 0) { if (port_id == 0) {
/* compute rssi only for port 0 */ /* compute rssi only for port 0 */
q->rssi[port_id] = srslte_chest_dl_rssi(q, input, port_id); q->rssi[port_id] = srslte_chest_dl_rssi(q, input, port_id);

@ -218,10 +218,7 @@ int srslte_refsignal_cs_put_sf(srslte_cell_t cell, uint32_t port_id, cf_t *pilot
} }
} }
/** Copies the RE containing references from an array of subframe symbols into the csr_signal[][]. /** Copies the RE containing references from an array of subframe symbols to the pilots array. */
* csr_signal[0] is the signal for the first OFDM symbol containing references and csr_signal[1] is the
* second OFDM symbol containing references (symbol 4 or 3 if port_id < 2)
*/
int srslte_refsignal_cs_get_sf(srslte_cell_t cell, uint32_t port_id, cf_t *sf_symbols, cf_t *pilots) int srslte_refsignal_cs_get_sf(srslte_cell_t cell, uint32_t port_id, cf_t *sf_symbols, cf_t *pilots)
{ {
uint32_t i, l; uint32_t i, l;

@ -37,7 +37,7 @@ ADD_TEST(chest_test_dl_cellid2 chest_test_dl -c 2 -r 50)
# Downlink MEX libs # Downlink MEX libs
######################################################################## ########################################################################
BuildMex(MEXNAME chest SOURCES chest_test_dl_mex.c LIBRARIES srslte) BuildMex(MEXNAME chest SOURCES chest_test_dl_mex.c LIBRARIES srslte srslte_mex)
######################################################################## ########################################################################

@ -35,10 +35,7 @@
#define CELLID prhs[0] #define CELLID prhs[0]
#define PORTS prhs[1] #define PORTS prhs[1]
#define INPUT prhs[2] #define INPUT prhs[2]
#define FREQ_FILTER prhs[3] #define NOF_INPUTS 3
#define TIME_FILTER prhs[4]
#define NOF_INPUTS 5
#define SFIDX prhs[5]
void help() void help()
{ {
@ -101,38 +98,7 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
} }
uint32_t sf_idx=0; uint32_t sf_idx=0;
if (nsubframes == 1) {
if (nrhs != NOF_INPUTS+1) {
mexErrMsgTxt("Received 1 subframe. Need to provide subframe index.\n");
help();
return;
}
sf_idx = (uint32_t) *((double*) mxGetPr(SFIDX));
}
if (nrhs > 5) {
uint32_t filter_len = 0;
float *filter;
double *f;
filter_len = mxGetNumberOfElements(FREQ_FILTER);
filter = malloc(sizeof(float) * filter_len);
f = (double*) mxGetPr(FREQ_FILTER);
for (i=0;i<filter_len;i++) {
filter[i] = (float) f[i];
}
srslte_chest_dl_set_filter_freq(&chest, filter, filter_len);
filter_len = mxGetNumberOfElements(TIME_FILTER);
filter = malloc(sizeof(float) * filter_len);
f = (double*) mxGetPr(TIME_FILTER);
for (i=0;i<filter_len;i++) {
filter[i] = (float) f[i];
}
srslte_chest_dl_set_filter_time(&chest, filter, filter_len);
}
double *inr=(double *)mxGetPr(INPUT); double *inr=(double *)mxGetPr(INPUT);
double *ini=(double *)mxGetPi(INPUT); double *ini=(double *)mxGetPi(INPUT);
@ -149,7 +115,7 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
output_signal2 = srslte_vec_malloc(nof_re * sizeof(cf_t)); output_signal2 = srslte_vec_malloc(nof_re * sizeof(cf_t));
srslte_precoding_init(&cheq, nof_re); srslte_precoding_init(&cheq, nof_re);
/* Create output values */ /* Create output values */
if (nlhs >= 1) { if (nlhs >= 1) {
plhs[0] = mxCreateDoubleMatrix(nof_re * nsubframes, cell.nof_ports, mxCOMPLEX); plhs[0] = mxCreateDoubleMatrix(nof_re * nsubframes, cell.nof_ports, mxCOMPLEX);
@ -167,6 +133,7 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
outi2 = mxGetPi(plhs[2]); outi2 = mxGetPi(plhs[2]);
} }
float noise_power=0;
for (int sf=0;sf<nsubframes;sf++) { for (int sf=0;sf<nsubframes;sf++) {
/* Convert input to C complex type */ /* Convert input to C complex type */
for (i=0;i<nof_re;i++) { for (i=0;i<nof_re;i++) {
@ -181,12 +148,16 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
if (nsubframes != 1) { if (nsubframes != 1) {
sf_idx = sf%10; sf_idx = sf%10;
} }
if (srslte_chest_dl_estimate(&chest, input_signal, ce, sf_idx)) { if (srslte_chest_dl_estimate(&chest, input_signal, ce, sf_idx)) {
mexErrMsgTxt("Error running channel estimator\n"); mexErrMsgTxt("Error running channel estimator\n");
return; return;
} }
if (sf==0) {
noise_power = srslte_chest_dl_get_noise_estimate(&chest);
}
if (cell.nof_ports == 1) { if (cell.nof_ports == 1) {
srslte_predecoding_single(input_signal, ce[0], output_signal2, nof_re, srslte_chest_dl_get_noise_estimate(&chest)); srslte_predecoding_single(input_signal, ce[0], output_signal2, nof_re, srslte_chest_dl_get_noise_estimate(&chest));
} else { } else {
@ -195,28 +166,24 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
} }
if (nlhs >= 1) { if (nlhs >= 1) {
for (int j=0;j<cell.nof_ports;j++) { for (i=0;i<nof_re;i++) {
for (i=0;i<nof_re;i++) { *outr0 = (double) crealf(ce[0][i]);
*outr0 = (double) crealf(ce[j][i]); if (outi0) {
if (outi0) { *outi0 = (double) cimagf(ce[0][i]);
*outi0 = (double) cimagf(ce[j][i]); }
} outr0++;
outr0++; outi0++;
outi0++; }
}
}
} }
if (nlhs >= 2) { if (nlhs >= 2) {
for (int j=0;j<cell.nof_ports;j++) { for (i=0;i<SRSLTE_REFSIGNAL_NUM_SF(cell.nof_prb,0);i++) {
for (i=0;i<SRSLTE_REFSIGNAL_NUM_SF(cell.nof_prb,j);i++) { *outr1 = (double) crealf(chest.pilot_estimates_average[i]);
*outr1 = (double) crealf(chest.pilot_estimates_average[j][i]); if (outi1) {
if (outi1) { *outi1 = (double) cimagf(chest.pilot_estimates_average[i]);
*outi1 = (double) cimagf(chest.pilot_estimates_average[j][i]);
}
outr1++;
outi1++;
} }
} outr1++;
outi1++;
}
} }
if (nlhs >= 3) { if (nlhs >= 3) {
for (i=0;i<nof_re;i++) { for (i=0;i<nof_re;i++) {
@ -231,7 +198,7 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
} }
if (nlhs >= 4) { if (nlhs >= 4) {
plhs[3] = mxCreateDoubleScalar(srslte_chest_dl_get_noise_estimate(&chest)); plhs[3] = mxCreateDoubleScalar(noise_power);
} }
if (nlhs >= 5) { if (nlhs >= 5) {
plhs[4] = mxCreateDoubleScalar(srslte_chest_dl_get_rsrp(&chest)); plhs[4] = mxCreateDoubleScalar(srslte_chest_dl_get_rsrp(&chest));

@ -285,7 +285,8 @@ int srslte_rm_turbo_tx_lut(uint8_t *w_buff, uint8_t *systematic, uint8_t *parity
} }
int srslte_rm_turbo_rx_lut(int16_t *input, int16_t *output, uint32_t in_len, uint32_t cb_idx, uint32_t rv_idx) int srslte_rm_turbo_rx_lut(int16_t *input, int16_t *output, uint32_t in_len, uint32_t cb_idx, uint32_t rv_idx)
{ {
#ifdef LV_HAVE_AVX #ifdef LV_HAVE_AVX
return srslte_rm_turbo_rx_lut_avx(input, output, in_len, cb_idx, rv_idx); return srslte_rm_turbo_rx_lut_avx(input, output, in_len, cb_idx, rv_idx);
#else #else
@ -295,9 +296,7 @@ int srslte_rm_turbo_rx_lut(int16_t *input, int16_t *output, uint32_t in_len, uin
if (rv_idx < 4 && cb_idx < SRSLTE_NOF_TC_CB_SIZES) { if (rv_idx < 4 && cb_idx < SRSLTE_NOF_TC_CB_SIZES) {
uint32_t out_len = 3*srslte_cbsegm_cbsize(cb_idx)+12; uint32_t out_len = 3*srslte_cbsegm_cbsize(cb_idx)+12;
uint16_t *deinter = deinterleaver[cb_idx][rv_idx]; uint16_t *deinter = deinterleaver[cb_idx][rv_idx];
for (int i=0;i<in_len;i++) {
for (int i=0;i<in_len;i++) {
//printf("i=%d=%d goes to %d\n", i%out_len, input[i], deinter[i%out_len]);
output[deinter[i%out_len]] += input[i]; output[deinter[i%out_len]] += input[i];
} }
return 0; return 0;

@ -69,8 +69,9 @@ void mod_qpsk_bytes(srslte_modem_table_t* q, uint8_t *bits, cf_t* symbols, uint3
for (int i=0;i<nbits/8;i++) { for (int i=0;i<nbits/8;i++) {
memcpy(&symbols[4*i], &q->symbol_table_qpsk[bits[i]], sizeof(qpsk_packed_t)); memcpy(&symbols[4*i], &q->symbol_table_qpsk[bits[i]], sizeof(qpsk_packed_t));
} }
// Encode last 1, 2 or 3 bit pairs if not multiple of 8
for (int i=0;i<(nbits%8)/2;i++) { for (int i=0;i<(nbits%8)/2;i++) {
symbols[8*(nbits/8)+i] = q->symbol_table[(bits[8*(nbits/8)]&mask_qpsk[i])>>shift_qpsk[i]]; symbols[4*(nbits/8)+i] = q->symbol_table[(bits[nbits/8]&mask_qpsk[i])>>shift_qpsk[i]];
} }
} }
@ -78,7 +79,10 @@ void mod_16qam_bytes(srslte_modem_table_t* q, uint8_t *bits, cf_t* symbols, uint
for (int i=0;i<nbits/8;i++) { for (int i=0;i<nbits/8;i++) {
memcpy(&symbols[2*i], &q->symbol_table_16qam[bits[i]], sizeof(qam16_packed_t)); memcpy(&symbols[2*i], &q->symbol_table_16qam[bits[i]], sizeof(qam16_packed_t));
} }
symbols[8*(nbits/8)] = q->symbol_table[(bits[8*(nbits/8)]&0xf0)>>4]; // Encode last 4 bits if not multiple of 8
if (nbits%8) {
symbols[2*(nbits/8)] = q->symbol_table[(bits[nbits/8]&0xf0)>>4];
}
} }
void mod_64qam_bytes(srslte_modem_table_t* q, uint8_t *bits, cf_t* symbols, uint32_t nbits) { void mod_64qam_bytes(srslte_modem_table_t* q, uint8_t *bits, cf_t* symbols, uint32_t nbits) {
@ -101,22 +105,22 @@ void mod_64qam_bytes(srslte_modem_table_t* q, uint8_t *bits, cf_t* symbols, uint
symbols[i*4+3] = q->symbol_table[in3]; symbols[i*4+3] = q->symbol_table[in3];
} }
if (nbits%24 >= 6) { if (nbits%24 >= 6) {
in80 = bits[24*(nbits/24)+0]; in80 = bits[3*(nbits/24)+0];
in0 = (in80&0xfc)>>2; in0 = (in80&0xfc)>>2;
symbols[24*(nbits/24)+0] = q->symbol_table[in0]; symbols[4*(nbits/24)+0] = q->symbol_table[in0];
} }
if (nbits%24 >= 12) { if (nbits%24 >= 12) {
in81 = bits[24*(nbits/24)+1]; in81 = bits[3*(nbits/24)+1];
in1 = (in80&0x03)<<4 | ((in81&0xf0)>>4); in1 = (in80&0x03)<<4 | ((in81&0xf0)>>4);
symbols[24*(nbits/24)+1] = q->symbol_table[in1]; symbols[4*(nbits/24)+1] = q->symbol_table[in1];
} }
if (nbits%24 >= 18) { if (nbits%24 >= 18) {
in82 = bits[24*(nbits/24)+2]; in82 = bits[3*(nbits/24)+2];
in2 = (in81&0x0f)<<2 | ((in82&0xc0)>>6); in2 = (in81&0x0f)<<2 | ((in82&0xc0)>>6);
symbols[24*(nbits/24)+2] = q->symbol_table[in2]; symbols[4*(nbits/24)+2] = q->symbol_table[in2];
} }
} }

@ -425,7 +425,7 @@ int srslte_pdsch_decode_rnti(srslte_pdsch_t *q,
* thus we don't need tot set it in the LLRs normalization * thus we don't need tot set it in the LLRs normalization
*/ */
srslte_demod_soft_demodulate_s(cfg->grant.mcs.mod, q->d, q->e, cfg->nbits.nof_re); srslte_demod_soft_demodulate_s(cfg->grant.mcs.mod, q->d, q->e, cfg->nbits.nof_re);
/* descramble */ /* descramble */
if (rnti != q->rnti) { if (rnti != q->rnti) {
srslte_sequence_t seq; srslte_sequence_t seq;
@ -522,10 +522,10 @@ int srslte_pdsch_encode_rnti(srslte_pdsch_t *q,
if (srslte_sequence_pdsch(&seq, rnti, 0, 2 * cfg->sf_idx, q->cell.id, cfg->nbits.nof_bits)) { if (srslte_sequence_pdsch(&seq, rnti, 0, 2 * cfg->sf_idx, q->cell.id, cfg->nbits.nof_bits)) {
return SRSLTE_ERROR; return SRSLTE_ERROR;
} }
srslte_scrambling_bytes_offset(&seq, (uint8_t*) q->e, 0, cfg->nbits.nof_bits); srslte_scrambling_bytes(&seq, (uint8_t*) q->e, cfg->nbits.nof_bits);
srslte_sequence_free(&seq); srslte_sequence_free(&seq);
} else { } else {
srslte_scrambling_bytes_offset(&q->seq[cfg->sf_idx], (uint8_t*) q->e, 0, cfg->nbits.nof_bits); srslte_scrambling_bytes(&q->seq[cfg->sf_idx], (uint8_t*) q->e, cfg->nbits.nof_bits);
} }
srslte_mod_modulate_bytes(&q->mod[cfg->grant.mcs.mod], (uint8_t*) q->e, q->d, cfg->nbits.nof_bits); srslte_mod_modulate_bytes(&q->mod[cfg->grant.mcs.mod], (uint8_t*) q->e, q->d, cfg->nbits.nof_bits);

@ -527,10 +527,10 @@ int srslte_pusch_uci_encode_rnti(srslte_pusch_t *q, srslte_pusch_cfg_t *cfg, srs
if (srslte_sequence_pusch(&seq, rnti, 2 * cfg->sf_idx, q->cell.id, cfg->nbits.nof_bits)) { if (srslte_sequence_pusch(&seq, rnti, 2 * cfg->sf_idx, q->cell.id, cfg->nbits.nof_bits)) {
return SRSLTE_ERROR; return SRSLTE_ERROR;
} }
srslte_scrambling_bytes_offset(&seq, (uint8_t*) q->q, 0, cfg->nbits.nof_bits); srslte_scrambling_bytes(&seq, (uint8_t*) q->q, cfg->nbits.nof_bits);
srslte_sequence_free(&seq); srslte_sequence_free(&seq);
} else { } else {
srslte_scrambling_bytes_offset(&q->seq[cfg->sf_idx], (uint8_t*) q->q, 0, cfg->nbits.nof_bits); srslte_scrambling_bytes(&q->seq[cfg->sf_idx], (uint8_t*) q->q, cfg->nbits.nof_bits);
} }
// Correct UCI placeholder bits // Correct UCI placeholder bits

@ -390,7 +390,6 @@ static int decode_tb(srslte_sch_t *q,
n_e = Qm * ((uint32_t) ceilf((float) Gp/cb_segm->C)); n_e = Qm * ((uint32_t) ceilf((float) Gp/cb_segm->C));
} }
bzero(softbuffer->buffer_f[i], (3*cb_len+12)*sizeof(int16_t));
/* Rate Unmatching */ /* Rate Unmatching */
if (srslte_rm_turbo_rx_lut(&e_bits[rp], softbuffer->buffer_f[i], n_e, cblen_idx, rv)) { if (srslte_rm_turbo_rx_lut(&e_bits[rp], softbuffer->buffer_f[i], n_e, cblen_idx, rv)) {
fprintf(stderr, "Error in rate matching\n"); fprintf(stderr, "Error in rate matching\n");

@ -108,6 +108,15 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
mexErrMsgTxt("Error computing CB segmentation\n"); mexErrMsgTxt("Error computing CB segmentation\n");
return; return;
} }
uint32_t tmp_rv=cfg.rv;
if (tmp_rv) {
cfg.rv = 0;
if (srslte_dlsch_encode(&dlsch, &cfg, &softbuffer, trblkin, e_bits)) {
mexErrMsgTxt("Error encoding TB\n");
return;
}
cfg.rv = tmp_rv;
}
if (srslte_dlsch_encode(&dlsch, &cfg, &softbuffer, trblkin, e_bits)) { if (srslte_dlsch_encode(&dlsch, &cfg, &softbuffer, trblkin, e_bits)) {
mexErrMsgTxt("Error encoding TB\n"); mexErrMsgTxt("Error encoding TB\n");
return; return;

@ -118,14 +118,6 @@ cf_t *slot_symbols[SRSLTE_MAX_PORTS];
srslte_pdsch_t pdsch; srslte_pdsch_t pdsch;
srslte_ofdm_t ofdm_tx, ofdm_rx; srslte_ofdm_t ofdm_tx, ofdm_rx;
int dummy_function() {
#ifdef DO_OFDM
srslte_ofdm_rx_sf(&ofdm_rx, sf_symbols, slot_symbols[1]);
#endif
srslte_softbuffer_rx_reset_tbs(&softbuffer_rx, grant.mcs.tbs);
return srslte_pdsch_decode(&pdsch, &pdsch_cfg, &softbuffer_rx, slot_symbols[0], ce, 0, data);
}
int main(int argc, char **argv) { int main(int argc, char **argv) {
uint32_t i, j; uint32_t i, j;
int ret = -1; int ret = -1;
@ -228,38 +220,53 @@ int main(int argc, char **argv) {
for (i=0;i<grant.mcs.tbs/8;i++) { for (i=0;i<grant.mcs.tbs/8;i++) {
data[i] = rand()%256; data[i] = rand()%256;
} }
for (rv=0;rv<=rv_idx;rv++) {
uint8_t databit[100000];
pdsch_cfg.rv = rv; srslte_bit_unpack_vector(data, databit, grant.mcs.tbs);
srslte_vec_save_file("data_in", databit, grant.mcs.tbs);
if (!input_file) {
if (!input_file) { if (rv_idx) {
/* Do 1st transmission for rv_idx!=0 */
pdsch_cfg.rv = 0;
if (srslte_pdsch_encode(&pdsch, &pdsch_cfg, &softbuffer_tx, data, slot_symbols)) { if (srslte_pdsch_encode(&pdsch, &pdsch_cfg, &softbuffer_tx, data, slot_symbols)) {
fprintf(stderr, "Error encoding PDSCH\n"); fprintf(stderr, "Error encoding PDSCH\n");
goto quit; goto quit;
} }
} }
pdsch_cfg.rv = rv_idx;
/* combine outputs */ if (srslte_pdsch_encode(&pdsch, &pdsch_cfg, &softbuffer_tx, data, slot_symbols)) {
for (i=0;i<cell.nof_ports;i++) { fprintf(stderr, "Error encoding PDSCH\n");
for (j=0;j<SRSLTE_SF_LEN_RE(cell.nof_prb, cell.cp);j++) { goto quit;
if (i > 0) { }
slot_symbols[0][j] += slot_symbols[i][j]; }
}
ce[i][j] = 1; /* combine outputs */
for (i=0;i<cell.nof_ports;i++) {
for (j=0;j<SRSLTE_SF_LEN_RE(cell.nof_prb, cell.cp);j++) {
if (i > 0) {
slot_symbols[0][j] += slot_symbols[i][j];
} }
ce[i][j] = 1;
} }
}
#ifdef DO_OFDM #ifdef DO_OFDM
srslte_ofdm_tx_sf(&ofdm_tx, slot_symbols[0], sf_symbols); srslte_ofdm_tx_sf(&ofdm_tx, slot_symbols[0], sf_symbols);
#endif #endif
}
} }
int M=1; int M=1;
int r=0; int r=0;
srslte_sch_set_max_noi(&pdsch.dl_sch, 10); srslte_sch_set_max_noi(&pdsch.dl_sch, 10);
gettimeofday(&t[1], NULL); gettimeofday(&t[1], NULL);
for (i=0;i<M;i++) { for (i=0;i<M;i++) {
r = dummy_function(); #ifdef DO_OFDM
srslte_ofdm_rx_sf(&ofdm_rx, sf_symbols, slot_symbols[1]);
#endif
srslte_softbuffer_rx_reset_tbs(&softbuffer_rx, grant.mcs.tbs);
r = srslte_pdsch_decode(&pdsch, &pdsch_cfg, &softbuffer_rx, slot_symbols[0], ce, 0, data);
} }
gettimeofday(&t[2], NULL); gettimeofday(&t[2], NULL);
get_time_interval(t); get_time_interval(t);

@ -53,7 +53,6 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
srslte_pdsch_t pdsch; srslte_pdsch_t pdsch;
srslte_chest_dl_t chest; srslte_chest_dl_t chest;
cf_t *input_fft; cf_t *input_fft;
int nof_re;
srslte_pdsch_cfg_t cfg; srslte_pdsch_cfg_t cfg;
srslte_softbuffer_rx_t softbuffer; srslte_softbuffer_rx_t softbuffer;
uint32_t rnti32; uint32_t rnti32;
@ -102,9 +101,6 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
return; return;
} }
nof_re = 2 * SRSLTE_CP_NORM_NSYMB * cell.nof_prb * SRSLTE_NRE;
srslte_ra_dl_grant_t grant; srslte_ra_dl_grant_t grant;
grant.mcs.tbs = mxGetScalar(TBS); grant.mcs.tbs = mxGetScalar(TBS);
if (grant.mcs.tbs == 0) { if (grant.mcs.tbs == 0) {
@ -187,10 +183,10 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
for (i=0;i<cell.nof_ports;i++) { for (i=0;i<cell.nof_ports;i++) {
ce[i] = srslte_vec_malloc(SRSLTE_SF_LEN_RE(cell.nof_prb, cell.cp) * sizeof(cf_t)); ce[i] = srslte_vec_malloc(SRSLTE_SF_LEN_RE(cell.nof_prb, cell.cp) * sizeof(cf_t));
} }
if (nrhs > NOF_INPUTS) { if (nrhs > NOF_INPUTS) {
cf_t *cearray = NULL; cf_t *cearray = NULL;
nof_re = mexutils_read_cf(prhs[NOF_INPUTS], &cearray); int nof_re = mexutils_read_cf(prhs[NOF_INPUTS], &cearray);
cf_t *cearray_ptr = cearray; cf_t *cearray_ptr = cearray;
for (i=0;i<cell.nof_ports;i++) { for (i=0;i<cell.nof_ports;i++) {
for (int j=0;j<nof_re/cell.nof_ports;j++) { for (int j=0;j<nof_re/cell.nof_ports;j++) {
@ -203,11 +199,12 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
} else { } else {
srslte_chest_dl_estimate(&chest, input_fft, ce, cfg.sf_idx); srslte_chest_dl_estimate(&chest, input_fft, ce, cfg.sf_idx);
} }
float noise_power; float noise_power;
if (nrhs > NOF_INPUTS + 1) { if (nrhs > NOF_INPUTS + 1) {
noise_power = mxGetScalar(prhs[NOF_INPUTS+1]); noise_power = mxGetScalar(prhs[NOF_INPUTS+1]);
} else { } else {
noise_power = 0; noise_power = srslte_chest_dl_get_noise_estimate(&chest);
} }
uint8_t *data_bytes = srslte_vec_malloc(sizeof(uint8_t) * grant.mcs.tbs/8); uint8_t *data_bytes = srslte_vec_malloc(sizeof(uint8_t) * grant.mcs.tbs/8);

@ -123,12 +123,21 @@ void srslte_interp_linear_vector_free(srslte_interp_linsrslte_vec_t *q) {
} }
void srslte_interp_linear_vector(srslte_interp_linsrslte_vec_t *q, cf_t *in0, cf_t *in1, cf_t *between, uint32_t M) void srslte_interp_linear_vector(srslte_interp_linsrslte_vec_t *q, cf_t *in0, cf_t *in1, cf_t *between, uint32_t M)
{
srslte_interp_linear_vector2(q, in0, in1, NULL, between, M);
}
void srslte_interp_linear_vector2(srslte_interp_linsrslte_vec_t *q, cf_t *in0, cf_t *in1, cf_t *start, cf_t *between, uint32_t M)
{ {
uint32_t i; uint32_t i;
srslte_vec_sub_ccc(in1, in0, q->diff_vec, q->vector_len); srslte_vec_sub_ccc(in1, in0, q->diff_vec, q->vector_len);
srslte_vec_sc_prod_cfc(q->diff_vec, (float) 1/M, q->diff_vec, q->vector_len); srslte_vec_sc_prod_cfc(q->diff_vec, (float) 1/(M+1), q->diff_vec, q->vector_len);
srslte_vec_sum_ccc(in0, q->diff_vec, between, q->vector_len); if (start) {
srslte_vec_sum_ccc(start, q->diff_vec, between, q->vector_len);
} else {
srslte_vec_sum_ccc(in0, q->diff_vec, between, q->vector_len);
}
for (i=0;i<M-1;i++) { for (i=0;i<M-1;i++) {
srslte_vec_sum_ccc(between, q->diff_vec, &between[q->vector_len], q->vector_len); srslte_vec_sum_ccc(between, q->diff_vec, &between[q->vector_len], q->vector_len);
between += q->vector_len; between += q->vector_len;
@ -193,7 +202,7 @@ void srslte_interp_linear_offset(srslte_interp_lin_t *q, cf_t *input, cf_t *outp
i=0; i=0;
for (j=0;j<off_st;j++) { for (j=0;j<off_st;j++) {
output[j] = input[i] + (j+1) * (input[i+1]-input[i]) / q->M; output[off_st-j-1] = input[i] - (j+1) * (input[i+1]-input[i]) / q->M;
} }
srslte_vec_sub_ccc(&input[1], input, q->diff_vec, (q->vector_len-1)); srslte_vec_sub_ccc(&input[1], input, q->diff_vec, (q->vector_len-1));
srslte_vec_sc_prod_cfc(q->diff_vec, (float) 1/q->M, q->diff_vec, q->vector_len-1); srslte_vec_sc_prod_cfc(q->diff_vec, (float) 1/q->M, q->diff_vec, q->vector_len-1);

@ -28,6 +28,7 @@
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <assert.h> #include <assert.h>
#include "srslte/utils/bit.h"
#include "srslte/utils/vector.h" #include "srslte/utils/vector.h"
#include "srslte/scrambling/scrambling.h" #include "srslte/scrambling/scrambling.h"
@ -58,47 +59,47 @@ void srslte_scrambling_c_offset(srslte_sequence_t *s, cf_t *data, int offset, in
srslte_vec_prod_cfc(data, &s->c_float[offset], data, len); srslte_vec_prod_cfc(data, &s->c_float[offset], data, len);
} }
void scrambling_b(uint8_t *c, uint8_t *data, int offset, int len) { void scrambling_b(uint8_t *c, uint8_t *data, int len) {
int i; int i;
// Do XOR on a word basis for (i = 0; i < len; i++) {
data[i] = (data[i] ^ c[i]);
if (!(len%8)) { }
uint64_t *x = (uint64_t*) data; }
uint64_t *y = (uint64_t*) &c[offset];
for (int i=0;i<len/8;i++) { void scrambling_b_word(uint8_t *c, uint8_t *data, int len) {
x[i] = (x[i] ^ y[i]); // Do XOR every 64 bits
} // FIXME: Use 32-bit in 32-bit machines
} else if (!(len%4)) { uint64_t *x = (uint64_t*) data;
uint32_t *x = (uint32_t*) data; uint64_t *y = (uint64_t*) c;
uint32_t *y = (uint32_t*) &c[offset]; for (int i=0;i<len/8;i++) {
for (int i=0;i<len/4;i++) { x[i] = (x[i] ^ y[i]);
x[i] = (x[i] ^ y[i]);
}
} else if (!(len%2)) {
uint16_t *x = (uint16_t*) data;
uint16_t *y = (uint16_t*) &c[offset];
for (int i=0;i<len/2;i++) {
x[i] = (x[i] ^ y[i]);
}
} else {
for (i = 0; i < len; i++) {
data[i] = (data[i] ^ c[i + offset]);
}
} }
// Do XOR every 8 bits
scrambling_b(&c[8*(len/8)], &data[8*(len/8)], len%8);
} }
void srslte_scrambling_b(srslte_sequence_t *s, uint8_t *data) { void srslte_scrambling_b(srslte_sequence_t *s, uint8_t *data) {
scrambling_b(s->c, data, 0, s->len); scrambling_b_word(s->c, data, s->len);
} }
void srslte_scrambling_b_offset(srslte_sequence_t *s, uint8_t *data, int offset, int len) { void srslte_scrambling_b_offset(srslte_sequence_t *s, uint8_t *data, int offset, int len) {
scrambling_b(s->c, data, offset, len); if (offset%8) {
} // Do not load words if offset is not word-aligned
scrambling_b(&s->c[offset], data, len);
void srslte_scrambling_bytes(srslte_sequence_t *s, uint8_t *data) { } else {
scrambling_b(s->c_bytes, data, 0, s->len/8); scrambling_b_word(&s->c[offset], data, len);
}
} }
void srslte_scrambling_bytes_offset(srslte_sequence_t *s, uint8_t *data, int offset, int len) { void srslte_scrambling_bytes(srslte_sequence_t *s, uint8_t *data, int len) {
scrambling_b(s->c_bytes, data, offset, len/8); scrambling_b_word(s->c_bytes, data, len/8);
// Scramble last bits
if (len%8) {
uint8_t tmp_bits[8];
srslte_bit_unpack_vector(&data[len/8], tmp_bits, len%8);
scrambling_b(&s->c[8*(len/8)], tmp_bits, len%8);
srslte_bit_pack_vector(tmp_bits, &data[len/8], len%8);
}
} }

@ -254,6 +254,12 @@ void srslte_pss_put_slot(cf_t *pss_signal, cf_t *slot, uint32_t nof_prb, srslte_
memset(&slot[k + SRSLTE_PSS_LEN], 0, 5 * sizeof(cf_t)); memset(&slot[k + SRSLTE_PSS_LEN], 0, 5 * sizeof(cf_t));
} }
void srslte_pss_get_slot(cf_t *slot, cf_t *pss_signal, uint32_t nof_prb, srslte_cp_t cp) {
int k;
k = (SRSLTE_CP_NSYMB(cp) - 1) * nof_prb * SRSLTE_NRE + nof_prb * SRSLTE_NRE / 2 - 31;
memcpy(pss_signal, &slot[k], SRSLTE_PSS_LEN * sizeof(cf_t));
}
/** Sets the current N_id_2 value. Returns -1 on error, 0 otherwise /** Sets the current N_id_2 value. Returns -1 on error, 0 otherwise
*/ */

@ -39,8 +39,6 @@
#define MAX_CANDIDATES 64 #define MAX_CANDIDATES 64
#define PDSCH_DO_ZF
srslte_dci_format_t ue_formats[] = {SRSLTE_DCI_FORMAT1A, SRSLTE_DCI_FORMAT1}; // SRSLTE_DCI_FORMAT1B should go here also srslte_dci_format_t ue_formats[] = {SRSLTE_DCI_FORMAT1A, SRSLTE_DCI_FORMAT1}; // SRSLTE_DCI_FORMAT1B should go here also
const uint32_t nof_ue_formats = 2; const uint32_t nof_ue_formats = 2;
@ -227,11 +225,9 @@ int srslte_ue_dl_decode_rnti_rv_packet(srslte_ue_dl_t *q, srslte_ra_dl_grant_t *
srslte_softbuffer_rx_reset(&q->softbuffer); srslte_softbuffer_rx_reset(&q->softbuffer);
} }
#ifdef PDSCH_DO_ZF // Uncoment next line to do ZF by default in pdsch_ue example
float noise_estimate = 0; //float noise_estimate = 0;
#else
float noise_estimate = srslte_chest_dl_get_noise_estimate(&q->chest); float noise_estimate = srslte_chest_dl_get_noise_estimate(&q->chest);
#endif
if (q->pdsch_cfg.grant.mcs.mod > 0 && q->pdsch_cfg.grant.mcs.tbs >= 0) { if (q->pdsch_cfg.grant.mcs.mod > 0 && q->pdsch_cfg.grant.mcs.tbs >= 0) {
ret = srslte_pdsch_decode_rnti(&q->pdsch, &q->pdsch_cfg, &q->softbuffer, ret = srslte_pdsch_decode_rnti(&q->pdsch, &q->pdsch_cfg, &q->softbuffer,

Loading…
Cancel
Save