%% End-to-End VHT Simulation with Frequency Correction
% This example shows how to generate, transmit, recover and view a VHT MIMO waveform.
% Steps in the example:
% Transmit a VHT waveform through a MIMO channel with AWGN
% Perform a two-stage process to estimate and correct for a frequency offset
% Estimate the channel response
% Recover the VHT data field
% Compare the transmitted and received PSDUs to determine if bit errors occurred
% Set the parameters used throughout the example.

cbw = 'CBW160';                    % Channel bandwidth
fs = 160e6;                        % Sample rate (Hz)
ntx = 2;                           % Number of transmit antennas
nsts = 2;                          % Number of space-time streams
nrx = 2;                           % Number of receive antennas

%
% Create a VHT configuration object that supports a 2x2 MIMO transmission and has an APEP length of 2000.

vht = wlanVHTConfig('ChannelBandwidth',cbw,'APEPLength',2000, ...
    'NumTransmitAntennas',ntx,'NumSpaceTimeStreams',nsts, ...
    'SpatialMapping','Direct','STBC',false);

%
% Generate a VHT waveform containing a random PSDU.

txPSDU = randi([0 1],vht.PSDULength*8,1);
txPPDU = wlanWaveformGenerator(txPSDU,vht);

%
% Create a 2x2 TGac channel and an AWGN channel.

tgacChan = wlanTGacChannel('SampleRate',fs,'ChannelBandwidth',cbw, ...
    'NumTransmitAntennas',ntx,'NumReceiveAntennas',nrx, ...
    'LargeScaleFadingEffect','Pathloss and shadowing', ...
    'DelayProfile','Model-C');
awgnChan = comm.AWGNChannel('NoiseMethod','Variance', ...
    'VarianceSource','Input port');

%
% Create a phase/frequency offset object.

pfOffset = comm.PhaseFrequencyOffset('SampleRate',fs,'FrequencyOffsetSource','Input port');

%
% Calculate the noise variance for a receiver with a 9 dB noise figure. Pass the transmitted waveform through the noisy TGac channel.

nVar = 10^((-228.6 + 10*log10(290) + 10*log10(fs) + 9)/10);
rxPPDU = awgnChan(tgacChan(txPPDU), nVar);

%
% Introduce a frequency offset of 500 Hz.

rxPPDUcfo = pfOffset(rxPPDU,500);

%
% Find the start and stop indices for all component fields of the PPDU.

ind = wlanFieldIndices(vht);

%
% Extract the L-STF. Estimate and correct for the carrier frequency offset.

rxLSTF = rxPPDUcfo(ind.LSTF(1):ind.LSTF(2),:);

foffset1 = wlanCoarseCFOEstimate(rxLSTF,cbw);
rxPPDUcorr = pfOffset(rxPPDUcfo,-foffset1);

%
% Extract the L-LTF from the corrected signal. Estimate and correct for the residual frequency offset.

rxLLTF = rxPPDUcorr(ind.LLTF(1):ind.LLTF(2),:);

foffset2 = wlanFineCFOEstimate(rxLLTF,cbw);
rxPPDU2 = pfOffset(rxPPDUcorr,-foffset2);

%
% Extract and demodulate the VHT-LTF. Estimate the channel coefficients.

rxVHTLTF = rxPPDU2(ind.VHTLTF(1):ind.VHTLTF(2),:);
dLTF = wlanVHTLTFDemodulate(rxVHTLTF,vht);
chEst = wlanVHTLTFChannelEstimate(dLTF,vht);

%
% Extract the VHT data field from the received and frequency-corrected PPDU. Recover the data field.

rxVHTData = rxPPDU2(ind.VHTData(1):ind.VHTData(2),:);
rxPSDU = wlanVHTDataRecover(rxVHTData,chEst,nVar,vht);

%
% Calculate the number of bit errors in the received packet.

numErr = biterr(txPSDU,rxPSDU)

% Copyright 2012 The MathWorks, Inc.