%% 解包头 function [cfgRx,cfgUsers,rmsEVM,failCRC] = demodSIG(rx,rx_format,cfgUI)%% Packet Format Detection %% 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 [ <#16 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 % 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 = preHECommonPhaseErrorTracking(helsigDemod,lltfChanEst,'L-SIG',chanBW); % Estimate channel on extra 4 subcarriers per subchannel and create full % channel estimate preheInfo = wlanHEOFDMInfo('L-SIG',chanBW); preHEChanEst = preHEChannelEstimate(helsigDemod,lltfChanEst,preheInfo.NumSubchannels); % Average L-SIG and RL-SIG before equalization helsigDemod = mean(helsigDemod,2); % Equalize data carrying subcarriers, merging 20 MHz subchannels [eqLSIGSym,csi] = preHESymbolEqualize(helsigDemod(preheInfo.DataIndices,:,:), ... preHEChanEst(preheInfo.DataIndices,:,:),noiseVar,preheInfo.NumSubchannels); % 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); %% % 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 = preHECommonPhaseErrorTracking(sigaDemod,preHEChanEst,'HE-SIG-A',chanBW); % Equalize data carrying subcarriers, merging 20 MHz subchannels preheInfo = wlanHEOFDMInfo('HE-SIG-A',chanBW); [eqSIGASym,csi] = preHESymbolEqualize(hesigaDemod(preheInfo.DataIndices,:,:), ... preHEChanEst(preheInfo.DataIndices,:,:), ... noiseVar,preheInfo.NumSubchannels); % 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)); %% Interpret Recovered HE-SIG-A bits % The 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) %% 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 [ <#16 1> Table. 27-23]. 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 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 [ <#16 1> % Table. 27-25, 27-26]. % % 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+(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 end