Sample Code Ofdm

17
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:

Transcript of Sample Code Ofdm

Page 1: Sample Code Ofdm

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.040.11 * Incomplete * 09.11.040.12 Generic OFDM with Cyclic Prefixing 09.12.04

0.13Added 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:

 

Page 2: Sample Code Ofdm

Fig. 1. Random input data samples 

Fig. 2. QPSK signal constellation of the input data 

Page 3: Sample Code Ofdm

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

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

Page 4: Sample Code Ofdm

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 dataM = 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. Modulationmsg_tx = pskmod(input, M);scatterplot(msg_tx);

Page 5: Sample Code Ofdm

% 3. Serial to Parallelparallel_mod_data = reshape(msg_tx,8,8);

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

% 5. Parallel to serialofdm_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 Parallelofdm_msg_rx = reshape(ofdm_msg_tx, 8,8);

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

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

% 4. Demodulationmsg_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% =======================================================================%% ---------------

Page 6: Sample Code Ofdm

% A: Definitions% ---------------M = 4; % use M=4 for QPSK modulationno_of_data_points = 64; % have 64 data pointsno_of_channels = no_of_data_points/8; % make each symbol block length 8

% 1. Generate 1 x 64 vector of random data pointsdata_source = randsrc(1, no_of_data_points, 0:M-1);

% 2. Perform QPSK modulationqpsk_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 8parallel_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. 

Page 7: Sample Code Ofdm

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 = 4after 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: 

Page 8: Sample Code Ofdm

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 allclcclose % 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 constellationno_of_data_points = 64; % have 128 data pointsblock_size = 8; % size of each ofdm block

Page 9: Sample Code Ofdm

cp_len = ceil(0.1*block_size); % length of cyclic prefixno_of_ifft_points = block_size; % 128 points for the FFT/IFFTno_of_fft_points = block_size;% ---------------------------------------------% B: % +++++ TRANSMITTER HEAD END +++++% ---------------------------------------------% 1. Generate 1 x 128 vector of random data pointsdata_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 modulationqpsk_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 reshapingnum_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 datacp_start = block_size-cp_len;cp_end = block_size;

% Third: Operate columnwise & do CPfor 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 transmittedofdm_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

Page 10: Sample Code Ofdm

%+++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 FFTrecvd_signal_matrix = reshape(recvd_signal,rows_ifft_data, cols_ifft_data);

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

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

% 7. Convert to serial streamrecvd_serial_data = reshape(fft_data_matrix, 1,(block_size*num_cols));

% 8. Demodulate the dataqpsk_demodulated_data = pskdemod(recvd_serial_data,M);

figure(4)stem(data_source)hold onstem(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. 

Page 11: Sample Code Ofdm

See the code ofdm_013

 Results of running this script: 

Fig. 1. Superposition of TX (blue) & RX (red) data after channel effects and equalization 

Page 12: Sample Code Ofdm

Fig. 2. Same data stream with 0 dB AWGN 

Fig. 3. Notice that as the SNR increases the number of errors will decrease

Page 13: Sample Code Ofdm

clear allclcclose % 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 constellationno_of_data_points = 16; % have 128 data pointsblock_size = 8; % size of each ofdm blockcp_len = ceil(0.4*block_size); % length of cyclic prefixno_of_ifft_points = block_size; % 128 points for the FFT/IFFTno_of_fft_points = block_size;% ---------------------------------------------% B: % +++++ TRANSMITTER HEAD END +++++% ---------------------------------------------% 1. Generate 1 x 128 vector of random data pointsdata_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 modulationqpsk_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 reshapingnum_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 datacp_start = block_size-cp_len;cp_end = block_size;

% Third: Operate columnwise & do CPfor 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);

Page 14: Sample Code Ofdm

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 transmittedofdm_signal = reshape(ifft_data, 1, len_ofdm_data);

% 6. Calculate the signal powersignal_power = abs(ofdm_signal);

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

% 2. Pass the ofdm signal through the channelafter_channel = filter(channel, 1, ofdm_signal);

% ------------------------------------------% D: % +++++ RECEIVER TAIL END +++++% ------------------------------------------%% 3. Add Noiseawgn_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 FFTrecvd_signal_matrix = reshape(recvd_signal,rows_ifft_data, cols_ifft_data);

% 5. Remove CPrecvd_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 FFTfor i=1:cols_ifft_data, % FFT fft_data_matrix(:,i) = fft(recvd_signal_matrix(:,i),no_of_fft_points);end

Page 15: Sample Code Ofdm

% 8. Convert to serial streamrecvd_serial_data = reshape(fft_data_matrix, 1,(block_size*num_cols));

% 9. Demodulate the dataqpsk_demodulated_data = pskdemod(recvd_serial_data,M);

figure(4)stem(data_source)hold onstem(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 =

0

no_of_errors =

9

ber =

0.2813