OTFS代码学习记录2(OFDM与OTFS性能比较)

 该代码仿真了在无线链路多径衰落的环境下的OFDM与OTFS性能差异,同时加入了LDCP码

Reference
%--------------------------------------------------------------------------
%
% Author: Bradley Bates
% University of Bristol, UK
% email address: [email protected]
% May 2020
%
% Copyright (c) 2020, Bradley Bates
%
%--------------------------------------------------------------------------

主函数

主函数main的运行需要用到的function文件:

% The following files are required:
% dataGen.m
% multipathChannel.m
% modOFDM.m
% demodOFDM.m
% ISFFT.m
% SFFT.m
% equaliser.m
% plotGraphs.m

接下来开始主函数的研究

首先是各种参数的设置

%--------------------------------------------------------------------------
% Define simulation parameters
%--------------------------------------------------------------------------
M = 16;                         % Modulation alphabet
k = log2(M);                    % Bits/symbol
cpSize = 0.07;                  % OFDM cyclic prefix size
scs = 15e3;                     % Subcarrier spacing Hz
Bw = 10e6;                      % System bandwidth Hz
ofdmSym = 14;                   % No. OFDM symbols / subframe 
EbNo = (-3:1:30)';              % Range of energy/bit to noise power ratio
velocity = 120;                 % Velocity of mobile rx relative tx km/hr
codeRate = 2/4;                 % FEC code rate used
maxIterations = 25;             % Set maximum no. of iterations for LDPC decoder
totalBits = 1e6;                % The approx. total no. of bits simulated
repeats = 1;                    % Number of simulation repetitions 

然后是各部分初始化

%--------------------------------------------------------------------------
%                    Initialise Simulation Components
%--------------------------------------------------------------------------

% Initialise OFDM Mod/Demod variables
numSC = pow2(ceil(log2(Bw/scs))); % 计算载波数为1024
cpLen = floor(cpSize * numSC);    % 计算循环前缀编码的长度(注意ceil和floor都是向上取整函数)
numDC = (numSC - 12);             % 数据载波数量=载波数-12

% Initialise the AWGN channel
awgnChannel = comm.AWGNChannel('NoiseMethod','Variance', 'VarianceSource','Input port');
errorRate = comm.ErrorRate('ResetInputPort',true);
errorRate1 = comm.ErrorRate('ResetInputPort',true);

% Initialise the LDPC coder/decoder
parityCheck_matrix = dvbs2ldpc(codeRate);               % Generate DVB-S.2 paraity check matrix
ldpcEncoder = comm.LDPCEncoder(parityCheck_matrix);     % Create encoder system object
ldpcDecoder = comm.LDPCDecoder(parityCheck_matrix);     % Create decoder system object
ldpcDecoder.MaximumIterationCount = maxIterations;      % Assign decoder's maximum iterations
noCodedbits = size(parityCheck_matrix,2);               % Find the Codeword length

% Create Vectors for storing error data
berOFDM = zeros(length(EbNo),3); berCOFDM = zeros(length(EbNo),3); berOTFS = zeros(length(EbNo),3); berCOTFS = zeros(length(EbNo),3);
errorStats_coded = zeros(1,3); errorStats_uncoded = zeros(1,3);

for repetition=1:repeats                                % Repeat simulation multiple times with a unqique channel for each repeat
    
    % Generate and Encode data
    [dataIn, dataBits_in, codedData_in, packetSize, numPackets, numCB] = dataGen(k,numDC,ofdmSym,totalBits,codeRate,ldpcEncoder);
    
    % Generate Rayleigh Fading Channel Impulse Response
    txSig_size = zeros((numSC+cpLen),ofdmSym);                       % Assign the size of the channel
    rayChan = multipathChannel(cpSize, scs, txSig_size, velocity);   % Create fading channel impulse response
    
    % QAM Modulator
    qamTx = qammod(dataIn,M,'InputType','bit','UnitAveragePower',true);    % Apply QAM modulation
    parallelTx = reshape(qamTx,[numDC,ofdmSym*packetSize]);                % Convert to parallel
    
    % Add nulls at index 1
    guardbandTx = [zeros(1,ofdmSym*packetSize); parallelTx];
    % Add 11 nulls around DC
    guardbandTx = [guardbandTx(1:(numDC/2),:); zeros(11,ofdmSym*packetSize); guardbandTx((numDC/2)+1:end,:)];
    

