function rfFingerprintingUnknownClassDataCollectionRx(varargin)
%rfFingerprintingUnknownClassDataCollectionRx RF Fingerprinting Unknown Class Receiver
%   rfFingerprintingUnknownClassDataCollectionRx uses a PlutoSDR to receive
%   and detect WLAN preambles transmitted using the
%   rfFingerprintingUnknownClassDataCollectionTx function. This function
%   then saves the detected preambles in a file named
%   'rfFingerprintingCapturedUnknownFramesUser.mat'. By default, this
%   function saves 200 frames from 10 locations. Use this function to
%   generate the data corresponding to the Unknown class in the "Test a
%   Deep Neural Network with Captured Data to Detect WLAN Router
%   Impersonation" example.
%
%   First, run the rfFingerprintingUnknownClassDataCollectionTx function.
%   Then, run this function to start data collection. To better generalize
%   over different channels, place the radio at different locations. The
%   script will pause every time data collection is completed at a certain
%   location. Press any keyboard key to resume data collection.
%
%   rfFingerprintingUnknownClassDataCollectionRx(NUMFRAMES) saves NUMFRAMES
%   frames from 10 locations.
%
%   rfFingerprintingUnknownClassDataCollectionRx(NUMFRAMES, NUMLOC) saves
%   NUMFRAMES frames from NUMLOC locations.
% 
%   See also rfFingerprintingUnknownClassDataCollectionTx,
%   rfFingerprintingRouterDataCollection and
%   DesignRFFingerprintingDeepLearningNetworkExample

%   Copyright 2019 The MathWorks, Inc.

narginchk(0,2)
if nargin < 1
    framesPerLocation = 200;
    numLocations = 10;
elseif nargin < 2
    framesPerLocation = varargin{1};
    numLocations = 10;
else
    framesPerLocation = varargin{1};
    numLocations = varargin{2};
end

% Create a wlanNONHTConfig object, 20MHz bandwidth and MCS 1 are used
nonHTcfg = wlanNonHTConfig('ChannelBandwidth', "CBW20");
fs = wlanSampleRate(nonHTcfg);
frameLength = 160;

% Set up PlutoSDR as a Receiver
if helperIsPlutoSDRInstalled
    radios = findPlutoRadio();
    if ~isempty(radios)
        
        % Set ADALM-PLUTO as a receiver
        deviceNameSDR = 'Pluto';
        osf=2;
        sdrReceiver = sdrrx(deviceNameSDR);
        sdrReceiver.RadioID = 'usb:0';
        sdrReceiver.BasebandSampleRate =fs*osf;
        sdrReceiver.CenterFrequency = helperWLANChannelFrequency(153, 5);
        sdrReceiver.GainSource ='Manual';
        sdrReceiver.Gain = 50;
        sdrReceiver.OutputDataType = 'double';
        sdrReceiver.EnableBurstMode=true;
        sdrReceiver.NumFramesInBurst = 1;
        samplesPerFrame = (1520+160)*osf;
        sdrReceiver.SamplesPerFrame = 2*samplesPerFrame;
    else
        error(message("comm_demos:common:RadioNeeded", 1, "ADALM-PLUTO"));
    end
else
    error(message("comm_demos:common:CSTSupportPKGNotFound", ...
      "Analog Devices ADALM-PLUTO Radio"));
end

rxData = zeros(frameLength, numLocations*framesPerLocation);


% The <matlab:edit('rfFingerprintingNonHTFrontEnd.m')
% rfFingerprintingNonHTFrontEnd> object performs front-end processing and
% L-SIG decoding. The object is configured with a channel bandwidth of 20
% MHz to process non-HT packets.
rxFrontEnd = rfFingerprintingNonHTFrontEnd('ChannelBandwidth', 'CBW20');

decimator = dsp.FIRDecimator('DecimationFactor',osf);
    
% Capture data from numLocations different locations
for location = 1:numLocations
    
    capturedFrames = 0;
    % Loop until framesPerLocation are captured
    while capturedFrames < framesPerLocation
        
        rxSig = sdrReceiver();
        rxSig = decimator(rxSig);
        
        % Perform front-end processing and payload buffering
        [payloadFull, cfgNonHT, rxNonHTData, chanEst, noiseVar, LLTF] = ...
            rxFrontEnd(rxSig);
        
        if payloadFull
            
            % Recover payload bits
            recBits = wlanNonHTDataRecover(rxNonHTData, chanEst, ...
                noiseVar, cfgNonHT, 'EqualizationMethod', 'ZF');
            
            % Decode and evaluate recovered bits
            mpduCfg = wlanMPDUDecode(recBits, cfgNonHT);
            
            if mpduCfg.Address2 == "DEE71EA52156"
               % Update counter
                capturedFrames = capturedFrames+1; 
                
                rxData(:, (location-1)*framesPerLocation+ capturedFrames) = LLTF;
                disp("Frame " + num2str((location-1)*framesPerLocation+ capturedFrames) ...
                + "\" + num2str(framesPerLocation*numLocations) ...
                + " received with max(abs(LLTF)) = " + num2str(max(abs(LLTF))));
            end
            
        end
    end
    
    if location < numLocations
        disp(message('comm_demos:rfFingerprinting:DataCollectionInstructions3').getString)
        pause;
    end
end

release(sdrReceiver);

% Separate I/Q and reshape to obtain [frameLength x 2 x 1 x
% numLocations*framesPerLocation] matrix
rxData = rxData(:);
rxData = [real(rxData), imag(rxData)];
unknownFrames = permute(reshape(rxData,...
  [frameLength, numLocations*framesPerLocation, 2, 1]), [1 3 4 2]);

save('rfFingerprintingCapturedUnknownFramesUser.mat', 'unknownFrames');
end 
