Sei sulla pagina 1di 15

Sample Code

Here I will provide all the code that I am developing. I will start in ascending
order, that is, from the first program written onwards. I hope that the
explanations will be sufficient. All the code will be in HTML format, just copy
and paste into the MATLAB editor and you will be good to go.
 
Version Short Description Date
     
0.10 Standard MCM communications system 09.10.04
0.11 * Incomplete * 09.11.04
0.12 Generic OFDM with Cyclic Prefixing 09.12.04
0.13 Added Channel equalization & AWGN noise effects 09.20.04
     
 
Other Necessary Functions

1. do_padding

Takes the serial input data and the user specified block size, then checks
the serial data if it can be completely divided into an integer number of
blocks. If not, it will add zeros to the end of the stream until an integer
number of blocks can be created.

OFDM Version 0.10

Version 0.10 is basically a trial run to get back into the mode of things. This is
a simple MCM communications system. The code is pretty self-explanatory.
 

See the code ofdm_010

 
Results of running this script:
 
Fig. 1. Random input data samples
 

Fig. 2. QPSK signal constellation of the input data


 
Fig. 3. Real part of the OFDM signal that is transmitted
 

Fig. 4. Complex part of the OFDM signal that is transmitted


 
Fig. 5. Received data samples
 
 
%
% OFDM System Version 0.10
% Created on September 10, 2004 by Surujlal Dasrath
% ------------
% Description:
% ------------
% Use function RANDSRC to generate random information symbols taken from
% source alphabet of M symbols. A fixed number of data points will be
% used. No training or noise will be added to this system.
%
% NOTE: This is not exactly OFDM since no Cyclic Prefixing was used.
% =======================================================================
%
% ------------------------
% A: Transmitter End
% ------------------------
% 1. Generate random serial data with M symbols (RANDSRC will do this)
% 2. Perform modulation (4-PSK = QPSK for now)
% 3. Serial to parallel
% 4. IFFT
% 5. Parallel to serial

% 1. Generate data
M = 4;
no_of_data_points = 64;
input = randsrc(1,no_of_data_points, 0:M-1);
figure(1)
stem(input); grid on; xlabel('Data'); ylabel('Amplitude');title('Input')

% 2. Modulation
msg_tx = pskmod(input, M);
scatterplot(msg_tx);
% 3. Serial to Parallel
parallel_mod_data = reshape(msg_tx,8,8);

% 4. 64-point IFFT
ofdm_msg = ifft(parallel_mod_data);

% 5. Parallel to serial
ofdm_msg_tx = reshape(ofdm_msg, 1,64);
figure(3)
plot(real(ofdm_msg_tx)); grid on;title('Real part of OFDM signal')
figure(4)
plot(imag(ofdm_msg_tx)); grid on;title('Imaginary part of OFDM signal')

% ---------------------
% B: Receiver End
% ---------------------

% 1. Serial to Parallel
ofdm_msg_rx = reshape(ofdm_msg_tx, 8,8);

% 2. 64-point FFT
msg_rx = fft(ofdm_msg_rx);

% 3. Parallel to serial
msg_rx_ser = reshape(msg_rx, 1, 64);

% 4. Demodulation
msg_demod = pskdemod(msg_rx_ser, M);
figure(5)
stem(msg_demod); grid on;title('Output')

%
% OFDM System Version 0.11 - !!! InComplete !!!!
% Created on September 11, 2004 by Surujlal Dasrath
%
% ** New in Version 0.11 **
% 1. Add pilot symbols to the input data just before transmission
% 2. Implement cyclic prefix (CP), use 10% of symbol length. Divide the 64
% input data points into 8-bit streams, generate and append the CP based
% on each symbol
% 3. Include complex noise into transmitted signal
%
% Organization of Transmitter end of OFDM System
% a. Generate Data
% b. Modulate
% c. Serial to Parallel
% d. Cyclic Prefix (CP)
% e. Add Pilot points
% f. IFFT
% g. Parallel to Serial
% =======================================================================
%
% ---------------
% A: Definitions
% ---------------
M = 4; % use M=4 for QPSK modulation
no_of_data_points = 64; % have 64 data points
no_of_channels = no_of_data_points/8; % make each symbol block length 8

% 1. Generate 1 x 64 vector of random data points


data_source = randsrc(1, no_of_data_points, 0:M-1);

% 2. Perform QPSK modulation


qpsk_modulated_data = pskmod(data_source, M);

% 3. Serial to parallel: create 8 channels (rows) consisting of 8


% columns each, basically looks like an 8 x 8 matrix, with each column
% consisting of 8 data points from the serial stream
% EX: serial_data = [1 2 3 4 5 6 7 8] converted to 4 channels will look
% like
% parallel_data = 1 5
% 2 6
% 3 7
% 4 8
parallel_mod_data = reshape(qpsk_modulated_data, no_of_channels,8);

% 4. Append pilot symbols to the end of each data block. Now the new
% matrix will have an extra row. Each pilot will have unit amplitude
% and zero phase for future reference
% EX: If pilots were added to the above example, it will look like:
%
% parallel_data = 1 5
% 2 6
% 3 7
% 4 8
% -------
% 1 1
%
pilot_data = ones(1,8);
data_and_pilot = [parallel_mod_data;pilot_data]

% 5. Create cyclic prefix. Make its length 10% that of the parallel
% data stream. In this case, we have 8 parallel rows consisting of data
% points and one extra row with the pilot points

OFDM Version 0.12

This is a more complete (well the first one anyway) OFDM system. It involves
all the necessary steps to generate an OFDM signal.
 

See the code ofdm_012

 
In this instance of the program, the user can specify how to do block processing
of the incoming signal. Here are the basic steps.
 
Transmitter End:
1. Define constants, such as block size, number of FFT/IFFT points, etc.
2. Call user written function 'do_padding'. This will take the length
(number) input data points and divide it by the block size. If the result is
an integer, then no padding is necessary. Otherwise, it will pad the data
stream with zeros so that there are an integer number of blocks.
Example:     input = [1 2 3 4 5];     block_size = 4
after calling 'do_padding', input becomes [1 2 3 4 5 0 0 0]
3. Do modulation. In this case, I used the MATLAB function, 'pskmod' &
'pskdemod' pairs.
4. Do serial to parallel, i.e. reshape the serial 1 x N vector into a matrix
where the number of rows equal the block size. In this way, IFFT can
be performed columnwise and each column will represent one block of
data.
5. Do IFFT on each column of the data matrix.
6. Compute, generate and append the Cyclic Prefix to the data matrix in
4.
7. Reshape the matrix back to a 1 x N + cyclic prefix length vector for
transmission.
 
Receiver End:
Just do the opposite to all of the above!
 
Results of running this script:
 
Fig. 1. OFDM system without the effects of the channel or noise. Note that the red "x"
(received) perfectly matches up to the blue "o" (transmitted).
clear all
clc
close % closes any open figures
%
% OFDM System Version 0.12
% Created on September 12, 2004 by Surujlal Dasrath
%
% ** New in Version 0.12 **
% Transmitter
% 1. Function (do_padding) to do padding if the serial data cannot be
% segmented into an integer number of blocks
% 2. Create blocks of data points from the serial stream, in matrix
% form where after IFFT & Cyclic Prefixing (CP), each block
% will become an OFDM block
% 3. Add CP to exisiting blocks of data
% 4. Convert martix of blocks of data & CP into an OFDM signal for TX
%
% Receiver
% 5. On the RX end, add a multipath channel via "filer" command
% 6. Remove CP, do FFT & demodulate

% ---------------
% A: Definitions
% ---------------
M = 4; % QPSK signal constellation
no_of_data_points = 64; % have 128 data points
block_size = 8; % size of each ofdm block
cp_len = ceil(0.1*block_size); % length of cyclic prefix
no_of_ifft_points = block_size; % 128 points for the FFT/IFFT
no_of_fft_points = block_size;
% ---------------------------------------------
% B: % +++++ TRANSMITTER HEAD END +++++
% ---------------------------------------------
% 1. Generate 1 x 128 vector of random data points
data_source = randsrc(1, no_of_data_points, 0:M-1);
figure(1)
stem(data_source); grid on; xlabel('Data Points'); ylabel('Amplitude')
title('Transmitted Data "O"')

% 2. Call 'do_padding' function to check if an integer number of blocks


% can be generated from block_size as specified by the user. If not,
% zero-pad the stream to make this true
[padded_data no_of_blocks]=do_padding(data_source, block_size);

% 3. Perform QPSK modulation


qpsk_modulated_data = pskmod(padded_data, M);
scatterplot(qpsk_modulated_data);title('QPSK Modulation')

