www.gusucode.com > MIMO与SISO仿真程序 > MIMO-OFDM/results_MIMO_v1.m

    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%   Student:      Benjamin Pham
%   ID:           25957066
%   
%   Version:        Final
%   Changes:        
%   Description:    a 2x2 MIMO OFDM System
%                                   
%   Simulates a 2x2 MIMO OFDM system. This system includes the
%   Transmitter: 
%   QAM Modulation, S/P converter, Space-Time Block encoding
%   IFFT, Add Cyclic Prefix, P/S converter
%   Channel: 
%   Frequency flat fading Channel modelled by Complex number, AWGN, 
%   Time Offset
%   Receiver: 
%   S/P converter, Removal of Cyclic Prefix, DFT, P/S converter
%   Space-time block decoding, QAM Demodulation
%
%   Simulation performs a BER test vs SNR when various time offsets are
%   inputted by sending binary data through the system and measuring the
%   amount of errors at the receiver. Time offsets can be changed beginning
%   on line 130 for different channels.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
clc; clear all; close all; warning off

%% Input parameters
% data points
data = 2^16;                                   

% fft size
n_fft = 64;                                     

% cyclic prefix length
n_cp = 0.25*n_fft;                                  % CP length 25% of FFT size

% OFDM frame length
OFDM = n_fft + n_cp;

% Signal to Noise Ratios for AWGN
snr = [0:1:30];

% Channel modelled by random complex number
h = [randn()+randn()*1i, randn()+randn()*1i; randn()+randn()*1i, randn()+randn()*1i];

% Initialise variables
errors = zeros(size(snr));
ber = zeros(size(snr));

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%                          TRANSMITTER                                  %%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Generate binary data
binary_data = round(rand(data,1));      

