Fixed bug in LS linear interpolation. Removed pilot averaging. Added SNR estimation through PSS.

master
ismagom 9 years ago
parent 3fd5eb4522
commit a506505ad7

@ -6,30 +6,35 @@ clear
plot_noise_estimation_only=false;
SNR_values_db=10;%linspace(0,30,8);
Nrealizations=1 ;
SNR_values_db=linspace(0,30,7);
Nrealizations=4;
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=10;
N=512;
K=300;
rstart=(N-K)/2;
P=K/6;
Rhphp=zeros(P,P);
Rhhp=zeros(K,P);
Rhh=zeros(K,K);
enb.NDLRB = 6; % Number of resource blocks
enb.NDLRB = 25; % Number of resource blocks
enb.CellRefP = 1; % One transmit antenna port
enb.NCellID = 0; % Cell ID
enb.CyclicPrefix = 'Normal'; % Normal cyclic prefix
enb.DuplexMode = 'FDD'; % FDD
%% 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 = 'EVA';
cfg.Seed = 2; % Random channel seed
cfg.NRxAnts = 2; % 1 receive antenna
cfg.DelayProfile = 'EVA'; % EVA delay spread
cfg.DopplerFreq = 120; % 120Hz Doppler frequency
% doppler 5, 70 300
cfg.DopplerFreq = 200; % 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=5;
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.mmse','r.mmse2'};
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,229 @@ 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
if (offset==-1)
offset = lteDLFrameOffset(enb,rxWaveform);
rxWaveform = rxWaveform(1+offset+2:end,:);
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);
[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]);
% 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;
% for i=1:length(hidx)
% hp=hls(3,(1:P)+P*(i-1));
% hest{3}(:,hidx(i))=W*transpose(hp);
% end
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}));
%% Robust MMSE estimation using srsLTE (Eurecom paper)
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/snr_lin)^(-1);
W2=F_l*Wi*F_p';
% for i=1:length(hidx)
% hp=hls(3,(1:P)+P*(i-1));
% hest{4}(:,hidx(i))=W2*transpose(hp);
% end
w2=reshape(transpose(W2),1,[]);
[tmp, ~, ~, noiseEst(4,nreal,snr_idx)] = srslte_chest(enb.NCellID,enb.CellRefP,rxGrid,w2);
hest{4}=reshape(tmp, size(hest{1}));
%% Another robust method from Infocom research paper
c_l=ones(Lp,1)/Lp;
c_l2=[c_l; zeros(N-Lp,1)];
C_l=diag(c_l2);
F=dftmtx(N);
R_hh=F*C_l*F';
R_hphp=R_hh(prows,prows);
R_hhp=R_hh((rstart+1):(K+rstart),prows);
W3=R_hhp*(R_hphp+(1/snr_lin)*eye(P))^-1;
% for i=1:length(hidx)
% hp=hls(3,(1:P)+P*(i-1));
% hest{5}(:,hidx(i))=W3*transpose(hp);
% end
w3=reshape(transpose(W3),1,[]);
[tmp, ~, ~, noiseEst(5,nreal,snr_idx)] = srslte_chest(enb.NCellID,enb.CellRefP,rxGrid,w3);
hest{5}=reshape(tmp, size(hest{1}));
%% Compute MSE
for i=1:Ntests
MSE(i,nreal,snr_idx)=mean(mean(abs(h(:,:)-hest{i}(:,:)).^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(1,2,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;
u(1+ceil(chinfo.PathSampleDelays))=chinfo.PathGains(1,:);
subplot(1,2,2)
plot(1:P,real(W(150,:)),1:P,real(W2(150,:)),1:P,real(W3(150,:)))
legend('mmse','robust1','robust2')
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)))
% u=zeros(N,1);
% u(1+ceil(chinfo.PathSampleDelays))=mean(chinfo.PathGains(7680+(1:512+40),:));
%
% % 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')
% grid on
% end
% subplot(2,2,1)
% plot(1:length(u),abs(u))
%
% % subplot(1,2,2)
% if plot_noise_estimation_only
% SNR_matlab = 1./(noiseEst*sqrt(2.0)*enb.CellRefP);
% subplot(2,2,2)
% plot(abs(fftshift(fft(u,N))))
%
% 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(2,2,3)
% hf=[zeros((N-K)/2,1); h(1:K/2,1); 0; h(K/2+1:end,1); zeros((N-K)/2-1,1)];
% plot(1:Lp,real(ifft(ifftshift(h(:,1)),Lp)))
%
% 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(2,2,4)
% plot(abs(hf))
%
% subplot(1,3,3)
% plot(1:10*length(SNR_values_db),RSRP,10*(1:length(SNR_values_db)),meanRSRP)
% end
end
end
end
%% 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,2,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
xlabel('SNR (dB)')
ylabel('Estimated SNR (dB)')
end

