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:

  1. Import Python Librariers

  2. Generate the objects required for implementations

  3. Generate Payload (bits/blocks) and CRC encode it.

  4. Symbol Map the encoded bits

  5. Pass symbols through the channels.

  6. Demap the noisy symbols

  7. Compute the CRC Check for block error detection

  8. BER/BLER Computation

  9. Constellation Diagram

  10. Link Level Simulation

This tutorial will simulation the following setup image1

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

[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()
_images/test_GettingStarted_21_0.png

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()
_images/test_GettingStarted_25_0.png
[ ]: