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
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;
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)))
if (length(TBs) == 1)
%disp(info)
disp(error)
n=1:length(mat);
plot(abs(double(mat)-double(lib)))
else
plot(error)
end
[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
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
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.NRxAnts = 2; % 1 receive antenna
cfg.DelayProfile = 'EVA'; % EVA delay spread
cfg.DopplerFreq = 120; % 120Hz Doppler frequency
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);
% True channel
h=rxGrid_nonoise./(txGrid);
%% 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
%% 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);
[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
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) {
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_noise = srslte_vec_malloc(sizeof(cf_t) * SRSLTE_SF_LEN_RE(cell.nof_prb, cell.cp));
if (!q->tmp_noise) {
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;
}
q->tmp_timeavg_mult = srslte_vec_malloc(sizeof(cf_t) * 12*cell.nof_prb);
if (!q->tmp_timeavg_mult) {
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;
}
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_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;
}
/* Uses the difference between the averaged and non-averaged pilot estimates */
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;
}
void srslte_chest_dl_set_filter_time_ema(srslte_chest_dl_t *q, float ema_coefficient) {
q->filter_time_ema = ema_coefficient;
}
#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);
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;
}
}
/* 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);
#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);
/* Compute average power */
float power = 2*q->cell.nof_ports*srslte_vec_avg_power_cf(q->tmp_pss_noisy, SRSLTE_PSS_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 */
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;
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;
/* 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
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++) {
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]);
}
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);
}
void srslte_scrambling_bytes(srslte_sequence_t *s, uint8_t *data) {
scrambling_b(s->c_bytes, data, 0, s->len/8);
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_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…
Cancel
Save