220 lines
9.1 KiB
Mathematica
220 lines
9.1 KiB
Mathematica
![]() |
%% 解包头
|
||
|
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
|
||
|
% <matlab:edit('wlanHERecoveryConfig.m') 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 = 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 <matlab:edit('wlanHERecoveryConfig.m') 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)
|
||
|
|
||
|
%% 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 <matlab:edit('wlanHERecoveryConfig.m') 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 [ <#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
|
||
|
|