Recovery Procedure for an 802.11ax Packet
This example shows how to detect a packet and decode payload bits in a received IEEE® 802.11ax™ 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 transmission parameters are signaled to the receiver using the L-SIG, HE-SIG-A, and HE-SIG-B preamble fields [ 1 ]:
The L-SIG field contains information to allow the receiver to determine 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 combination of length information in the L-SIG field, the modulation type, and the number of OFDM symbols in the HE-SIG-A field determines 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.
In this example we detect and decode an HE-MU packet within a generated waveform. This example can also recover HE-SU and HE-EXT-SU packets. All transmission parameters apart from the channel bandwidth are assumed to be unknown and are therefore retrieved from the decoded L-SIG, HE-SIG-A, and HE-SIG-B preamble fields. The recovered transmission parameters are used to decode the HE-Data field. Additionally, the following analysis is performed:
The waveform of the detected packet is recovered and displayed.
The spectrum of the detected packet is recovered and displayed.
The constellation of the equalized data symbols for all spatial streams is displayed.
The Error Vector Magnitude (EVM) of each field is measured.
An A-MPDU is detected and Frame Check Sequence (FCS) is determined for the recovered MAC frame.
The EVM per data symbol and spatial stream averaged over subcarriers is displayed.
The EVM per data subcarrier and spatial stream averaged over symbols is displayed.
Waveform Transmission
In this example an 802.11ax HE-MU waveform is synthesized but you can use a captured waveform. You can use MATLAB® to acquire I/Q data from a wide range of instruments with the Instrument Control Toolbox™ and software defined radio platforms.
The synthesized waveform is impaired by a 2x2 TGax indoor fading channel, additive white Gaussian noise, and carrier frequency offset. To generate an HE-MU waveform we configure an HE-MU format configuration object wlanHEMUConfig. Note that the wlanHEMUConfig configuration object is used at the transmitter side only. The receiver will formulate an HE recovery configuration object wlanHERecoveryConfig. The unknown properties of the HE recovery configuration object are set 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. The following processing steps are performed:
A random payload of MSDUs is created for the MAC frame, which is encoded into an HE-MU packet.
The waveform is passed through a TGax indoor fading channel model.
Carrier frequency offset (CFO) and Additive white Gaussian noise (AWGN) are added to the waveform.
% A mixed OFDMA and MU-MIMO configuration is defined 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 a MU-MIMO % configuration. 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
The signal to process is stored in the variable rx
. The processing steps to recover a packet are:
An HE recovery configuration object, wlanHERecoveryConfig is created. The object properties are updated as preamble fields are decoded.
The packet is detected and synchronized.
The L-LTF is extracted and demodulated. The demodulated L-LTF symbols do not include tone rotation for each 20 MHz segment as described in [ 2 ], section 21.3.7.5.
The demodulated L-LTF symbols are used for channel and noise estimates.
The time-domain signal containing samples equivalent to four OFDM symbols immediately following the L-LTF are used to determine the HE packet format. The packet format is updated in the wlanHERecoveryConfig object.
The L-LTF is demodulated. The demodulated L-LTF symbols include tone rotation for each 20 MHz segment as described in [ 2 ], section 21.3.7.5. The L-LTF channel estimates (with tone rotation) are used to decode the pre-HE-LTF.
The L-SIG and RL-SIG fields are extracted. The channel is estimated on an extra four subcarriers per subchannel in the L-SIG and RL-SIG fields. The L-LTF channel estimates are updated to include the channel estimates on the extra subcarriers.
The information bits in the L-SIG field are recovered to determine the length of the packet in microseconds.
After HE-SIG-A decoding, the recovery configuration object is updated with common transmission parameters for an HE-MU packet and all transmission parameters for HE-SU and HE-EXT-SU packets.
For an HE-MU packet format the HE-SIG-B field is decoded. For a non-compressed SIGB waveform the HE-SIG-B common field is decoded first followed by 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 the RU allocation and user transmission parameters are recovered from the HE-SIG-B field. For a compressed SIGB waveform the RU allocation information is inferred from HE-SIG-A field and the user transmission parameters are determined from the HE-SIG-B user field bits.
The wlanHERecoveryConfig object is created using the recovered transmission parameters for each user after HE-SIG-B decoding.
The HE-LTF field is extracted and demodulated. The demodulated symbols are used for channel estimation of the subcarriers allocated to the user of interest. The MIMO channel estimates are used to decode the HE-Data field.
The HE-Data field is extracted and the PSDU bits are recovered using the wlanHERecoveryConfig object for each user.
Detect A-MPDU within the recovered PSDU and check the FCS for the recovered MAC frame.
Setup Waveform Recovery Parameters
In this example all transmission parameters apart from the channel bandwidth are assumed to be unknown and will be recovered. A recovery configuration object, wlanHERecoveryConfig, is created to store the recovered information in the L-SIG, HE-SIG-A, and HE-SIG-B preamble fields. The transmission properties in wlanHERecoveryConfig are updated after subsequent decoding of the preamble fields. The following code configures objects 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. This can be: % 'Joint' - use joint common phase error and sample rate offset tracking % 'CPE' - use only common phase error tracking % When recovering 26-tone RUs only CPE tracking is used as the joint % tracking algorithm is susceptible to noise. pilotTracking = 'Joint'; % 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 consists of packet detection, coarse carrier frequency offset correction, timing synchronization, and fine carrier frequency offset correction. A while
loop is used to detect and synchronize a packet within the received waveform. The sample offset searchOffset
is used to index into rx
to detect a packet. The first packet within rx
is detected and processed. If the synchronization fails for the detected packet, the sample index offset searchOffset
is incremented to move beyond the processed packet in rx
. This is repeated until a packet has been successfully detected and 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 % Scale the waveform based on L-STF power (AGC) gain = 1./(sqrt(mean(rxLSTF.*conj(rxLSTF)))); rx = rx.*gain;
Packet detected at index 404 Estimated CFO: 61942.9 Hz
Packet Format Detection
The time-domain samples equivalent to four OFDM symbols immediately following the L-LTF are used to determine the HE packet format [ 1 Figure. 27-63]. The L-LTF is extracted and demodulated. 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. The demodulated L-LTF is used for channel and noise estimation. The L-LTF channel (without tone rotation) and noise power estimates are used to detect the packet format.
rxLLTF = rx(pktOffset+(ind.LLTF(1):ind.LLTF(2)),:); lltfDemod = wlanLLTFDemodulate(rxLLTF,chanBW); lltfChanEst = wlanLLTFChannelEstimate(lltfDemod,chanBW); noiseVar = wlanLLTFNoiseEstimate(lltfDemod); disp('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); % Set the packet format in the recovery object and update the field indices cfgRx.PacketFormat = pktFormat; ind = wlanFieldIndices(cfgRx);
Detect packet format... HE-MU packet detected
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 L-LTF channel estimates (with tone rotation) are used 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 is used to determine the receive time, or RXTIME, of the packet. The RXTIME is calculated using the length bits of the L-SIG payload. The L-SIG and RL-SIG fields are recovered to perform the channel estimate on the extra subcarriers in the L-SIG and RL-SIG fields. The lltfChanEst
channel estimates are updated to include the channel estimates on extra subcarriers in the L-SIG and RL-SIG fields. The L-SIG payload is decoded using an estimate of the channel and noise power obtained from the L-LTF field. The L-SIG length property in wlanHERecoveryConfig is updated after L-SIG decoding.
disp('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 % 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)); % 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); fprintf(' Number of samples in the packet: %d\n\n',numRxSamples);
Decoding L-SIG... L-SIG check pass L-SIG EVM: -36.91dB RXTIME: 536us Number of samples in the packet: 10720
The waveform and spectrum of the detected packet within rx
is displayed given the calculated RXTIME and corresponding number of samples.
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. An estimate of the channel and noise power obtained from the L-LTF is required to decode the HE-SIG-A field.
disp('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 % 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));
Decoding HE-SIG-A... HE-SIG-A CRC pass HE-SIG-A EVM: -35.17dB
Interpret Recovered HE-SIG-A bits
The wlanHERecoveryConfig object is updated 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 HE-SIG-A field for an HE-MU packet. The properties indicated by -1 are unknown or undefined. The unknown user-related properties are updated after successful decoding of 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 contains:
The RU allocation information for a non-compressed SIGB waveform is inferred from HE-SIG-B Common field [ 1 Table. 27-24]. For a compressed SIGB waveform the RU allocation information is inferred from the recovered HE-SIG-A bits.
For a non-compressed SIGB waveform the number of HE-SIG-B symbols are updated in the wlanHERecoveryConfig object. The symbols are only updated if the number of HE-SIG-B symbols indicated in the HE-SIG-A field is set to 15 and all content channels pass the CRC. The number of HE-SIG-B symbols indicated in the HE-SIG-A field are not updated if any HE-SIG-B content channel fails the CRC.
The user transmission parameters for both SIGB compressed and non-compressed waveforms are inferred from the HE-SIG-B user field [ 1 Table. 27-27, 27-28].
An estimate of the channel and noise power obtained from the L-LTF is required to decode the HE-SIG-B field.
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
The updated wlanHERecoveryConfig object for each user can then be used to recover the PSDU bits for each user in the HE-Data field.
cfgDataRec = trackingRecoveryConfig; cfgDataRec.PilotTracking = pilotTracking; fprintf('Decoding HE-Data...\n'); 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 timing 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 CPE only tracking for 26-tone RU as algorithm susceptible % to noise cfgDataRec.PilotTracking = 'CPE'; else cfgDataRec.PilotTracking = pilotTracking; 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 HE-Data... Decoding User:1, STAID:1, RUSize:52 A-MPDU deaggregation successful FCS pass for MPDU:1 HE-Data EVM:-28.61dB Decoding User:2, STAID:2, RUSize:52 A-MPDU deaggregation successful FCS pass for MPDU:1 HE-Data EVM:-39.94dB Decoding User:3, STAID:3, RUSize:106 A-MPDU deaggregation successful FCS pass for MPDU:1 HE-Data EVM:-28.22dB Decoding User:4, STAID:4, RUSize:106 A-MPDU deaggregation successful FCS pass for MPDU:1 HE-Data EVM:-31.44dB
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.