I think this code is very useful and you should read OFDM tutorial from complex to real. Because it was written for beginners.
% 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.
%
soc.li/GLIaMyO% 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
clear, clc, close all
% 1. Generate data 00_0 01_1 10_2 11_3
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 0_1 1_i 2_-1 3_-i
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')