% 4. Do IFFT on each block


% Make the serial stream a matrix where each column represents a pre-OFDM
% block (w/o cyclic prefixing)
% First: Find out the number of colums that will exist after reshaping
num_cols=length(qpsk_modulated_data)/block_size;
padded_data_matrix = reshape(qpsk_modulated_data, block_size, num_cols);

% Second: Create empty matix to put the IFFT'd data


cp_start = block_size-cp_len;
cp_end = block_size;

% Third: Operate columnwise & do CP


for i=1:num_cols,
ifft_data_matrix(:,i) = ifft((padded_data_matrix(:,i)),no_of_ifft_points);
% Compute and append Cyclic Prefix
for j=1:cp_len,
actual_cp(j,i) = ifft_data_matrix(j+cp_start,i);
end
% Append the CP to the existing block to create the actual OFDM block
ifft_data(:,i) = vertcat(actual_cp(:,i),ifft_data_matrix(:,i));
end

% 5. Convert to serial stream for transmission


[rows_ifft_data cols_ifft_data]=size(ifft_data);
len_ofdm_data = rows_ifft_data*cols_ifft_data;

% Actual OFDM signal to be transmitted


ofdm_signal = reshape(ifft_data, 1, len_ofdm_data);
figure(3)
plot(real(ofdm_signal)); xlabel('Time'); ylabel('Amplitude');
title('OFDM Signal');grid on;

% --------------------------------
% C: % +++++ CHANNEL +++++
% --------------------------------
% Create a complex multipath channel
%+++channel = randn(1,block_size) + sqrt(-1)*randn(1,block_size);

% ------------------------------------------
% D: % +++++ RECEIVER TAIL END +++++
% ------------------------------------------
%
% 1. Generate random complex noise
%+++noise = randn(1,len_ofdm_data) + sqrt(-1)*randn(1,len_ofdm_data);

% 2. Pass the ofdm signal through the channel


%++after_channel = filter(channel, 1, ofdm_signal);

% 3. Add noise to signal...


%++recvd_signal = after_channel + noise;
recvd_signal = ofdm_signal;

% 4. Convert Data back to "parallel" form to perform FFT


recvd_signal_matrix = reshape(recvd_signal,rows_ifft_data, cols_ifft_data);

% 5. Remove CP
recvd_signal_matrix(1:cp_len,:)=[];

% 6. Perform FFT
for i=1:cols_ifft_data,
% FFT
fft_data_matrix(:,i) = fft(recvd_signal_matrix(:,i),no_of_fft_points);
end

% 7. Convert to serial stream


recvd_serial_data = reshape(fft_data_matrix, 1,(block_size*num_cols));

% 8. Demodulate the data


qpsk_demodulated_data = pskdemod(recvd_serial_data,M);

figure(4)
stem(data_source)
hold on
stem(qpsk_demodulated_data,'rx');
grid on;xlabel('Data Points');ylabel('Amplitude');title('Received Data "X"')

OFDM Version 0.13

I have further added a very simple Linear Equalizer to the code, where I
assume that the channel is perfectly known. Note that for equalization to work
here, the prefix length must be equal to or greater than the length of the
channel.
 
Afterwards, I added some AWGN noise to the received data. The figures
below shows some of the results.
 
See the code ofdm_013

 
Results of running this script:
 

Fig. 1. Superposition of TX (blue) & RX (red) data after channel effects and equalization
 
Fig. 2. Same data stream with 0 dB AWGN
 

Fig. 3. Notice that as the SNR increases the number of errors will decrease
clear all
clc
close % closes any open figures
%
% OFDM System Version 0.13
% Created on September 20, 2004 by Surujlal Dasrath
%
% ** New in Version 0.13 **
% 1. Added channel effects, i.e the channel is an FIR filter
% 2. Equalization after data passes through randomly generated channel
% 3. Implementation of AWGN noise after channel effects
% 3. Calculated Number of Errors and Bit Error Rate

% ---------------
% A: Definitions
% ---------------
M = 4; % QPSK signal constellation
no_of_data_points = 16; % have 128 data points
block_size = 8; % size of each ofdm block
cp_len = ceil(0.4*block_size); % length of cyclic prefix
no_of_ifft_points = block_size; % 128 points for the FFT/IFFT
no_of_fft_points = block_size;
% ---------------------------------------------
% B: % +++++ TRANSMITTER HEAD END +++++
% ---------------------------------------------
% 1. Generate 1 x 128 vector of random data points
data_source = randsrc(1, no_of_data_points, 0:M-1);
%figure(1)
%stem(data_source); grid on; xlabel('Data Points'); ylabel('Amplitude')
%title('Transmitted Data "O"')