注意上面使用的comm.AWGNChannel、comm.ErrorRate以及comm.LDPCEncoder均是调用matlab的函数来为信道添加高斯噪声,误码率以及LDCP编码器等,与调用函数类似。参考Add white Gaussian noise to input signal - MATLAB - MathWorks 中国

举个例子:

For example:
awgnchan = comm.AWGNChannel('NoiseMethod','Variance', ...'VarianceSource','Input port');
var = 12;    %specifies the variance of the white Gaussian noise
...
outsignal = awgnchan(insignal,var);%计算输出信号

同样是初始化那一副图

parityCheck_matrix = dvbs2ldpc(codeRate)

该函数用于生成DVB—S2标准的LDPC码,dvbs2ldpc(r),r是码率,该函数返回的是该码率下的校验矩阵,输出的该矩阵是稀疏矩阵,r可以是1/4  1/3  2/5   1/2  3/5 2/3  3/4 4/5  5/6  8/9   9/10,码长是64800

初始化完成之后就开始OFDM误码率的计算

%--------------------------------------------------------------------------
%                       OFDM BER Calculation
%--------------------------------------------------------------------------
    
    % Calculate SNR
    snr = EbNo + 10*log10(codeRate*k) + 10*log10(numDC/((numSC)));
    
    % Multicarrier Modulation
    frameBuffer = guardbandTx;          % Create a 'buffer' so subframes can be individually modulated
    txframeBuffer = [];                 % Initilaise matrix
    for w = 1:packetSize
        ofdmTx = modOFDM(frameBuffer(:,1:ofdmSym),numSC,cpLen,ofdmSym);    % Apply OFDM modulation to a subframe of data
        frameBuffer(:, 1:ofdmSym) = [];                                    % Delete modulated data from frameBuffer
        txframeBuffer = [txframeBuffer;ofdmTx];                            % Add modulated subframe to transmit buffer
    end
    
    
    % Loop through different values of EbNo
    for m = 1:length(EbNo)
        % Loop through the of packets to be transmitted
        for j = 1:numPackets
            rxframeBuffer = [];                 % Initialise matrix
            
            % Transmit each subframe individually
            for u = 1:packetSize
                
                % Remove next subframe from the transmit buffer
                txSig = txframeBuffer( ((u-1)*numel(ofdmTx)+1) : u*numel(ofdmTx) );
                
                % Apply Channel to input signal
                fadedSig = zeros(size(txSig));                    % Pre-allocate vector size
                for i = 1:size(txSig,1)                           % Perform elementwise...
                    for j = 1:size(txSig,2)                       % ...matrix multiplication
                        fadedSig(i,j) = txSig(i,j).*rayChan(i,j);
                    end
                end
                
                % AWGN Channel
                release(awgnChannel);
                powerDB = 10*log10(var(fadedSig));            % Calculate Tx signal power
                noiseVar = 10.^(0.1*(powerDB-snr(m)));        % Calculate the noise variance
                rxSig = awgnChannel(fadedSig,noiseVar);       % Pass the signal through a noisy channel
                
                % Equalisation
                eqSig = equaliser(rxSig,fadedSig,txSig,ofdmSym);
                
                % Demodulation
                rxSubframe = demodOFDM(eqSig,cpLen,ofdmSym);     % Apply OFDM demodulation
                rxframeBuffer = [rxframeBuffer';rxSubframe']';         % Store demodulated subframe in rx buffer
            end
            % Remove all null carriers
            parallelRx = rxframeBuffer;
            parallelRx((numDC/2)+1:(numDC/2)+11, :) = [];     % Remove nulls around the DC input
            parallelRx(1:1, :) = [];                          % Remove nulls at index 1
            qamRx = reshape(parallelRx,[numel(parallelRx),1]);% Convert to serial
            
            % Uncoded demodulation of entire packet
            dataOut = qamdemod(qamRx,M,'OutputType','bit','UnitAveragePower',true);% Apply QAM demodulation
            codedData_out = randdeintrlv(dataOut,4831);                            % De-interleave data
            codedData_out(numel(codedData_in)+1:end) = [];                         % Remove pad bits
            errorStats_uncoded = errorRate(codedData_in,codedData_out,0);          % Collect error statistics
          
            % Coded demodulation of entire packet
            powerDB = 10*log10(var(qamRx));                                   % Calculate Rx signal power
            noiseVar = 10.^(0.1*(powerDB-(EbNo(m) + 10*log10(codeRate*k) - 10*log10(sqrt(numDC)))));            % Calculate the noise variance
            dataOut = qamdemod(qamRx,M,'OutputType', 'approxllr','UnitAveragePower',true,'NoiseVariance',noiseVar);% Apply QAM demodulation
            codedData_out1 = randdeintrlv(dataOut,4831);                      % De-interleave data
            codedData_out1(numel(codedData_in)+1:end) = [];                   % Remove pad bits
            
            % Decode individual code blocks
            dataBits_out = [];                                                % Initialise matrix
            dataOut_buffer = codedData_out1;
            for q = 1:numCB
                dataBits_out = [dataBits_out;ldpcDecoder(dataOut_buffer(1:noCodedbits))]; % Decode data & add it to the data bits out matrix
                dataOut_buffer(1:noCodedbits) = [];                                       % Delete decoded data from buffer
            end
            dataBits_out = double(dataBits_out);                              % Convert to a double compatible w/ errorStats
            errorStats_coded = errorRate1(dataBits_in,dataBits_out,0);        % Collect error statistics
            
        end
        berOFDM(m,:) = errorStats_uncoded;                                  % Save uncoded BER data
        berCOFDM(m,:) = errorStats_coded;                                   % Save  coded BER data
        errorStats_uncoded = errorRate(codedData_in,codedData_out,1);       % Reset the error rate calculator
        errorStats_coded = errorRate1(dataBits_in,dataBits_out,1);          % Reset the error rate calculator
        
    end

