www.gusucode.com > wlan工具箱matlab源码程序 > wlan/wlanexamples/helperVHTConfigRecover.m
function [cfgVHTRx, numDataSym, crcBits, apepLen] = ... helperVHTConfigRecover(LSIGBits, VHTSIGABits, varargin) %helperVHTConfigRecover Recover VHT transmission configuration % % CFGVHT = helperVHTConfigRecover(LSIGBITS,VHTSIGABITS) returns a VHT % configuration object of type <a href="matlab:help('wlanVHTConfig')">wlanVHTConfig</a> given recovered % bits from L-SIG and VHT-SIG-A fields for a single-user or multi-user % transmission. % % CFGVHT = helperVHTConfigRecover(LSIGBITS,VHTSIGABITS,VHTSIGBBITS) % returns a VHT configuration object of type <a href="matlab:help('wlanVHTConfig')">wlanVHTConfig</a> given recovered % bits from L-SIG, VHT-SIG-A, and VHT-SIG-B fields for a single-user % transmission only. % % CFGVHT = helperVHTConfigRecover(LSIGBITS,VHTSIGABITS,VHTSIGBBITS, ... % USERNUMBER) returns a VHT configuration object of type <a href="matlab:help('wlanVHTConfig')">wlanVHTConfig</a> % given recovered bits from L-SIG, VHT-SIG-A, and VHT-SIG-B fields for a % user specified by USERNUMBER for a multi-user transmission. % % See also wlanVHTDataRecover, wlanVHTConfig. % Copyright 2015-2016 The MathWorks, Inc. %#codegen % Note: Best effort processing implies offering as much configuration % detail as possible based on inputs: % LSIG + VHTSIGA : for Single-user Tx % LSIG + VHTSIGA + VHTSIGB : for Single-user Tx % LSIG + VHTSIGA + VHTSIGB + UserNum : for Multi-user Tx narginchk(2,4); if nargin==3 VHTSIGBBits = varargin{1}; % For single-user transmission userNum = 1; elseif nargin==4 VHTSIGBBits = varargin{1}; % For multi-user transmission userNum = varargin{2}; else % two inputs VHTSIGBBits = []; % For single-user transmission userNum = 1; end % Retrieve information from VHT-SIG-A bits VHTSIGABits = double(reshape(VHTSIGABits, 24, 2)'); if all(VHTSIGABits(1,1:2) == [0 0]) chanBW = 'CBW20'; numSD = 52; elseif all(VHTSIGABits(1,1:2) == [1 0]) chanBW = 'CBW40'; numSD = 108; elseif all(VHTSIGABits(1,1:2) == [0 1]) chanBW = 'CBW80'; numSD = 234; else chanBW = 'CBW160'; numSD = 468; end stbc = logical(VHTSIGABits(1, 4)); groupID = bi2de(VHTSIGABits(1, 5:10)); if groupID == 0 || groupID == 63 isSUTx = true; else isSUTx = false; % is MU transmission end % Get extra OFDM symbol information from VHTSIG-A bits if VHTSIGABits(2,4)==1 LDPCextraOFDMsymbol = 1; else LDPCextraOFDMsymbol = 0; end % Retrieve rxTime from L-SIG bits rxTime = getRxTime(LSIGBits); % default assignments crcBits = zeros(8, 1, 'int8'); apepLen = 0; if isSUTx % SINGLE-USER Transmission numSpaceTimeStreams = bi2de(VHTSIGABits(1, 11:13)) + 1; partialAID = bi2de(VHTSIGABits(1, 14:22)); mcs = bi2de(VHTSIGABits(2, 5:8)); beamforming = logical(VHTSIGABits(2, 9)); channelCodingBit = bi2de(VHTSIGABits(2, 3)); if channelCodingBit==1 % Channel coding is LDPC channelCoding = {'LDPC'}; else % Channel coding is BCC channelCoding = {'BCC'}; end % Get number of OFDM Data symbols [numDataSym, guardInterval] = getDataSym(VHTSIGABits, ... numSpaceTimeStreams, rxTime); % Calculate received PSDULength and set it to be the APEPLength [numDBPS, numES] = getMCSTable(mcs, numSD, ... numSpaceTimeStreams/(1+stbc), channelCoding{1}); if strcmp(channelCoding{1}, 'BCC') numTailBits = 6; psduLength = floor((numDataSym*numDBPS - numTailBits*numES - 16)/8); else % LDPC psduLength = floor(((numDataSym-LDPCextraOFDMsymbol*(1+stbc))*numDBPS - 16)/8); end % Create the returned object from individual parameters cfgVHTRx = wlanVHTConfig('ChannelBandwidth', chanBW, ... 'NumSpaceTimeStreams', numSpaceTimeStreams, ... 'GroupID', groupID, ... 'STBC', stbc, ... 'Beamforming', beamforming, ... 'PartialAID', partialAID, ... 'MCS', mcs, ... 'ChannelCoding', channelCoding, ... 'GuardInterval', guardInterval, ... 'APEPLength', psduLength); % Dont necessarily need the SIGB bits for SU recovery. % If passed in, confirm the actual lengths are appropriate if ~isempty(VHTSIGBBits) [crcBits, apepLen] = helperInterpretSIGB(VHTSIGBBits, chanBW, true); % Confirm APEP lengths and PSDU length are commensurate if psduLength < apepLen coder.internal.error('wlan:helperVHTConfigRecover:InvalidLengths'); end end else % MULTI-USER Transmission % Get coded NSTS per user numSTS = [bi2de(VHTSIGABits(1, 11:13)) ... bi2de(VHTSIGABits(1, 14:16)) bi2de(VHTSIGABits(1, 17:19)) ... bi2de(VHTSIGABits(1, 20:22))]; % Derive other properties from numSTS: numUsers, UserPositions, % NumSpaceTimeStreams, channelCodingBits maxUsers = 4; % Maximum allowed uPositions = 0:3; % correspond to max. users channelCodingBits = ones(1, maxUsers); % corresponding to max. users for userIdx = 1:maxUsers % Read off the received channelCoding bits if userIdx == 1 % Read B2 for 1 user channelCodingBits(1) = bi2de(VHTSIGABits(2, 3)); else % Read B4:B6 for 2:4 users channelCodingBits(userIdx) = bi2de(VHTSIGABits(2, 3+userIdx)); end end % Check numSTS values and revise properties uPositions = uPositions(numSTS~=0); channelCodingBits = channelCodingBits(numSTS~=0); numUsers = length(uPositions); numSpaceTimeStreams = numSTS(numSTS~=0); % Per-user coding information % 0 indicates BCC, 1 indicates LDPC for present users. channelCoding = cell(1, numUsers); for userIdx = 1:numUsers if channelCodingBits(userIdx) == 1 % Channel coding is LDPC channelCoding{userIdx} = 'LDPC'; else % Channel coding is BCC channelCoding{userIdx} = 'BCC'; end end % Get number of OFDM Data symbols [numDataSym, guardInterval] = getDataSym(VHTSIGABits, ... sum(numSpaceTimeStreams), rxTime); if ~isempty(VHTSIGBBits) % Individual user processing (based on userNum) % apepLen Rounded to 4-byte multiple [crcBits, apepLen, mcs] = helperInterpretSIGB(VHTSIGBBits, chanBW, false); % Calculate received PSDULength and set it to be the APEPLength [numDBPS, numES] = getMCSTable(mcs, numSD, ... numSpaceTimeStreams(userNum)/(1+stbc), channelCoding{userNum}); if strcmp(channelCoding{userNum}, 'BCC') numTailBits = 6; psduLength = floor((numDataSym*numDBPS - numTailBits*numES - 16)/8); else % LDPC psduLength = floor(((numDataSym-LDPCextraOFDMsymbol*(1+stbc))*numDBPS - 16)/8); end % Confirm APEP lengths and PSDU length are commensurate if psduLength < apepLen coder.internal.error('wlan:helperVHTConfigRecover:InvalidLengths'); end % Create the returned object from individual parameters % Set this to be a single-user config. cfgVHTRx = wlanVHTConfig('ChannelBandwidth', chanBW, ... 'NumUsers', 1, ... 'NumSpaceTimeStreams', numSpaceTimeStreams(userNum), ... 'GroupID', groupID, ... 'STBC', stbc, ... 'MCS', mcs, ... 'ChannelCoding', {channelCoding{userNum}}, ... 'GuardInterval', guardInterval, ... 'APEPLength', psduLength ); %#ok<CCAT1> % Required for codegen else % Create the returned object from individual parameters % Set this to be a MULTI-USER configuration % But with no length information (only the default) cfgVHTRx = wlanVHTConfig('ChannelBandwidth', chanBW, ... 'NumUsers', numUsers, ... 'UserPositions', uPositions, ... 'NumSpaceTimeStreams', numSpaceTimeStreams, ... 'GroupID', groupID, ... 'STBC', stbc, ... 'ChannelCoding', channelCoding, ... 'GuardInterval', guardInterval); end end end %-------------------------------------------------------------------------- function rxTime = getRxTime(LSIGBits) % Retrieve RXTime from L-SIG for VHT transmission % 4 symbol range, [RXTime - 3: RXTime] rxTime = (bi2de(double(LSIGBits(6:17)')) + 3)/3*4 + 20; end %-------------------------------------------------------------------------- function [numDataSym, giType] = getDataSym(VHTSIGABits, numSTSTotal, rxTime) % Recover number of OFDM symbols and guard interval type NVHTLTFVec = [1 2 4 4 6 6 8 8]; numPreambSym = 9 + NVHTLTFVec(numSTSTotal); if VHTSIGABits(2, 1) giType = 'Short'; numDataSym = floor((rxTime/4 - numPreambSym)*10.0/9.0) - VHTSIGABits(2, 2); else giType = 'Long'; numDataSym = rxTime/4 - numPreambSym; % Precise end end %-------------------------------------------------------------------------- function [Ndbps, Nes] = getMCSTable(MCS, Nsd, Nss, channelCoding) % Similar to wlan.internal.getRateTable, but with modified inputs switch MCS case 0 Nbpscs = 1; % 'BPSK' rate = 1/2; case 1 Nbpscs = 2; % 'QPSK' rate = 1/2; case 2 Nbpscs = 2; rate = 3/4; case 3 Nbpscs = 4; % '16QAM' rate = 1/2; case 4 Nbpscs = 4; rate = 3/4; case 5 Nbpscs = 6; % '64QAM' rate = 2/3; case 6 Nbpscs = 6; rate = 3/4; case 7 Nbpscs = 6; rate = 5/6; case 8 Nbpscs = 8; % 256QAM rate = 3/4; otherwise % MCS == 9 Nbpscs = 8; rate = 5/6; end Ndbps = Nsd * Nbpscs * Nss * rate; if strcmp(channelCoding, 'LDPC') Nes = 1; % always the case else % BCC % Handle exceptions to Nes generic rule - Table 7.13 [2]. % For each case listed, work off the Ndbps value and create a look-up % table for the Nes value. % Only 9360 has a valid value from the generic rule also, % all others are exceptions NdbpsVec = [2457 8190 9828 9360 14040 9828 16380 19656 21840 14976 22464]; expNes = [ 3 6 6 6 8 6 9 12 12 8 12]; exceptIdx = find(Ndbps == NdbpsVec); if ~isempty(exceptIdx) if (Ndbps == 9360) && (Nss == 5) % One valid case for 160, 80+80 Nes = 5; else % Two exception cases Nes = expNes(exceptIdx(1)); end else % Generic rule: 3.6*600 - for a net 600Mbps per encoder Nes = ceil(Ndbps/2160); end end end % [EOF]