%% Run BER test for 4QAM, 16QAM and 64 QAM
for mod_type = 1:3
    % Quadrature Amplitude Modulation
    if mod_type == 1                                % Modulation Type: 4QAM
        symbols = 2;                                % Bits per symbol
        % Padding for symbol mapping
        while floor(length(binary_data)/symbols) ~= length(binary_data)/symbols
            binary_data = [binary_data; zeros(1,1)];                                    
        end
        % Padding for subcarriers mapping
        while floor(length(binary_data)/symbols/n_fft) ~= length(binary_data)/symbols/n_fft
            binary_data = [binary_data; zeros(1,1)];                                    
        end        
    elseif mod_type == 2                            % Modulation Type: 16QAM
        symbols = 4;
        % Padding for symbol mapping
        while floor(length(binary_data)/symbols) ~= length(binary_data)/symbols
            binary_data = [binary_data; zeros(1,1)];                                    
        end
        % Padding for subcarriers mapping
        while floor(length(binary_data)/symbols/n_fft) ~= length(binary_data)/symbols/n_fft
            binary_data = [binary_data; zeros(1,1)];                                    
        end        
    elseif mod_type == 3                            % Modulation Type: 64QAM
        symbols = 6;
        % Padding for symbol mapping
        while floor(length(binary_data)/symbols) ~= length(binary_data)/symbols
            binary_data = [binary_data; zeros(1,1)];                                    
        end
        % Padding for subcarriers mapping
        while floor(length(binary_data)/symbols/n_fft) ~= length(binary_data)/symbols/n_fft
            binary_data = [binary_data; zeros(1,1)];                                    
        end
    end
    % Mapping binary data onto constellation maps
    mod_method = 2^symbols;                        
    mod_data = qammod(binary_data,mod_method,'unitaveragepower',true,'inputtype','bit');

    %% Space-Time Block Encoding
    % intialiase matrix
    STBC = zeros(2*length(mod_data),1);
    % [x1 -x2* ; x2 x1*] alogritm 
    % first column is first time slot, next column is next time slot
    for i = 0:(length(mod_data)/2-1)
        STBC(4*i+1) = mod_data(2*i+1);
        STBC(4*i+2) = mod_data(2*i+2);
        STBC(4*i+3) = -conj(mod_data(2*i+2));
        STBC(4*i+4) = conj(mod_data(2*i+1));
    end
    %% Splitting up the data between the transmitters
    STBC = reshape(STBC.',2,length(mod_data));
    Tx1 = STBC(1,:);                % Data to be sent from Tx1
    Tx2 = STBC(2,:);                % Data to be sent from Tx2

    %% Serial to Parallel Conversion
    % serial stream into 64 subcarriers
    Xk1 = reshape(Tx1,n_fft,length(Tx1)/n_fft);
    Xk2 = reshape(Tx2,n_fft,length(Tx2)/n_fft);
   
    %% Inverse Fast Fourier Transform
    Xn1 = ifft(Xk1);
    Xn2 = ifft(Xk2);

    %% Cyclic prefix
    Xn1_cp = [Xn1((end - n_cp + 1):end,:);Xn1];  
    Xn2_cp = [Xn2((end - n_cp + 1):end,:);Xn2]; 

    %% Parallel to Serial Conversion
    xn1 = Xn1_cp(:);
    xn2 = Xn2_cp(:);
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%                              Channel                                  %%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

    %% BER test for different SNR
    for k = 1:length(snr)
        %% Data passing through Channel
        % y time, receiver 
        yn11 = xn1*h(1,1);              % Tx1 to Rx1               
        yn21 = xn2*h(2,1);              % Tx2 to Rx1
        yn12 = xn1*h(1,2);              % Tx1 to Rx2
        yn22 = xn2*h(2,2);              % Tx2 to Rx2

        %% add noise
        dB = snr(k);
        yn11 = awgn(yn11,dB,'measured');
        yn21 = awgn(yn21,dB,'measured');
        yn12 = awgn(yn12,dB,'measured');
        yn22 = awgn(yn22,dB,'measured');

        %% offset added to between transmitter and receiver
        % CP length is 16, input time offset of 15 to match CP length of 16 
        % offset greater than CP length, 15, introduces ISI and increased BER
        % time offset is equal to duration of one symbol length
        delay11 = 0;          % offset between Tx1 and Rx1
        delay21 = 0;          % offset between Tx2 and Rx1
        delay12 = 0;          % offset between Tx1 and Rx2
        delay22 = 0;          % offset between Tx2 and Rx2

        % next OFDM symbol becomes superposition of delayed previous symbol
        % tail of previous symbol added to front of next symbol - ISI
        %% inter-symbol interference
        for i = 0:(length(yn11)/(OFDM))-2
            % ISI between transmitter 1 and receiver 1
            if delay11 ~= 0
                if delay11 == 1
                    yn11(1+OFDM+OFDM*i) = yn11(1+OFDM+OFDM*i) + yn11(OFDM-delay11+OFDM*i);
                else
                    yn11(1+OFDM+OFDM*i:1+OFDM+delay11+OFDM*i) = yn11(1+OFDM+OFDM*i:1+OFDM+delay11+OFDM*i) ...
                    + yn11(OFDM-delay11+OFDM*i:OFDM+OFDM*i);
                end
            end
            % ISI between transmitter 1 and receiver 2            
            if delay12 ~= 0
                if delay12 == 1
                    yn12(1+OFDM+OFDM*i) = yn12(1+OFDM+OFDM*i) + yn12(OFDM-delay11+OFDM*i);
                else                
                yn12(1+OFDM+OFDM*i:1+OFDM+delay12+OFDM*i) = yn12(1+OFDM+OFDM*i:1+OFDM+delay12+OFDM*i) ...
                    + yn12(OFDM-delay12+OFDM*i:OFDM+OFDM*i);
                end
            end
            % ISI between transmitter 2 and receiver 1            
            if delay21 ~= 0
                if delay21 == 1
                    yn21(1+OFDM+OFDM*i) = yn21(1+OFDM+OFDM*i) + yn21(OFDM-delay11+OFDM*i);
                else                
                yn21(1+OFDM+OFDM*i:1+OFDM+delay21+OFDM*i) = yn21(1+OFDM+OFDM*i:1+OFDM+delay21+OFDM*i) ...
                    + yn21(OFDM-delay21+OFDM*i:OFDM+OFDM*i);
                end
            end
            % ISI between transmitter 2 and receiver 2            
            if delay22 ~= 0
                if delay22 == 1
                    yn22(1+OFDM+OFDM*i) = yn22(1+OFDM+OFDM*i) + yn22(OFDM-delay11+OFDM*i);
                else                
                yn22(1+OFDM+OFDM*i:1+OFDM+delay22+OFDM*i) = yn22(1+OFDM+OFDM*i:1+OFDM+delay22+OFDM*i) ...
                    + yn22(OFDM-delay22+OFDM*i:OFDM+OFDM*i);
                end
            end
        end
        % Time offset transmitter 1 and receiver 1
        if delay11 ~= 0
            if delay11 == 1
                 yn11(1:OFDM) = [zeros(delay11,1);yn11(1:OFDM-delay11)];
            else
                yn11(1:OFDM) = [zeros(delay11+1,1);yn11(1:OFDM-delay11-1)];
            end
        end
        % Time offset transmitter 1 and receiver 2        
        if delay12 ~= 0
            if delay12 == 1
                 yn12(1:OFDM) = [zeros(delay12,1);yn12(1:OFDM-delay12)];
            else
                yn12(1:OFDM) = [zeros(delay12+1,1);yn12(1:OFDM-delay12-1)];
            end
        end
        % Time offset transmitter 2 and receiver 1        
        if delay21 ~= 0
            if delay21 == 1
                 yn21(1:OFDM) = [zeros(delay21,1);yn11(1:OFDM-delay21)];
            else
                yn21(1:OFDM) = [zeros(delay21+1,1);yn11(1:OFDM-delay21-1)];
            end
        end
        % Time offset transmitter 2 and receiver 2        
        if delay22 ~= 0
            if delay22 == 1
                 yn22(1:OFDM) = [zeros(delay22,1);yn22(1:OFDM-delay22)];
            else
                yn22(1:OFDM) = [zeros(delay22+1,1);yn22(1:OFDM-delay22-1)];
            end
        end
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%                              RECEIVER                                 %%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
        % superposition of two received signals at receiver       
        %% y(1) = h1*x1 + h2*x2 ; y(2) = -h2* x1* + h1 * x2*
        yn1 = yn11 + yn21;              % combined signal at receiver 1                
        yn2 = yn12 + yn22;              % combined signal at receiver 2

        %% Serial to Parallel Conversion
        yn1_sp = reshape(yn1,OFDM,size(Xn1_cp,2));
        yn2_sp = reshape(yn2,OFDM,size(Xn2_cp,2));
        
        %% Remove cyclic prefix
        yn1_rcp = yn1_sp((n_cp + 1):end,:);
        yn2_rcp = yn2_sp((n_cp + 1):end,:);

        %% Discrete fourier transform
        Yk1_block = fft(yn1_rcp);
        Yk2_block = fft(yn2_rcp);
        
        %% Serial to parallel conversion
        Yk1 = Yk1_block(:);              
        Yk2 = Yk2_block(:);

        %% Space-Time Block Decoding
        % Assume perfect channel estimation        
        abs_h = sum(sum(abs(h).^2));
        H = [ conj(h(1,1)) , conj(h(1,2)), h(2,1), h(2,2) ; ...         % pseudo inverse
            conj(h(2,1)), conj(h(2,2)), -h(1,1) , -h(1,2)]./ abs_h;
        
        % initialise matrix
        X_hat1 = zeros(length(Tx1)/2,1);
        X_hat2 = zeros(length(Tx2)/2,1);
        X = zeros(length(Tx1)/2,1);

        for i = 0:length(Yk1)/2-1
            Yk1(2*i+2) = conj(Yk1(2*i+2));
            Yk2(2*i+2) = conj(Yk2(2*i+2));

            X_hat1(i+1) = H(1,1)*Yk1(2*i+1) + H(1,2)*Yk2(2*i+1) + H(1,3)*Yk1(2*i+2) + H(1,4)*Yk2(2*i+2);       
            X_hat2(i+1) = H(2,1)*Yk1(2*i+1) + H(2,2)*Yk2(2*i+1) + H(2,3)*Yk1(2*i+2) + H(2,4)*Yk2(2*i+2);

            X(2*i+1) = X_hat1(i+1);
            X(2*i+2) = X_hat2(i+1);
        end

        %% QAM demodulation
        X_demod = qamdemod(X,mod_method,'unitaveragepower',true,'outputtype','bit');
        output = X_demod(:).';
        
        %% Calculating BER
        errors(mod_type,k) = 0;
        for i = 1:length(binary_data)-n_fft*symbols
            if output(i+n_fft*symbols) ~= binary_data(i+n_fft*symbols)
                errors(mod_type,k) = errors(mod_type,k) + 1;
            end
        end
        ber(mod_type,k) = errors(mod_type,k)/length(binary_data);
    end
    
    % Plotting BER vs Eb/No
    semilogy(snr-10*log10(symbols),ber(mod_type,:),'-');
    title('Two transmitter Two Receiver'); legend('4QAM','16QAM','64QAM');
    xlabel('E_b/N_o (dB)'); ylabel('BER'); grid on; hold on
end