接着是OTFS的误码率计算

%--------------------------------------------------------------------------
%                       OTFS BER Calculation
%--------------------------------------------------------------------------
    
    % Calculate SNR
    snr = EbNo + 10*log10(codeRate*k) + 10*log10(numDC/((numSC))) + 10*log10(sqrt(ofdmSym));
    
    % Multicarrier Modulation
    frameBuffer = guardbandTx;          % Create a 'buffer' so subframes can be individually modulated
    txframeBuffer = [];                 % Initilaise matrix
    for w = 1:packetSize
        otfsTx = ISFFT(frameBuffer(:,1:ofdmSym));       % Apply OTFS modulation to a subframe of data
        ofdmTx = modOFDM(otfsTx,numSC,cpLen,ofdmSym);    % Apply OFDM modulation
        frameBuffer(:, 1:ofdmSym) = [];                  % Delete modulated data from frameBuffer
        txframeBuffer = [txframeBuffer;ofdmTx];          % Add modulated subframe to transmit buffer
    end
    
    % Loop through different values of EbNo
    for m = 1:length(EbNo)
        % Loop through the of packets to be transmitted
        for j = 1:numPackets
            rxframeBuffer = [];                 % Initialise matrix
            
            % Transmit each subframe individually
            for u = 1:packetSize
                
                % Remove next subframe from the transmit buffer
                txSig = txframeBuffer( ((u-1)*numel(ofdmTx)+1) : u*numel(ofdmTx) );
                
                % Apply Channel to input signal
                fadedSig = zeros(size(txSig));                    % Pre-allocate vector size
                for i = 1:size(txSig,1)                           % Perform elementwise...
                    for j = 1:size(txSig,2)                       % ...matrix multiplication
                        fadedSig(i,j) = txSig(i,j).*rayChan(i,j);
                    end
                end
                
                % AWGN Channel
                release(awgnChannel);
                powerDB = 10*log10(var(fadedSig));            % Calculate Tx signal power
                noiseVar = 10.^(0.1*(powerDB-snr(m)));        % Calculate the noise variance
                rxSig = awgnChannel(fadedSig,noiseVar);       % Pass the signal through a noisy channel
                
                % Equalisation
                eqSig = equaliser(rxSig,fadedSig,txSig,ofdmSym);
                
                % Demodulation
                otfsRx = demodOFDM(eqSig,cpLen,ofdmSym);     % Apply OFDM demodulation
                rxSubframe = SFFT(otfsRx);                      % Apply OTFS demodulation
                rxframeBuffer = [rxframeBuffer';rxSubframe']';     % Store demodulated subframe in rx buffer
            end
            % Remove all null carriers
            parallelRx = rxframeBuffer;
            parallelRx((numDC/2)+1:(numDC/2)+11, :) = [];         % Remove nulls around the DC input
            parallelRx(1:1, :) = [];                              % Remove nulls at index 1
            qamRx = reshape(parallelRx,[numel(parallelRx),1]);    % Convert to serial
            
            % Uncoded demodulation of entire packet
            dataOut = qamdemod(qamRx,M,'OutputType','bit','UnitAveragePower',true);% Apply QAM demodulation
            codedData_out = randdeintrlv(dataOut,4831);                            % De-interleave data
            codedData_out(numel(codedData_in)+1:end) = [];                         % Remove pad bits
            errorStats_uncoded = errorRate(codedData_in,codedData_out,0);          % Collect error statistics
            

            % Coded demodulation of entire packet
            powerDB = 10*log10(var(qamRx));                                   % Calculate Rx signal power
            noiseVar = 10.^(0.1*(powerDB-(EbNo(m) + 10*log10(codeRate*k) - 10*log10(sqrt(numDC)))));            % Calculate the noise variance
            dataOut = qamdemod(qamRx,M,'OutputType', 'approxllr','UnitAveragePower',true,'NoiseVariance',noiseVar);% Apply QAM demodulation
            codedData_out1 = randdeintrlv(dataOut,4831);                      % De-interleave data
            codedData_out1(numel(codedData_in)+1:end) = [];                   % Remove pad bits
            
            % Decode individual code blocks
            dataBits_out = [];                                                % Initialise matrix
            dataOut_buffer = codedData_out1;
            for q = 1:numCB
                dataBits_out = [dataBits_out;ldpcDecoder(dataOut_buffer(1:noCodedbits))]; % Decode data & add it to the data bits out matrix
                dataOut_buffer(1:noCodedbits) = [];                                       % Delete decoded data from buffer
            end
            dataBits_out = double(dataBits_out);                              % Convert to a double compatible w/ errorStats
            errorStats_coded = errorRate1(dataBits_in,dataBits_out,0);     % Collect error statistics
            
        end
        berOTFS(m,:) = errorStats_uncoded;                                  % Save uncoded BER data
        berCOTFS(m,:) = errorStats_coded;                                   % Save coded BER data
        errorStats_uncoded = errorRate(codedData_in,codedData_out,1);       % Reset the error rate calculator
        errorStats_coded = errorRate1(dataBits_in,dataBits_out,1);          % Reset the error rate calculator
        
    end
    
