From a506505ad793ee224182116c9c629283fd5509c1 Mon Sep 17 00:00:00 2001 From: ismagom Date: Tue, 16 Feb 2016 00:03:06 +0100 Subject: [PATCH] Fixed bug in LS linear interpolation. Removed pilot averaging. Added SNR estimation through PSS. --- matlab/tests/equalizer_test.m | 359 +++++++++++++----- matlab/tests/pdsch_bler.m | 28 +- srslte/examples/pdsch_ue.c | 12 +- .../include/srslte/ch_estimation/chest_dl.h | 34 +- srslte/include/srslte/resampling/interp.h | 7 +- srslte/include/srslte/sync/pss.h | 5 + srslte/lib/ch_estimation/src/chest_dl.c | 281 ++++++-------- srslte/lib/ch_estimation/test/CMakeLists.txt | 2 +- .../ch_estimation/test/chest_test_dl_mex.c | 62 ++- srslte/lib/phch/test/pdsch_test_mex.c | 18 +- srslte/lib/resampling/src/interp.c | 15 +- srslte/lib/sync/src/pss.c | 6 + 12 files changed, 474 insertions(+), 355 deletions(-) diff --git a/matlab/tests/equalizer_test.m b/matlab/tests/equalizer_test.m index ecc3c4cc2..07010e0b6 100644 --- a/matlab/tests/equalizer_test.m +++ b/matlab/tests/equalizer_test.m @@ -6,30 +6,35 @@ clear plot_noise_estimation_only=false; -SNR_values_db=10;%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); - - -enb.NDLRB = 6; % Number of resource blocks +SNR_values_db=linspace(0,30,7); +Nrealizations=4; + +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 = 25; % 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 +cfg.Seed = 0; % Random channel seed +cfg.InitTime = 0; +cfg.NRxAnts = 1; % 1 receive antenna +cfg.DelayProfile = 'EVA'; + +% 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 = 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 -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); - -[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 +% 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 -% -% % 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 +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 -% -% % 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) + +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(2,2,1) +% plot(1:length(u),abs(u)) +% +% subplot(2,2,2) +% plot(abs(fftshift(fft(u,N)))) +% +% 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(2,2,4) +% plot(abs(hf)) +% +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 + diff --git a/matlab/tests/pdsch_bler.m b/matlab/tests/pdsch_bler.m index 0d5f4a162..a6b2997f1 100644 --- a/matlab/tests/pdsch_bler.m +++ b/matlab/tests/pdsch_bler.m @@ -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)') diff --git a/srslte/examples/pdsch_ue.c b/srslte/examples/pdsch_ue.c index 948e29c8b..5f5eb6f8c 100644 --- a/srslte/examples/pdsch_ue.c +++ b/srslte/examples/pdsch_ue.c @@ -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; @@ -541,11 +541,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); } diff --git a/srslte/include/srslte/ch_estimation/chest_dl.h b/srslte/include/srslte/ch_estimation/chest_dl.h index 6b9147b8d..22d4c76c2 100644 --- a/srslte/include/srslte/ch_estimation/chest_dl.h +++ b/srslte/include/srslte/ch_estimation/chest_dl.h @@ -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, diff --git a/srslte/include/srslte/resampling/interp.h b/srslte/include/srslte/resampling/interp.h index a6208ad6d..e2676d286 100644 --- a/srslte/include/srslte/resampling/interp.h +++ b/srslte/include/srslte/resampling/interp.h @@ -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 */ diff --git a/srslte/include/srslte/sync/pss.h b/srslte/include/srslte/sync/pss.h index e85df72b0..0c7830792 100644 --- a/srslte/include/srslte/sync/pss.h +++ b/srslte/include/srslte/sync/pss.h @@ -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, diff --git a/srslte/lib/ch_estimation/src/chest_dl.c b/srslte/lib/ch_estimation/src/chest_dl.c index 8c4c7acf6..a79f64899 100644 --- a/srslte/lib/ch_estimation/src/chest_dl.c +++ b/srslte/lib/ch_estimation/src/chest_dl.c @@ -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;itmp_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_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; } - for (int i=0;ipilot_estimates[i] = srslte_vec_malloc(2*sizeof(cf_t) * SRSLTE_REFSIGNAL_NUM_SF(cell.nof_prb, i)); - if (!q->pilot_estimates[i]) { - perror("malloc"); - goto clean_exit; - } - q->pilot_recv_signal[i] = srslte_vec_malloc(sizeof(cf_t) * SRSLTE_REFSIGNAL_NUM_SF(cell.nof_prb, i)); - if (!q->pilot_recv_signal[i]) { - perror("malloc"); - goto clean_exit; - } - } - if (srslte_interp_linear_vector_init(&q->srslte_interp_linvec, SRSLTE_NRE*cell.nof_prb)) { fprintf(stderr, "Error initializing vector interpolator\n"); goto clean_exit; @@ -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;ipilot_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;ifilter_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; -} - -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;ifilter_time[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.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); + + /* Get channel estimates for PSS position */ + srslte_pss_get_slot(ce, q->tmp_pss_noisy, q->cell.nof_prb, q->cell.cp); + /* Multiply known PSS by channel estimates */ + srslte_vec_prod_ccc(q->tmp_pss_noisy, q->pss_signal, q->tmp_pss_noisy, SRSLTE_PSS_LEN); -#if NOISE_POWER_METHOD==0 -/* 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); + /* 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 = 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;lcell.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;scell.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;lcell.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;ifilter_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); - } - } + /* 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 { - memcpy(&ce[l*12*q->cell.nof_prb], &q->tmp_freqavg[l*12*q->cell.nof_prb], nref * sizeof(cf_t)); - } + 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 { + 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 */ @@ -285,10 +241,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); @@ -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); - - /* Average channel estimates */ - average_estimates(q, 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); + /* TESTING: Use robust MMSE interpolation filter */ + if (q->w_filter) { + interpolate_filter_pilots(q, q->pilot_estimates, q->w_filter, 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 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_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) { diff --git a/srslte/lib/ch_estimation/test/CMakeLists.txt b/srslte/lib/ch_estimation/test/CMakeLists.txt index dd4a77505..4fff63002 100644 --- a/srslte/lib/ch_estimation/test/CMakeLists.txt +++ b/srslte/lib/ch_estimation/test/CMakeLists.txt @@ -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) ######################################################################## diff --git a/srslte/lib/ch_estimation/test/chest_test_dl_mex.c b/srslte/lib/ch_estimation/test/chest_test_dl_mex.c index b1150316c..a26b312c2 100644 --- a/srslte/lib/ch_estimation/test/chest_test_dl_mex.c +++ b/srslte/lib/ch_estimation/test/chest_test_dl_mex.c @@ -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,38 +98,7 @@ 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 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= 2) { for (int j=0;j= 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)); diff --git a/srslte/lib/phch/test/pdsch_test_mex.c b/srslte/lib/phch/test/pdsch_test_mex.c index 5bcc099b7..28f223c9e 100644 --- a/srslte/lib/phch/test/pdsch_test_mex.c +++ b/srslte/lib/phch/test/pdsch_test_mex.c @@ -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]); diff --git a/srslte/lib/resampling/src/interp.c b/srslte/lib/resampling/src/interp.c index f602d5cc4..dfdeab7c3 100644 --- a/srslte/lib/resampling/src/interp.c +++ b/srslte/lib/resampling/src/interp.c @@ -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;idiff_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;jM; + 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); diff --git a/srslte/lib/sync/src/pss.c b/srslte/lib/sync/src/pss.c index 77587bae2..76ab9534e 100644 --- a/srslte/lib/sync/src/pss.c +++ b/srslte/lib/sync/src/pss.c @@ -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 */