www.gusucode.com > wlan工具箱matlab源码程序 > wlan/wlanexamples/helperSymbolTiming.m
function startIdx = helperSymbolTiming(x, chanBW, varargin) %helperSymbolTiming Perform symbol timing based on L-LTF in time-domain % STARTIDX = helperSymbolTiming(X, CHANBW) returns the estimated starting % index for the Non-HT Long Training Field (L-LTF), using % cross-correlation method. % % STARTIDX is an integer scalar indicating the starting index relative to % X for the first L-LTF this function successfully detects. STARTIDX % could be a non-positive number, which typically happens when X starts % in the middle of a L-LTF. STARTIDX is set to empty when this function % does not detect any L-LTF. % % X is the received time-domain signal on which symbol timing is % performed. It is a Ns-by-Nr matrix of real or complex values, where Ns % represents the number of time-domain samples and Nr represents the % number of receive antennas. % % CHANBW is the channel bandwidth, one of 'CBW20', 'CBW40', 'CBW80' and % 'CBW160'. % % STARTIDX = helperSymbolTiming(..., THRESHOLD) specifies the relative % threshold for L-LTF peak detection after cross-correlation as a real % scalar between 0 and 1, exclusive. When unspecified a value of 0.3 is % used. % % % Example: % % Introduce a delay to L-LTF and perform symbol timing on it. % % cfgHT = wlanHTConfig('ChannelBandwidth', 'CBW40'); % txLLTF = wlanLLTF(cfgHT); % L-LTF generation % txSig = [zeros(15,1); txLLTF]; % Introduce a delay % rxSig = awgn(txSig, 1, 1); % Add noise % % % Perform symbol timing and expect the returned index to be 16 % LLTFIdx = helperSymbolTiming(rxSig, 'CBW40') % % % If the input starts in L-LTF, the returned index can be 0 or negative % LLTFIdx = helperSymbolTiming(rxSig(17:end,:), 'CBW40') % Should be 0 % LLTFIdx = helperSymbolTiming(rxSig(18:end,:), 'CBW40') % Should be -1 % % See also wlanCoarseCFOEstimate, wlanFineCFOEstimate. %#codegen narginchk(2,3); validateattributes(x, {'double'}, {'2d','finite'}, mfilename, 'signal input'); if isempty(x) startIdx = []; return; end if ~any(strcmp(chanBW,{'CBW5','CBW10','CBW20','CBW40','CBW80','CBW160'})) error(['The chanBW input must be one of ''CBW5'', ''CBW10'',' ... ' ''CBW20'', ''CBW40'', ''CBW80'' and ''CBW160''.']); end if nargin == 2 threshold = .3; else validateattributes(varargin{1}, {'double'}, ... {'real','scalar','>',0,'<',1}, mfilename, 'threshold'); threshold = varargin{1}; end FFTLen = helperFFTLength(chanBW); symLen = FFTLen * 5/4; bufLen = 4*symLen; xLen = size(x, 1); if (strcmp(chanBW,'CBW5') || strcmp(chanBW,'CBW10')) chanBW = 'CBW20'; % override for VHTConfig use below. end cfgVHT = wlanVHTConfig('ChannelBandwidth', chanBW); LLTF = wlanLLTF(cfgVHT); coeff = conj(flipud(LLTF(1:symLen,1))); if xLen <= FFTLen startIdx = []; elseif xLen <= bufLen corr = sum(abs(filter(coeff, 1, x)).^2, 2); peakIdx = find(corr > max(corr)*threshold); startIdx = processCorr(peakIdx, FFTLen, symLen, bufLen, 0); else % xLen > bufLen bufEndIdx = 0; filterState = complex(zeros(symLen-1, size(x, 2))); numSampNext = bufLen; corr = zeros(bufLen, 1); startIdxInBuf = []; while numSampNext > 0 [corrNew, filterState] = filter(coeff, 1, x(bufEndIdx+(1:numSampNext), :), filterState); bufEndIdx = bufEndIdx + numSampNext; corr(1:bufLen) = [corr(numSampNext+1:bufLen, 1); sum(abs(corrNew).^2, 2)]; peakIdx = find(corr > max(corr)*threshold); [startIdxInBuf, numSampNext] = processCorr(peakIdx, FFTLen, symLen, bufLen, xLen - bufEndIdx); end startIdx = bufEndIdx - bufLen + startIdxInBuf; end startIdx = startIdx - symLen + 1; end function [startIdx, numSampNext] = processCorr(peakIdx, FFTLen, symLen, bufLen, leftSamples) numPeaks = length(peakIdx); if numPeaks > .1*bufLen % Most likely noise input if 10% samples are over threshold startIdx = []; numSampNext = min(symLen, leftSamples); else % do some validation [numPairs, lastPair1stIdx, lastPair2ndIdx] = deal(0); i = 1; secondClusterStartIdx = numPeaks+1; while i < secondClusterStartIdx thisPair2ndIdx = find(peakIdx(i) + FFTLen == peakIdx); if ~isempty(thisPair2ndIdx) numPairs = numPairs + 1; lastPair1stIdx = peakIdx(i); lastPair2ndIdx = peakIdx(thisPair2ndIdx(1)); if (numPairs == 1) && (secondClusterStartIdx == numPeaks + 1) secondClusterStartIdx = thisPair2ndIdx(1); end end i = i + 1; end if numPairs == 0 startIdx = []; numSampNext = min(3*symLen, leftSamples); elseif (lastPair2ndIdx > bufLen - symLen/2) && (leftSamples > 0) % numPairs > 0 startIdx = []; numSampNext = min(symLen, leftSamples); else startIdx = lastPair1stIdx; numSampNext = 0; end end end % [EOF]