90 lines
3.1 KiB
Mathematica
90 lines
3.1 KiB
Mathematica
![]() |
function [rx_datafield,MCS,PSDULength,failCheck,rec_frameNo,estNumerlogy,numeroError] = rx_preambleprocess(rx)
|
||
|
|
||
|
searchOffset = 0; % Offset from start of waveform in samples
|
||
|
rxWaveLen = 30000;
|
||
|
cfg = wlanNonHTConfig('SignalChannelBandwidth',true, ...
|
||
|
'BandwidthOperation','Static');
|
||
|
|
||
|
% Generate field indices
|
||
|
ind = wlanFieldIndices(cfg);
|
||
|
chanBW = cfg.ChannelBandwidth;
|
||
|
sr = wlanSampleRate(cfg); % Sample rate
|
||
|
|
||
|
% while (searchOffset + minPktLen) <= rxWaveLen
|
||
|
|
||
|
% Packet detection
|
||
|
threshold = 0.8;
|
||
|
|
||
|
[pktOffset,M] = wlanPacketDetect(rx,chanBW,searchOffset,threshold);
|
||
|
plot(M)
|
||
|
% 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 = helperFrequencyOffset(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 = helperFrequencyOffset(rx,sr,-fineFreqOffset);
|
||
|
|
||
|
% Scale the waveform based on L-STF power (AGC)
|
||
|
gain = 1./(sqrt(mean(rxLSTF.*conj(rxLSTF))));
|
||
|
rx = rx.*gain;
|
||
|
|
||
|
% Packet Format Detection
|
||
|
rxLLTF = rx(pktOffset+(ind.LLTF(1):ind.LLTF(2)),:);
|
||
|
lltfDemod = wlanLLTFDemodulate(rxLLTF,chanBW);
|
||
|
lltfChanEst = wlanLLTFChannelEstimate(lltfDemod,chanBW);
|
||
|
noiseVar = helperNoiseEstimate(lltfDemod);
|
||
|
|
||
|
% Recover L-SIG field bits
|
||
|
[rxLSIGBits, failCheck, ~] = wlanLSIGRecover(rx(pktOffset + (ind.LSIG(1):ind.LSIG(2)), :), lltfChanEst, noiseVar, chanBW);
|
||
|
[MCS,PSDULength] = interpretLSIG(rxLSIGBits);
|
||
|
rec_frameNo = bi2de(rxLSIGBits(19:24).','right-msb');
|
||
|
|
||
|
if failCheck % Skip L-STF length of samples and continue searching
|
||
|
disp('** L-SIG check fail **');
|
||
|
else
|
||
|
disp('L-SIG check pass');
|
||
|
end
|
||
|
|
||
|
% Recover Numerology field bits
|
||
|
rxLSTF = rx(pktOffset+(ind.LSTF(1):ind.LSTF(2)), :);
|
||
|
[estNumerlogy,numeroError] = STS_demod(rxLSTF);
|
||
|
if numeroError
|
||
|
disp('** Numerology check fail **');
|
||
|
else
|
||
|
disp('Numerology check pass');
|
||
|
end
|
||
|
|
||
|
% output data field
|
||
|
% rx_datafield = rx(pktOffset+(ind.NonHTData(1):ind.NonHTData(2)), :);
|
||
|
rx_datafield = rx(pktOffset+ind.NonHTData(1):end, :);
|
||
|
end
|
||
|
%%
|
||
|
function [MCS,PSDULength] = interpretLSIG(recLSIGBits)
|
||
|
% InterpretLSIG Interprets recovered L-SIG bits
|
||
|
%
|
||
|
% [MCS,PSDULENGTH] = interpretLSIG(RECLSIGBITS) returns the
|
||
|
% modulation and coding scheme and PSDU length given the recovered L-SIG
|
||
|
% bits
|
||
|
|
||
|
% Rate and length are determined from bits
|
||
|
rate = double(recLSIGBits(1:3));
|
||
|
length = double(recLSIGBits(5+(1:12)));
|
||
|
|
||
|
% MCS rate table, IEEE Std 802.11-2016, Table 17-6.
|
||
|
R = wlan.internal.nonHTRateSignalBits();
|
||
|
mcstmp = find(all(bsxfun(@eq,R(1:3,:),rate)))-1;
|
||
|
MCS = mcstmp(1); % For codegen
|
||
|
PSDULength = bi2de(length.');
|
||
|
|
||
|
end
|