Impl task1 some part of task2
This commit is contained in:
@@ -0,0 +1,245 @@
|
||||
classdef hWLANPacketDetector < handle & comm.internal.ConfigBase
|
||||
%hWLANPacketDetector OFDM packet detection using the L-STF
|
||||
%
|
||||
% WPD = hWLANPacketDetector(X,CBW) creates an hWLANPacketDetector object,
|
||||
% WPD, that sets the Waveform property to X and ChannelBandwidth to CBW.
|
||||
%
|
||||
% WPD = hWLANPacketDetector(...,Name,Value) creates an
|
||||
% hWLANPacketDetector object, WPD, with the specified property Name set
|
||||
% to the specified Value. You can specify additional name-value pair
|
||||
% arguments in any order as (Name1,Value1,...,NameN,ValueN).
|
||||
%
|
||||
% hWLANPacketDetector methods:
|
||||
%
|
||||
% findPacketStart - Returns the offset to the start of a detected
|
||||
% packet in Waveform
|
||||
%
|
||||
% hWLANPacketDetector properties:
|
||||
%
|
||||
% Waveform - A time-domain signal specified as a Ns-by-Nr
|
||||
% matrix of real or complex float values where Ns
|
||||
% represents the number of time domain samples and
|
||||
% Nr represents the number of receive antennas.
|
||||
% ChannelBandwidth - A text scalar describing the channel bandwidth of
|
||||
% WAVEFORM. The value must be 'CBW5', 'CBW10',
|
||||
% 'CBW20', 'CBW40', 'CBW80', 'CBW160', or 'CBW320'.
|
||||
% OversamplingFactor - The oversampling factor of WAVEFORM. The value
|
||||
% must be greater than or equal to 1. The default is
|
||||
% 1.
|
||||
% Threshold - The threshold which the decision statistic must
|
||||
% meet or exceed to detect a packet in WAVEFORM when
|
||||
% calling FINDPACKETSTART. The value must be a real
|
||||
% scalar that is greater than 0 and less than or
|
||||
% equal to 1. The default is 0.5.
|
||||
% SearchOffset - The index from which FINDPACKETSTART looks for a
|
||||
% packet. The value must be a real scalar integer
|
||||
% that is greater than or equal to 0 and less than
|
||||
% Ns in WAVEFORM. The default is 0.
|
||||
%
|
||||
%
|
||||
% % Example 1:
|
||||
% % Detect a received 802.11a packet
|
||||
% cfgNonHT = wlanNonHTConfig; % Create packet configuration
|
||||
%
|
||||
% % Generate transmit waveform
|
||||
% txWaveform = wlanWaveformGenerator([1;0;0;1],cfgNonHT, ...
|
||||
% 'WindowTransitionTime',0);
|
||||
%
|
||||
% % Delay the signal by appending zeros at the start
|
||||
% rxWaveform = [zeros(20,1);txWaveform];
|
||||
%
|
||||
% wpd = hWLANPacketDetector(rxWaveform,cfgNonHT.ChannelBandwidth);
|
||||
% wpd.SearchOffset = 5;
|
||||
% wpd.Threshold = 0.99;
|
||||
%
|
||||
% startOffset = findPacketStart(wpd);
|
||||
%
|
||||
% disp("Packet start offset: " + startOffset)
|
||||
|
||||
% Copyright 2024 The MathWorks, Inc.
|
||||
|
||||
properties
|
||||
Waveform {mustBeFloat,mustBeFinite} = [];
|
||||
ChannelBandwidth {mustBeTextScalar} = 'CBW20';
|
||||
OversamplingFactor (1,1) {mustBeNumeric, mustBeFinite, mustBeGreaterThanOrEqual(OversamplingFactor, 1)} = 1;
|
||||
Threshold (1,1) {mustBeFloat, mustBeReal, mustBeInRange(Threshold,0,1,'exclude-lower')} = 0.5;
|
||||
SearchOffset (1,1) {mustBeNumeric,mustBeInteger,mustBeNonnegative} = 0;
|
||||
end
|
||||
|
||||
properties(Access=private)
|
||||
UpdateDecisionStatistic = true;
|
||||
UpdatePacketOffsets = true;
|
||||
FoundOffsets;
|
||||
DecisionStatistic;
|
||||
DetectedColumnIndicies;
|
||||
end
|
||||
|
||||
methods
|
||||
function obj = hWLANPacketDetector(wav,cbw,opts)
|
||||
arguments
|
||||
wav;
|
||||
cbw;
|
||||
opts.Threshold
|
||||
opts.OversamplingFactor
|
||||
opts.SearchOffset
|
||||
end
|
||||
nvpairs = [{'Waveform' wav 'ChannelBandwidth' cbw} namedargs2cell(opts)];
|
||||
obj@comm.internal.ConfigBase(nvpairs{:});
|
||||
end
|
||||
|
||||
function [startOffset,M] = findPacketStart(obj)
|
||||
%findPacketStart Return the offset of a detected packet
|
||||
%
|
||||
% [STARTOFFSET,M] = findPacketStart(OBJ) returns the index of a
|
||||
% detected packet in WAVEFORM. The index returned is the next
|
||||
% closest index to SEARCHOFFSET. If no packet is detected an empty
|
||||
% value is returned.
|
||||
%
|
||||
% OBJ is a hWLANPacketDetector object.
|
||||
%
|
||||
% STARTOFFSET is an integer scalar indicating the location of the
|
||||
% start of a detected packet.
|
||||
%
|
||||
% M is a real vector of size N-by-1, representing the decision
|
||||
% statistics based on auto-correlation of WAVEFORM. The
|
||||
% length of N depends on index of a successful detection of a
|
||||
% packet.
|
||||
|
||||
if isempty(obj.Waveform)
|
||||
startOffset = [];
|
||||
M = [];
|
||||
return;
|
||||
end
|
||||
|
||||
cbw = obj.ChannelBandwidth;
|
||||
[fftLen,nsc] = wlan.internal.cbw2nfft(cbw);
|
||||
osf = obj.OversamplingFactor;
|
||||
wlan.internal.validateOFDMOSF(osf, fftLen, 0); % Validate OSF
|
||||
|
||||
Td = 0.8e-6; % Time period of a short training symbol for 20MHz
|
||||
symbolLength = Td*osf*nsc*20e6;
|
||||
|
||||
lenLSTF = symbolLength*10; % Length of 10 L-STF symbols
|
||||
lenHalfLSTF = lenLSTF/2; % Length of 5 L-STF symbols
|
||||
|
||||
if obj.UpdateDecisionStatistic
|
||||
inpLength = size(obj.Waveform,1);
|
||||
|
||||
% Append zeros to make the input equal to multiple of L-STF/2
|
||||
if inpLength<=lenHalfLSTF
|
||||
numPadSamples = lenLSTF - inpLength;
|
||||
else
|
||||
numPadSamples = lenHalfLSTF*ceil(inpLength/lenHalfLSTF) - inpLength;
|
||||
end
|
||||
|
||||
padSamples = zeros(numPadSamples,size(obj.Waveform,2),'like',obj.Waveform);
|
||||
|
||||
% Process the input waveform in blocks of L-STF length. The processing
|
||||
% blocks are offset by half the L-STF length.
|
||||
numBlocks = (inpLength + numPadSamples)/lenHalfLSTF;
|
||||
|
||||
searchBuffer = reshape([obj.Waveform;padSamples],lenHalfLSTF,numBlocks,size(obj.Waveform,2));
|
||||
searchBuffer = [searchBuffer(:,1:end-1,:);searchBuffer(:,2:end,:)];
|
||||
|
||||
[obj.FoundOffsets,obj.DecisionStatistic,obj.DetectedColumnIndicies] = ...
|
||||
wlan.internal.detectPackets(searchBuffer,symbolLength, ...
|
||||
lenLSTF,obj.Threshold);
|
||||
|
||||
obj.UpdateDecisionStatistic = false;
|
||||
obj.UpdatePacketOffsets = false;
|
||||
elseif obj.UpdatePacketOffsets
|
||||
% obj.Threshold was updated so update the offsets
|
||||
[obj.FoundOffsets,obj.DetectedColumnIndicies] = ...
|
||||
getPacketOffsets(obj.DecisionStatistic,symbolLength, ...
|
||||
lenLSTF,obj.Threshold);
|
||||
|
||||
obj.UpdatePacketOffsets = false;
|
||||
end
|
||||
|
||||
idx = find(obj.FoundOffsets >= obj.SearchOffset,1);
|
||||
startOffset = obj.FoundOffsets(idx);
|
||||
|
||||
if isempty(idx)
|
||||
endIdx = size(obj.DecisionStatistic,2);
|
||||
else
|
||||
endIdx = obj.DetectedColumnIndicies(idx);
|
||||
end
|
||||
|
||||
M = double([reshape(obj.DecisionStatistic(1:lenHalfLSTF,1:endIdx-1),[],1); ...
|
||||
reshape(obj.DecisionStatistic(:,endIdx),[],1)]);
|
||||
end % function findPacketStart
|
||||
|
||||
% Setters
|
||||
function set.Waveform(obj,value)
|
||||
if ~isequal(obj.Waveform,value)
|
||||
obj.Waveform = value;
|
||||
obj.UpdateDecisionStatistic = true; %#ok<*MCSUP>
|
||||
end
|
||||
end
|
||||
|
||||
function set.ChannelBandwidth(obj,value)
|
||||
if ~strcmpi(obj.ChannelBandwidth,value)
|
||||
obj.ChannelBandwidth = wlan.internal.validateParam('NONHTEHTCHANBW', value, mfilename);
|
||||
obj.UpdateDecisionStatistic = true;
|
||||
end
|
||||
end
|
||||
|
||||
function set.OversamplingFactor(obj,value)
|
||||
if ~isequal(obj.OversamplingFactor,value)
|
||||
obj.OversamplingFactor = value;
|
||||
obj.UpdateDecisionStatistic = true;
|
||||
end
|
||||
end
|
||||
|
||||
function set.Threshold(obj,value)
|
||||
if ~isequal(obj.Threshold,value)
|
||||
obj.Threshold = value;
|
||||
obj.UpdatePacketOffsets = true;
|
||||
end
|
||||
end
|
||||
|
||||
function set.SearchOffset(obj,value)
|
||||
coder.internal.errorIf(~isempty(obj.Waveform) && value>size(obj.Waveform, 1)-1, 'wlan:shared:InvalidOffsetValue')
|
||||
obj.SearchOffset = value;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function [packetStarts,colIdxs] = getPacketOffsets(mn,symbolLength,lenLSTF,threshold)
|
||||
% mn: Decision statistic
|
||||
% threshold: Decision threshold as specified by user
|
||||
N = mn > threshold;
|
||||
colDesc = sum(N) >= symbolLength*1.5;
|
||||
N(:,~colDesc) = false;
|
||||
colIdxs = find(colDesc);
|
||||
|
||||
% Create a matrix of indicies where each column has the value 1:corrLen
|
||||
% then extract indices based on N and desc and calculate all possible
|
||||
% packet start locations
|
||||
corrLen = lenLSTF - (symbolLength*2) + 1;
|
||||
idxs = repmat((1:corrLen)',1,size(N,2));
|
||||
idxs(~N) = NaN;
|
||||
idxs = idxs(:,colDesc);
|
||||
packetStarts = min(idxs) + (colIdxs-1)*lenLSTF/2 - 1;
|
||||
|
||||
% Check relative distances between peaks for all detected packets
|
||||
if ~isempty(packetStarts)
|
||||
packetStarts = arrayfun(@(x)checkRelativeDist(packetStarts(x),idxs(:,x),symbolLength),1:length(packetStarts));
|
||||
end
|
||||
|
||||
% Extract non-NaN values
|
||||
colIdxs = colIdxs(~isnan(packetStarts));
|
||||
packetStarts = packetStarts(~isnan(packetStarts));
|
||||
|
||||
end
|
||||
|
||||
function pS = checkRelativeDist(pS,idxs,symbolLength)
|
||||
% Check the relative distance between peaks relative to the first peak. If
|
||||
% this exceed three times the symbol length then the packet is not
|
||||
% detected.
|
||||
nonan = idxs(~isnan(idxs));
|
||||
if any(nonan(2:symbolLength) - nonan(1)>symbolLength*3)
|
||||
pS = NaN;
|
||||
end
|
||||
|
||||
end
|
||||
Reference in New Issue
Block a user