end

ok最后就是plot

%--------------------------------------------------------------------------
%                           Figures
%-------------------------------------------------------------------------- 

% Plot BER / EbNo curves
plotGraphs(berOFDM, berCOFDM, berOTFS, berCOTFS, M, numSC, EbNo);

二者误码率图像:

dataGen.m

%--------------------------------------------------------------------------
%
%               Generates and encodes random binary data
%
%--------------------------------------------------------------------------
% Input arguments: 
%
% k                             Bits/Symbol
% numDC                         Number of data subcarriers
% ofdmSym                       Totol ofdm symbols per subframe
% totalBits                     The approximate total bits to be simulated by the system
% codeRate                      LDPC code rate
% ldpcEncoder                   LDPC encode system object
% 
%--------------------------------------------------------------------------
% Function returns: 
% 
% dataIn                        The input encoded data to the modulator
% dataBits_in                   The binary generated initial data before coding
% codedData_in                  The binary codewords
% packetSize                    No. of subframes / "packet"
% numPackets                    Number of packets required to satisfy totalBits
% numCB                         No. of code blocks / "subframe"
%
%--------------------------------------------------------------------------
% Calculate subframe size
% Initialise information about frames to be transmitted
packetSize = 1;              % No. of subframes / "packet"
numCB = 1;                   % No. of code blocks / "subframe"
noCodedbits = 64800;         % Codeword length

