%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% 
% Author:       Data Translation GmbH
%               
%
% Date:         15.02.2018
%
% Version:      2.2
%
% Description:  
% Matlab Input function for Data Translation's HPF-file format.
%
% Changes:
% 15.02.2018 Changes from V2.1 to 2.2
%       - added the TimeAxis in Seconds from Start
%
% 30.06.2015 Changes from V2.0 to 2.1
%	   - added conversation to char to have the same output format
%	     like in the past.
%
% 16.06.2015 changes from V1.1 to 2.0:
%          - Modifications for Matlab 2015a. Remove XML nodes.
%          - Add Struct for return data which contains all required
%            information.
%
% Input Paramter: 
% SelectedChannel = Channel to read from the HPF-file. 1 as first channel.
% InputFile = Complete path to the input HPF-file.
%
% Output Data:
% ReturnData = Matrix with all Data for the selected channel
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 

function Result = ReadHPFdata (SelectedChannel, InputFile)
%InputFile = 'C:\Users\ECM\Desktop\Rohdaten RHT\experimental_data_1.hpf';
%SelectedChannel = 7;

dat.in = InputFile;
%dat.out = 'Z:\02_PraDiDo\2001_BA_Rauscher\07_hpf_Datenumformung\Beispielablage\190624_50N_3_15Hz_10min_110Grad_Pause-18.txt';


%disp('-- Start');
global stack SensorOffset SensorScale;
global ReturnData;
global TimeAxis;
 
% Clear variables
stack = {};
ReturnData = {};
%TimeAxis = {};

pos = 0;
off = 0;

in.file = fopen(dat.in);                                  % pens the file locate in dat.in, for binary read access, and returns an integer file identifier equal to or greater than 3
while ~feof(in.file)                                      % wait till the End of the file
    in.chunkID = fread(in.file, 1, 'int64');              % Read the  values into a 1-by-0 array. Specify that the source data is class uint64
    off = fread(in.file, 1, 'int64');                     % number of Data available  
    
    if feof(in.file) || off == 0                          % look if the end of the file is reached or the data are finish
       break; 
    end;
    
    switch in.chunkID
        case 4096                                        % chunkID 2^12
            %disp('- Parsing Header Chunk');
            in.ChratorID = fread(in.file, 4, 'char');
            in.fileVersion = fread(in.file, 1, 'int64');
            in.indexChunkOffset = fread(in.file, 1, 'int64');

            in.XMLdata = fread(in.file, off-(ftell(in.file)-pos), 'char');
            % transform the file
            in.XMLdata = in.XMLdata';
            
            % Read out recording date
            start = strfind(in.XMLdata, '<RecordingDate>');
            stop = strfind(in.XMLdata, '</RecordingDate>');
            Information = in.XMLdata(start +15: stop-1);
            %disp(['RecordingDate: '  Information]);
            Result.RecordingDate = char(Information);
            
        case 8192
            %disp('- Parsing Channel Information Chunk');
            in.groupID = fread(in.file, 1, 'int32');
            in.numberOfChannals = fread(in.file, 1, 'int32');

            in.XMLdata = fread(in.file, off-(ftell(in.file)-pos), 'char');
            % transform the file
            in.XMLdata = in.XMLdata';
                    
            % Name
            start = strfind(in.XMLdata, '<Name>');
            stop = strfind(in.XMLdata, '</Name>');

            % display the total number of channels
            disp(['Total Channel: ', num2str(length(start))]);

            % check if the selected channel exists
            if length(start) < SelectedChannel
                %disp ('Wrong channel selected');
                return;
            end
            
            % Store Channel in return struct
            Result.Channel = SelectedChannel;
            
            %disp('Selected Channel Information:'); 

            Information = in.XMLdata(start(SelectedChannel) +6: stop(SelectedChannel) -1);
            %disp(['Name: '  Information]);
            Result.Name = char(Information);

            % Unit     
            start = strfind(in.XMLdata, '<Unit>');
            stop = strfind(in.XMLdata, '</Unit>');
            Information = in.XMLdata(start(SelectedChannel) +6: stop(SelectedChannel) -1);
            %disp(['Unit: '  Information]);
            Result.Unit = char(Information);

            % Channel Type
            start = strfind(in.XMLdata, '<ChannelType>');
            stop = strfind(in.XMLdata, '</ChannelType>');
            Information = in.XMLdata(start(SelectedChannel) +13: stop(SelectedChannel) -1);
            %disp(['ChannelType: '  Information]);
            Result.ChannelType = char(Information);

            % Assigned Time Channel Index
            start = strfind(in.XMLdata, '<AssignedTimeChannelIndex>');
            stop = strfind(in.XMLdata, '</AssignedTimeChannelIndex>');
            Information = in.XMLdata(start(SelectedChannel) +26: stop(SelectedChannel) -1);
            %disp(['AssignedTimeChannelIndex: '  Information]);
            Result.AssignedTimeChannelIndex = char(Information);

            % Data Type
            start = strfind(in.XMLdata, '<DataType>');
            stop = strfind(in.XMLdata, '</DataType>');
            Information = in.XMLdata(start(SelectedChannel) +10: stop(SelectedChannel) -1);
            %disp(['DataType: '  Information]);
            Result.DataType = char(Information);

            % Data Index
            start = strfind(in.XMLdata, '<DataIndex>');
            stop = strfind(in.XMLdata, '</DataIndex>');
            Information = in.XMLdata(start(SelectedChannel) +11: stop(SelectedChannel)-1);
            %disp(['DataIndex: '  Information]);
            Result.DataIndex = char(Information);

            % Start Time                
            start = strfind(in.XMLdata, '<StartTime>');
            stop = strfind(in.XMLdata, '</StartTime>');
            Information = in.XMLdata(start(SelectedChannel) +11: stop(SelectedChannel)-1);
            disp(['StartTime: '  Information]);
            Result.StartTime = char(Information);

            % Time Increment
            start = strfind(in.XMLdata, '<TimeIncrement>');
            stop = strfind(in.XMLdata, '</TimeIncrement>');
            Information = in.XMLdata(start(SelectedChannel) +15: stop(SelectedChannel)-1);
            %disp(['TimeIncrement: '  Information]);
            Result.TimeIncrement = char(Information);

            % RangeMin        
            start = strfind(in.XMLdata, '<RangeMin>');
            stop = strfind(in.XMLdata, '</RangeMin>');
            Information = in.XMLdata(start(SelectedChannel) +10: stop(SelectedChannel)-1);
            %disp(['RangeMin: '  Information]);
            Result.RangeMin = char(Information);

            % Range Max
            start = strfind(in.XMLdata, '<RangeMax>');
            stop = strfind(in.XMLdata, '</RangeMax>');
            Information = in.XMLdata(start(SelectedChannel) +10: stop(SelectedChannel)-1);
            %disp(['RangeMax: '  Information]);
            Result.RangeMax = char(Information);

            % Data Scale
            start = strfind(in.XMLdata, '<DataScale>');
            stop = strfind(in.XMLdata, '</DataScale>');
            Information = in.XMLdata(start(SelectedChannel) +11: stop(SelectedChannel)-1);
            %disp(['DataScale: '  Information]);
            Result.DataScale = char(Information);

            % Data Offset
            start = strfind(in.XMLdata, '<DataOffset>');
            stop = strfind(in.XMLdata, '</DataOffset>');
            Information = in.XMLdata(start(SelectedChannel) +12: stop(SelectedChannel)-1);
            %disp(['DataOffset: '  Information]);
            Result.DataOffset = char(Information);

            % Sensor Scale
            start = strfind(in.XMLdata, '<SensorScale>');
            stop = strfind(in.XMLdata, '</SensorScale>');
            Information = in.XMLdata(start(SelectedChannel) +13: stop(SelectedChannel)-1);
            %disp(['SensorScale: '  Information]);
            Result.SensorScale = char(Information);
            SensorScale=char(Information);
            SensorScale=str2num( SensorScale);


            % Sensor Offset
            start = strfind(in.XMLdata, '<SensorOffset>');
            stop = strfind(in.XMLdata, '</SensorOffset>');
            Information = in.XMLdata(start(SelectedChannel) +14: stop(SelectedChannel)-1);
            %disp(['SensorOffset: '  Information]);
            Result.SensorOffset = char(Information);
            SensorOffset=char(Information);
            SensorOffset=str2num( SensorOffset);

            % Per Channel Sample Rate
            start = strfind(in.XMLdata, '<PerChannelSampleRate>');
            stop = strfind(in.XMLdata, '</PerChannelSampleRate>');
            Information = in.XMLdata(start(SelectedChannel) +22: stop(SelectedChannel)-1);
            %disp(['PerChannelSampleRate: '  Information]);
            Result.PerChannelSampleRate = char(Information);

            % Physical Channel Number
            start = strfind(in.XMLdata, '<PhysicalChannelNumber>');
            stop = strfind(in.XMLdata, '</PhysicalChannelNumber>');
            Information = in.XMLdata(start(SelectedChannel) +23: stop(SelectedChannel)-1);
            %disp(['PhysicalChannelNumber: '  Information]);
            Result.PhysicalChannelNumber = char(Information);
            
        case 12288
            %disp('- Parsing Data Chunk');
            in.chunksize = off;                                 % ChunkSize
            in.groupID = fread(in.file, 1, 'int32');            % GroupID
            in.dataStartIndex = fread(in.file, 1, 'int64');     % DataStartIndex
            in.chanalDataCount = fread(in.file, 1, 'int32');    % ChannelDataCount
            
            for count = 1:in.chanalDataCount
                if count == (SelectedChannel)
                    stack{count,1} = fread(in.file, 1, 'int32');    % Channel Offset
                    stack{count,2} = fread(in.file, 1, 'int32');    % Channel Length
                else
                    fread(in.file, 2, 'int32');
                end;
            end;

            ignoreCount = 0;
            for count = 1:in.chanalDataCount    

                if  count == (SelectedChannel)

                    divider = 8;                                                        % QuickDaq records only in Double format
                    fseek(in.file, stack{count,1} - (32 + (in.chanalDataCount*8)), 0);  % -32 bytes is the headersize plus 2*4 Bytes per Channel
                    tmpData = fread(in.file, stack{count,2}/divider, 'double');         % QuickDaq records only in Double format
                    % Append Data
                    ReturnData = vertcat(ReturnData,tmpData);             
                else
                    ignoreCount = ignoreCount + 1;
                end;
            end;
        case 28672 %16384
             %disp('- Parsing Undocumented Part');
             fseek(in.file,7,0);
    end;

    Position = off - (ftell(in.file) - pos) ;%
    fseek(in.file, Position, 0); % jump over offset to go to the next chunk
    pos = ftell(in.file);

end;
Result.ReturnData = cell2mat(ReturnData);
Result.ReturnData=(Result.ReturnData*SensorScale)+SensorOffset
% Generate Time Axis in Seconds from Start
tmpData = 0;
TimeIncrement = str2double(Result.TimeIncrement);
TimeAxis = zeros(size(Result.ReturnData));

for n = 1:size(Result.ReturnData)
    TimeAxis(n) = tmpData;
    tmpData = tmpData + TimeIncrement;
end

Result.TimeAxis = TimeAxis

fclose(in.file);

% If required you can store the data to a tab separated Ascii file
%dlmwrite(dat.out, Result.ReturnData, '\t');

%disp('-- Finish');
end

