mirror of https://github.com/PentHertz/srsLTE.git
Merge branch 'improve_chest' into next
This commit is contained in:
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
|
||||
enbConfig=struct('NCellID',1,'CyclicPrefix','Normal','CellRefP',1);
|
||||
pdschConfig=struct('Modulation','64QAM','RV',0,'TxScheme','Port0');
|
||||
enbConfig=struct('NCellID',0,'CyclicPrefix','Normal','CellRefP',1);
|
||||
pdschConfig=struct('Modulation','64QAM','RV',1,'TxScheme','Port0','NTurboDecIts',10);
|
||||
|
||||
addpath('../../build/srslte/lib/phch/test')
|
||||
|
||||
TBs=36696;
|
||||
e_bits=41400;
|
||||
error=zeros(size(TBs));
|
||||
for i=1:length(TBs)
|
||||
trblkin=randi(2,TBs(i),1)-1;
|
||||
%TBs=18336;
|
||||
i=1;
|
||||
e_bits=3450*6;
|
||||
%error=zeros(size(TBs));
|
||||
%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);
|
||||
lib=srslte_dlsch_encode(enbConfig,pdschConfig,e_bits,trblkin);
|
||||
error(i)=mean(abs(double(mat)-double(lib)));
|
||||
end
|
||||
mat(mat==0)=-1;
|
||||
mat=mat*10;
|
||||
|
||||
if (length(TBs) == 1)
|
||||
%disp(info)
|
||||
disp(error)
|
||||
n=1:length(mat);
|
||||
plot(abs(double(mat)-double(lib)))
|
||||
else
|
||||
plot(error)
|
||||
end
|
||||
rec = lteRateRecoverTurbo(mat,length(trblkin),pdschConfig.RV);
|
||||
rec2 = reshape(reshape(rec{1},[],3)',[],1);
|
||||
out = lteTurboDecode(rec{1});
|
||||
|
||||
x=read_int16('../../build/rmout_0.dat');
|
||||
subplot(2,1,1)
|
||||
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;
|
||||
|
||||
SNR_values_db=10;%linspace(0,30,8);
|
||||
Nrealizations=1 ;
|
||||
SNR_values_db=30;%linspace(0,30,8);
|
||||
Nrealizations=1;
|
||||
|
||||
preEVM = zeros(length(SNR_values_db),Nrealizations);
|
||||
postEVM_mmse = zeros(length(SNR_values_db),Nrealizations);
|
||||
postEVM_mmse_lin = zeros(length(SNR_values_db),Nrealizations);
|
||||
postEVM_srslte = zeros(length(SNR_values_db),Nrealizations);
|
||||
Lp=5;
|
||||
N=512;
|
||||
enb.NDLRB = 25; % Number of resource blocks
|
||||
|
||||
|
||||
enb.NDLRB = 6; % Number of resource blocks
|
||||
enb.CellRefP = 1; % One transmit antenna port
|
||||
enb.NCellID = 0; % Cell ID
|
||||
enb.NCellID = 0; % Cell ID
|
||||
enb.CyclicPrefix = 'Normal'; % Normal cyclic prefix
|
||||
enb.DuplexMode = 'FDD'; % FDD
|
||||
|
||||
%% Channel Model Configuration
|
||||
rng(1); % Configure random number generators
|
||||
K=enb.NDLRB*12;
|
||||
rstart=(N-K)/2;
|
||||
P=K/6;
|
||||
Rhphp=zeros(P,P);
|
||||
Rhhp=zeros(K,P);
|
||||
Rhh=zeros(K,K);
|
||||
|
||||
cfg.Seed = 2; % Random channel seed
|
||||
cfg.NRxAnts = 2; % 1 receive antenna
|
||||
cfg.DelayProfile = 'EVA'; % EVA delay spread
|
||||
cfg.DopplerFreq = 120; % 120Hz Doppler frequency
|
||||
%% Channel Model Configuration
|
||||
cfg.Seed = 0; % Random channel seed
|
||||
cfg.InitTime = 0;
|
||||
cfg.NRxAnts = 1; % 1 receive antenna
|
||||
cfg.DelayProfile = 'EPA';
|
||||
|
||||
% doppler 5, 70 300
|
||||
|
||||
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
|
||||
|
@ -42,25 +47,42 @@ cec.PilotAverage = 'UserDefined'; % Type of pilot symbol averaging
|
|||
cec.FreqWindow = 9; % Frequency window size
|
||||
cec.TimeWindow = 9; % Time window size
|
||||
cec.InterpType = 'Linear'; % 2D interpolation type
|
||||
cec.InterpWindow = 'Centered'; % Interpolation window type
|
||||
cec.InterpWindow = 'Causal'; % Interpolation window type
|
||||
cec.InterpWinSize = 1; % Interpolation window size
|
||||
|
||||
%% Subframe Resource Grid Size
|
||||
|
||||
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
|
||||
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
|
||||
%% Transmit Resource Grid
|
||||
txGrid = [];
|
||||
RSRP = [];
|
||||
|
||||
%% Payload Data Generation
|
||||
% Number of bits needed is size of resource grid (K*L*P) * number of bits
|
||||
% per symbol (2 for QPSK)
|
||||
numberOfBits = K*L*P*2;
|
||||
numberOfBits = Ks*L*Ports*2;
|
||||
|
||||
% Create random bit stream
|
||||
inputBits = randi([0 1], numberOfBits, 1);
|
||||
|
@ -104,7 +126,7 @@ for sf = 0:10
|
|||
|
||||
end
|
||||
|
||||
txGrid([1:5 68:72],6:7) = zeros(10,2);
|
||||
txGrid([1:5 68:72],6:7) = ones(10,2);
|
||||
|
||||
%% OFDM Modulation
|
||||
|
||||
|
@ -112,19 +134,16 @@ txGrid([1:5 68:72],6:7) = zeros(10,2);
|
|||
txGrid = txGrid(:,1:140);
|
||||
|
||||
%% SNR Configuration
|
||||
|
||||
for snr_idx=1:length(SNR_values_db)
|
||||
SNRdB = SNR_values_db(snr_idx); % Desired SNR in dB
|
||||
SNR = 10^(SNRdB/20); % Linear SNR
|
||||
|
||||
fprintf('SNR=%.1f dB\n',SNRdB)
|
||||
|
||||
%% Fading Channel
|
||||
|
||||
cfg.SamplingRate = info.SamplingRate;
|
||||
|
||||
% Pass data through the fading channel model
|
||||
%rxWaveform = lteFadingChannel(cfg,txWaveform);
|
||||
rxWaveform = txWaveform;
|
||||
[rxWaveform, chinfo] = lteFadingChannel(cfg,txWaveform);
|
||||
|
||||
%% Additive Noise
|
||||
|
||||
|
@ -134,91 +153,176 @@ N0 = 1/(sqrt(2.0*enb.CellRefP*double(info.Nfft))*SNR);
|
|||
% Create additive white Gaussian noise
|
||||
noise = N0*complex(randn(size(rxWaveform)),randn(size(rxWaveform)));
|
||||
|
||||
noiseTx(snr_idx) = N0;
|
||||
% Add noise to the received time domain waveform
|
||||
rxWaveform_nonoise = rxWaveform;
|
||||
rxWaveform = rxWaveform + noise;
|
||||
|
||||
%% Synchronization
|
||||
|
||||
offset = lteDLFrameOffset(enb,rxWaveform);
|
||||
rxWaveform = rxWaveform(1+offset+2:end,:);
|
||||
if (offset==-1)
|
||||
offset = lteDLFrameOffset(enb,rxWaveform);
|
||||
end
|
||||
|
||||
rxWaveform = rxWaveform(1+offset:end,:);
|
||||
rxWaveform_nonoise = rxWaveform_nonoise(1+offset:end,:);
|
||||
|
||||
%% OFDM Demodulation
|
||||
rxGrid = lteOFDMDemodulate(enb,rxWaveform);
|
||||
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
|
||||
[estChannel, noiseEst(snr_idx)] = lteDLChannelEstimate(enb,cec,rxGrid);
|
||||
output=[];
|
||||
snrest_srslte = zeros(10,1);
|
||||
noise_srslte = zeros(10,1);
|
||||
rsrp = zeros(1,10);
|
||||
% True channel
|
||||
h=rxGrid_nonoise./(txGrid);
|
||||
|
||||
[d, ~, out] = srslte_chest(enb.NCellID,enb.CellRefP,rxGrid);
|
||||
output = [output out];
|
||||
%RSRP = [RSRP rsrp];
|
||||
%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
|
||||
%% Channel Estimation with Matlab
|
||||
tmpnoise=zeros(10,1);
|
||||
for i=1:10
|
||||
enb.NSubframe=i-1;
|
||||
[hest{1}(:,(1:14)+(i-1)*14), tmpnoise(i), hls(:,(1:4*P)+(i-1)*4*P)] = ...
|
||||
lteDLChannelEstimate2(enb,cec,rxGrid(:,(i-1)*14+1:i*14));
|
||||
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
|
||||
%
|
||||
% % subplot(1,2,1)
|
||||
%
|
||||
% if ~plot_noise_estimation_only
|
||||
% plot(SNR_values_db, mean(preEVM,2), ...
|
||||
% SNR_values_db, mean(postEVM_mmse,2), ...
|
||||
% SNR_values_db, mean(postEVM_srslte,2))
|
||||
% legend('No Eq','MMSE-lin','MMSE-srslte')
|
||||
|
||||
|
||||
%% Compute average MSE and noise estimation
|
||||
mean_mse=mean(MSE,2);
|
||||
mean_snr=10*log10(1./mean(noiseEst,2));
|
||||
|
||||
|
||||
%% 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
|
||||
% end
|
||||
%
|
||||
% % subplot(1,2,2)
|
||||
% 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
|
||||
% xlabel('SNR (dB)')
|
||||
% ylabel('Estimated SNR (dB)')
|
||||
end
|
||||
|
||||
|
|
|
@ -2,15 +2,39 @@
|
|||
|
||||
%% Cell-Wide Settings
|
||||
% A structure |enbConfig| is used to configure the eNodeB.
|
||||
%clear
|
||||
%clear12
|
||||
|
||||
recordedSignal=[];
|
||||
|
||||
Npackets = 5;
|
||||
SNR_values = linspace(18,25,5);
|
||||
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.9',[1;0;0;1]);
|
||||
[waveform,rgrid,rmccFgOut] = lteRMCDLTool('R.0',[1;0;0;1]);
|
||||
waveform = sum(waveform,2);
|
||||
|
||||
if ~isempty(recordedSignal)
|
||||
|
@ -28,12 +52,12 @@ end
|
|||
|
||||
flen=rmccFgOut.SamplingRate/1000;
|
||||
|
||||
Nsf = 10;
|
||||
Nsf = 9;
|
||||
|
||||
%% Setup Fading channel model
|
||||
cfg.Seed = 8; % Random channel seed
|
||||
cfg.Seed = 0; % Random channel seed
|
||||
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.MIMOCorrelation = 'Low'; % Low (no) MIMO correlation
|
||||
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.TimeWindow = 9; % Time window size
|
||||
cec.InterpType = 'linear'; % 2D interpolation type
|
||||
cec.InterpWindow = 'Centered'; % Interpolation window type
|
||||
cec.InterpWindow = 'Causal'; % Interpolation window type
|
||||
cec.InterpWinSize = 1; % Interpolation window size
|
||||
|
||||
addpath('../../build/srslte/lib/phch/test')
|
||||
|
@ -61,13 +85,17 @@ 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;
|
||||
%rxWaveform = lteFadingChannel(cfg,waveform);
|
||||
rxWaveform = waveform;
|
||||
|
||||
%% Noise Addition
|
||||
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;
|
||||
|
||||
% 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);
|
||||
[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)
|
||||
[dec2, data, pdschRx, pdschSymbols2, cws2] = srslte_pdsch(rmccFgOut, rmccFgOut.PDSCH, ...
|
||||
rmccFgOut.PDSCH.TrBlkSizes(sf_idx+1), ...
|
||||
subframe_rx, hest, nest);
|
||||
subframe_rx);
|
||||
else
|
||||
dec2 = 1;
|
||||
end
|
||||
|
@ -117,8 +145,8 @@ for snr_idx=1:length(SNR_values)
|
|||
end
|
||||
|
||||
if (length(SNR_values)>1)
|
||||
semilogy(SNR_values,1-decoded/Npackets/(Nsf+1),'bo-',...
|
||||
SNR_values,1-decoded_srslte/Npackets/(Nsf+1), 'ro-')
|
||||
semilogy(SNR_values,1-decoded/Npackets/(Nsf),'bo-',...
|
||||
SNR_values,1-decoded_srslte/Npackets/(Nsf), 'ro-')
|
||||
grid on;
|
||||
legend('Matlab','srsLTE')
|
||||
xlabel('SNR (dB)')
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -39,7 +39,6 @@
|
|||
|
||||
#include "srslte/srslte.h"
|
||||
|
||||
|
||||
#ifndef DISABLE_RF
|
||||
#include "srslte/rf/rf.h"
|
||||
#include "srslte/rf/rf_utils.h"
|
||||
|
@ -519,9 +518,9 @@ int main(int argc, char **argv) {
|
|||
|
||||
nof_trials++;
|
||||
|
||||
rsrq = SRSLTE_VEC_EMA(srslte_chest_dl_get_rsrq(&ue_dl.chest), rsrq, 0.05);
|
||||
rsrp = SRSLTE_VEC_EMA(srslte_chest_dl_get_rsrp(&ue_dl.chest), rsrp, 0.05);
|
||||
noise = SRSLTE_VEC_EMA(srslte_chest_dl_get_noise_estimate(&ue_dl.chest), noise, 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.1);
|
||||
noise = SRSLTE_VEC_EMA(srslte_chest_dl_get_noise_estimate(&ue_dl.chest), noise, 0.1);
|
||||
nframes++;
|
||||
if (isnan(rsrq)) {
|
||||
rsrq = 0;
|
||||
|
@ -541,11 +540,11 @@ int main(int argc, char **argv) {
|
|||
gain = 10*log10(srslte_agc_get_gain(&ue_sync.agc));
|
||||
}
|
||||
printf("CFO: %+6.2f KHz, "
|
||||
"SNR: %4.1f dB, "
|
||||
"PDCCH-Miss: %5.2f%%, PDSCH-BLER: %5.2f%%\r",
|
||||
"SNR: %4.1f dB, "
|
||||
"PDCCH-Miss: %5.2f%%, PDSCH-BLER: %5.2f%%\r",
|
||||
|
||||
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),
|
||||
(float) 100*ue_dl.pkt_errors/ue_dl.pkts_total);
|
||||
}
|
||||
|
|
|
@ -48,26 +48,20 @@
|
|||
#include "srslte/resampling/interp.h"
|
||||
#include "srslte/ch_estimation/refsignal_dl.h"
|
||||
#include "srslte/common/phy_common.h"
|
||||
#include "srslte/sync/pss.h"
|
||||
|
||||
#define SRSLTE_CHEST_MAX_FILTER_FREQ_LEN 21
|
||||
#define SRSLTE_CHEST_MAX_FILTER_TIME_LEN 40
|
||||
#define SRSLTE_CHEST_DL_MAX_SMOOTH_FIL_LEN 65
|
||||
|
||||
typedef struct {
|
||||
srslte_cell_t cell;
|
||||
srslte_refsignal_cs_t csr_signal;
|
||||
cf_t *pilot_estimates[SRSLTE_MAX_PORTS];
|
||||
cf_t *pilot_estimates_average[SRSLTE_MAX_PORTS];
|
||||
cf_t *pilot_recv_signal[SRSLTE_MAX_PORTS];
|
||||
|
||||
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 *pilot_estimates;
|
||||
cf_t *pilot_estimates_average;
|
||||
cf_t *pilot_recv_signal;
|
||||
cf_t *tmp_noise;
|
||||
cf_t *tmp_freqavg;
|
||||
cf_t *tmp_timeavg[SRSLTE_CHEST_MAX_FILTER_TIME_LEN];
|
||||
cf_t *tmp_timeavg_mult;
|
||||
|
||||
uint32_t smooth_filter_len;
|
||||
float smooth_filter[SRSLTE_CHEST_DL_MAX_SMOOTH_FIL_LEN];
|
||||
|
||||
srslte_interp_linsrslte_vec_t srslte_interp_linvec;
|
||||
srslte_interp_lin_t srslte_interp_lin;
|
||||
|
@ -75,7 +69,11 @@ typedef struct {
|
|||
float rssi[SRSLTE_MAX_PORTS];
|
||||
float rsrp[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;
|
||||
|
||||
|
||||
|
@ -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 int srslte_chest_dl_set_filter_freq(srslte_chest_dl_t *q,
|
||||
float *filter,
|
||||
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 void srslte_chest_dl_set_smooth_filter(srslte_chest_dl_t *q,
|
||||
float *filter,
|
||||
uint32_t filter_len);
|
||||
|
||||
SRSLTE_API int srslte_chest_dl_estimate(srslte_chest_dl_t *q,
|
||||
cf_t *input,
|
||||
|
|
|
@ -80,7 +80,12 @@ SRSLTE_API void srslte_interp_linear_vector(srslte_interp_linsrslte_vec_t *q,
|
|||
cf_t *between,
|
||||
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 */
|
||||
|
||||
|
|
|
@ -49,12 +49,8 @@ SRSLTE_API void srslte_scrambling_b_offset(srslte_sequence_t *s,
|
|||
int len);
|
||||
|
||||
SRSLTE_API void srslte_scrambling_bytes(srslte_sequence_t *s,
|
||||
uint8_t *data);
|
||||
|
||||
SRSLTE_API void srslte_scrambling_bytes_offset(srslte_sequence_t *s,
|
||||
uint8_t *data,
|
||||
int offset,
|
||||
int len);
|
||||
uint8_t *data,
|
||||
int len);
|
||||
|
||||
SRSLTE_API void srslte_scrambling_f(srslte_sequence_t *s,
|
||||
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,
|
||||
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,
|
||||
cf_t *slot,
|
||||
uint32_t nof_prb,
|
||||
|
|
|
@ -39,31 +39,29 @@
|
|||
#include "srslte/utils/vector.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_TIME_LEN 3
|
||||
#define DEFAULT_FILTER_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 t[DEFAULT_FILTER_TIME_LEN];
|
||||
float fil[SRSLTE_CHEST_DL_MAX_SMOOTH_FIL_LEN];
|
||||
|
||||
for (int i=0;i<DEFAULT_FILTER_FREQ_LEN/2+1;i++) {
|
||||
f[i] = 1+i;
|
||||
f[DEFAULT_FILTER_FREQ_LEN-i-1] = 1+i;
|
||||
for (int i=0;i<filter_len/2;i++) {
|
||||
fil[i] = i+1;
|
||||
fil[i+filter_len/2+1]=filter_len/2-i;
|
||||
}
|
||||
float norm = srslte_vec_acc_ff(f, DEFAULT_FILTER_FREQ_LEN);
|
||||
srslte_vec_sc_prod_fff(f, 1.0/norm, f, DEFAULT_FILTER_FREQ_LEN);
|
||||
srslte_chest_dl_set_filter_freq(q, f, DEFAULT_FILTER_FREQ_LEN);
|
||||
fil[filter_len/2]=filter_len/2+1;
|
||||
|
||||
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;
|
||||
float s=0;
|
||||
for (int i=0;i<filter_len;i++) {
|
||||
s+=fil[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_filter_time(q, t, DEFAULT_FILTER_TIME_LEN);
|
||||
for (int i=0;i<filter_len;i++) {
|
||||
fil[i]/=s;
|
||||
}
|
||||
|
||||
srslte_chest_dl_set_smooth_filter(q, fil, filter_len);
|
||||
}
|
||||
|
||||
/** 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;
|
||||
}
|
||||
|
||||
q->tmp_freqavg = srslte_vec_malloc(sizeof(cf_t) * SRSLTE_SF_LEN_RE(cell.nof_prb, cell.cp));
|
||||
if (!q->tmp_freqavg) {
|
||||
perror("malloc");
|
||||
goto clean_exit;
|
||||
}
|
||||
q->tmp_noise = 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_noise) {
|
||||
perror("malloc");
|
||||
goto clean_exit;
|
||||
}
|
||||
q->tmp_timeavg_mult = srslte_vec_malloc(sizeof(cf_t) * 12*cell.nof_prb);
|
||||
if (!q->tmp_timeavg_mult) {
|
||||
q->pilot_estimates = srslte_vec_malloc(sizeof(cf_t) * SRSLTE_REFSIGNAL_MAX_NUM_SF(cell.nof_prb));
|
||||
if (!q->pilot_estimates) {
|
||||
perror("malloc");
|
||||
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;
|
||||
}
|
||||
q->pilot_estimates_average = srslte_vec_malloc(sizeof(cf_t) * SRSLTE_REFSIGNAL_MAX_NUM_SF(cell.nof_prb));
|
||||
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");
|
||||
goto clean_exit;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -145,72 +142,62 @@ void srslte_chest_dl_free(srslte_chest_dl_t *q)
|
|||
{
|
||||
srslte_refsignal_cs_free(&q->csr_signal);
|
||||
|
||||
if (q->tmp_freqavg) {
|
||||
free(q->tmp_freqavg);
|
||||
}
|
||||
if (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_free(&q->srslte_interp_lin);
|
||||
|
||||
for (int i=0;i<SRSLTE_MAX_PORTS;i++) {
|
||||
if (q->pilot_estimates[i]) {
|
||||
free(q->pilot_estimates[i]);
|
||||
}
|
||||
if (q->pilot_recv_signal[i]) {
|
||||
free(q->pilot_recv_signal[i]);
|
||||
}
|
||||
if (q->pilot_estimates) {
|
||||
free(q->pilot_estimates);
|
||||
}
|
||||
if (q->pilot_estimates_average) {
|
||||
free(q->pilot_estimates_average);
|
||||
}
|
||||
if (q->pilot_recv_signal) {
|
||||
free(q->pilot_recv_signal);
|
||||
}
|
||||
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) {
|
||||
if (filter_len <= SRSLTE_CHEST_MAX_FILTER_FREQ_LEN) {
|
||||
q->filter_freq_len = filter_len;
|
||||
for (int i=0;i<filter_len;i++) {
|
||||
q->filter_freq[i] = filter[i];
|
||||
}
|
||||
return SRSLTE_SUCCESS;
|
||||
} else {
|
||||
return SRSLTE_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
#if NOISE_POWER_METHOD==0
|
||||
/* Uses the difference between the averaged and non-averaged pilot estimates */
|
||||
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 */
|
||||
srslte_vec_sub_ccc(average, ce, q->tmp_noise, len);
|
||||
return srslte_vec_avg_power_cf(q->tmp_noise, len);
|
||||
static float estimate_noise_pilots(srslte_chest_dl_t *q, cf_t *ce, uint32_t port_id)
|
||||
{
|
||||
int nref=SRSLTE_REFSIGNAL_NUM_SF(q->cell.nof_prb, port_id);
|
||||
/* Get averaged pilots from channel estimates */
|
||||
srslte_refsignal_cs_get_sf(q->cell, port_id, ce, q->tmp_noise);
|
||||
/* Substract noisy pilot estimates */
|
||||
srslte_vec_sub_ccc(q->tmp_noise, q->pilot_estimates, q->tmp_noise, nref);
|
||||
/* Compute average power */
|
||||
float power = sqrt(2)*q->cell.nof_ports*srslte_vec_avg_power_cf(q->tmp_noise, nref);
|
||||
return power;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if NOISE_POWER_METHOD==1
|
||||
#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);
|
||||
|
||||
/* Substract received signal */
|
||||
srslte_vec_sub_ccc(q->tmp_pss_noisy, q->tmp_pss, q->tmp_pss_noisy, SRSLTE_PSS_LEN);
|
||||
|
||||
/* Compute average power */
|
||||
float power = 2*q->cell.nof_ports*srslte_vec_avg_power_cf(q->tmp_pss_noisy, SRSLTE_PSS_LEN);
|
||||
return power;
|
||||
}
|
||||
|
||||
|
||||
#else
|
||||
|
||||
/* 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;
|
||||
float noise_power = 0;
|
||||
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
|
||||
|
||||
|
||||
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)]
|
||||
|
||||
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 */
|
||||
if (SRSLTE_CP_ISNORM(q->cell.cp)) {
|
||||
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(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(12), 2);
|
||||
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(7), &cesymb(11), &cesymb(8), 3);
|
||||
srslte_interp_linear_vector2(&q->srslte_interp_linvec, &cesymb(7), &cesymb(11), &cesymb(11), &cesymb(12), 2);
|
||||
} 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(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(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(9), 2);
|
||||
srslte_interp_linear_vector2(&q->srslte_interp_linvec, &cesymb(6), &cesymb(9), &cesymb(9), &cesymb(10), 2);
|
||||
} 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(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) {
|
||||
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;
|
||||
}
|
||||
|
||||
#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)
|
||||
{
|
||||
/* 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 */
|
||||
srslte_vec_prod_conj_ccc(q->pilot_recv_signal[port_id], q->csr_signal.pilots[port_id/2][sf_idx],
|
||||
q->pilot_estimates[port_id], SRSLTE_REFSIGNAL_NUM_SF(q->cell.nof_prb, port_id));
|
||||
|
||||
srslte_vec_prod_conj_ccc(q->pilot_recv_signal, q->csr_signal.pilots[port_id/2][sf_idx],
|
||||
q->pilot_estimates, SRSLTE_REFSIGNAL_NUM_SF(q->cell.nof_prb, port_id));
|
||||
if (ce != NULL) {
|
||||
/* Interpolate to create channel estimates for all resource grid */
|
||||
interpolate_pilots(q, q->pilot_estimates[port_id], ce, port_id);
|
||||
if (q->smooth_filter_len > 0) {
|
||||
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);
|
||||
}
|
||||
} else {
|
||||
interpolate_pilots(q, q->pilot_estimates, ce, port_id);
|
||||
|
||||
#if NOISE_POWER_METHOD==1
|
||||
if (sf_idx == 0 || sf_idx == 5) {
|
||||
q->noise_estimate[port_id] = estimate_noise_port(q, input);
|
||||
/* 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 */
|
||||
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) {
|
||||
/* compute rssi only for port 0 */
|
||||
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[][].
|
||||
* 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)
|
||||
*/
|
||||
/** Copies the RE containing references from an array of subframe symbols to the pilots array. */
|
||||
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;
|
||||
|
|
|
@ -37,7 +37,7 @@ ADD_TEST(chest_test_dl_cellid2 chest_test_dl -c 2 -r 50)
|
|||
# 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 PORTS prhs[1]
|
||||
#define INPUT prhs[2]
|
||||
#define FREQ_FILTER prhs[3]
|
||||
#define TIME_FILTER prhs[4]
|
||||
#define NOF_INPUTS 5
|
||||
#define SFIDX prhs[5]
|
||||
#define NOF_INPUTS 3
|
||||
|
||||
void help()
|
||||
{
|
||||
|
@ -101,37 +98,6 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
|
|||
}
|
||||
|
||||
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);
|
||||
|
@ -167,6 +133,7 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
|
|||
outi2 = mxGetPi(plhs[2]);
|
||||
}
|
||||
|
||||
float noise_power=0;
|
||||
for (int sf=0;sf<nsubframes;sf++) {
|
||||
/* Convert input to C complex type */
|
||||
for (i=0;i<nof_re;i++) {
|
||||
|
@ -187,6 +154,10 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
|
|||
return;
|
||||
}
|
||||
|
||||
if (sf==0) {
|
||||
noise_power = srslte_chest_dl_get_noise_estimate(&chest);
|
||||
}
|
||||
|
||||
if (cell.nof_ports == 1) {
|
||||
srslte_predecoding_single(input_signal, ce[0], output_signal2, nof_re, srslte_chest_dl_get_noise_estimate(&chest));
|
||||
} else {
|
||||
|
@ -195,27 +166,23 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
|
|||
}
|
||||
|
||||
if (nlhs >= 1) {
|
||||
for (int j=0;j<cell.nof_ports;j++) {
|
||||
for (i=0;i<nof_re;i++) {
|
||||
*outr0 = (double) crealf(ce[j][i]);
|
||||
if (outi0) {
|
||||
*outi0 = (double) cimagf(ce[j][i]);
|
||||
}
|
||||
outr0++;
|
||||
outi0++;
|
||||
for (i=0;i<nof_re;i++) {
|
||||
*outr0 = (double) crealf(ce[0][i]);
|
||||
if (outi0) {
|
||||
*outi0 = (double) cimagf(ce[0][i]);
|
||||
}
|
||||
outr0++;
|
||||
outi0++;
|
||||
}
|
||||
}
|
||||
if (nlhs >= 2) {
|
||||
for (int j=0;j<cell.nof_ports;j++) {
|
||||
for (i=0;i<SRSLTE_REFSIGNAL_NUM_SF(cell.nof_prb,j);i++) {
|
||||
*outr1 = (double) crealf(chest.pilot_estimates_average[j][i]);
|
||||
if (outi1) {
|
||||
*outi1 = (double) cimagf(chest.pilot_estimates_average[j][i]);
|
||||
}
|
||||
outr1++;
|
||||
outi1++;
|
||||
for (i=0;i<SRSLTE_REFSIGNAL_NUM_SF(cell.nof_prb,0);i++) {
|
||||
*outr1 = (double) crealf(chest.pilot_estimates_average[i]);
|
||||
if (outi1) {
|
||||
*outi1 = (double) cimagf(chest.pilot_estimates_average[i]);
|
||||
}
|
||||
outr1++;
|
||||
outi1++;
|
||||
}
|
||||
}
|
||||
if (nlhs >= 3) {
|
||||
|
@ -231,7 +198,7 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
|
|||
}
|
||||
|
||||
if (nlhs >= 4) {
|
||||
plhs[3] = mxCreateDoubleScalar(srslte_chest_dl_get_noise_estimate(&chest));
|
||||
plhs[3] = mxCreateDoubleScalar(noise_power);
|
||||
}
|
||||
if (nlhs >= 5) {
|
||||
plhs[4] = mxCreateDoubleScalar(srslte_chest_dl_get_rsrp(&chest));
|
||||
|
|
|
@ -286,6 +286,7 @@ 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)
|
||||
{
|
||||
|
||||
#ifdef LV_HAVE_AVX
|
||||
return srslte_rm_turbo_rx_lut_avx(input, output, in_len, cb_idx, rv_idx);
|
||||
#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) {
|
||||
uint32_t out_len = 3*srslte_cbsegm_cbsize(cb_idx)+12;
|
||||
uint16_t *deinter = deinterleaver[cb_idx][rv_idx];
|
||||
|
||||
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];
|
||||
}
|
||||
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++) {
|
||||
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++) {
|
||||
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++) {
|
||||
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) {
|
||||
|
@ -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];
|
||||
}
|
||||
if (nbits%24 >= 6) {
|
||||
in80 = bits[24*(nbits/24)+0];
|
||||
in80 = bits[3*(nbits/24)+0];
|
||||
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) {
|
||||
in81 = bits[24*(nbits/24)+1];
|
||||
in81 = bits[3*(nbits/24)+1];
|
||||
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) {
|
||||
in82 = bits[24*(nbits/24)+2];
|
||||
in82 = bits[3*(nbits/24)+2];
|
||||
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];
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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)) {
|
||||
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);
|
||||
} 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);
|
||||
|
|
|
@ -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)) {
|
||||
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);
|
||||
} 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
|
||||
|
|
|
@ -390,7 +390,6 @@ static int decode_tb(srslte_sch_t *q,
|
|||
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 */
|
||||
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");
|
||||
|
|
|
@ -108,6 +108,15 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
|
|||
mexErrMsgTxt("Error computing CB segmentation\n");
|
||||
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)) {
|
||||
mexErrMsgTxt("Error encoding TB\n");
|
||||
return;
|
||||
|
|
|
@ -118,14 +118,6 @@ cf_t *slot_symbols[SRSLTE_MAX_PORTS];
|
|||
srslte_pdsch_t pdsch;
|
||||
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) {
|
||||
uint32_t i, j;
|
||||
int ret = -1;
|
||||
|
@ -228,38 +220,53 @@ int main(int argc, char **argv) {
|
|||
for (i=0;i<grant.mcs.tbs/8;i++) {
|
||||
data[i] = rand()%256;
|
||||
}
|
||||
for (rv=0;rv<=rv_idx;rv++) {
|
||||
|
||||
pdsch_cfg.rv = rv;
|
||||
uint8_t databit[100000];
|
||||
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)) {
|
||||
fprintf(stderr, "Error encoding PDSCH\n");
|
||||
goto quit;
|
||||
}
|
||||
}
|
||||
pdsch_cfg.rv = rv_idx;
|
||||
|
||||
/* 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;
|
||||
}
|
||||
if (srslte_pdsch_encode(&pdsch, &pdsch_cfg, &softbuffer_tx, data, slot_symbols)) {
|
||||
fprintf(stderr, "Error encoding PDSCH\n");
|
||||
goto quit;
|
||||
}
|
||||
}
|
||||
|
||||
/* 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
|
||||
srslte_ofdm_tx_sf(&ofdm_tx, slot_symbols[0], sf_symbols);
|
||||
srslte_ofdm_tx_sf(&ofdm_tx, slot_symbols[0], sf_symbols);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
int M=1;
|
||||
int r=0;
|
||||
srslte_sch_set_max_noi(&pdsch.dl_sch, 10);
|
||||
gettimeofday(&t[1], NULL);
|
||||
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);
|
||||
get_time_interval(t);
|
||||
|
|
|
@ -53,7 +53,6 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
|
|||
srslte_pdsch_t pdsch;
|
||||
srslte_chest_dl_t chest;
|
||||
cf_t *input_fft;
|
||||
int nof_re;
|
||||
srslte_pdsch_cfg_t cfg;
|
||||
srslte_softbuffer_rx_t softbuffer;
|
||||
uint32_t rnti32;
|
||||
|
@ -102,9 +101,6 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
|
|||
return;
|
||||
}
|
||||
|
||||
|
||||
nof_re = 2 * SRSLTE_CP_NORM_NSYMB * cell.nof_prb * SRSLTE_NRE;
|
||||
|
||||
srslte_ra_dl_grant_t grant;
|
||||
grant.mcs.tbs = mxGetScalar(TBS);
|
||||
if (grant.mcs.tbs == 0) {
|
||||
|
@ -190,7 +186,7 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
|
|||
|
||||
if (nrhs > NOF_INPUTS) {
|
||||
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;
|
||||
for (i=0;i<cell.nof_ports;i++) {
|
||||
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 {
|
||||
srslte_chest_dl_estimate(&chest, input_fft, ce, cfg.sf_idx);
|
||||
}
|
||||
|
||||
float noise_power;
|
||||
if (nrhs > NOF_INPUTS + 1) {
|
||||
noise_power = mxGetScalar(prhs[NOF_INPUTS+1]);
|
||||
} 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);
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
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;
|
||||
|
||||
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_sum_ccc(in0, q->diff_vec, between, q->vector_len);
|
||||
srslte_vec_sc_prod_cfc(q->diff_vec, (float) 1/(M+1), q->diff_vec, 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++) {
|
||||
srslte_vec_sum_ccc(between, q->diff_vec, &between[q->vector_len], 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;
|
||||
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_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 <string.h>
|
||||
#include <assert.h>
|
||||
#include "srslte/utils/bit.h"
|
||||
#include "srslte/utils/vector.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);
|
||||
}
|
||||
|
||||
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;
|
||||
// Do XOR on a word basis
|
||||
|
||||
if (!(len%8)) {
|
||||
uint64_t *x = (uint64_t*) data;
|
||||
uint64_t *y = (uint64_t*) &c[offset];
|
||||
for (int i=0;i<len/8;i++) {
|
||||
x[i] = (x[i] ^ y[i]);
|
||||
}
|
||||
} else if (!(len%4)) {
|
||||
uint32_t *x = (uint32_t*) data;
|
||||
uint32_t *y = (uint32_t*) &c[offset];
|
||||
for (int i=0;i<len/4;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]);
|
||||
}
|
||||
for (i = 0; i < len; i++) {
|
||||
data[i] = (data[i] ^ c[i]);
|
||||
}
|
||||
}
|
||||
|
||||
void scrambling_b_word(uint8_t *c, uint8_t *data, int len) {
|
||||
// Do XOR every 64 bits
|
||||
// FIXME: Use 32-bit in 32-bit machines
|
||||
uint64_t *x = (uint64_t*) data;
|
||||
uint64_t *y = (uint64_t*) c;
|
||||
for (int i=0;i<len/8;i++) {
|
||||
x[i] = (x[i] ^ y[i]);
|
||||
}
|
||||
|
||||
// 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) {
|
||||
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) {
|
||||
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);
|
||||
} else {
|
||||
scrambling_b_word(&s->c[offset], data, len);
|
||||
}
|
||||
}
|
||||
|
||||
void srslte_scrambling_bytes(srslte_sequence_t *s, uint8_t *data) {
|
||||
scrambling_b(s->c_bytes, data, 0, s->len/8);
|
||||
}
|
||||
|
||||
void srslte_scrambling_bytes_offset(srslte_sequence_t *s, uint8_t *data, int offset, int len) {
|
||||
scrambling_b(s->c_bytes, data, offset, len/8);
|
||||
void srslte_scrambling_bytes(srslte_sequence_t *s, uint8_t *data, int len) {
|
||||
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));
|
||||
}
|
||||
|
||||
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
|
||||
*/
|
||||
|
|
|
@ -39,8 +39,6 @@
|
|||
|
||||
#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
|
||||
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);
|
||||
}
|
||||
|
||||
#ifdef PDSCH_DO_ZF
|
||||
float noise_estimate = 0;
|
||||
#else
|
||||
// Uncoment next line to do ZF by default in pdsch_ue example
|
||||
//float noise_estimate = 0;
|
||||
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) {
|
||||
ret = srslte_pdsch_decode_rnti(&q->pdsch, &q->pdsch_cfg, &q->softbuffer,
|
||||
|
|
Loading…
Reference in New Issue