% Calculate exact no. of frames and bits required for simulation
subframeSize = [k*numDC*ofdmSym 1];               % Calculate size of a subframe
maxSubframes = ceil(totalBits./subframeSize(1));  % Total no. of subframes to be transmitted

% Determine number of code block and number of subframes/packet
if subframeSize(1) == noCodedbits               % If same size do nothing
    numCB = 1;
    packetSize = 1;
    
elseif subframeSize(1) > noCodedbits            % Match for when subframe > codeword
    [numCB, packetSize] = rat(subframeSize(1)./ noCodedbits,1e-1);
    
elseif subframeSize(1) < noCodedbits            % Match for when subframe < codeword
    [packetSize, numCB] = rat(noCodedbits./ subframeSize(1),1e-1);
end   

% Ensure theres always enough data bit capacity
while numCB*noCodedbits >= subframeSize(1)*packetSize
    packetSize = packetSize + 1;
    % Divide both by 2 if possible
    if (rem(numCB,2) == 0) && (rem(packetSize,2) == 0) && numCB*noCodedbits <= subframeSize(1)*packetSize
        packetSize = packetSize./2;
        numCB = numCB./2;
    end
end 

% Calculate the pad bits required to round up to the nearest whole subframe
padBits = zeros((subframeSize(1)*packetSize - numCB*noCodedbits),1);% Calculate the number of pad bits
numPackets = round(maxSubframes./packetSize);                       % Total no. of "packets" to be transmitted
numPackets(~numPackets)=1;                                          % If 0 packets set to 1

% Generate Random Input Data
%range shuffle;                               % Shuffle random no. generator
codedData_in = [];                           % Initialse arrays
dataBits_in = [];
for q = 1:numCB
    dataBits = randi([0,1],[noCodedbits*codeRate,1]);      % Generate binary datafor each frame of the burst
    dataBits_in = [dataBits_in;dataBits];                  % Concatenate binary data  
    codedData_in = [codedData_in; ldpcEncoder(dataBits)];  % Generate LDPC codeblocks
end
paddedData_in = [codedData_in; padBits];             % Append pad bits to coded bits
dataIn = randintrlv(paddedData_in,4831);             % Interleave paddedData randdeintrlv


% Print info about data output
% fprintf(['\n',num2str(numCB),' code block(s)\n', num2str(packetSize), ' subframes/packet \n'])
% fprintf([ num2str(numel(padBits)),' pad bits out of ', num2str((subframeSize(1)*packetSize)),' data bits = ', num2str(100*(numel(padBits)/(subframeSize(1)*packetSize))),' percent pad bits!\n'])
% fprintf(['Total packets: ', num2str(numPackets),'\n'])
% fprintf(['Total bits:    ', num2str(numPackets*packetSize*(subframeSize(1))),'\n'])

end

 SFFT.m

%--------------------------------------------------------------------------
% Input arguments: 
% inSig                     Input N x M matrix to be transformed
%--------------------------------------------------------------------------
% Function returns: 
% outSig                    Output N x M matrix
%--------------------------------------------------------------------------
[N, M] = size(inSig);                                      % Calculate N and M
outSig = sqrt(M/N) * ifft( fft(inSig, [], 1), [], 2);      % Apply transform

注意fft和ifft如果未指定任何值[],则输出的大小与输入相同,1、2表示维度

举个例子

a =

     1     2     3
     4     5     6

>> [N, M] = size(a); 
>> outSig = sqrt(M/N) * ifft( fft(a, [], 1), [], 2);
>> outSig

