HARQ event callback
This notebook shows how to define and use a HARQ event callback.
[1]:
import numpy as np
import time
from neoradium import LdpcEncoder, HarqEntity, random, Modem
from neoradium.utils import toLinear
Creating an LDPC Encoder object
[2]:
modulation="16QAM" # Modulation scheme
codeRate = 490/1024 # Target code rate
numLayers = 1 # To test this with 2 codewords, set this to a value between 5 and 8
ldpcEncoder = LdpcEncoder(baseGraphNo=1, modulation=modulation, txLayers=numLayers, targetRate=codeRate)
ldpcEncoder.print() # Print the LDPC encoder's properties
LDPC Encoder Properties:
Base Graph: 1
Modulation: 16QAM
Number of layers: 1
Target Rate: 0.478515625
Defining a callback function and passing it to the HARQ entity
[3]:
# Define a simple call back function which prints the event information:
def handleEvents(event, harqCW):
# event: The event string. It can be one of ”RXFAILED”, ”RXSUCCESS”, or ”TIMEOUT”
# harqCW: The instance of HarqCW class that triggered the event
print(f"HARQ Process {harqCW.process.id} CW{harqCW.cwIdx+1}: {event:10s} curTry: {harqCW.curTry} RV: {harqCW.rv} TxBlock: {harqCW.txBlockNo}")
# Create the HARQ entity with "Chase Combining" and 8 processes
harq = HarqEntity(ldpcEncoder, harqType="CC", numProc=8, eventCallback=handleEvents)
Main transmission loop
[4]:
ebNoDb = 3 # Set the Eb/No ratio (dB)
snrDb = ebNoDb + 10*np.log10(ldpcEncoder.qm * codeRate) # Convert Eb/No to SNR (dB)
snr = toLinear(snrDb) # Linear SNR
noiseStd = np.sqrt(1/snr) # Noise standard deviation
rangen = random.getGenerator(123) # Create new random generator and make results reproducible
modem = Modem(modulation) # The Modem instance used for modulation/demodulation
numTransmissions = 50 # Total number of transmissions
txBlockSizes = harq.numCW*[10000] # Transport block sizes. One per codeword.
harq.reset() # Reset HARQ for each execution of this cell
for t in range(numTransmissions): # Run this "numTransmissions" times
txBlocks = [] # Transport blocks. One per codeword.
for c in range(harq.numCW):
if harq.needNewData[c]: # New transmission.
txBlocks += [ random.bits(txBlockSizes[c]) ] # Create random bits for the new transport block
else: # Retransmission
txBlocks += [ None ] # Set transport block to None to indicate retransmission
rateMatchedCodeWords = harq.getRateMatchedCodeBlocks(txBlocks) # Prepare the bitstream for transmission
llrs = [] # Received Log-Likelihood Ratios. One per codeword.
for c in range(harq.numCW):
channelOutput = modem.modulate(rateMatchedCodeWords[c]) # Modulate the codeblocks
noisyRxSignal = channelOutput + rangen.awgn(channelOutput.shape, noiseStd) # Add Noise
llrs += [ modem.getLLRsFromSymbols(noisyRxSignal, noiseStd**2) ] # Calculate the LLRs for each codeword
decodedTxBlocks, blockErrors = harq.decodeLLRs(llrs, txBlockSizes)
harq.goNext() # Get ready for the next transmission
harq.printStats() # Print HARQ entity's statistics
HARQ Process 0 CW1: RXFAILED curTry: 0 RV: 0 TxBlock: 0
HARQ Process 1 CW1: RXFAILED curTry: 0 RV: 0 TxBlock: 1
HARQ Process 2 CW1: RXFAILED curTry: 0 RV: 0 TxBlock: 2
HARQ Process 3 CW1: RXFAILED curTry: 0 RV: 0 TxBlock: 3
HARQ Process 4 CW1: RXFAILED curTry: 0 RV: 0 TxBlock: 4
HARQ Process 5 CW1: RXFAILED curTry: 0 RV: 0 TxBlock: 5
HARQ Process 6 CW1: RXFAILED curTry: 0 RV: 0 TxBlock: 6
HARQ Process 7 CW1: RXFAILED curTry: 0 RV: 0 TxBlock: 7
HARQ Process 0 CW1: RXSUCCESS curTry: 1 RV: 0 TxBlock: 0
HARQ Process 1 CW1: RXSUCCESS curTry: 1 RV: 0 TxBlock: 1
HARQ Process 2 CW1: RXSUCCESS curTry: 1 RV: 0 TxBlock: 2
HARQ Process 3 CW1: RXSUCCESS curTry: 1 RV: 0 TxBlock: 3
HARQ Process 4 CW1: RXSUCCESS curTry: 1 RV: 0 TxBlock: 4
HARQ Process 5 CW1: RXSUCCESS curTry: 1 RV: 0 TxBlock: 5
HARQ Process 6 CW1: RXSUCCESS curTry: 1 RV: 0 TxBlock: 6
HARQ Process 7 CW1: RXSUCCESS curTry: 1 RV: 0 TxBlock: 7
HARQ Process 0 CW1: RXFAILED curTry: 0 RV: 0 TxBlock: 8
HARQ Process 1 CW1: RXFAILED curTry: 0 RV: 0 TxBlock: 9
HARQ Process 2 CW1: RXFAILED curTry: 0 RV: 0 TxBlock: 10
HARQ Process 3 CW1: RXFAILED curTry: 0 RV: 0 TxBlock: 11
HARQ Process 4 CW1: RXFAILED curTry: 0 RV: 0 TxBlock: 12
HARQ Process 5 CW1: RXFAILED curTry: 0 RV: 0 TxBlock: 13
HARQ Process 6 CW1: RXFAILED curTry: 0 RV: 0 TxBlock: 14
HARQ Process 7 CW1: RXFAILED curTry: 0 RV: 0 TxBlock: 15
HARQ Process 0 CW1: RXSUCCESS curTry: 1 RV: 0 TxBlock: 8
HARQ Process 1 CW1: RXSUCCESS curTry: 1 RV: 0 TxBlock: 9
HARQ Process 2 CW1: RXSUCCESS curTry: 1 RV: 0 TxBlock: 10
HARQ Process 3 CW1: RXSUCCESS curTry: 1 RV: 0 TxBlock: 11
HARQ Process 4 CW1: RXSUCCESS curTry: 1 RV: 0 TxBlock: 12
HARQ Process 5 CW1: RXSUCCESS curTry: 1 RV: 0 TxBlock: 13
HARQ Process 6 CW1: RXSUCCESS curTry: 1 RV: 0 TxBlock: 14
HARQ Process 7 CW1: RXSUCCESS curTry: 1 RV: 0 TxBlock: 15
HARQ Process 0 CW1: RXFAILED curTry: 0 RV: 0 TxBlock: 16
HARQ Process 1 CW1: RXFAILED curTry: 0 RV: 0 TxBlock: 17
HARQ Process 2 CW1: RXFAILED curTry: 0 RV: 0 TxBlock: 18
HARQ Process 3 CW1: RXFAILED curTry: 0 RV: 0 TxBlock: 19
HARQ Process 4 CW1: RXFAILED curTry: 0 RV: 0 TxBlock: 20
HARQ Process 5 CW1: RXFAILED curTry: 0 RV: 0 TxBlock: 21
HARQ Process 6 CW1: RXFAILED curTry: 0 RV: 0 TxBlock: 22
HARQ Process 7 CW1: RXFAILED curTry: 0 RV: 0 TxBlock: 23
HARQ Process 0 CW1: RXSUCCESS curTry: 1 RV: 0 TxBlock: 16
HARQ Process 1 CW1: RXSUCCESS curTry: 1 RV: 0 TxBlock: 17
HARQ Process 2 CW1: RXSUCCESS curTry: 1 RV: 0 TxBlock: 18
HARQ Process 3 CW1: RXSUCCESS curTry: 1 RV: 0 TxBlock: 19
HARQ Process 4 CW1: RXSUCCESS curTry: 1 RV: 0 TxBlock: 20
HARQ Process 5 CW1: RXSUCCESS curTry: 1 RV: 0 TxBlock: 21
HARQ Process 6 CW1: RXSUCCESS curTry: 1 RV: 0 TxBlock: 22
HARQ Process 7 CW1: RXSUCCESS curTry: 1 RV: 0 TxBlock: 23
HARQ Process 0 CW1: RXFAILED curTry: 0 RV: 0 TxBlock: 24
HARQ Process 1 CW1: RXFAILED curTry: 0 RV: 0 TxBlock: 25
HARQ Entity Statistics:
txBits (per try): [260000 240000 0 0]
rxBits (per try): [ 0 240000 0 0]
txBlocks (per try): [26 24 0 0]
rxBlocks (per try): [ 0 24 0 0]
numTimeouts: 0
totalTxBlocks: 50
totalRxBlocks: 24
totalTxBits: 500000
totalRxBits: 240000
throughput: 48.00%
bler: 52.00%
Average Num. Retries: 1.00%
[ ]:
[ ]: