Using HARQ
This notebook shows how to use HARQ functionality in NeoRadium.
[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
Instantiating a HARQ entity object
[3]:
harqType = "IR" # "IR" -> "Incremental Redundancy", "CC" -> "Chase Combining"
numProc = 16 # Number of HARQ processes
harq = HarqEntity(ldpcEncoder, harqType, numProc) # Create the HARQ entity
harq.print() # Print the HARQ entity's properties
HARQ Entity Properties:
HARQ Type: IR
Num. Processes: 16
Num. Codewords: 1
RV sequence: [0, 2, 3, 1]
maxTries: 4
Encoder:
Base Graph: 1
Modulation: 16QAM
Number of layers: 1
Target Rate: 0.478515625
Decoder:
Base Graph: 1
Modulation: 16QAM
Number of layers: 1
Main transmission loop
[6]:
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 = 1000 # Total number of transmissions
txBlockSizes = harq.numCW*[10000] # Transport block sizes. One per codeword.
# Print the header lines:
print("Tx Bits Rx Bits Throughput(%) TX Blocks RX Blocks BLER(%) Retry Mean time(Sec.)")
print("---------- ---------- ------------- --------- --------- ------- ---------- ----------")
t0 = time.time() # Start our timer
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) # Decode the LLRs into transport blocks
# Print the statistics so far:
print("\r%-10d %-10d %-13.2f %-9d %-9d %-7.2f %-10.2f %-10.2f"
%(harq.totalTxBits, harq.totalRxBits, harq.throughput, harq.totalTxBlocks,
harq.totalRxBlocks, harq.bler, harq.meanTries, time.time()-t0), end='')
harq.goNext() # Get ready for the next transmission
harq.printStats() # Print HARQ entity's statistics
Tx Bits Rx Bits Throughput(%) TX Blocks RX Blocks BLER(%) Retry Mean time(Sec.)
---------- ---------- ------------- --------- --------- ------- ---------- ----------
10000000 4960000 49.60 1000 496 50.40 1.00 64.76
HARQ Entity Statistics:
txBits (per try): [5040000 4960000 0 0]
rxBits (per try): [ 0 4960000 0 0]
txBlocks (per try): [504 496 0 0]
rxBlocks (per try): [ 0 496 0 0]
numTimeouts: 0
totalTxBlocks: 1000
totalRxBlocks: 496
totalTxBits: 10000000
totalRxBits: 4960000
throughput: 49.60%
bler: 50.40%
Average Num. Retries: 1.00%
[ ]: