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

    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%   Student:      Benjamin Pham
%   ID:           25957066
%   
%   Version:        Final
%   Changes:        
%   Description:    a two user one receiver OFDM System
%                                   
%   Simulates a multi-user OFDM system. This system includes the
%   Transmitter: 
%   QAM Modulation, S/P converter, IFFT, Add Cyclic Prefix, 
%   Sub-carrier allocation, P/S converter
%   Channel: 
%   Frequency flat fading Channel modelled by Complex number, AWGN, 
%   Time Offset
%   Receiver: 
%   S/P converter, Sub-carrier Demux, Removal of Cyclic Prefix, DFT, 
%   P/S converter, 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 140 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 = 2*n_fft+2*n_cp;

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

% Channel modelled by random complex number
% 1 for same channels or any other number different channels
channel = 1;
% Simulate users with same channel or different channels
if channel == 1
    h = [randn() + randn()*1i];                                  
    h = [h h];
else
    h = [randn()+randn()*1i , randn()+randn()*1i]; 
end

% Initialise variables
errors1 = zeros(size(snr));
ber1 = zeros(size(snr));
errors2 = zeros(size(snr));
ber2 = zeros(size(snr));

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%                          TRANSMITTER                                  %%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Generate binary data
binary_data1 = round(rand(data,1));             % User 1
binary_data2 = round(rand(data,1));             % User 2

