Recovery Procedure for an 802.11ax Packet
This example shows how to detect a packet and decode the payload bits in a received IEEE® 802.11ax™ (Wi-Fi 6) waveform. The receiver recovers the packet format parameters from the preamble fields to decode the data field and the MAC frame.
Introduction
In an 802.11ax packet, the L-SIG, HE-SIG-A, and HE-SIG-B preamble fields signal transmission parameters to the receiver [1]:
The L-SIG field contains the transmission time of the packet.
The HE-SIG-A field contains common transmission parameters for HE MU users and all transmission parameters for HE SU and HE EXT SU packets.
The length information in the L-SIG field, the modulation type, and the number of OFDM symbols in the HE-SIG-A field determine the HE packet format.
The HE-SIG-B field contains resource unit (RU) allocation information and the transmission parameters for the users in an HE MU packet.
This example shows how to recover these transmission parameters from an HE MU packet within a generated waveform. This example can also recover HE SU and HE EXT SU packets. The example assumes knowledge of only the channel bandwidth. The receiver obtains the other transmission parameters from the decoded L-SIG, HE-SIG-A, and HE-SIG-B preamble fields. You then use these parameters to decode the HE-Data field. You can use this example to perform the following analyses:
Recover and display the waveform of the detected packet.
Recover and display the spectrum of the detected packet.
Display the constellation of the equalized data symbols for all spatial streams.
Measure the error vector magnitude (EVM) of each field.
Detect an A-MPDU and determine the frame check sequence (FCS) for the recovered MAC frame.
Display the EVM per data symbol and spatial stream averaged over subcarriers.
Display the EVM per data subcarrier and spatial stream averaged over symbols.
Waveform Generation
For this example, you synthesize a 802.11ax HE MU waveform. To synthesize an HE MU waveform, you create an HE MU format configuration object wlanHEMUConfig
. The synthesized waveform is impaired by a 2x2 TGax indoor fading channel, additive white Gaussian noise (AWGN), and carrier frequency offset.
Note that the wlanHEMUConfig
object is used at the transmitter side only. The receiver uses an HE recovery configuration object wlanHERecoveryConfig
. The receiver sets the unknown properties of the HE recovery configuration object after decoding the information bits in the L-SIG, HE-SIG-A, and HE-SIG-B fields. The helper function helperSigRecGenerateWaveform generates the impaired waveform by:
Creating a random payload of MSDUs for the MAC frame, which is encoded into an HE MU packet
Passing the waveform through a TGax indoor fading channel model
Adding carrier frequency offset (CFO) and AWGN to the waveform
Alternatively, you can capture a waveform by using Instrument Control Toolbox™ to acquire I/Q data from a wide range of instruments and software-defined radio (SDR) platforms. If you capture an off-the-air waveform using an SDR, see the Recover and Analyze Packets in 802.11 Waveform example.
Define a mixed OFDMA and MU-MIMO configuration for an HE MU packet. The allocation index 17 defines two 52-tone RUs, with one user in each RU, and one 106-tone RU. The 106-tone RU has two users in an MU-MIMO configuration. The waveform to process is stored in the variable rx
.
cfgMU = wlanHEMUConfig(17); cfgMU.NumTransmitAntennas = 2; % Configure RU 1 and user 1 cfgMU.RU{1}.SpatialMapping = 'Direct'; cfgMU.User{1}.STAID = 1; cfgMU.User{1}.APEPLength = 1e3; cfgMU.User{1}.MCS = 5; cfgMU.User{1}.NumSpaceTimeStreams = 2; cfgMU.User{1}.ChannelCoding = 'LDPC'; % Configure RU 2 and user 2 cfgMU.RU{2}.SpatialMapping = 'Fourier'; cfgMU.User{2}.STAID = 2; cfgMU.User{2}.APEPLength = 500; cfgMU.User{2}.MCS = 4; cfgMU.User{2}.NumSpaceTimeStreams = 1; cfgMU.User{2}.ChannelCoding = 'BCC'; % Configure RU 3 and user 1 cfgMU.RU{3}.SpatialMapping = 'Fourier'; cfgMU.User{3}.STAID = 3; cfgMU.User{3}.APEPLength = 100; cfgMU.User{3}.MCS = 2; cfgMU.User{3}.NumSpaceTimeStreams = 1; cfgMU.User{3}.ChannelCoding = 'BCC'; % Configure RU 3 and user 2 cfgMU.User{4}.STAID = 4; cfgMU.User{4}.APEPLength = 500; cfgMU.User{4}.MCS = 3; cfgMU.User{4}.NumSpaceTimeStreams = 1; cfgMU.User{4}.ChannelCoding = 'LDPC'; % Specify propagation channel numRx = 2; % Number of receive antennas delayProfile = 'Model-D'; % TGax channel delay profile % Specify impairments noisePower = -40; % Noise power to apply in dBW cfo = 62e3; % Carrier frequency offset Hz % Generate waveform rx = helperSigRecGenerateWaveform(cfgMU,numRx,delayProfile,noisePower,cfo);
Packet Recovery
To recover a packet, you process the waveform by following these steps:
Create an HE recovery configuration object,
wlanHERecoveryConfig
. After decoding the preamble fields in the waveform, the receiver updates the object properties.Detect and synchronize the packet.
Extract and demodulate the L-LTF. The demodulated L-LTF symbols do not include tone rotation for each 20 MHz segment as described in [2], Section 21.3.7.5.
Use the demodulated L-LTF symbols for channel and noise estimates.
Use the time-domain signal containing samples equivalent to four OFDM symbols that immediately follow the L-LTF to determine the HE packet format. Update the packet format in the
wlanHERecoveryConfig
object.Demodulate the L-LTF. The demodulated L-LTF symbols include tone rotation for each 20 MHz segment as described in [2], Section 21.3.7.5. Use the L-LTF channel estimates (with tone rotation) to decode the pre-HE-LTF fields.
Extract the L-SIG and RL-SIG fields. Estimate the channel on an extra four subcarriers per subchannel in the L-SIG and RL-SIG fields. Update the L-LTF channel estimates to include the channel estimates on the extra subcarriers.
Determine the length of the packet in microseconds from the information bits in the L-SIG field.
Update the recovery configuration object after decoding the HE-SIG-A field. In an HE MU packet, the HE-SIG-A field contains the common transmission parameters. In an HE SU or HE EXT SU packet, the HE-SIG-A field contains all the transmission parameters.
For an HE MU packet format, decode the HE-SIG-B field. For a non-compressed SIGB waveform the HE-SIG-B common field is decoded first followed by the HE-SIG-B user field. For a compressed SIGB waveform only the HE-SIG-B user field is decoded.
For an HE MU format without SIGB compression, recover the RU allocation and user transmission parameters from the HE-SIG-B field. For a compressed SIGB waveform, determine the RU allocation information from the HE-SIG-A field and the user transmission parameters from the HE-SIG-B user field bits.
Create the
wlanHERecoveryConfig
object using the recovered transmission parameters for each user after HE-SIG-B decoding.Extract and demodulate the HE-LTF field. Use the demodulated symbols for channel estimation of the subcarriers allocated to the user of interest. Use the MIMO channel estimates to decode the HE-Data field.
Extract the HE-Data field and recover the PSDU bits using the
wlanHERecoveryConfig
object for each user.Detect the A-MPDU within the recovered PSDU and check the FCS for the recovered MAC frame.
Recovery Parameter Setup
To recover the received packet from the waveform, create an HE recovery configuration object, wlanHERecoveryConfig
. The recovery object stores the recovered information from the L-SIG, HE-SIG-A, and HE-SIG-B preamble fields. After decoding the preamble fields, the receiver updates the unknown properties of the object. The following code configures the object and variables for processing.
chanBW = cfgMU.ChannelBandwidth; % Assume channel bandwidth is known sr = wlanSampleRate(cfgMU); % Sample rate % Specify pilot tracking method for recovering the data field. When % recovering 26-tone RUs only phase tracking is used as both time and phase % tracking algorithm is susceptible to noise. phaseTracking = true; timeTracking = true; % Create an HE recovery configuration object and set the channel bandwidth cfgRx = wlanHERecoveryConfig; cfgRx.ChannelBandwidth = chanBW; % The recovery configuration object is used to get the start and end % indices of the pre-HE-SIG-B field. ind = wlanFieldIndices(cfgRx); % Setup plots for the example [spectrumAnalyzer,timeScope,ConstellationDiagram,EVMPerSubcarrier,EVMPerSymbol] = helperSigRecSetupPlots(sr); % Minimum packet length is 10 OFDM symbols lstfLength = double(ind.LSTF(2)); minPktLen = lstfLength*5; % Number of samples in L-STF rxWaveLen = size(rx,1);
Front-End Processing
The front-end processing uses a while
loop for packet detection, coarse carrier frequency offset correction, timing synchronization, and fine carrier frequency offset correction. To detect a packet, the sample offset searchOffset
indexes into rx
. If synchronization fails for the first packet, the searchOffset
is incremented to move beyond that packet. This process repeats until a packet is successfully synchronized.
searchOffset = 0; % Offset from start of waveform in samples while (searchOffset + minPktLen) <= rxWaveLen % Packet detection pktOffset = wlanPacketDetect(rx,chanBW,searchOffset); % Adjust packet offset pktOffset = searchOffset + pktOffset; if isempty(pktOffset) || (pktOffset + ind.LSIG(2) > rxWaveLen) error('** No packet detected **'); end % Coarse frequency offset estimation and correction using L-STF rxLSTF = rx(pktOffset+(ind.LSTF(1):ind.LSTF(2)), :); coarseFreqOffset = wlanCoarseCFOEstimate(rxLSTF,chanBW); rx = frequencyOffset(rx,sr,-coarseFreqOffset); % Symbol timing synchronization searchBufferLLTF = rx(pktOffset+(ind.LSTF(1):ind.LSIG(2)),:); pktOffset = pktOffset+wlanSymbolTimingEstimate(searchBufferLLTF,chanBW); % Fine frequency offset estimation and correction using L-STF rxLLTF = rx(pktOffset+(ind.LLTF(1):ind.LLTF(2)),:); fineFreqOffset = wlanFineCFOEstimate(rxLLTF,chanBW); rx = frequencyOffset(rx,sr,-fineFreqOffset); % Timing synchronization complete: packet detected fprintf('Packet detected at index %d\n',pktOffset + 1); % Display estimated carrier frequency offset cfoCorrection = coarseFreqOffset + fineFreqOffset; % Total CFO fprintf('Estimated CFO: %5.1f Hz\n\n',cfoCorrection); break; % Front-end processing complete, stop searching for a packet end
Packet detected at index 404
Estimated CFO: 62017.7 Hz
% Scale the waveform based on L-STF power (AGC)
gain = 1./(sqrt(mean(rxLSTF.*conj(rxLSTF))));
rx = rx.*gain;
Packet Format Detection
To determine the packet format, the receiver uses the time-domain samples equivalent to the four OFDM symbols immediately following the L-LTF [1 Figure 27-63]. Extract and demodulate the L-LTF. For format detection, the demodulated L-LTF symbols must not include tone rotation for each 20 MHz segment as described in [2], Section 21.3.7.5. Use the demodulated L-LTF symbols for channel and noise estimation. Detect the packet format using the L-LTF channel (without tone rotation) and noise power estimates.
rxLLTF = rx(pktOffset+(ind.LLTF(1):ind.LLTF(2)),:);
lltfDemod = wlanLLTFDemodulate(rxLLTF,chanBW);
lltfChanEst = wlanLLTFChannelEstimate(lltfDemod,chanBW);
noiseVar = wlanLLTFNoiseEstimate(lltfDemod);
disp('Detect packet format...');
Detect packet format...
rxSIGA = rx(pktOffset+(ind.LSIG(1):ind.HESIGA(2)),:);
pktFormat = wlanFormatDetect(rxSIGA,lltfChanEst,noiseVar,chanBW);
fprintf(' %s packet detected\n\n',pktFormat);
HE-MU packet detected
% Set the packet format in the recovery object and update the field indices
cfgRx.PacketFormat = pktFormat;
ind = wlanFieldIndices(cfgRx);
L-LTF Channel Estimate
Demodulate the L-LTF and perform channel estimation. The demodulated L-LTF symbols include tone rotation for each 20 MHz segment as described in [2], Section 21.3.7.5. The receiver uses the L-LTF channel estimates (with tone rotation) to equalize and decode the pre-HE-LTF fields.
lltfDemod = wlanHEDemodulate(rxLLTF,'L-LTF',chanBW);
lltfChanEst = wlanLLTFChannelEstimate(lltfDemod,chanBW);
L-SIG and RL-SIG Decoding
The L-SIG field determines the receive time, or RXTIME, of the packet. The receiver calculates RXTIME using the length bits of the L-SIG payload. The receiver recovers the L-SIG and RL-SIG fields to estimate the channel at the extra subcarriers in these fields. It then updates the lltfChanEst
channel estimates to include the channel estimates at the extra subcarriers in the L-SIG and RL-SIG fields. Using the estimates of the channel and the noise power from the L-LTF, the receiver decodes the L-SIG payload. After L-SIG decoding, update the L-SIG length property in the wlanHERecoveryConfig
object.
disp('Decoding L-SIG... ');
Decoding L-SIG...
% Extract L-SIG and RL-SIG fields rxLSIG = rx(pktOffset+(ind.LSIG(1):ind.RLSIG(2)),:); % OFDM demodulate helsigDemod = wlanHEDemodulate(rxLSIG,'L-SIG',chanBW); % Estimate CPE and phase correct symbols helsigDemod = wlanHETrackPilotError(helsigDemod,lltfChanEst,cfgRx,'L-SIG'); % Estimate channel on extra 4 subcarriers per subchannel and create full % channel estimate preheInfo = wlanHEOFDMInfo('L-SIG',chanBW); preHEChanEst = wlanPreHEChannelEstimate(helsigDemod,lltfChanEst,chanBW); % Average L-SIG and RL-SIG before equalization helsigDemod = mean(helsigDemod,2); % Equalize data carrying subcarriers, merging 20 MHz subchannels [eqLSIGSym,csi] = wlanHEEqualize(helsigDemod(preheInfo.DataIndices,:,:), ... preHEChanEst(preheInfo.DataIndices,:,:),noiseVar,cfgRx,'L-SIG'); % Decode L-SIG field [~,failCheck,lsigInfo] = wlanLSIGBitRecover(eqLSIGSym,noiseVar,csi); if failCheck disp(' ** L-SIG check fail **'); else disp(' L-SIG check pass'); end
L-SIG check pass
% Get the length information from the recovered L-SIG bits and update the % L-SIG length property of the recovery configuration object lsigLength = lsigInfo.Length; cfgRx.LSIGLength = lsigLength; % Measure EVM of L-SIG symbols EVM = comm.EVM; EVM.ReferenceSignalSource = 'Estimated from reference constellation'; EVM.Normalization = 'Average constellation power'; EVM.ReferenceConstellation = wlanReferenceSymbols('BPSK'); rmsEVM = EVM(eqLSIGSym); fprintf(' L-SIG EVM: %2.2fdB\n\n',20*log10(rmsEVM/100));
L-SIG EVM: -36.78dB
% Calculate the receive time and corresponding number of samples in the % packet RXTime = ceil((lsigLength + 3)/3) * 4 + 20; % In microseconds numRxSamples = round(RXTime * 1e-6 * sr); % Number of samples in time fprintf(' RXTIME: %dus\n',RXTime);
RXTIME: 536us
fprintf(' Number of samples in the packet: %d\n\n',numRxSamples);
Number of samples in the packet: 10720
Given the RXTIME and corresponding number of samples within rx
, plot and display the waveform and the spectrum of the received packet.
sampleOffset = max((-lstfLength + pktOffset),1); % First index to plot sampleSpan = numRxSamples + 2*lstfLength; % Number samples to plot % Plot as much of the packet (and extra samples) as we can plotIdx = sampleOffset:min(sampleOffset + sampleSpan,rxWaveLen); % Configure timeScope to display the packet timeScope.TimeSpan = sampleSpan/sr; timeScope.TimeDisplayOffset = sampleOffset/sr; timeScope.YLimits = [0 max(abs(rx(:)))]; timeScope(abs(rx(plotIdx,:))); release(timeScope);
% Display the spectrum of the detected packet
spectrumAnalyzer(rx(pktOffset + (1:numRxSamples),:));
release(spectrumAnalyzer);
HE-SIG-A Decoding
The HE-SIG-A field contains the transmission configuration of an HE packet. Decode the HE-SIG-A field using estimates of the channel and the noise power from the L-LTF field.
disp('Decoding HE-SIG-A...')
Decoding HE-SIG-A...
rxSIGA = rx(pktOffset+(ind.HESIGA(1):ind.HESIGA(2)),:); sigaDemod = wlanHEDemodulate(rxSIGA,'HE-SIG-A',chanBW); hesigaDemod = wlanHETrackPilotError(sigaDemod,preHEChanEst,cfgRx,'HE-SIG-A'); % Equalize data carrying subcarriers, merging 20 MHz subchannels preheInfo = wlanHEOFDMInfo('HE-SIG-A',chanBW); [eqSIGASym,csi] = wlanHEEqualize(hesigaDemod(preheInfo.DataIndices,:,:), ... preHEChanEst(preheInfo.DataIndices,:,:), ... noiseVar,cfgRx,'HE-SIG-A'); % Recover HE-SIG-A bits [sigaBits,failCRC] = wlanHESIGABitRecover(eqSIGASym,noiseVar,csi); % Perform the CRC on HE-SIG-A bits if failCRC disp(' ** HE-SIG-A CRC fail **'); else disp(' HE-SIG-A CRC pass'); end
HE-SIG-A CRC pass
% Measure EVM of HE-SIG-A symbols release(EVM); if strcmp(pktFormat,'HE-EXT-SU') % The second symbol of an HE-SIG-A field for an HE EXT SU packet is % QBPSK. EVM.ReferenceConstellation = wlanReferenceSymbols('BPSK',[0 pi/2 0 0]); % Account for scaling of L-LTF for an HE EXT SU packet rmsEVM = EVM(eqSIGASym*sqrt(2)); else EVM.ReferenceConstellation = wlanReferenceSymbols('BPSK'); rmsEVM = EVM(eqSIGASym); end fprintf(' HE-SIG-A EVM: %2.2fdB\n\n',20*log10(mean(rmsEVM)/100));
HE-SIG-A EVM: -35.85dB
Interpret Recovered HE-SIG-A Bits
Update the wlanHERecoveryConfig
object after interpreting the recovered HE-SIG-A bits.
cfgRx = interpretHESIGABits(cfgRx,sigaBits);
ind = wlanFieldIndices(cfgRx); % Update field indices
Display the common transmission configuration obtained from the HE-SIG-A field for an HE MU packet. The properties indicated by -1
are unknown or undefined. You can update the unknown user-related properties after successfully decoding the HE-SIG-B field.
disp(cfgRx)
wlanHERecoveryConfig with properties: PacketFormat: 'HE-MU' ChannelBandwidth: 'CBW20' LSIGLength: 383 SIGBCompression: 0 SIGBMCS: 0 SIGBDCM: 0 NumSIGBSymbolsSignaled: 5 STBC: 0 LDPCExtraSymbol: 0 PreFECPaddingFactor: 4 PEDisambiguity: 0 GuardInterval: 3.2000 HELTFType: 4 NumHELTFSymbols: 2 UplinkIndication: 0 BSSColor: 0 SpatialReuse: 0 TXOPDuration: 127 HighDoppler: 0 AllocationIndex: -1 NumUsersPerContentChannel: -1 RUTotalSpaceTimeStreams: -1 RUSize: -1 RUIndex: -1 STAID: -1 MCS: -1 DCM: -1 ChannelCoding: 'Unknown' Beamforming: -1 NumSpaceTimeStreams: -1 SpaceTimeStreamStartingIndex: -1
HE-SIG-B Decoding
For an HE MU packet the HE-SIG-B field stores this information:
The RU allocation information for a non-compressed SIGB waveform is stored in the HE-SIG-B common field [1 Table. 27-24]. For a compressed SIGB waveform the RU allocation information is determined by the recovered HE-SIG-A bits.
The HE-SIG-B user field stores user transmission parameters for both SIGB compressed and non-compressed waveforms [1 Table. 27-27, 27-28].
For a non-compressed SIGB waveform, update the number of HE-SIG-B symbols in the wlanHERecoveryConfig
object. The example updates the symbols only if the number of HE-SIG-B symbols indicated in the HE-SIG-A field is 15 and all content channels pass the CRC. The example does not update the number of HE-SIG-B symbols indicated in the HE-SIG-A field if any HE-SIG-B content channel fails the CRC.
To decode the HE-SIG-B field, you require an estimate of the channel and noise power obtained from the L-LTF.
if strcmp(pktFormat,'HE-MU') fprintf('Decoding HE-SIG-B...\n'); if ~cfgRx.SIGBCompression fprintf(' Decoding HE-SIG-B common field...\n'); s = getSIGBLength(cfgRx); % Get common field symbols. The start of HE-SIG-B field is known rxSym = rx(pktOffset+(double(ind.HESIGA(2))+(1:s.NumSIGBCommonFieldSamples)),:); % Decode HE-SIG-B common field [status,cfgRx] = heSIGBCommonFieldDecode(rxSym,preHEChanEst,noiseVar,cfgRx); % CRC on HE-SIG-B content channels if strcmp(status,'Success') fprintf(' HE-SIG-B (common field) CRC pass\n'); elseif strcmp(status,'ContentChannel1CRCFail') fprintf(' ** HE-SIG-B CRC fail for content channel-1\n **'); elseif strcmp(status,'ContentChannel2CRCFail') fprintf(' ** HE-SIG-B CRC fail for content channel-2\n **'); elseif any(strcmp(status,{'UnknownNumUsersContentChannel1','UnknownNumUsersContentChannel2'})) error(' ** Unknown packet length, discard packet\n **'); else % Discard the packet if all HE-SIG-B content channels fail error(' ** HE-SIG-B CRC fail **'); end % Update field indices as the number of HE-SIG-B symbols are % updated ind = wlanFieldIndices(cfgRx); end % Get complete HE-SIG-B field samples rxSIGB = rx(pktOffset+(ind.HESIGB(1):ind.HESIGB(2)),:); fprintf(' Decoding HE-SIG-B user field... \n'); % Decode HE-SIG-B user field [failCRC,cfgUsers] = heSIGBUserFieldDecode(rxSIGB,preHEChanEst,noiseVar,cfgRx); % CRC on HE-SIG-B users if ~all(failCRC) fprintf(' HE-SIG-B (user field) CRC pass\n\n'); numUsers = numel(cfgUsers); elseif all(failCRC) % Discard the packet if all users fail the CRC error(' ** HE-SIG-B CRC fail for all users **'); else fprintf(' ** HE-SIG-B CRC fail for at least one user\n **'); % Only process users with valid CRC numUsers = numel(cfgUsers); end else % HE SU, HE EXT SU cfgUsers = {cfgRx}; numUsers = 1; end
Decoding HE-SIG-B...
Decoding HE-SIG-B common field...
HE-SIG-B (common field) CRC pass
Decoding HE-SIG-B user field...
HE-SIG-B (user field) CRC pass
HE-Data Decoding
Use the updated wlanHERecoveryConfig
object for each user to recover the PSDU bits for each user in the HE-Data field.
cfgDataRec = trackingRecoveryConfig;
fprintf('Decoding HE-Data...\n');
Decoding HE-Data...
for iu = 1:numUsers % Get recovery configuration object for each user user = cfgUsers{iu}; if strcmp(pktFormat,'HE-MU') fprintf(' Decoding User:%d, STAID:%d, RUSize:%d\n',iu,user.STAID,user.RUSize); else fprintf(' Decoding RUSize:%d\n',user.RUSize); end heInfo = wlanHEOFDMInfo('HE-Data',chanBW,user.GuardInterval,[user.RUSize user.RUIndex]); % HE-LTF demodulation and channel estimation rxHELTF = rx(pktOffset+(ind.HELTF(1):ind.HELTF(2)),:); heltfDemod = wlanHEDemodulate(rxHELTF,'HE-LTF',chanBW,user.GuardInterval,user.HELTFType,[user.RUSize user.RUIndex]); [chanEst,pilotEst] = wlanHELTFChannelEstimate(heltfDemod,user); % Number of expected data OFDM symbols symLen = heInfo.FFTLength+heInfo.CPLength; numOFDMSym = double((ind.HEData(2)-ind.HEData(1)+1))/symLen; % HE-Data demodulation with pilot phase and time tracking % Account for extra samples when extracting data field from the packet % for sample rate offset tracking. Extra samples may be required if the % receiver clock is significantly faster than the transmitter. maxSRO = 120; % Parts per million Ne = ceil(numRxSamples*maxSRO*1e-6); % Number of extra samples Ne = min(Ne,rxWaveLen-numRxSamples); % Limited to length of waveform numRxSamplesProcess = numRxSamples+Ne; rxData = rx(pktOffset+(ind.HEData(1):numRxSamplesProcess),:); if user.RUSize==26 % Force phase only tracking for 26-tone RU as algorithm susceptible to noise cfgDataRec.PilotTimeTracking = false; cfgDataRec.PilotPhaseTracking = phaseTracking; else cfgDataRec.PilotTimeTracking = timeTracking; cfgDataRec.PilotPhaseTracking = phaseTracking; end demodSym = helperTrackingOFDMDemodulate(rxData,chanEst,numOFDMSym,user,cfgDataRec); % Estimate noise power in HE fields demodPilotSym = demodSym(heInfo.PilotIndices,:,:); nVarEst = wlanHEDataNoiseEstimate(demodPilotSym,pilotEst,user); % Equalize [eqSym,csi] = wlanHEEqualize(demodSym,chanEst,nVarEst,user,'HE-Data'); % Discard pilot subcarriers eqSymUser = eqSym(heInfo.DataIndices,:,:); csiData = csi(heInfo.DataIndices,:); % Demap and decode bits rxPSDU = wlanHEDataBitRecover(eqSymUser,nVarEst,csiData,user,'LDPCDecodingMethod','norm-min-sum'); % Deaggregate the A-MPDU [mpduList,~,status] = wlanAMPDUDeaggregate(rxPSDU,wlanHESUConfig); if strcmp(status,'Success') fprintf(' A-MPDU deaggregation successful \n'); else fprintf(' A-MPDU deaggregation unsuccessful \n'); end % Decode the list of MPDUs and check the FCS for each MPDU for i = 1:numel(mpduList) [~,~,status] = wlanMPDUDecode(mpduList{i},wlanHESUConfig,'DataFormat','octets'); if strcmp(status,'Success') fprintf(' FCS pass for MPDU:%d\n',i); else fprintf(' FCS fail for MPDU:%d\n',i); end end % Plot equalized constellation of the recovered HE data symbols for all % spatial streams per user helperPlotEQConstellation(eqSymUser,user,ConstellationDiagram,iu,numUsers); % Measure EVM of HE-Data symbols release(EVM); EVM.ReferenceConstellation = wlanReferenceSymbols(user); rmsEVM = EVM(eqSymUser(:)); fprintf(' HE-Data EVM:%2.2fdB\n\n',20*log10(rmsEVM/100)); % Plot EVM per symbol of the recovered HE data symbols helperPlotEVMPerSymbol(eqSymUser,user,EVMPerSymbol,iu,numUsers); % Plot EVM per subcarrier of the recovered HE data symbols helperPlotEVMPerSubcarrier(eqSymUser,user,EVMPerSubcarrier,iu,numUsers); end
Decoding User:1, STAID:1, RUSize:52
A-MPDU deaggregation successful
FCS pass for MPDU:1
HE-Data EVM:-28.89dB
Decoding User:2, STAID:2, RUSize:52
A-MPDU deaggregation successful
FCS pass for MPDU:1
HE-Data EVM:-39.59dB
Decoding User:3, STAID:3, RUSize:106
A-MPDU deaggregation successful
FCS pass for MPDU:1
HE-Data EVM:-28.07dB
Decoding User:4, STAID:4, RUSize:106
A-MPDU deaggregation successful
FCS pass for MPDU:1
HE-Data EVM:-30.89dB
Selected Bibliography
IEEE Std 802.11ax™-2021. IEEE Standard for Information Technology - Telecommunications and Information Exchange between Systems - Local and Metropolitan Area Networks - Specific Requirements - Part 11: Wireless LAN Medium Access Control (MAC) and Physical Layer (PHY) Specifications - Amendment 1: Enhancements for High-Efficiency WLAN.
IEEE Std 802.11™-2020 Standard for Information Technology - Telecommunications and Information Exchange between Systems - Local and Metropolitan Area Networks - Specific Requirements - Part 11: Wireless LAN Medium Access Control (MAC) and Physical Layer (PHY) Specifications.