outSig =

   8.5732 + 0.0000i  -1.2247 - 0.7071i  -1.2247 + 0.7071i
  -3.6742 + 0.0000i   0.0000 + 0.0000i   0.0000 + 0.0000i
返回的是与a大小一样的

ISFFT.m

%--------------------------------------------------------------------------
% Input arguments: 
% inSig                     Input N x M matrix to be transformed
%--------------------------------------------------------------------------
% Function returns: 
% outSig                    Output N x M matrix of doppler-Delay domain symbols
%--------------------------------------------------------------------------
[N, M] = size(inSig);                                      % Calculate N and M
outSig = sqrt(N/M) * fft( ifft(inSig, [], 1), [], 2);      % Apply inverse transform

modOFDM.m(实现OFDM编码)

%--------------------------------------------------------------------------
%
%               Modulates random input data into OFDM symbols
%
%--------------------------------------------------------------------------
% Input Arguments: 
% dataIn                         Input data vector
% numSC                          The number of subcarriers used
% cpLen                          Length of the cyclic prefix
% ofdmSym                        No. of ofdm symbols per subframe
%--------------------------------------------------------------------------
% Function returns: 
% dataOut                        Output OFDM symbols
%--------------------------------------------------------------------------
% Calculate variables
cyclicPrefix_start  = numSC - cpLen;

% Perform IFFT
ifftSubcarrier = ifft(dataIn,[],2); 

%Finding cyclic prefix for each subcarrier
for i=1:cpLen
    for j=1:ofdmSym                   
        cyclicPrefix_data(i,j) = ifftSubcarrier(i+cyclicPrefix_start,j);
    end
end

% Add cyclic prefix to the data
appendedCP = vertcat(cyclicPrefix_data, ifftSubcarrier);

% Convert to serial
dataOut = reshape(appendedCP,[numel(appendedCP),1]);

multipathChannel.m

%--------------------------------------------------------------------------
%
%               Generates and encodes random binary data
%
%--------------------------------------------------------------------------
% Input arguments: 
%
% cpSize                        Size of the cyclic prefix
% delta_f                       OFDM subcarrier spacing (Hz)
% inSig                         Input signal dimensions used to generate channel dimensions
% totalBits                     The approximate total bits to be simulated by the system
% velocity                      Channel mobility in km/hr
% 
%--------------------------------------------------------------------------
% Function returns: 
% 
% outSig                        Channel impulse response (serial vector)
%
%--------------------------------------------------------------------------
% Create N x M channel matrix 
[N, M]= size(inSig');                                     % Size of inSig is used to create channel model
n = zeros(1,N);                                          % delay_Doppler rows (doppler)
m = zeros(1,M);                                          % delay_Doppler cols (delay)
H = transpose(n).*m;                                     % Create matrix

% Generate Channel Parameter
maxDelayspread = 0.5*((cpSize)/delta_f);  % Calculate max delay spread with 1/2 rule pf thumb
L = round(2*maxDelayspread * M*delta_f);  % Calculate necesary paths from bandwidth
step = maxDelayspread/L;                  % calculate difference between delays
pathDelays = (0:step:maxDelayspread);     % Discrete even delays of L-path channel
%range shuffle;                            % Shuffle random no. generator
avgPathGains_dB = -(randi([3,7],[L,1]));  % Generate  random path gains in dB
avgPathGains = 10.^(0.1*avgPathGains_dB); % Convert to linear

% Calculate Max Doppler Shift
v = velocity*1e3/3600;                   % Mobile speed (m/s)
fc = 3.5e9;                              % Carrier frequency
fd = round(v*fc/physconst('lightspeed'));% Maximum Doppler shift to nearest Hz

% Generate doppler spreads w/ Jake's model
for l=0:L-1
    Vi(l+1) = fd* cos( (2*pi*l)/(L-1) );
end

% Initialize channel variables
T = 1/delta_f;                  % unextended OFDM symbol period
Ts = (1+cpSize)/delta_f;        % OFDM symbol period)
Ti = pathDelays;                % Path delays
hi = avgPathGains;              % Path gains

