OFDM is a multi-carrier transmission scheme used in WiMAX and WLAN standards.
It was introduced in the IEE 802.11a physical layer specification and later introduced in the IEEE 802.16-2004 physical layer.
Its OFDMA variant is widely used in 4G LTE system and later versions of cellular standards.
WIMAX OFDM Physical Transmitter
Transmitter modules which include Scrambler, EFC encoder, interleaver, data modulation, IFFT, CP insertion etc. Receiver consists of reverse functionalities of transmitter modules. In addition receiver has time offset/frequency offset correction and channel equalization modules.
Python Script – OFDM Code
# Python Library import
import random
import numpy as np
import matplotlib.pyplot as plt
from scipy.fftpack import fft, ifft, ifftshift
# Step1 : WiMaX OFDM 256 Parameters configuration for simulation
dataCarriers = 192 # Number of data sub carriers in a symbol
mu = 2 # bits per symbol for QPSK modulation type (mu = 4 for 16QAM, mu = 6 for 64QAM)
payloadBits_per_OFDM = dataCarriers * mu # number of payload bits per OFDM symbol 192*2 = 384 bits
input_data = ""
len1 = payloadBits_per_OFDM # length of input data
pilot = [1, -1, 1, -1, -1, -1, 1, 1] # 8 Nos. pilot sub carriers
pilot_pop = [41, 66, 91, 116, 142, 167, 192, 217] # Positions of pilot sub carriers in OFDM symbol
mode = 2 # Modulation Order for QPSK
mapping_table = {
0: 0.7071 + 0.7071j,
1: - 0.7071 + 0.7071j,
2: 0.7071 - 0.7071j,
3: - 0.7071 - 0.7071j}
# Step 2 : Binary data generation for 1 symbol data carriers i.e. 384 bits
for i in range(len1):
temp1 = str(random.randint(0, 1))
input_data += temp1
print(input_data)
# Step-3: Converting binary vector into group of 2 bits (as per QPSK) and
# map the same as per mapping table
s1 = input_data
s2 = []
chunks = [s1[i:i+mode] for i in range(0, len(s1), mode)]
for piece in chunks:
temp = int(piece, 2)
s2.append(temp)
print(s2)
Q = np.zeros((192,), dtype=complex)
j = 0
for val in s2:
Q[j] = mapping_table[val]
j += 1
print(Q)
# Step 4 : Arranging data sub carriers as per WiMAX OFDM symbol format
list1 = [i for i in range(29, 41)]
list2 = [i for i in range(42, 66)]
list3 = [i for i in range(67, 91)]
list4 = [i for i in range(92, 116)]
list5 = [i for i in range(117, 129)]
list6 = [i for i in range(130, 142)]
list7 = [i for i in range(143, 167)]
list8 = [i for i in range(168, 192)]
list9 = [i for i in range(193, 217)]
list10 = [i for i in range(218, 230)]
list = list1 + list2 + list3 + list4 + list5 + list6 + list7 + list8 + list9 + list10
# print(list)
dummy = [0 for element in range(256)]
print('all zeros:', dummy)
# Step 5 : Modulation values (to data sub carriers) and pilot values (to pilot sub carriers) insertion
i = 0
for val1 in list:
dummy[val1] = Q[i]
i += 1
print('complex value inserted:', dummy)
i = 0
for val2 in pilot_pop:
dummy[val2] = pilot[i]
i += 1
print('pilot values inserted:', dummy)
# Step 6 : Inverse fourier transform for size 256 for entire symbol
N =256
OFDM_sym = ifft(dummy, N)
CP =16 # Cyclic prefix of 16 samples
CP_samples = OFDM_sym[N-CP:] # extraction of CP samples from symbol
OFDM_sym_cp = np.append([CP_samples], [OFDM_sym]) # Concatenate CP and Symbol
x = ifftshift(OFDM_sym_cp)
# Initialise the subplot function
figure, axis = plt.subplots(2, 2)
# For Built in convolution
axis[0,0].plot(Q.real, Q.imag, 'bo')
axis[0,0].set_title("QPSK Constellation Diagram")
# For Our own function
axis[0,1].plot(dummy, 'ro')
axis[0,1].set_title("# Sub-carriers: Data(192),Pilot(8),Null(55),DC(1)")
axis[1, 0].plot(OFDM_sym)
axis[1, 0].set_title("1 symbol OFDM power (After IFFT) vs time")
Xfft = fft(OFDM_sym, 256)
axis[1, 1].plot(abs(Xfft))
axis[1, 1].set_title("OFDM absolute value (After FFT) vs frequency")
plt.show()
Output