%% LTE Downlink Channel Estimation and Equalization %% Cell-Wide Settings clear plot_noise_estimation_only=false; SNR_values_db=30;%linspace(0,30,8); Nrealizations=1; Lp=5; N=512; 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 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 cfg.Seed = 0; % Random channel seed cfg.InitTime = 0; cfg.NRxAnts = 1; % 1 receive antenna cfg.DelayProfile = 'EPA'; % doppler 5, 70 300 cfg.DopplerFreq = 5; % 120Hz Doppler frequency cfg.MIMOCorrelation = 'Low'; % Low (no) MIMO correlation cfg.NTerms = 16; % Oscillators used in fading model cfg.ModelType = 'GMEDS'; % Rayleigh fading model type cfg.InitPhase = 'Random'; % Random initial phases cfg.NormalizePathGains = 'On'; % Normalize delay profile power cfg.NormalizeTxAnts = 'On'; % Normalize for transmit antennas %% Channel Estimator Configuration cec = struct; % Channel estimation config structure 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 = 'Causal'; % Interpolation window type cec.InterpWinSize = 1; % Interpolation window size %% Subframe Resource Grid Size gridsize = lteDLResourceGridSize(enb); Ks = gridsize(1); % Number of subcarriers L = gridsize(2); % Number of OFDM symbols in one subframe 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 = []; %% Payload Data Generation % Number of bits needed is size of resource grid (K*L*P) * number of bits % per symbol (2 for QPSK) numberOfBits = Ks*L*Ports*2; % Create random bit stream inputBits = randi([0 1], numberOfBits, 1); % Modulate input bits inputSym = lteSymbolModulate(inputBits,'QPSK'); %% Frame Generation % For all subframes within the frame for sf = 0:10 % Set subframe number enb.NSubframe = mod(sf,10); % Generate empty subframe subframe = lteDLResourceGrid(enb); % Map input symbols to grid subframe(:) = inputSym; % Generate synchronizing signals pssSym = ltePSS(enb); sssSym = lteSSS(enb); pssInd = ltePSSIndices(enb); sssInd = lteSSSIndices(enb); % Map synchronizing signals to the grid subframe(pssInd) = pssSym; subframe(sssInd) = sssSym; % Generate cell specific reference signal symbols and indices cellRsSym = lteCellRS(enb); cellRsInd = lteCellRSIndices(enb); % Map cell specific reference signal to grid subframe(cellRsInd) = cellRsSym; % Append subframe to grid to be transmitted txGrid = [txGrid subframe]; %#ok end txGrid([1:5 68:72],6:7) = ones(10,2); %% OFDM Modulation [txWaveform,info] = lteOFDMModulate(enb,txGrid); 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; [rxWaveform, chinfo] = lteFadingChannel(cfg,txWaveform); %% Additive Noise % Calculate noise gain 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))); % Add noise to the received time domain waveform rxWaveform_nonoise = rxWaveform; rxWaveform = rxWaveform + noise; %% Synchronization 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); 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 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,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 % xlabel('SNR (dB)') % ylabel('Estimated SNR (dB)') end