Getting Started with 5G Toolkit
This is first quick and simple tutorial for getting newbies started with 5G Toolkit. The tutorial is organized as follows:
Import Python Librariers
This tutorial will simulation the following setup
Import Python Libraries
[1]:
import toolkit5G as tk
tk.__version__
2023-07-29 19:08:21.651000: I tensorflow/core/util/port.cc:110] oneDNN custom operations are on. You may see slightly different numerical results due to floating-point round-off errors from different computation orders. To turn them off, set the environment variable `TF_ENABLE_ONEDNN_OPTS=0`.
2023-07-29 19:08:21.779554: I tensorflow/core/platform/cpu_feature_guard.cc:182] This TensorFlow binary is optimized to use available CPU instructions in performance-critical operations.
To enable the following instructions: AVX2 AVX512F AVX512_VNNI FMA, in other operations, rebuild TensorFlow with the appropriate compiler flags.
2023-07-29 19:08:22.478801: W tensorflow/compiler/tf2tensorrt/utils/py_utils.cc:38] TF-TRT Warning: Could not find TensorRT
[1]:
'R23a.0.10'
[1]:
import os
os.environ["CUDA_VISIBLE_DEVICES"] = "-1"
os.environ['TF_CPP_MIN_LOG_LEVEL'] = '3'
import numpy as np
# %matplotlib widget
import matplotlib.pyplot as plt
Import 5G Toolkit Libraries
[2]:
import sys
sys.path.append("../")
from toolkit5G.CRC import CRCEncoder
from toolkit5G.CRC import CRCDecoder
from toolkit5G.SymbolMapping import Mapper
from toolkit5G.SymbolMapping import Demapper
from toolkit5G.ChannelProcessing import AddNoise
[3]:
# from IPython.display import display, HTML
# display(HTML("<style>.container { width:80% !important; }</style>"))
Create Objects
CRC Encoder: toolkit5G.CRC.CRCEncoder
CRC Decoder: toolkit5G.CRC.CRCDecoder
QAM Mapper: toolkit5G.SymbolMapping.Mapper
QAM Demapper:toolkit5G.SymbolMapping.Demapper
AWGN Channel:toolkit5G.ChannelProcessing.AddNoise
[4]:
num_bits_per_symbol = 4
demapping_method = "app"
crcEncoder = CRCEncoder(crcType="CRC24C") # Create object of CRC Encoder
crcDecoder = CRCDecoder("CRC24C") # Create object of CRC Decoder
qamMapper = Mapper("qam",num_bits_per_symbol) # Create Mapper Object
qamDemapper = Demapper(demapping_method = "app",
constellation_type="qam",
num_bits_per_symbol = num_bits_per_symbol,
hard_out = True) # Create Demapper Object
awgn = AddNoise()
Payload Bits Generation and Encoding
The payload bits are segregated into blocks where each block has a certain number of bits.
[5]:
numBlocks = 100
nBitsPerBlock = 384
bits = np.random.randint(0, 2, size = (numBlocks,nBitsPerBlock)) # Bits to be Encoded
crcBits = crcEncoder(bits)
Symbol Mapper
Maps the bits to symbols
The order of mapping (modulation order) is set on to the object itself.
[6]:
symbols = qamMapper(crcBits)
AWGN Channel
Pass the symbols to be passed through the noisy channel.
Control the amount of noise to be added.
[7]:
snr = 100
rxsymbols = awgn(symbols, (1/snr))
Demapping the Symbols
Demaps the bits to symbols
The order of mapping (modulation order) is set on to the object itself.
[8]:
bitsEst = qamDemapper([np.complex64(rxsymbols), 1/snr])
CRC Decoder: Error Detection
Remove the CRC bits
Compute CRC check: Wheather all the bits in a blocks are correct or not.
[9]:
rBits, checks = crcDecoder(bitsEst)
BER and Block Error Computation
Compute the
block error rate: \(\frac{\text{blocks in Error}}{\text{Total number of blocks}}\)
bit error rate: \(\frac{\text{bits in Error}}{\text{Total number of bits}}\)
[10]:
ber = np.mean(np.abs(bits-rBits))
bler= 1-np.mean(checks)
print(" Bit error rate = "+str(ber))
print("Block error rate = "+str(bler))
Bit error rate = 0.0
Block error rate = 0.0
Constellation Diagram
Compare the constellation of the transmitted and received (noisy) symbols.
[11]:
fig, ax = plt.subplots()
ax.set_aspect(True)
ax.scatter(np.real(rxsymbols), np.imag(rxsymbols), color = "red", marker=".", s=2, label="Received Symbols")
ax.scatter(np.real(symbols), np.imag(symbols), color = "blue", label="Transmitted Symbols")
ax.set_xlabel("Real part $\mathfrak{R} \{x\}$")
ax.set_ylabel("Imaginary part $\mathfrak{I} \{x\}$")
ax.set_title("Contellation Diagram for 16-QAM symbols")
ax.grid(which='both')
ax.legend(loc="best")
plt.savefig("Constellation.svg", dpi=9600, transparent=True, format="svg")
plt.show()
Link Level Simulation
Key performance parameters:
Block error rate
Bit error rate.
Parameters of simulations:
x-label: Signal to noise ratio (SNR)
y-label: BER/BLER
Variables: Modulation order
2: QPSK
4: 16-QAM
6: 64-QAM
Simulation Setup
[12]:
crcEncoder = CRCEncoder(crcType="CRC24C") # Create object of CRC Encoder
crcDecoder = CRCDecoder("CRC24C") # Create object of CRC Decoder
awgn = AddNoise()
SNRdB = np.linspace(0,25,10)
SNR = 10**(SNRdB/10)
modOrder = np.array([2,4,6], dtype=np.int32)
ber = np.zeros((modOrder.size, SNR.size))
bler = np.zeros((modOrder.size, SNR.size))
numBlocks = 10000
nBitsPerBlock = 384
i = 0
j = 0
for m in modOrder:
qamMapper = Mapper("qam",int(m)) # Create Mapper Object
qamDemapper = Demapper(demapping_method = "app",
constellation_type="qam",
num_bits_per_symbol = int(m),
hard_out = True) # Create Demapper Object
bits = np.random.randint(0, 2, size = (numBlocks,nBitsPerBlock)) # Bits to be Encoded
crcBits = crcEncoder(bits)
symbols = qamMapper(crcBits)
j = 0
for snr in SNR:
rxsymbols = awgn(symbols, (1/snr))
bitsEst = qamDemapper([np.complex64(rxsymbols), np.float32(1/snr)])
rBits, checks = crcDecoder(bitsEst)
ber[i,j] = np.mean(np.abs(bits-rBits))
bler[i,j] = 1-np.mean(checks)
print("For modOrder = "+str(m)+" | snr = "+str(snr)+" Bit error rate = "+str(ber[i,j]))
print("For modOrder = "+str(m)+" | snr = "+str(snr)+"Block error rate = "+str(bler[i,j]))
j = j + 1
i = i + 1
For modOrder = 2 | snr = 1.0 Bit error rate = 0.15873515625
For modOrder = 2 | snr = 1.0Block error rate = 1.0
For modOrder = 2 | snr = 1.8957356524063758 Bit error rate = 0.08426328125
For modOrder = 2 | snr = 1.8957356524063758Block error rate = 1.0
For modOrder = 2 | snr = 3.5938136638046276 Bit error rate = 0.029006510416666666
For modOrder = 2 | snr = 3.5938136638046276Block error rate = 1.0
For modOrder = 2 | snr = 6.812920690579611 Bit error rate = 0.004522395833333333
For modOrder = 2 | snr = 6.812920690579611Block error rate = 0.8428
For modOrder = 2 | snr = 12.91549665014884 Bit error rate = 0.00016276041666666666
For modOrder = 2 | snr = 12.91549665014884Block error rate = 0.06489999999999996
For modOrder = 2 | snr = 24.484367468222267 Bit error rate = 7.8125e-07
For modOrder = 2 | snr = 24.484367468222267Block error rate = 0.00029999999999996696
For modOrder = 2 | snr = 46.41588833612777 Bit error rate = 0.0
For modOrder = 2 | snr = 46.41588833612777Block error rate = 0.0
For modOrder = 2 | snr = 87.99225435691065 Bit error rate = 0.0
For modOrder = 2 | snr = 87.99225435691065Block error rate = 0.0
For modOrder = 2 | snr = 166.81005372000593 Bit error rate = 0.0
For modOrder = 2 | snr = 166.81005372000593Block error rate = 0.0
For modOrder = 2 | snr = 316.22776601683796 Bit error rate = 0.0
For modOrder = 2 | snr = 316.22776601683796Block error rate = 0.0
For modOrder = 4 | snr = 1.0 Bit error rate = 0.28259557291666665
For modOrder = 4 | snr = 1.0Block error rate = 1.0
For modOrder = 4 | snr = 1.8957356524063758 Bit error rate = 0.21662265625
For modOrder = 4 | snr = 1.8957356524063758Block error rate = 1.0
For modOrder = 4 | snr = 3.5938136638046276 Bit error rate = 0.1511671875
For modOrder = 4 | snr = 3.5938136638046276Block error rate = 1.0
For modOrder = 4 | snr = 6.812920690579611 Bit error rate = 0.09119765625
For modOrder = 4 | snr = 6.812920690579611Block error rate = 1.0
For modOrder = 4 | snr = 12.91549665014884 Bit error rate = 0.04033958333333333
For modOrder = 4 | snr = 12.91549665014884Block error rate = 1.0
For modOrder = 4 | snr = 24.484367468222267 Bit error rate = 0.010061197916666667
For modOrder = 4 | snr = 24.484367468222267Block error rate = 0.9855
For modOrder = 4 | snr = 46.41588833612777 Bit error rate = 0.0008690104166666667
For modOrder = 4 | snr = 46.41588833612777Block error rate = 0.2984
For modOrder = 4 | snr = 87.99225435691065 Bit error rate = 8.333333333333334e-06
For modOrder = 4 | snr = 87.99225435691065Block error rate = 0.0032999999999999696
For modOrder = 4 | snr = 166.81005372000593 Bit error rate = 0.0
For modOrder = 4 | snr = 166.81005372000593Block error rate = 0.0
For modOrder = 4 | snr = 316.22776601683796 Bit error rate = 0.0
For modOrder = 4 | snr = 316.22776601683796Block error rate = 0.0
For modOrder = 6 | snr = 1.0 Bit error rate = 0.3536518229166667
For modOrder = 6 | snr = 1.0Block error rate = 1.0
For modOrder = 6 | snr = 1.8957356524063758 Bit error rate = 0.3059221354166667
For modOrder = 6 | snr = 1.8957356524063758Block error rate = 1.0
For modOrder = 6 | snr = 3.5938136638046276 Bit error rate = 0.24816536458333333
For modOrder = 6 | snr = 3.5938136638046276Block error rate = 1.0
For modOrder = 6 | snr = 6.812920690579611 Bit error rate = 0.18723645833333333
For modOrder = 6 | snr = 6.812920690579611Block error rate = 1.0
For modOrder = 6 | snr = 12.91549665014884 Bit error rate = 0.1307921875
For modOrder = 6 | snr = 12.91549665014884Block error rate = 1.0
For modOrder = 6 | snr = 24.484367468222267 Bit error rate = 0.08174973958333333
For modOrder = 6 | snr = 24.484367468222267Block error rate = 1.0
For modOrder = 6 | snr = 46.41588833612777 Bit error rate = 0.040142447916666664
For modOrder = 6 | snr = 46.41588833612777Block error rate = 1.0
For modOrder = 6 | snr = 87.99225435691065 Bit error rate = 0.011923697916666667
For modOrder = 6 | snr = 87.99225435691065Block error rate = 0.9943
For modOrder = 6 | snr = 166.81005372000593 Bit error rate = 0.0014354166666666667
For modOrder = 6 | snr = 166.81005372000593Block error rate = 0.43820000000000003
For modOrder = 6 | snr = 316.22776601683796 Bit error rate = 2.96875e-05
For modOrder = 6 | snr = 316.22776601683796Block error rate = 0.01200000000000001
Performance Evaluations
Display BER/BLER vs SNR.
[13]:
fig,ax = plt.subplots(1,2, figsize=(15,6))
ls = [":*","-o","--P"]
for i in np.arange(modOrder.size):
ax[0].semilogy(SNRdB, ber[i], ls[i], lw=3, ms=9)
ax[1].semilogy(SNRdB, bler[i], ls[i], lw=3, ms=9)
ax[0].set_xlabel("SNR (dB)")
ax[0].set_ylabel("Bit error rate")
ax[0].set_title("BER vs SNR (dB) for different modulation order")
ax[0].set_xticks(SNRdB, minor=False);
ax[0].grid(which='both')
ax[0].legend(["QPSK","16QAM","64QAM"])
ax[1].set_xlabel("SNR (dB)")
ax[1].set_ylabel("Block error rate")
ax[1].set_title("BLER vs SNR (dB) for different modulation order")
ax[1].set_xticks(SNRdB, minor=False);
ax[1].grid(which='both')
ax[1].legend(["QPSK","16QAM","64QAM"])
plt.savefig("BERvsSNR.svg", dpi=9600, transparent=True, format="svg")
plt.show()
[ ]: