function [timeVector, dataVector, waveformLabelCon] = importKeysightPA2200ABin(inputFilename, varargin)
% importKeysightPA2200ABin reads the Keysight Binary Waveform filetype.
% [timeVector, dataVector, waveformLabelCon] = importKeysightPA2200ABin(inputFilename)
% [timeVector, dataVector, waveformLabelCon] = importKeysightPA2200ABin(inputFilename, waveform_index)
% if waveformIndex is not provided, all waveforms will be read

if (~exist(inputFilename))
    error('inputFilename missing.');
end

fileId = fopen(inputFilename, 'r');

% read file header
fileCookie = fread(fileId, 2, 'char');
fileVersion = fread(fileId, 2, 'char');
fileSize = fread(fileId, 1, 'int32');
nWaveforms = fread(fileId, 1, 'int32');

% verify cookie
fileCookie = char(fileCookie');
if (~strcmp(fileCookie, 'KT'))
    fclose(fileId);
    error('Unrecognized file format.');
end

% read all waveforms (default), else determine which waveform to read
waveformSelectAll = false;
waveformSelect = 1;
if ( length(varargin) >= 1 )
    if ( (size(varargin) == 1) & (varargin{1} <= nWaveforms) )
        waveformSelect = varargin{1};
    end
else
    waveformSelectAll = true;
end

% define multiple waveform variables
bigDataVector = [];
bigTimeVector = [];
waveformLabelConArray = {};

for waveformIndex = 1:nWaveforms
    % read waveform header
    headerSize = fread(fileId, 1, 'int32'); bytesLeft = headerSize - 4;
    waveformType = fread(fileId, 1, 'int32'); bytesLeft = bytesLeft - 4;
    nWaveformBuffers = fread(fileId, 1, 'int32'); bytesLeft = bytesLeft - 4;
    nPoints = fread(fileId, 1, 'int32'); bytesLeft = bytesLeft - 4;
    reserved1 = fread(fileId, 1, 'int32');  bytesLeft = bytesLeft - 4;
    xDisplayRange = fread(fileId, 1, 'float32');  bytesLeft = bytesLeft - 4;
    xDisplayOrigin = fread(fileId, 1, 'double');  bytesLeft = bytesLeft - 8;
    xIncrement = fread(fileId, 1, 'double');  bytesLeft = bytesLeft - 8;
    xOrigin = fread(fileId, 1, 'double');  bytesLeft = bytesLeft - 8;
    xUnits = fread(fileId, 1, 'int32');  bytesLeft = bytesLeft - 4;
    yUnits = fread(fileId, 1, 'int32');  bytesLeft = bytesLeft - 4;
    reserved2 = fread(fileId, 16, 'char'); bytesLeft = bytesLeft - 16;
    reserved3 = fread(fileId, 16, 'char'); bytesLeft = bytesLeft - 16;
    frameString = fread(fileId, 24, 'char'); bytesLeft = bytesLeft - 24;
    waveformLabel = fread(fileId, 16, 'char'); bytesLeft = bytesLeft - 16;
    reserved4 = fread(fileId, 1, 'double'); bytesLeft = bytesLeft - 8;
    reserved5 = fread(fileId, 1, 'uint32'); bytesLeft = bytesLeft - 4;
    
    % skip over any remaining data in the header
    fseek(fileId, bytesLeft, 'cof');
    
    % generate time vector from xIncrement and xOrigin values
    if ( (waveformIndex == waveformSelect) || waveformSelectAll )
        timeVector = (xIncrement * [0:(nPoints-1)]') + xOrigin;
    end
    
    for bufferIndex = 1:nWaveformBuffers
        % read waveform buffer header
        headerSize = fread(fileId, 1, 'int32'); bytesLeft = headerSize - 4;
        bufferType = fread(fileId, 1, 'int16'); bytesLeft = bytesLeft - 2;
        bytesPerPoint = fread(fileId, 1, 'int16'); bytesLeft = bytesLeft - 2;
        bufferSize = fread(fileId, 1, 'int32'); bytesLeft = bytesLeft - 4;
        
        % skip over any remaining data in the header
        fseek(fileId, bytesLeft, 'cof');
        
        if ( (waveformIndex == waveformSelect) || waveformSelectAll )
            if (bufferType == 1)
                % bufferType is NORMAL
                dataVector(:, bufferIndex) = fread(fileId, nPoints, 'float');
            else
                % unrecognized bufferType read as unformated bytes
                dataVector(:, bufferIndex) = fread(fileId, bufferSize, '*uint8');
            end
            Idx = find(waveformLabel);
            waveformLabelCon{1} = char(waveformLabel(1:max(Idx))');
        else
            fseek(fileId, bufferSize, 'cof');
        end
    end
    if (bufferIndex == 1 && waveformSelectAll)
        bigTimeVector = [bigTimeVector timeVector];
        bigDataVector = [bigDataVector dataVector];
        waveformLabelConArray{end+1} = waveformLabelCon{1};
    end
    
end
fclose(fileId);
if waveformSelectAll
    dataVector = bigDataVector;
    timeVector = bigTimeVector;
    waveformLabelCon = waveformLabelConArray;
end