@ -6,11 +6,11 @@
recordedSignal=[];
Npackets = 5;
SNR_values = linspace(18,25,5);
Npackets = 30;
SNR_values = linspace(9,24,5);
%% 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,13 +28,13 @@ 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.DopplerFreq = 5; % 120Hz Doppler frequency
cfg.DelayProfile = 'EPA'; % EVA delay spread
cfg.DopplerFreq = 120; % 120Hz Doppler frequency
cfg.MIMOCorrelation = 'Low'; % Low (no) MIMO correlation
cfg.InitTime = 0; % Initialize at time zero
cfg.NTerms = 16; % Oscillators used in fading model
@ -49,7 +49,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,6 +61,10 @@ 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)
@ -86,7 +90,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 +103,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 +121,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)')

@ -519,9 +519,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;
@ -545,7 +545,7 @@ int main(int argc, char **argv) {
"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,6 +48,7 @@
#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
@ -55,19 +56,10 @@
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_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;
cf_t *w_filter;
srslte_interp_linsrslte_vec_t srslte_interp_linvec;
srslte_interp_lin_t srslte_interp_lin;
@ -75,7 +67,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 +80,8 @@ 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_filter_w(srslte_chest_dl_t *q,
cf_t *w);
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 */

@ -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,32 +39,7 @@
#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 DEFAULT_FILTER_FREQ_LEN 11 // Must be odd
#define DEFAULT_FILTER_TIME_LEN 3
static void init_default_filters(srslte_chest_dl_t *q) {
float f[DEFAULT_FILTER_FREQ_LEN];
float t[DEFAULT_FILTER_TIME_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;
}
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);
for (int i=0;i<DEFAULT_FILTER_TIME_LEN/2+1;i++) {
t[i] = 1+i;
t[DEFAULT_FILTER_TIME_LEN-i-1] = 1+i;
}
norm = srslte_vec_acc_ff(t, DEFAULT_FILTER_TIME_LEN);
srslte_vec_sc_prod_fff(t, 1.0/norm, t, DEFAULT_FILTER_TIME_LEN);
srslte_chest_dl_set_filter_time(q, t, DEFAULT_FILTER_TIME_LEN);
}
#define ESTIMATE_NOISE_LS_PSS
/** 3GPP LTE Downlink channel estimator and equalizer.
* Estimates the channel in the resource elements transmitting references and interpolates for the rest
@ -89,34 +64,21 @@ 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]) {
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;
}
q->pilot_recv_signal[i] = srslte_vec_malloc(sizeof(cf_t) * SRSLTE_REFSIGNAL_NUM_SF(cell.nof_prb, i));
if (!q->pilot_recv_signal[i]) {
perror("malloc");
goto clean_exit;
}
}
if (srslte_interp_linear_vector_init(&q->srslte_interp_linvec, SRSLTE_NRE*cell.nof_prb)) {
fprintf(stderr, "Error initializing vector interpolator\n");
@ -128,7 +90,13 @@ 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->w_filter = NULL;
q->cell = cell;
}
@ -145,72 +113,63 @@ 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_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_w(srslte_chest_dl_t *q, cf_t *w) {
q->w_filter = w;
}
void srslte_chest_dl_set_filter_time_ema(srslte_chest_dl_t *q, float ema_coefficient) {
q->filter_time_ema = ema_coefficient;
}
/* 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.0)*q->cell.nof_ports*srslte_vec_avg_power_cf(q->tmp_noise, nref);
return power;
}
#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 = q->cell.nof_ports*srslte_vec_avg_power_cf(q->tmp_pss_noisy, SRSLTE_PSS_LEN)/sqrt(2);
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,50 +183,47 @@ 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)
#define cesymb(i) ce[SRSLTE_RE_IDX(q->cell.nof_prb,i,0)]
static void interpolate_filter_pilots(srslte_chest_dl_t *q, cf_t *pilot_estimates, cf_t *w, 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));
int nsymbols = srslte_refsignal_cs_nof_symbols(port_id);
int nsc=SRSLTE_NRE*q->cell.nof_prb;
int nref=2*q->cell.nof_prb;
// Interpolation filter in frequency domain
for (uint32_t s=0;s<nsymbols;s++) {
for (int i=0;i<nsc;i++) {
uint32_t sym_idx=srslte_refsignal_cs_nsymbol(s,q->cell.cp, port_id);
ce[nsc*sym_idx+i] = srslte_vec_dot_prod_ccc(&pilot_estimates[s*nref], &w[i*nref], nref);
}
}
#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);
/* 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_vector2(&q->srslte_interp_linvec, &cesymb(7), &cesymb(11), &cesymb(11), &cesymb(12), 2);
} 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);
}
srslte_interp_linear_vector(&q->srslte_interp_linvec, &cesymb(8), &cesymb(1), &cesymb(0), 1);
srslte_interp_linear_vector(&q->srslte_interp_linvec, &cesymb(1), &cesymb(8), &cesymb(2), 6);
srslte_interp_linear_vector(&q->srslte_interp_linvec, &cesymb(1), &cesymb(8), &cesymb(9), 5);
}
} else {
memcpy(&ce[l*12*q->cell.nof_prb], &q->tmp_freqavg[l*12*q->cell.nof_prb], nref * sizeof(cf_t));
if (nsymbols == 4) {
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);
} 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);
srslte_interp_linear_vector(&q->srslte_interp_linvec, &cesymb(1), &cesymb(7), &cesymb(8), 4);
}
}
}
#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)
{
/* interpolate the symbols with references in the freq domain */
@ -288,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(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_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);
@ -320,43 +276,40 @@ 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);
/* TESTING: Use robust MMSE interpolation filter */
if (q->w_filter) {
interpolate_filter_pilots(q, q->pilot_estimates, q->w_filter, ce, port_id);
/* Average channel estimates */
average_estimates(q, ce, port_id);
/* Estimate noise from difference from averaged and estimated pilots */
if (sf_idx == 0 || sf_idx == 5) {
q->noise_estimate[port_id] = estimate_noise_pilots(q, ce, port_id);
}
/* If w filter not defined, resort to LS estimate + linear interpolation */
} else {
interpolate_pilots(q, q->pilot_estimates, ce, port_id);
#if NOISE_POWER_METHOD==1
/* If not averaging, compute noise from empty subcarriers */
if (sf_idx == 0 || sf_idx == 5) {
q->noise_estimate[port_id] = estimate_noise_port(q, input);
}
#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
}
}
}
/* 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_estimates, 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);
@ -380,7 +333,7 @@ float srslte_chest_dl_get_noise_estimate(srslte_chest_dl_t *q) {
}
float srslte_chest_dl_get_snr(srslte_chest_dl_t *q) {
return srslte_chest_dl_get_rsrp(q)/srslte_chest_dl_get_noise_estimate(q);
return srslte_chest_dl_get_rsrp(q)/srslte_chest_dl_get_noise_estimate(q)-1;
}
float srslte_chest_dl_get_rssi(srslte_chest_dl_t *q) {

@ -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);
@ -150,6 +116,13 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
srslte_precoding_init(&cheq, nof_re);
cf_t *w=NULL;
if (nrhs > NOF_INPUTS) {
mexutils_read_cf(prhs[NOF_INPUTS], &w);
srslte_chest_dl_set_filter_w(&chest, w);
}
/* Create output values */
if (nlhs >= 1) {
plhs[0] = mxCreateDoubleMatrix(nof_re * nsubframes, cell.nof_ports, mxCOMPLEX);
@ -167,6 +140,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 +161,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 {
@ -209,9 +187,9 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
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]);
*outr1 = (double) crealf(chest.pilot_estimates[i]);
if (outi1) {
*outi1 = (double) cimagf(chest.pilot_estimates_average[j][i]);
*outi1 = (double) cimagf(chest.pilot_estimates[i]);
}
outr1++;
outi1++;
@ -230,8 +208,12 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
}
}
if (w) {
free(w);
}
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));

@ -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) {
@ -188,6 +184,18 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
ce[i] = srslte_vec_malloc(SRSLTE_SF_LEN_RE(cell.nof_prb, cell.cp) * sizeof(cf_t));
}
cf_t *w=NULL;
if (nrhs > NOF_INPUTS) {
mexutils_read_cf(prhs[NOF_INPUTS], &w);
srslte_chest_dl_set_filter_w(&chest, w);
srslte_chest_dl_estimate(&chest, input_fft, ce, cfg.sf_idx);
free(w);
} else {
srslte_chest_dl_estimate(&chest, input_fft, ce, cfg.sf_idx);
}
/*
if (nrhs > NOF_INPUTS) {
cf_t *cearray = NULL;
nof_re = mexutils_read_cf(prhs[NOF_INPUTS], &cearray);
@ -203,6 +211,8 @@ 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]);

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

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

Loading…
Cancel
Save