Continuous Learning N. Metternich 3/10/2024 The crux of the modeling of BPSK is the use of the DigiCommPy\passband.py\bpsk_mod function: """ Passband simulation models - modulation and demodulation techniques (Chapter 2) @author: Mathuranathan Viswanathan Created on Jul 17, 2019 """ import numpy as np import matplotlib.pyplot as plt def bpsk_mod(ak,L): """ Function to modulate an incoming binary stream using BPSK (baseband) Parameters: ak : input binary data stream (0's and 1's) to modulate L : oversampling factor (Tb/Ts) Returns: (s_bb,t) : tuple of following variables s_bb: BPSK modulated signal(baseband) - s_bb(t) t : generated time base for the modulated signal """ from scipy.signal import upfirdn s_bb = upfirdn(h=[1]*L, x=2*ak-1, up = L) # NRZ encoder t=np.arange(start = 0,stop = len(ak)*L) #discrete time base return (s_bb,t) def bpsk_demod(r_bb,L): """ Function to demodulate a BPSK (baseband) signal Parameters: r_bb : received signal at the receiver front end (baseband) L : oversampling factor (Tsym/Ts) Returns: ak_hat : detected/estimated binary stream """ x = np.real(r_bb) # I arm x = np.convolve(x,np.ones(L)) # integrate for Tb duration (L samples) x = x[L-1:-1:L] # I arm - sample at every L ak_hat = (x > 0).transpose() # threshold detector return ak_hat Continuous Learning N. Metternich 3/10/2024 Not really sure what the scipy.signal\upfirdn function is doing; nor what the system transfer function, h = “ones” of length L is about. Need to study this to see what happens when an MSK signal is modeled: sure hope it is! Edited the BPSK Performance example. I think I started with Started with the “perf_bpsk_demo.py” under folder “Chapter 2”. Also set the Path statement to the highlighted directory so VS Code would find the stuff under “DIGICOMMPY”. I re-compiled all the files and deleted those .pcy starting with initial since I don’t know how Python uses one file or another. C:\Users\norbert.metternich\Documents\projects\python>tree DigiCommPy Folder PATH listing Volume serial number is EA30-38DC C:\USERS\NORBERT.METTERNICH\DOCUMENTS\PROJECTS\PYTHON\DIGICOMMPY ├───.vscode ├───chapter_1 │ ├───snippets │ │ └───__pycache__ │ └───__pycache__ ├───chapter_2 │ └───__pycache__ ├───chapter_4 │ └───__pycache__ ├───chapter_5 │ └───__pycache__ ├───chapter_6 │ └───__pycache__ └───__pycache__ (1) reduced the plot size so it would finish in a timely manneradded a directive to use the axis labels had some errors: don’t know how it ever worked for the author. ''' File: nhm_student_chapter2_bpsk_performance_demo.py @student: Norbert Metternich Last edit on March 10, 2024 ''' """ Performance of BPSK tx/rx chain (waveform simulation) @author: Mathuranathan Viswanathan Created on Jul 18, 2019 """ Continuous Learning N. Metternich 3/10/2024 #Use of exec is frowned upon. #Execute in Python3: exec(open("chapter_2/bpsk.py").read()) # %% # Import program components/initialize data import numpy as np #for numerical computing import matplotlib matplotlib.use('TkAgg') # or any other backend that supports LaTeX import matplotlib.pyplot as plt #for plotting functions #plt.rcParams.update(plt.rcParamsDefault) from passband_modulations import bpsk_mod, bpsk_demod from channels import awgn from nhm_user_control import prompt_to_continue from scipy.special import erfc from numpy import sum,isrealobj,sqrt from numpy.random import standard_normal N=100000 # Number of symbols to transmit EbN0dB = np.arange(start=-4,stop = 11,step = 2) # Eb/N0 range in dB for simulation L=16 # oversampling factor,L=Tb/Ts(Tb=bit period,Ts=sampling period) # if a carrier is used, use L = Fs/Fc, where Fs >> 2xFc Fc=800 # carrier frequency Fs=L*Fc # sampling frequency BER = np.zeros(len(EbN0dB)) # for BER values for each Eb/N0 ak = np.random.randint(2, size=N) # uniform random symbols from 0's and 1's (s_bb,t)= bpsk_mod(ak,L) # BPSK modulation(waveform) - baseband s = s_bb*np.cos(2*np.pi*Fc*t/Fs) # with carrier # %% # Waveforms at the transmitter # The author said plot the first 10 bis - so find the indexes for that: fst10=np.arange(start=0,stop=L*10,step=1) fig1, axs = plt.subplots(2, 2) axs[0, 0].plot(t[fst10],s_bb[fst10]) # baseband wfm zoomed to first 10 bits axs[0, 0].set_xlabel('t(s)') axs[0, 0].set_ylabel(r'$s_{bb}(t)$-baseband') axs[0, 1].plot(t[fst10],s[fst10]) # transmitted wfm zoomed to first 10 bits Continuous Learning N. Metternich 3/10/2024 axs[0, 1].set_xlabel('t(s)') axs[0, 1].set_ylabel('s(t)-with carrier') axs[0, 1].set_xlim(0,10*L) axs[0, 1].set_xlim(0,10*L) # The signals are not complex - so, the imaginary part is always zero! #signal constellation at transmitter axs[1, 0].plot(np.real(s_bb[fst10]),np.imag(s_bb[fst10]),'o') axs[1, 0].set_xlim(-1.5,1.5) axs[1, 0].set_ylim(-1.5,1.5) axs[1, 0].set_xlabel(r'Re($s_{bb}$)') axs[1, 0].set_ylabel(r'Im($s_{bb}$)') plt.tight_layout() fig1.show() for i,EbN0 in enumerate(EbN0dB): # Compute and add AWGN noise r = awgn(s,EbN0,L) # refer Chapter section 4.1 r_bb = r*np.cos(2*np.pi*Fc*t/Fs) # recovered baseband signal ak_hat = bpsk_demod(r_bb,L) # baseband correlation demodulator BER[i] = np.sum(ak !=ak_hat)/N # Bit Error Rate Computation # Received signal waveform zoomed to first 10 bits axs[1, 1].plot(t[fst10],r[fst10]) # received signal (with noise) axs[1, 1].set_xlabel('t(s)') axs[1, 1].set_ylabel('r(t)') axs[1, 1].set_xlim(0,10*L) plt.tight_layout() fig1.show() #------Theoretical Bit/Symbol Error Rates------------theoreticalBER = 0.5*erfc(np.sqrt(10**(EbN0dB/10))) # Theoretical bit error rate #-------------Plots--------------------------fig2, ax1 = plt.subplots(nrows=1,ncols = 1) ax1.semilogy(EbN0dB,BER,'k*',label='Simulated') # simulated BER ax1.semilogy(EbN0dB,theoreticalBER,'r-',label='Theoretical') ax1.set_xlabel(r'$E_b/N_0$ (dB)') ax1.set_ylabel(r'Probability of Bit Error - $P_b$') ax1.set_title('Probability of Bit Error for BPSK modulation') Continuous Learning N. Metternich 3/10/2024 plt.tight_layout() ax1.legend() fig2.show() # ChatGPT module #if prompt_to_continue(): # print("Continuing...") #else: # print("Exiting...") ## %% # %% The Python file I was using appeared to have a problem pointing to the correct subplot; and either I messed it all up or it was messed up from the start. Instead of having xlabel and ylabel statements on the same line, I placed them underneath one another and cleaned up the handles (which I may have broken to begin with). Note: the “Constellation” in the bottom left shows that the BPSK is comprised of phases at 180 and +180-degrees. I have used +90 and +270 (anything that is orthogonal for BPSK -- I think works – for Matlab auto-correlation and I am pretty sure that is OK to do. This communications toolbox is true to either a signal at base-band (bb) or a signal up-converted to a carrier (fC) frequency. I have a concern that that frequencies that result MSK should be orthogonal to one another; that is the modulation that produces the hopefully the RF of one symbol period or one half symbol period (if I have the nomenclature right) results in orthogonal frequencies. This concern is based on a discussion on BFSK in “wirelesspiminimum-shift-keying-msk-a-tutorial.pdf” by Qasim Chaudhari which may or may not relate to MSK. Continuous Learning N. Metternich 3/10/2024 Continuous Learning N. Metternich 3/10/2024