% 2. Call 'do_padding' function to check if an integer number of blocks


% can be generated from block_size as specified by the user. If not,
% zero-pad the stream to make this true
[padded_data no_of_blocks]=do_padding(data_source, block_size);

% 3. Perform QPSK modulation


qpsk_modulated_data = pskmod(padded_data, M);
%scatterplot(qpsk_modulated_data);title('QPSK Modulation')

% 4. Do IFFT on each block


% Make the serial stream a matrix where each column represents a pre-OFDM
% block (w/o cyclic prefixing)
% First: Find out the number of colums that will exist after reshaping
num_cols=length(qpsk_modulated_data)/block_size;
padded_data_matrix = reshape(qpsk_modulated_data, block_size, num_cols);

% Second: Create empty matix to put the IFFT'd data


cp_start = block_size-cp_len;
cp_end = block_size;

% Third: Operate columnwise & do CP


for i=1:num_cols,
ifft_data_matrix(:,i) = ifft((padded_data_matrix(:,i)),no_of_ifft_points);
% Compute and append Cyclic Prefix
for j=1:cp_len,
actual_cp(j,i) = ifft_data_matrix(j+cp_start,i);
end
% Append the CP to the existing block to create the actual OFDM block
ifft_data(:,i) = vertcat(actual_cp(:,i),ifft_data_matrix(:,i));
end

% 5. Convert to serial stream for transmission


[rows_ifft_data cols_ifft_data]=size(ifft_data);
len_ofdm_data = rows_ifft_data*cols_ifft_data;

% Actual OFDM signal to be transmitted


ofdm_signal = reshape(ifft_data, 1, len_ofdm_data);

% 6. Calculate the signal power


signal_power = abs(ofdm_signal);

% --------------------------------
% C: % +++++ CHANNEL +++++
% --------------------------------
% 1. Create a complex multipath channel
channel = randn(1,2) + sqrt(-1)*randn(1,2);

% 2. Pass the ofdm signal through the channel


after_channel = filter(channel, 1, ofdm_signal);

% ------------------------------------------
% D: % +++++ RECEIVER TAIL END +++++
% ------------------------------------------
%
% 3. Add Noise
awgn_noise = awgn(zeros(1,length(after_channel)),0);
noise_power = abs(awgn_noise);

recvd_signal = after_channel; % Without noise


%recvd_signal = awgn_noise+after_channel; % With AWGN noise

% 4. Convert Data back to "parallel" form to perform FFT


recvd_signal_matrix = reshape(recvd_signal,rows_ifft_data, cols_ifft_data);

% 5. Remove CP
recvd_signal_matrix(1:cp_len,:)=[];

% 6. Do Equalization
% Take FFT of the channel & pad it to fit each data block
[pad_chan bl] = do_padding(channel,block_size);
chan_fft = fft(pad_chan,block_size);
chan_fft = reshape(chan_fft,length(chan_fft),1);

[r_recvd_sig_mat c_recvd_sig_mat]=size(recvd_signal_matrix);
for i=1:r_recvd_sig_mat
recvd_signal_matrix(i,:)=recvd_signal_matrix(i,:)./chan_fft(i);
end

% 7. Perform FFT
for i=1:cols_ifft_data,
% FFT
fft_data_matrix(:,i) = fft(recvd_signal_matrix(:,i),no_of_fft_points);
end
% 8. Convert to serial stream
recvd_serial_data = reshape(fft_data_matrix, 1,(block_size*num_cols));

% 9. Demodulate the data


qpsk_demodulated_data = pskdemod(recvd_serial_data,M);

figure(4)
stem(data_source)
hold on
stem(qpsk_demodulated_data,'rx');
grid on;xlabel('Data Points');ylabel('Amplitude');
title('Received Data "x"- with Channel Effects')

% --------------------------------------------
% E: % +++++ CALCULATE BIT ERROR +++++
% --------------------------------------------
[no_of_errors ber]=biterr(data_source,qpsk_demodulated_data)
existing_blocks =

no_of_errors =

ber =

0.2813

Potrebbero piacerti anche