228 lines
7.8 KiB
Matlab
228 lines
7.8 KiB
Matlab
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
|