Using HARQ
This notebook demonstrates how to use HARQ functionality in NeoRadium.
[1]:
import numpy as np
import time
from neoradium import LdpcCodec, HarqEntity, random, Modem
from neoradium.utils import toLinear
Creating an LdpcCodec 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
txBlockSizes = [10000,10000] # Transport block size (TBS) (one per codeword)
ldpc = LdpcCodec(modulation, coderate, txBlockSizes, numLayers)
ldpc.print() # Print the LDPC encoder's properties
LDPC Encode/Decode Properties:
Num layers: 1
Num codewords: 1
numIter: 5
nRef: 0
Modulation: 16QAM
Coderate: 490/1024
TBS: 10000
numLayers: 1
Base Graph: 1
Code Block Size: 5280
Num Code Blocks: 2
Lifting Size: 240
Instantiating a HARQ entity object
[3]:
harqType = "IR" # "IR" -> "Incremental Redundancy", "CC" -> "Chase Combining"
numProc = 16 # Number of HARQ processes
harq = HarqEntity(ldpc, 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
LDPC codec:
Num layers: 1
Num codewords: 1
numIter: 5
nRef: 0
Modulation: 16QAM
Coderate: 490/1024
TBS: 10000
numLayers: 1
Base Graph: 1
Code Block Size: 5280
Num Code Blocks: 2
Lifting Size: 240
Main transmission loop
[4]:
rangen = random.getGenerator(123) # Create new random generator and make results reproducible
modem = Modem(modulation) # The Modem instance used for modulation/demodulation
ebNoDb = 3 # Set the Eb/No ratio (dB)
snrDb = ebNoDb + 10*np.log10(modem.qm * coderate) # Convert Eb/No to SNR (dB)
snr = toLinear(snrDb) # Linear SNR
noiseStd = np.sqrt(1/snr) # Noise standard deviation
numTransmissions = 1000 # Total number of transmissions
# Print the header lines:
print("Tx Bits Rx Bits Throughput(%) TX Blocks RX Blocks BLER(%) Avg. Retransmissions 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
rateMatchedCodeBlocks = harq.encode(txBlocks) # Prepare the bitstream for transmission
llrs = [] # Received Log-Likelihood Ratios. One per codeword.
for c in range(harq.numCW):
channelOutput = modem.modulate(rateMatchedCodeBlocks[c]) # Modulate the code blocks
noisyRxSignal = channelOutput + rangen.awgn(channelOutput.shape, noiseStd) # Add Noise
llrs += [ modem.getLLRs(noisyRxSignal, noiseStd**2) ] # Calculate the LLRs for each codeword
decodedTxBlocks, crcMatches = harq.decode(llrs) # Decode the LLRs into transport blocks
# Print the statistics so far:
print("\r%-10d %-10d %-13.2f %-9d %-9d %-7.2f %-20.2f %-10.2f"
%(harq.totalTxBits, harq.totalRxBits, harq.throughput, harq.totalTxBlocks,
harq.totalRxBlocks, harq.bler, harq.meanRetransmissions, 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(%) Avg. Retransmissions time(Sec.)
---------- ---------- ------------- --------- --------- ------- -------------------- ----------
10000000 4960000 49.60 1000 496 50.40 1.00 105.29
HARQ Entity Statistics:
numTxBits (per try): [5040000 4960000 0 0]
numRxBits (per try): [ 0 4960000 0 0]
numTxBlocks (per try): [504 496 0 0]
numRxBlocks (per try): [ 0 496 0 0]
numTimeouts: 0
totalTxBlocks: 1000
totalRxBlocks: 496
totalTxBits: 10000000
totalRxBits: 4960000
throughput: 49.60%
bler: 50.40%
bler1st: 100.00%
Avg. retransmissions: 1.00
Avg. failed transmissions:1.00
[ ]: