function [rxPSDU,bitErrorRate,eqSymPlot] = heSUspecial(rx,cfgHE,userIdx,frameIdx,rxPSDU,cfgUI,SEED,bitErrorRate,eqSymPlot) % chanBW = cfgHE.ChannelBandwidth; % ind = wlanFieldIndices(cfgHE); % fs = wlanSampleRate(cfgHE); % ofdmInfo = wlanHEOFDMInfo('HE-Data',cfgHE); searchOffset = 0; % Offset from start of waveform in samples % rxWaveLen = length(rx); 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 pktOffset = wlanPacketDetect(rx,chanBW,searchOffset); % Adjust packet offset pktOffset = searchOffset + pktOffset; % if isempty(pktOffset) || (pktOffset + ind.LSIG(2) > rxWaveLen) % error('** No packet detected **'); % end LSTF = wlanLSTF(wlanNonHTConfig); if isempty(pktOffset) pktOffset = 0; end % Coarse frequency offset estimation and correction using L-STF rxLSTF = rx(pktOffset+(ind.LSTF(1):ind.LSTF(2)), :); tmp_xcorr = abs(xcorr(LSTF,rxLSTF)); if max(tmp_xcorr)>50 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_No,PSDULength] = interpretLSIG(rxLSIGBits); estNumerlogy = bi2de(rxLSIGBits(19:24).','right-msb'); MCS_set=[2,2;4,2;4,4;16,2;16,4;64,3;64,4;64,6]; MCS = MCS_set(MCS_No+1,:); if failCheck % Skip L-STF length of samples and continue searching disp('** L-SIG check fail **'); else disp('L-SIG check pass'); end %% load NumerologySet.mat NumerologySet NumerologySel = NumerologySet(estNumerlogy,:); [~,WaveformPara] = WaveformNumerologyCal(PSDULength,NumerologySel,MCS); % output data field % rx_datafield = rx(pktOffset+(ind.NonHTData(1):ind.NonHTData(2)), :); rx_datafield = rx(pktOffset+ind.NonHTData(1):pktOffset+ind.NonHTData(1)+WaveformPara.FrameLen-1, :); %% 生成信道响应 % N_carriers = WaveformPara.N_FFT; % rng(2); % channel_response=sqrt(1/2)*(randn(1,N_carriers)+1i*randn(1,N_carriers)); % N_windows = 8; % N_level = 10; % min_len_CP = 30; % CPset = Generate_CP(channel_response,N_windows,N_level,min_len_CP); % [rxDataModLs] = rx_PilotBlockChanEstForLabview(rx_datafield,WaveformPara,CPset); % 去CP的地方 [rxDataModLs] = rx_PilotBlockChanEst(rx_datafield,WaveformPara); % scatterplot(rxDataModLs(1:end)); dataDemod = qamdemod(rxDataModLs,WaveformPara.Mod,'OutputType','bit','UnitAveragePower',true); % scatter(real(rxDataModLs),imag(rxDataModLs)) % dataDemod = reshape(dataDemod,1,[]); dataDePadded = dataDemod(1:end - WaveformPara.DataPadding); tb = 8; trellis = poly2trellis(7,[171 133]); % decoded = vitdec(dataDePadded,trellis,tb,'trunc','unquant',WaveformPara.puncpat); decoded = vitdec(dataDePadded,trellis,tb,'trunc','hard',WaveformPara.puncpat); [rxPSDU(:,frameIdx),PER] = RX_CRC32_deScramble(decoded); % rng(SEED); % dataPacketBits = randi([0 1],WaveformPara.Payload,1); % txPSDU = DataGenerate(cfgUI,'test',numpkt,SEED,psduLength); % [numErrors,BER] = biterr(dataPacketBits,rx); % Recover data rxPSDUbits = decoded; eqSymPlot = rxDataModLs; % [rxPSDU(:,frameIdx),~] = RX_CRC32(double(rxPSDUbits)); %% % Recover data EVM = comm.EVM; EVM.ReferenceSignalSource = 'Estimated from reference constellation'; EVM.Normalization = 'Average constellation power'; release(EVM); switch WaveformPara.Mod case 16 refsym = '16QAM'; case 4 refsym = 'QPSK'; case 2 refsym = 'BPSK'; case 64 refsym = '64QAM'; end EVM.ReferenceConstellation = wlanReferenceSymbols(refsym); Evm = EVM(rxDataModLs(:)); fprintf(' HE-Data EVM:%2.2fdB\n\n',20*log10(Evm)); rx = rx(pktOffset+ind.NonHTData(1)+WaveformPara.FrameLen:end,:); frameIdx = frameIdx+1; [rxPSDU,bitErrorRate,eqSymPlot] = heSUspecial(rx,cfgHE,userIdx,frameIdx,rxPSDU,cfgUI,SEED,bitErrorRate,eqSymPlot); else [~,numpkt] = size(rxPSDU); psduLength = length(rxPSDU(:,1))/8; txPSDU = DataGenerate(cfgUI,numpkt,SEED,psduLength,0); txPSDU = txPSDU{1}; bitError = sum(txPSDU(1:end,:)~=rxPSDU); bitErrorRate = bitError/length(rxPSDU); ACK = (bitErrorRate == 0); save(['TXPackets\ACKfeedback_for_User' num2str(userIdx) '.mat'],'ACK'); % scatterplot(rxDataModLs(1:end)); eqSymPlot = eqSymPlot(1:end); 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 %% function [rxDataModLs] = rx_PilotBlockChanEst(rAddAWGN,WaveformPara) N = WaveformPara.N_FFT; N_Used = WaveformPara.UsedSubcarrier; L = WaveformPara.CP_Len; m = WaveformPara.PilotNum; pnSequence = comm.PNSequence('Polynomial',[8 6 5 4 0], ... 'SamplesPerFrame',N_Used,'InitialConditions',[0 0 0 0 0 0 0 1]); pilot = generatePilot(pnSequence,1); rxOFDMsym = reshape(rAddAWGN,WaveformPara.SymbolLen,WaveformPara.FrameSymNum); rxOFDMcore = rxOFDMsym(L+1:L+N,:); rxDataModInMatrix = fft(rxOFDMcore,[],1)/sqrt(N); rxDataModInMatrix_shift = [rxDataModInMatrix(2:2+(N_Used-1)/2-1,:);rxDataModInMatrix(end - (N_Used-1)/2:end,:)]; rxPilot = rxDataModInMatrix_shift(:,1:WaveformPara.PilotInterval+1:WaveformPara.FrameSymNum); hLs = zeros(N_Used,m); rxDataRemovPilot = zeros(N_Used,WaveformPara.DataFrame); for i = 1:m-1 rxDataRemovPilot(:,(i-1)*WaveformPara.PilotInterval+1:i*(WaveformPara.PilotInterval)) = ... rxDataModInMatrix_shift(:,(i-1)*(WaveformPara.PilotInterval+1)+2:i*(WaveformPara.PilotInterval+1)); hLs(:,i) = rxPilot(:,i)./pilot; end rxDataRemovPilot(:,(m-1)*WaveformPara.PilotInterval+1:end) = ... rxDataModInMatrix_shift(:,(m-1)*(WaveformPara.PilotInterval+1)+2:end); hLs(:,m) = rxPilot(:,m)./pilot; if mod(WaveformPara.DataFrame,WaveformPara.PilotInterval)>0 hLs = [kron(hLs(:,1:m-1),ones(1,WaveformPara.PilotInterval)),kron(hLs(:,m),ones(1,mod(WaveformPara.DataFrame,WaveformPara.PilotInterval)))]; else hLs = kron(hLs(:,1:m),ones(1,WaveformPara.PilotInterval)); end eqDataModLs = zeros(N_Used,WaveformPara.DataFrame); for i = 1:WaveformPara.DataFrame eqDataModLs(:,i) = rxDataRemovPilot(:,i)./hLs(:,i); end rxDataModLs = reshape(eqDataModLs,[],1); end function pilot = generatePilot(pnSequence,Power) pilot = pnSequence(); bpskModulator = comm.BPSKModulator; pilot = bpskModulator(pilot)*sqrt(Power); end