Module DigiCommPy.scripts.chapter_5.isi_equalizers_bpsk

Script: DigiCommPy.chapter_5.isi_equalizers_bpsk.py Demonstration of Eb/N0 Vs SER for baseband BPSK modulation scheme over different ISI channels with MMSE and ZF equalizers

@author: Mathuranathan Viswanathan Created on Aug 29, 2019

Expand source code
"""
Script: DigiCommPy.chapter_5.isi_equalizers_bpsk.py
Demonstration of Eb/N0 Vs SER for baseband BPSK modulation scheme over different ISI channels with MMSE and ZF equalizers

@author: Mathuranathan Viswanathan
Created on Aug 29, 2019
"""
import numpy as np
import matplotlib.pyplot as plt #for plotting functions
from modem import PSKModem #import PSKModem
from channels import awgn
from equalizers import zeroForcing, MMSEEQ #import MMSE equalizer class
from errorRates import ser_awgn #for theoretical BERs
from scipy.signal import freqz
#---------Input Fields------------------------
N=10**6 # Number of bits to transmit
EbN0dBs = np.arange(start=0,stop=30,step=2) #  Eb/N0 range in dB for simulation
M=2 # 2-PSK
#h_c=[0.04, -0.05, 0.07, -0.21, -0.5, 0.72, 0.36, 0.21, 0.03, 0.07] # Channel A
#h_c=[0.407, 0.815, 0.407] # uncomment this for Channel B
h_c=[0.227, 0.460, 0.688, 0.460, 0.227] # uncomment this for Channel C
nTaps = 31 # Desired number of taps for equalizer filter
SER_zf = np.zeros(len(EbN0dBs)); SER_mmse = np.zeros(len(EbN0dBs))
#-----------------Transmitter---------------------
inputSymbols=np.random.randint(low=0,high=2,size=N) #uniform random symbols 0s & 1s
modem = PSKModem(M)
modulatedSyms = modem.modulate(inputSymbols)
x = np.convolve(modulatedSyms,h_c) # apply channel effect on transmitted symbols

for i,EbN0dB in enumerate(EbN0dBs):
    receivedSyms = awgn(x,EbN0dB) #add awgn noise
    
    # DELAY OPTIMIZED MMSE equalizer
    mmse_eq = MMSEEQ(nTaps) #initialize MMSE equalizer (object) of length nTaps
    mmse_eq.design(h_c,EbN0dB) #Design MMSE equalizer
    optDelay = mmse_eq.opt_delay #get the optimum delay of the equalizer
    #filter received symbols through the designed equalizer    
    equalizedSamples = mmse_eq.equalize(receivedSyms)
    y_mmse=equalizedSamples[optDelay:optDelay+N] # samples from optDelay position
    
    # DELAY OPTIMIZED ZF equalizer
    zf_eq = zeroForcing(nTaps) #initialize ZF equalizer (object) of length nTaps
    zf_eq.design(h_c) #Design ZF equalizer
    optDelay = zf_eq.opt_delay #get the optimum delay of the equalizer
    #filter received symbols through the designed equalizer
    equalizedSamples = zf_eq.equalize(receivedSyms)
    y_zf = equalizedSamples[optDelay:optDelay+N] # samples from optDelay position
    
    # Optimum Detection in the receiver - Euclidean distance Method
    estimatedSyms_mmse = modem.demodulate(y_mmse)
    estimatedSyms_zf = modem.demodulate(y_zf)    
    # SER when filtered thro MMSE eq.
    SER_mmse[i]=sum((inputSymbols != estimatedSyms_mmse))/N
    # SER when filtered thro ZF eq.
    SER_zf[i]=sum((inputSymbols != estimatedSyms_zf))/N
        
SER_theory = ser_awgn(EbN0dBs,'PSK',M=2) #theoretical SER

fig1, ax1 = plt.subplots(nrows=1,ncols = 1)
ax1.semilogy(EbN0dBs,SER_zf,'g',label='ZF Equalizer');
ax1.semilogy(EbN0dBs,SER_mmse,'r',label='MMSE equalizer')
ax1.semilogy(EbN0dBs,SER_theory,'k',label='No interference')
ax1.set_title('Probability of Symbol Error for BPSK signals');
ax1.set_xlabel('$E_b/N_0$(dB)');ax1.set_ylabel('Probability of Symbol Error-$P_s$')
ax1.legend(); ax1.set_ylim(bottom=10**-4, top=1);fig1.show()

# compute and plot channel characteristics
Omega, H_c  = freqz(h_c) #frequency response of the channel
fig2, (ax2,ax3) = plt.subplots(nrows=1,ncols = 2)
ax2.stem(h_c,use_line_collection=True) # time domain
ax3.plot(Omega,20*np.log10(abs(H_c)/max(abs(H_c))));fig2.show()