classdef DDCTestUtils
    % Class containing helper functions for the
    % HDL Implementation of a Digital Down-Converter for LTE
    % example.
    %
    % Copyright 2019 The MathWorks, Inc.
    
    methods (Static)
        
        %----------------------------------------------------------------------
        
        function setPlotNameAndTitle(plotName)
            % Set both the figure title and the figure name property to plotName.
            
            title(plotName);
            set(gcf,'Name',plotName);
            
        end
        
        %----------------------------------------------------------------------
        
        function testSig = GenerateTestTone(Ft,Fc)
            % Generate a test signal consisting of a tone of frequency Ft modulated
            % onto a carrier frequency of Fc.
            
            Fsch = 122.88e6;
            L = 1e-3 * Fsch;  % Signal length is 10ms
            t = (0:L-1).'/Fsch;
            testSig = cos(2*pi*Ft*t) .* exp(2*pi*1i*Fc*t);
            testSig = 0.95 * testSig/max(abs(testSig));
            
        end
        
        %----------------------------------------------------------------------
        
        function [rx, sigInfo, tx] = GenerateLTETestSignal(Fc)
            % Generate and LTE test signal modulated onto a carrier frequency of Fc.
            
            % Channel sampling rate
            Fsch = 122.88e6;
            
            enb = lteRMCDL('R.4');
            [tx, ~, sigInfo] = lteRMCDLTool(enb,randi([0 1],1000,1));
            
            % Upsample tx waveform to channel sampling rate
            x = resample(tx,Fsch,sigInfo.SamplingRate);
            
            % Modulate onto the carrier frequency
            t = (0:length(x)-1).'/Fsch;
            y = x .* exp(1i*2*pi*Fc*t);
            
            % Generate some noise.
            n = 0.000 * randn(length(y),1);
            rx = y + n;
            
            % Normalize amplitude to the range -1 to +1.
            rx = 0.95 * rx / max(abs(rx));
            
        end
        
        %----------------------------------------------------------------------
        
        function y = DownConvert(rx,Fs,Fc,ddcFilterChain)
            % Execute the floating point simulation of the DDC. rx is the
            % input signal, Fs is the input sampling rate, Fc is the carrier
            % frequency and ddcFilterChain is the DDC filter cascade.
            
            % Translate from Fc to baseband
            t = (0:length(rx)-1).'/Fs;
            x = rx .* exp(1i*2*pi*-Fc*t);
            
            % Pass through filter chain.
            y = ddcFilterChain(x);
            
        end
        
        %----------------------------------------------------------------------
        
        function fig = PlotSpectrum(x,Fs)
            % Plot the spectrum of x, where Fs is the sampling rate.
            
            fig = figure();
            [pxx,f] = pwelch(x,[],[],[],Fs);
            pxxdb = pow2db(pxx);
            plot(f-(Fs/2),fftshift(pxxdb));
            ax = axis;
            axis ([ax(1) ax(2) min(pxxdb) max(pxxdb)+10]);
            xlabel('Frequency (kHz)')
            ylabel('PSD (dB/Hz)')
            
        end
        
        %----------------------------------------------------------------------
        
        function [evm, eqSymbols] = MeasureEVM(enb,sig)            
            % EVM Measurement
            
            offset = lteDLFrameOffset(enb,sig);
            sig = sig(1+offset:end,:);    % remove transient
            sig = [sig; zeros(offset,1)]; % pad with zeros
            
            rxGrid = lteOFDMDemodulate(enb,sig);
            chGrid = lteDLChannelEstimate(enb,rxGrid);
            L      = size(rxGrid,2) / enb.TotSubframes;
            
            EV            = [];
            startSubframe = enb.NSubframe;
            
            for n = 0:(enb.TotSubframes-1)
                
                enb.NSubframe = mod(startSubframe + n,10);
                
                rxSubframe = rxGrid(:,(1:L) + (n*L),:);
                chSubframe = chGrid(:,(1:L) + (n*L),:);
                
                crsIndices = lteCellRSIndices(enb);
                [rxSymbols,chSymbols] = ...
                    lteExtractResources(crsIndices,rxSubframe,chSubframe);
                
                eqSymbols = lteEqualizeZF(rxSymbols,chSymbols);
                
                crsSymbols  = lteCellRS(enb);
                evmSubframe = lteEVM(eqSymbols,crsSymbols);
                EV          = [EV; evmSubframe.EV]; %#ok<AGROW>
                
            end
            
            evm = lteEVM(EV);
            
        end
                
    end
    
end

