Hierarchical Beam Management with Sweeping, Probing, and Type-I PMI Feedback
This example demonstrates a hierarchical downlink beam-management and CSI-feedback procedure. The gNB first identifies a suitable transmit direction using one-port CSI-RS resources and then performs multi-layer precoding within the selected direction using a directional multi-port CSI-RS resource.
The procedure consists of three stages:
- Beam sweeping:The gNB transmits a set of one-port CSI-RS resources using relatively coarse steering directions. The UE measures these resources and reports a CSI-RS Resource Indicator (CRI) identifying the preferred sweeping beam.
- Beam probing:Based on the sweeping result, the gNB transmits a second set of one-port CSI-RS resources using finer steering directions around the selected sweeping beam. The UE reports a second CRI identifying the preferred probing beam.
- RI, PMI, and CQI acquisition:The gNB transmits a multi-port CSI-RS using the steering vector associated with the selected probing beam. The UE estimates the corresponding effective MIMO channel and reports:
Rank Indicator (RI): the recommended number of transmission layers;
Precoding Matrix Indicator (PMI): the preferred Type-I single-panel codebook precoder; and
Channel Quality Indicator (CQI): the recommended modulation and code-rate operating point.
After receiving the RI, PMI, and CQI report, the gNB configures the PDSCH and forms a composite precoder by combining:
the steering vector associated with the selected probing CRI; and
the Type-I codebook precoder indicated by the PMI.
The same steering transformation used for the directional multi-port CSI-RS is therefore also applied to the PDSCH. This ensures that the effective channel used by the UE for PMI selection is consistent with the effective channel experienced by the precoded data transmission.
The simulation includes:
coarse beam sweeping using one-port CSI-RS resources;
fine beam probing around the selected sweeping direction;
transmission of a directional multi-port CSI-RS using the selected probing beam;
UE-side CRI, RI, PMI, and CQI calculation;
gNB-side PDSCH configuration based on the reported RI and CQI;
PDSCH transmission using the combined probing-beam steering vector and PMI precoder; and
receiver equalization, LDPC decoding, and transport-block CRC verification.
The feedback generated at each stage is applied to subsequent transmissions. Consequently, the sweeping result determines the probing region, the probing result determines the steering vector used for the multi-port CSI-RS, and the resulting RI/PMI/CQI report determines the configuration and precoding of later PDSCH transmissions.
[1]:
import numpy as np
from neoradium import BandwidthPart, PDSCH, AntennaPanel, CdlChannel, random
from neoradium import CsiRsConfig, CsiReportMan
[2]:
numSlots = 100 # Number of slots in the communication loop
snrDb = -10 # SNR in dB
random.setSeed(1234) # Make results reproducible
prgSize = 0 # Set to 0 for wideband, 2 or 4 for subband precoding
# Create a bandwidth part with 24 resource blocks and 15 kHz subcarrier spacing
bwp = BandwidthPart(numRbs=24, spacing=15)
# Create a CDL channel model
channel = CdlChannel(bwp, profile='C', delaySpread=30, carrierFreq=4e9, dopplerShift=5,
txAntenna=AntennaPanel([2,4], polarization='x'), # 16 TX antennas
rxAntenna=AntennaPanel([1,2], polarization='x'), # 4 RX antennas
rxOrientation = [180,0,0])
# Create a typical CSI-RS configuration
csiRsConfig = CsiRsConfig.beamformingConfig(bwp, channel.txAntenna.numPorts, sweepsPerSlot=4)
# csiRsConfig.print() # Uncomment to print CSI-RS configuration details
# Get the CSI resource sets for beam sweeping, beam probing, and RI/PMI/CQI feedback
sweepSet, probeSet, pmiSet = csiRsConfig.csiRsSetList
# Create CSI reports and a CsiReportMan object for the CSI-RS configuration above
# Note that we are enabling subband precoders by setting 'prgSize' to 4, and limitting the rank
# to 1 by setting 'allowedRanks' to [1].
csiReportMan = CsiReportMan.beamformingReports(csiRsConfig, channel.txAntenna,
prgSize=prgSize, allowedRanks=[1,2])
# csiReportMan.print() # Uncomment to print CSI report configuration details
# Get the CSI report objects for beam sweeping, beam probing, and RI/PMI/CQI feedback
sweepRep, probeRep, pmiRep = csiReportMan.csiReports
numPhi = len(sweepSet) # Number of beams to sweep horizontally
numTheta = 1 # Number of beams to sweep vertically (Restrict sweeping to azimuth)
# Get a set of beam angles and precoders (weight vectors) for each beam
sweepWs, sweepBeams = channel.txAntenna.getSweepingBeams(numTheta, numPhi)
# Initialize beam sweeping parameters
probeWs, probeBeams = None, None # Probing steering vecors and angles
sweepCri, probeCri = None, None # The CRI feedback for sweeping and probing
# The PDSCH object is created once we have the first RI/PMI/CQI feedback and
# recreated later if CQI changes.
pdsch = None
precoder = None
pmiW = None # The steering vector used by the most recent RI/PMI/CQI CSI-RS resources
pdschW = None # The steering vector used by PDSCH (consistent with precoder from PMI)
failedSlots = 0
for slotNo in range(numSlots):
channelMatrix = channel.getChannelMatrix()
# Process CSI feedback:
csiReportInfo = csiReportMan.getFeedback() # Get all available CSI reports from CsiReport objects
for reportId, csiFeedback in csiReportInfo.items(): # Get the CSI feedback for each report
if reportId == sweepRep.reportId: # sweeping report
sweepCri = csiFeedback.cri.cri # CSI-RS resource ID of the best beam
print(f"Slot {slotNo}: Received CRI (ReportID: {reportId}), best beam (𝛳={sweepBeams[0][sweepCri-1]:.2f}°, "
f"𝝋={sweepBeams[1][sweepCri-1]:.2f}°), RSRP: {csiFeedback.cri.rsrp:.2f} dB")
probeSet.trigger() # Trigger Probing CSI-RS resource set
probeRep.trigger() # Trigger Probing report
elif reportId == probeRep.reportId: # probing report
probeCri = csiFeedback.cri.cri # CSI-RS resource ID of the best beam
beamIdx = probeCri - len(sweepSet) - 1 # Index of the best beam
print(f"Slot {slotNo}: Received CRI (ReportID: {reportId}), best beam (𝛳={probeBeams[0][beamIdx]:.2f}°, "
f"𝝋={probeBeams[1][beamIdx]:.2f}°), RSRP: {csiFeedback.cri.rsrp:.2f} dB")
pmiSet.active = True # Activate RI/PMI/CQI CSI-RS
pmiRep.active = True # Activate RI/PMI/CQI measurements
elif reportId == pmiRep.reportId: # RI/PMI/CQI report
print(f"Slot {slotNo}: Received RI/PMI/CQI (ReportID: {reportId})")
print(f" RI: {csiFeedback.ri.ri} (Score:{csiFeedback.ri.score:.3f})")
print(f" WB PMI: {csiFeedback.pmi.wbPMI}")
print(f" WB precoder shape: {csiFeedback.pmi.wbW.shape}")
if csiFeedback.pmi.sbWs is not None:
print(f" {len(csiFeedback.pmi.sbWs)} SB precoders: ")
for i, (rbIdx, w) in enumerate(csiFeedback.pmi.sbWs):
print(f" RBs: {str(rbIdx):<20} precoder shape: {str(w.shape):<10} PMI: {csiFeedback.pmi.sbPMIs[i]}")
if "cqi" in pmiRep.quantity.lower():
print(f" CQI: {csiFeedback.cqi.cqi}")
modulation, coderateX1024 = pmiRep.getModRate(csiFeedback.cqi.cqi)
print(f" Modulation: {modulation}")
print(f" Coderate: {coderateX1024}/1024")
print(f" CQI BLER: {csiFeedback.cqi.bler:.2f} %")
precoder = csiFeedback.pmi.wbW if csiFeedback.pmi.sbWs is None else csiFeedback.pmi.sbWs
pdschW = pmiW
if pdsch is None:
# First RI/PMI/CQI feedback -> create PDSCH and LDPC codec objects
print(f"Slot {slotNo}: Starting PDSCH (Mod:{modulation}, "
f"Coderate:{coderateX1024}/1024)")
pdsch = PDSCH(bwp, numLayers=csiFeedback.ri.ri, csiRsConfig=csiRsConfig,
modulation=modulation, prgSize=pmiRep.prgSize)
pdsch.setDMRS(additionalPos=2)
ldpc = pdsch.getLdpcCodec(coderates = coderateX1024/1024)
elif ( (pdsch.modems[0].modulation != modulation) or
(pdsch.numLayers != csiFeedback.ri.ri) ):
# Modulation or number of layers changed -> Recreate PDSCH and LDPC codec objects
print(f"Slot {slotNo}: CQI changed -> Mod:{modulation}, "
f"Coderate:{coderateX1024}/1024")
pdsch = PDSCH(bwp, numLayers=csiFeedback.ri.ri, csiRsConfig=csiRsConfig,
modulation=modulation, prgSize=pmiRep.prgSize)
pdsch.setDMRS(additionalPos=2)
ldpc = pdsch.getLdpcCodec(coderates = coderateX1024/1024)
elif ldpc.coderates[0] != (coderateX1024/1024):
# Coderate changed -> Recreate the LDPC codec object only
print(f"Slot {slotNo}: CQI changed -> Coderate:{coderateX1024}/1024")
ldpc = pdsch.getLdpcCodec(coderates = coderateX1024/1024)
else:
print(f"Unknown report: {reportId}")
# Create a transmitted resource grid.
txGrid = bwp.createGrid(channel.txAntenna.numEl)
if pdsch is not None:
# Create random data, LDPC encode it, and put it in the PDSCH's internal resource grid.
# Then precode the PDSCH into the transmitted resource grid - txGrid.
pdsch.initGrid()
numBits = pdsch.getBitCapacity()[0]
txBlock = random.bits(ldpc.txBlockSizes[0])
rateMatchedCodeBlocks = ldpc.encode(txBlock, numBits)
pdsch.setPdschData(rateMatchedCodeBlocks)
pdsch.precodeTo(txGrid, precoder, pdschW)
# Processing CSI-RS
# Check to see if there are any CSI-RS resources scheduled for this slot. If so,
# precode the CSI-RS resources into the txGrid
csiRsResources = csiRsConfig.getResources()
for csiSetId, setResources in csiRsResources.items():
if csiSetId == sweepSet.rsId: # Beam Sweeping
print(f"Slot {slotNo}: Sending sweeping CSI-RS (Set ID:{sweepSet.rsId}, {len(setResources)} beams)")
for resourceId, (lIdx, kIdx, sweepReValues) in setResources.items():
csiRs = csiRsConfig.getById(csiSetId, resourceId)
pf = np.sqrt( csiRs.numPorts/(channel.txAntenna.numEl*csiRs.cdmSize)) # Power factor
b = resourceId-1 # Beam Index
w = sweepWs[:,b:b+1] # nt x 1
# sweepReValues is a 1 x numCsiRsRE matrix. nt x 1 * 1 x numCsiRsRE = nt x numCsiRsRE
txGrid[:,lIdx, kIdx] = (w * sweepReValues * pf, "CSIRS_NZP", resourceId)
elif csiSetId == probeSet.rsId: # Beam probing:
print(f"Slot {slotNo}: Sending probing CSI-RS (Set ID:{probeSet.rsId}, {len(setResources)} beams)")
b = sweepCri-1 # Index of the best sweeping beam from CRI
theta0, phi0 = sweepBeams[0][b], sweepBeams[1][b] # Best sweeping beam angles
# Get a set of beam angles and precoders (weight vectors) for probing around the
# best sweeping beam (theta0, phi0).
probeWs, probeBeams = channel.txAntenna.getProbingBeams(theta0, phi0,
len(probeSet), polStrategy='equal')
for resourceId, (lIdx, kIdx, probeReValues) in setResources.items():
csiRs = csiRsConfig.getById(csiSetId, resourceId)
pf = np.sqrt( csiRs.numPorts/(channel.txAntenna.numEl*csiRs.cdmSize)) # Power factor
b = resourceId - len(sweepSet) - 1 # Beam Index
w = probeWs[:,b:b+1] # nt x 1
# probeReValues is a 1 x numCsiRsRE matrix. nt x 1 * 1 x numCsiRsRE = nt x numCsiRsRE
txGrid[:,lIdx, kIdx] = (w * probeReValues * pf, "CSIRS_NZP", resourceId)
elif csiSetId == pmiSet.rsId: # CSI-RS for RI/PMI/CQI:
print(f"Slot {slotNo}: Sending PMI resources (Set ID:{pmiSet.rsId})")
# Use the beamforming vector corresponding to the best probed beam. This will also be
# saved to pdschW when the report for this CSI-RS is received. pdschW is then combined with
# the PMI procoder to precode PDSCH.
wIdx = probeCri - len(sweepSet) - 1 # Index of the best probing beam from CRI
pmiW = probeWs[:,wIdx:wIdx+1].copy() # shape: nt x 1
for resourceId, (lIdx, kIdx, pmiReValues) in setResources.items():
# Simulation note:
# Scale the CSI-RS to keep its aggregate transmit power approximately
# consistent with the PDSCH. This avoids unintentionally reducing the
# effective PDSCH SNR in this simulation, where the noise variance is
# derived from the average received signal power. This is a simulation
# convenience only; it is **NOT** a 3GPP requirement or recommendation
# and is not representative of how practical systems necessarily
# implement CSI-RS transmission. (This comment also applies to the sweeping
# and probing cases above)
csiRs = csiRsConfig.getById(csiSetId, resourceId)
pf = np.sqrt( csiRs.numPorts/(channel.txAntenna.numEl*csiRs.cdmSize)) # Power factor
# pmiReValues is a nt x numCsiRsRE matrix. nt x 1 * nt x numCsiRsRE = nt x numCsiRsRE
txGrid[:,lIdx, kIdx] = (pmiW * pmiReValues * pf, "CSIRS_NZP", resourceId)
# Apply the channel model and add AWGN noise
rxGrid = txGrid.applyChannel(channelMatrix)
noisyRxGrid = rxGrid.addNoise(snrDb=snrDb)
if pdsch is not None:
# Receiver side processing of the PDSCH: equalization and LDPC decoding
# effChannelMatrix, errVar = pdsch.estimateChannel(noisyRxGrid)
# eqGrid, llrScales = pdsch.equalize(noisyRxGrid, effChannelMatrix, errVar)
effChannelMatrix = channel.getEffChannel(channelMatrix, precoder, pdschW)
eqGrid, llrScales = pdsch.equalize(noisyRxGrid, effChannelMatrix)
llrs = pdsch.getLLRs(eqGrid, llrScales)
decodedTxBlocks, crcMatch = ldpc.decode(llrs)
print(f"Slot {slotNo}: TxBlock CRC Match: {crcMatch[0][0]}")
failedSlots += 1-int(crcMatch[0][0])
# UE processing of the received resource grid to generate reports
csiReportMan.processRxGrid(noisyRxGrid, csiRsResources)
# Go to the next channel instance for the next slot
channel.goNext()
print(f"{failedSlots} of {numSlots} slots failed.")
Slot 0: Sending sweeping CSI-RS (Set ID:1, 4 beams)
Slot 1: Sending sweeping CSI-RS (Set ID:1, 4 beams)
Slot 5: Received CRI (ReportID: 11), best beam (𝛳=90.00°, 𝝋=-7.11°), RSRP: 13.09 dB
Slot 5: Sending probing CSI-RS (Set ID:2, 4 beams)
Slot 6: Received CRI (ReportID: 12), best beam (𝛳=95.00°, 𝝋=-7.11°), RSRP: 14.07 dB
Slot 10: Sending PMI resources (Set ID:3)
Slot 14: Received RI/PMI/CQI (ReportID: 13)
RI: 2 (Score:3.117)
WB PMI: (I1:[0, 0, 0], I2:0)
WB precoder shape: (16, 2)
CQI: 5
Modulation: QPSK
Coderate: 449/1024
CQI BLER: 0.12 %
Slot 14: Starting PDSCH (Mod:QPSK, Coderate:449/1024)
Slot 14: TxBlock CRC Match: True
Slot 15: TxBlock CRC Match: True
Slot 16: TxBlock CRC Match: True
Slot 17: TxBlock CRC Match: True
Slot 18: TxBlock CRC Match: True
Slot 19: TxBlock CRC Match: True
Slot 20: Sending sweeping CSI-RS (Set ID:1, 4 beams)
Slot 20: Sending PMI resources (Set ID:3)
Slot 20: TxBlock CRC Match: True
Slot 21: Sending sweeping CSI-RS (Set ID:1, 4 beams)
Slot 21: TxBlock CRC Match: True
Slot 22: TxBlock CRC Match: True
Slot 23: TxBlock CRC Match: True
Slot 24: Received RI/PMI/CQI (ReportID: 13)
RI: 2 (Score:3.286)
WB PMI: (I1:[0, 0, 0], I2:0)
WB precoder shape: (16, 2)
CQI: 5
Modulation: QPSK
Coderate: 449/1024
CQI BLER: 0.12 %
Slot 24: TxBlock CRC Match: True
Slot 25: Received CRI (ReportID: 11), best beam (𝛳=90.00°, 𝝋=-7.11°), RSRP: 13.65 dB
Slot 25: Sending probing CSI-RS (Set ID:2, 4 beams)
Slot 25: TxBlock CRC Match: True
Slot 26: Received CRI (ReportID: 12), best beam (𝛳=95.00°, 𝝋=-7.11°), RSRP: 13.51 dB
Slot 26: TxBlock CRC Match: True
Slot 27: TxBlock CRC Match: True
Slot 28: TxBlock CRC Match: True
Slot 29: TxBlock CRC Match: True
Slot 30: Sending PMI resources (Set ID:3)
Slot 30: TxBlock CRC Match: True
Slot 31: TxBlock CRC Match: True
Slot 32: TxBlock CRC Match: True
Slot 33: TxBlock CRC Match: True
Slot 34: Received RI/PMI/CQI (ReportID: 13)
RI: 2 (Score:3.125)
WB PMI: (I1:[0, 0, 0], I2:0)
WB precoder shape: (16, 2)
CQI: 5
Modulation: QPSK
Coderate: 449/1024
CQI BLER: 0.12 %
Slot 34: TxBlock CRC Match: True
Slot 35: TxBlock CRC Match: True
Slot 36: TxBlock CRC Match: True
Slot 37: TxBlock CRC Match: True
Slot 38: TxBlock CRC Match: True
Slot 39: TxBlock CRC Match: True
Slot 40: Sending sweeping CSI-RS (Set ID:1, 4 beams)
Slot 40: Sending PMI resources (Set ID:3)
Slot 40: TxBlock CRC Match: True
Slot 41: Sending sweeping CSI-RS (Set ID:1, 4 beams)
Slot 41: TxBlock CRC Match: True
Slot 42: TxBlock CRC Match: True
Slot 43: TxBlock CRC Match: True
Slot 44: Received RI/PMI/CQI (ReportID: 13)
RI: 2 (Score:3.335)
WB PMI: (I1:[0, 0, 0], I2:1)
WB precoder shape: (16, 2)
CQI: 5
Modulation: QPSK
Coderate: 449/1024
CQI BLER: 0.12 %
Slot 44: TxBlock CRC Match: True
Slot 45: Received CRI (ReportID: 11), best beam (𝛳=90.00°, 𝝋=7.11°), RSRP: 13.53 dB
Slot 45: Sending probing CSI-RS (Set ID:2, 4 beams)
Slot 45: TxBlock CRC Match: True
Slot 46: Received CRI (ReportID: 12), best beam (𝛳=90.00°, 𝝋=1.10°), RSRP: 14.21 dB
Slot 46: TxBlock CRC Match: True
Slot 47: TxBlock CRC Match: True
Slot 48: TxBlock CRC Match: True
Slot 49: TxBlock CRC Match: True
Slot 50: Sending PMI resources (Set ID:3)
Slot 50: TxBlock CRC Match: True
Slot 51: TxBlock CRC Match: True
Slot 52: TxBlock CRC Match: True
Slot 53: TxBlock CRC Match: True
Slot 54: Received RI/PMI/CQI (ReportID: 13)
RI: 2 (Score:3.460)
WB PMI: (I1:[1, 0, 0], I2:0)
WB precoder shape: (16, 2)
CQI: 6
Modulation: QPSK
Coderate: 602/1024
CQI BLER: 4.16 %
Slot 54: CQI changed -> Coderate:602/1024
Slot 54: TxBlock CRC Match: True
Slot 55: TxBlock CRC Match: True
Slot 56: TxBlock CRC Match: True
Slot 57: TxBlock CRC Match: True
Slot 58: TxBlock CRC Match: True
Slot 59: TxBlock CRC Match: True
Slot 60: Sending sweeping CSI-RS (Set ID:1, 4 beams)
Slot 60: Sending PMI resources (Set ID:3)
Slot 60: TxBlock CRC Match: True
Slot 61: Sending sweeping CSI-RS (Set ID:1, 4 beams)
Slot 61: TxBlock CRC Match: True
Slot 62: TxBlock CRC Match: True
Slot 63: TxBlock CRC Match: True
Slot 64: Received RI/PMI/CQI (ReportID: 13)
RI: 2 (Score:3.466)
WB PMI: (I1:[1, 0, 0], I2:1)
WB precoder shape: (16, 2)
CQI: 6
Modulation: QPSK
Coderate: 602/1024
CQI BLER: 2.00 %
Slot 64: TxBlock CRC Match: True
Slot 65: Received CRI (ReportID: 11), best beam (𝛳=90.00°, 𝝋=7.11°), RSRP: 14.01 dB
Slot 65: Sending probing CSI-RS (Set ID:2, 4 beams)
Slot 65: TxBlock CRC Match: True
Slot 66: Received CRI (ReportID: 12), best beam (𝛳=90.00°, 𝝋=1.10°), RSRP: 13.65 dB
Slot 66: TxBlock CRC Match: True
Slot 67: TxBlock CRC Match: True
Slot 68: TxBlock CRC Match: True
Slot 69: TxBlock CRC Match: True
Slot 70: Sending PMI resources (Set ID:3)
Slot 70: TxBlock CRC Match: False
Slot 71: TxBlock CRC Match: True
Slot 72: TxBlock CRC Match: True
Slot 73: TxBlock CRC Match: True
Slot 74: Received RI/PMI/CQI (ReportID: 13)
RI: 2 (Score:3.277)
WB PMI: (I1:[1, 1, 0], I2:0)
WB precoder shape: (16, 2)
CQI: 5
Modulation: QPSK
Coderate: 449/1024
CQI BLER: 0.12 %
Slot 74: CQI changed -> Coderate:449/1024
Slot 74: TxBlock CRC Match: True
Slot 75: TxBlock CRC Match: True
Slot 76: TxBlock CRC Match: True
Slot 77: TxBlock CRC Match: True
Slot 78: TxBlock CRC Match: True
Slot 79: TxBlock CRC Match: True
Slot 80: Sending sweeping CSI-RS (Set ID:1, 4 beams)
Slot 80: Sending PMI resources (Set ID:3)
Slot 80: TxBlock CRC Match: True
Slot 81: Sending sweeping CSI-RS (Set ID:1, 4 beams)
Slot 81: TxBlock CRC Match: True
Slot 82: TxBlock CRC Match: True
Slot 83: TxBlock CRC Match: True
Slot 84: Received RI/PMI/CQI (ReportID: 13)
RI: 2 (Score:3.333)
WB PMI: (I1:[0, 0, 0], I2:0)
WB precoder shape: (16, 2)
CQI: 5
Modulation: QPSK
Coderate: 449/1024
CQI BLER: 0.12 %
Slot 84: TxBlock CRC Match: True
Slot 85: Received CRI (ReportID: 11), best beam (𝛳=90.00°, 𝝋=-7.11°), RSRP: 13.68 dB
Slot 85: Sending probing CSI-RS (Set ID:2, 4 beams)
Slot 85: TxBlock CRC Match: True
Slot 86: Received CRI (ReportID: 12), best beam (𝛳=90.00°, 𝝋=-1.10°), RSRP: 14.54 dB
Slot 86: TxBlock CRC Match: True
Slot 87: TxBlock CRC Match: True
Slot 88: TxBlock CRC Match: True
Slot 89: TxBlock CRC Match: True
Slot 90: Sending PMI resources (Set ID:3)
Slot 90: TxBlock CRC Match: True
Slot 91: TxBlock CRC Match: True
Slot 92: TxBlock CRC Match: True
Slot 93: TxBlock CRC Match: True
Slot 94: Received RI/PMI/CQI (ReportID: 13)
RI: 2 (Score:3.186)
WB PMI: (I1:[1, 0, 0], I2:1)
WB precoder shape: (16, 2)
CQI: 5
Modulation: QPSK
Coderate: 449/1024
CQI BLER: 0.12 %
Slot 94: TxBlock CRC Match: True
Slot 95: TxBlock CRC Match: True
Slot 96: TxBlock CRC Match: True
Slot 97: TxBlock CRC Match: True
Slot 98: TxBlock CRC Match: True
Slot 99: TxBlock CRC Match: True
1 of 100 slots failed.
[ ]:
[ ]:
[ ]: