HE/heSUspecial.m

228 lines
7.8 KiB
Mathematica
Raw Normal View History

2024-03-30 16:35:40 +08:00
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