%% 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_data1)/symbols) ~= length(binary_data1)/symbols
        binary_data1 = [binary_data1; zeros(1,1)];                                    
        end
        while floor(length(binary_data1)/symbols/(2*n_fft)) ~= length(binary_data1)/symbols/(2*n_fft)
        binary_data1 = [binary_data1; zeros(1,1)];                                    
        end
        % Padding for subcarriers mapping
        while floor(length(binary_data2)/symbols) ~= length(binary_data2)/symbols
        binary_data2 = [binary_data2; zeros(1,1)];                                    
        end
        while floor(length(binary_data2)/symbols/(2*n_fft)) ~= length(binary_data2)/symbols/(2*n_fft)
        binary_data2 = [binary_data2; zeros(1,1)];                                    
        end       
    elseif mod_type == 2                            % Modulation Type: 16QAM
        symbols = 4;
        % Padding for symbol mapping
        while floor(length(binary_data1)/symbols) ~= length(binary_data1)/symbols
        binary_data1 = [binary_data1; zeros(1,1)];                                    
        end
        while floor(length(binary_data1)/symbols/(2*n_fft)) ~= length(binary_data1)/symbols/(2*n_fft)
        binary_data1 = [binary_data1; zeros(1,1)];                                    
        end
        % Padding for subcarriers mapping
        while floor(length(binary_data2)/symbols) ~= length(binary_data2)/symbols
        binary_data2 = [binary_data2; zeros(1,1)];                                    
        end
        while floor(length(binary_data2)/symbols/(2*n_fft)) ~= length(binary_data2)/symbols/(2*n_fft)
        binary_data2 = [binary_data2; zeros(1,1)];                                    
        end     
    elseif mod_type == 3                            % Modulation Type: 64QAM
        symbols = 6;
        % Padding for symbol mapping
        while floor(length(binary_data1)/symbols) ~= length(binary_data1)/symbols
        binary_data1 = [binary_data1; zeros(1,1)];                                    
        end
        while floor(length(binary_data1)/symbols/(2*n_fft)) ~= length(binary_data1)/symbols/(2*n_fft)
        binary_data1 = [binary_data1; zeros(1,1)];                                    
        end
        % Padding for subcarriers mapping
        while floor(length(binary_data2)/symbols) ~= length(binary_data2)/symbols
        binary_data2 = [binary_data2; zeros(1,1)];                                    
        end
        while floor(length(binary_data2)/symbols/(2*n_fft)) ~= length(binary_data2)/symbols/(2*n_fft)
        binary_data2 = [binary_data2; zeros(1,1)];                                    
        end
    end
    % Mapping binary data onto constellation maps
    mod_method = 2^symbols;       
    mod_data1 = qammod(binary_data1,mod_method,'unitaveragepower',true,'inputtype','bit');
    mod_data2 = qammod(binary_data2,mod_method,'unitaveragepower',true,'inputtype','bit');

    %% splitting data up between the users
    Tx1 = mod_data1;
    Tx2 = mod_data2;

    %% Serial to Parallel Conversion
    % serial stream into 64 subcarriers
    Xk1 = reshape(Tx1,n_fft,length(Tx1)/(n_fft)); % 64 sub carriers, per user
    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];  
  
    %% Sub-carrier allocation    
    Xn1_pad = [ Xn1_cp ; zeros(size(Xn1_cp)) ];
    Xn2_pad = [ zeros( size(Xn2_cp)) ; Xn2_cp ];

    %% Parallel to Serial Conversion
    xn1 = Xn1_pad(:);
    xn2 = Xn2_pad(:);

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%                              Channel                                  %%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% BER test for different SNR
    for k = 1:length(snr)
    %% Data passing through Channel
        yn11 = xn1*h(1);           
        yn21 = xn2*h(2);
        
        %% add noise
        db = snr(k);
        yn11 = awgn(yn11,db,'measured');
        yn21 = awgn(yn21,db,'measured');
        
        %% offset added to between User 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 User1 and Rx1
        delay21 = 0;          % offset between User2 and Rx1

        % 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 delay21 ~= 0
                if delay21 == 1
                    yn21(1+OFDM+OFDM*i) = yn21(1+OFDM+OFDM*i) + yn21(OFDM-delay21+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
        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 delay21 ~= 0
            if delay21 == 1
                 yn21(1:OFDM) = [zeros(delay21,1);yn21(1:OFDM-delay21)];
            else
                yn21(1:OFDM) = [zeros(delay21+1,1);yn21(1:OFDM-delay21-1)];
            end
        end
        
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%                              RECEIVER                                 %%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%        
        % superposition of two received signals at receiver
        %% y(1) = h1*x1 + h2*x2
        yn = yn11 + yn21;               % combined signal at receiver 1  
        
        %% Serial to Parallel Conversion
        yn_sub = reshape(yn,OFDM,size(Xn1,2));
        
        %% Sub-Carrier Demux
        Yn_sub1 = yn_sub(1:80,:);                              
        Yn_sub2 = yn_sub(81:160,:);

        %% Remove cyclic prefix
        yn_sub_rcp1 = Yn_sub1((n_cp+1):end,:);
        yn_sub_rcp2 = Yn_sub2((n_cp+1):end,:);


        %% Discrete fourier transform
        Yk_block1 = fft(yn_sub_rcp1);
        Yk_block2 = fft(yn_sub_rcp2);
        
        %% Serial to parallel conversion
        Yk1_s = Yk_block1(:);             
        Yk2_s = Yk_block2(:);       

        %% Channel estimation
        % assume perfect channel estimation through pilot symbols and using
        % zero forcing
        Xhat1 = Yk1_s./h(1);
        Xhat2 = Yk2_s./h(2);

        %% QAM demodulation
        X_demod1 = qamdemod(Xhat1,mod_method,'unitaveragepower',true,'outputtype','bit');
        X_demod2 = qamdemod(Xhat2,mod_method,'unitaveragepower',true,'outputtype','bit');

        output1 = X_demod1(:).';
        output2 = X_demod2(:).';
        
        %% Calculating BER
        % BER for User 1
        errors1(mod_type,k) = 0;
        for i = 1:length(binary_data1)-n_fft*symbols
            if output1(i+n_fft*symbols) ~= binary_data1(i+n_fft*symbols)
                errors1(mod_type,k) = errors1(mod_type,k) + 1;
            end
        end
        ber1(mod_type,k) = errors1(mod_type,k)/length(binary_data1);
        
        % BER for User 2
        errors2(mod_type,k) = 0;
        for i = 1:length(binary_data2)-n_fft*symbols
            if output2(i+n_fft*symbols) ~= binary_data2(i+n_fft*symbols)
                errors2(mod_type,k) = errors2(mod_type,k) + 1;
            end
        end
        ber2(mod_type,k) = errors2(mod_type,k)/length(binary_data2);

    end
    
    % Plotting BER vs Eb/No
    semilogy(snr-10*log10(symbols),ber1(mod_type,:),'-',snr-10*log10(symbols),ber2(mod_type,:),'-')
    title('Two users One receiver'); legend('4QAM user1','4QAM user2','16QAM user1','16QAM user2','64QAM user1','64QAM user2');
    xlabel('E_b/N_o (dB)'); ylabel('BER'); grid on;hold on
end