% Create matrix representation of channel
for m=1:M               % Loop along the rows
    for n=1:N           % Loop down the cols
        
        for x=1:L       % Loop to sum terms in the channel memory     
            % Define terms of model
            expTerm = (-2*1i*(pi)) * ((m+M/2).*delta_f.*Ti(x) - Vi(x).*(n).*Ts);
            hiPrime = hi(x)*(1 + 1i*(pi).*Vi(x).*T);
            % Produce channel impulse response model
            H(n, m) = H(n, m) + exp(expTerm) * hiPrime;
            
        end
    end

end

% Convert to serial
outSig = reshape(H',[n*m,1]);
end

equaliser

%--------------------------------------------------------------------------
%
%                   Equalises a faded signal 
%
%--------------------------------------------------------------------------
% Input arguments: 
%
% rxSig                         The received faded signal w/ noise applied
% fadedSig                      The received faded signal, NO noise
% txSig                         Transmitted signal prior to channel
% ofdmSym                       Totol ofdm symbols per subframe
% 
%--------------------------------------------------------------------------
% Function returns: 
% 
% eqSig                         The equalised output signal (serial vector)
%
%--------------------------------------------------------------------------
% Input parameters
pilotSpacing = 4;                       % Subcarrier sampling period (4 is best)
noSamples = numel(rxSig)/ofdmSym;       % No. of times the channel is sampled
numSC = pow2(floor(log2(noSamples)));   % Calc. no. of OFDM subcarrier

% Reformat input data into a matrix to make sampling easier
fadedSig_matrix = reshape(fadedSig, [noSamples,ofdmSym]);
txSig_matrix = reshape(txSig, [noSamples,ofdmSym]);

% Remove cyclic prefix as do no need to equalise it
fadedSig_matrix(1:(noSamples-numSC),:) = [];   % Remove cp
txSig_matrix(1:(noSamples-numSC),:) = [];   % Remove cp

% Sample signal
h = zeros(size(txSig_matrix));                          % Pre allocate matrix
for i = 1:size(txSig_matrix,1)                          % Loop rows
    for j = 1:size(txSig_matrix,2)                      % Loop Columns
        % Sample every pilotSpacing subcarrier (incuding first and last subcarriers)
        if i==1
             sample(i,j) = fadedSig_matrix(i,j)./txSig_matrix(i,j);
        elseif 0 == mod(i,pilotSpacing)
            sample(i/pilotSpacing+1,j) = fadedSig_matrix(i,j)./txSig_matrix(i,j);
        end
    end    
end

% Linearly Interpolate samples between subcarriers 
interpPoints = ( (1+(1/pilotSpacing)) : (1/pilotSpacing) : size(sample,1) );% Calc. points to interpolate
for j = 1:size(txSig_matrix,2)
    h(:,j) = interp1(sample(:,j),interpPoints);
end

% Keep only 1st, 7th and 14th samples per carrier
h1 = [h(:,1)';h(:,7)';h(:,14)']';

% Linearly Interpolate samples between symbols
interpPoints1 = ( 1 : (1/6) : 2 );              % Calc. points to interpolate
interpPoints2 = ( (2+(1/7)) : (1/7) : 3 );
for i = 1:size(txSig_matrix,1)
    h17(i,:) = interp1(h1(i,:),interpPoints1);  % Interpolate 1-7
    h714(i,:) = interp1(h1(i,:),interpPoints2); % interpolate 7-14
end

% Concatenate matracies 
h = [h17';h714']';

% Set eq of CP carriers to same as 1st carrier
for k = 1:(noSamples-numSC)
    h = [h(1,:);h];
end

% Convert back into serial
H = reshape(h,[numel(h),1]);
H(isnan(H)) = 1;                  % Set all NaN's to 1

% Equalise the signal 
eqSig = rxSig ./ H;
eqSig(isnan(eqSig))=0;            % Set all NaN's to 0

猜你喜欢

转载自blog.csdn.net/weixin_44810982/article/details/127230163
今日推荐