 function [f,fid] = ReadNeuroscanStruct(filename)
%   This software is protected by german copyright and international treaties.             
%   Copyright 2004 Markus Junghöfer & Peter Peyk. All Rights Reserved.                     
%                                                                                          
%   THIS SOFTWARE AND DOCUMENTATION IS PROVIDED "AS IS," AND COPYRIGHT HOLDERS MAKE        
%   NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO,    
%   WARRANTIES OF MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE OR THAT THE USE    
%   OF THE SOFTWARE OR DOCUMENTATION WILL NOT INFRINGE ANY THIRD PARTY PATENTS, COPYRIGHTS,
%   TRADEMARKS OR OTHER RIGHTS. COPYRIGHT HOLDERS WILL NOT BE LIABLE FOR ANY DIRECT,       
%   INDIRECT, SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF ANY USE OF THE SOFTWARE      
%   OR DOCUMENTATION.                                                                      
global evtags offset
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% Read a Neuroscan average or cnt file
%
% Useage:   [f,fid] = ReadNeuroscan(filename)
%
% where:    filename is a complete 'path\fileprefix.ext' string;
%           the file must be a neuroscan 4.1 avg or cnt file.
%
%           f is a structure containing:
%           
%               f.header
%               f.electloc
%               f.tag
%				f.events
% if strcmp(f.filetype,'.avg')
%               f.data
%               f.variance
% end
%           fid is a file handle to 'filename'
%
% Author:   Sean Fitzgibbon <psspf@id.psy.flinders.edu.au>
% Created:  08/2000
% Modified: 07/2001, Darren.Weber@flinders.edu.au
%                    tab formatted this file and added help
% Modified: 12/2002, Markus.Junghoefer@uni-konstanz.de
%                    added events and filetypes (reads also cnt files)
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
if nargin<1; filename=[]; end

if isempty(filename) & (~exist('ReadFilePath','file') | ~exist('SetDefPath','file')); 
	f=[]; fid=[]; 
	return; 
else
	DefDataFilePath=SetDefPath('r');
	[File,Path,filename]=ReadFilePath(filename,DefDataFilePath);
	if File==0; return; end
	SetDefPath('w',Path);
end

FiletypeStr=lower(filename(length(filename)-3:length(filename)));

if strcmp(FiletypeStr,'.cnt') | strcmp(FiletypeStr,'.tnt')
	f.filetype='cnt';
elseif strcmp(FiletypeStr,'.avg')
	f.filetype='avg';
else
	error('Unknown Neuroscan filetype')
end
fid = fopen(filename,'r','l');
h.rev               = fread(fid,12,'char');
h.nextfile          = fread(fid,1,'long');
h.prevfile          = fread(fid,1,'long');
h.type              = fread(fid,1,'char');
h.id                = fread(fid,20,'char');
h.oper              = fread(fid,20,'char');
h.doctor            = fread(fid,20,'char');
h.referral          = fread(fid,20,'char');
h.hospital          = fread(fid,20,'char');
h.patient           = fread(fid,20,'char');
h.age               = fread(fid,1,'short');
h.sex               = fread(fid,1,'char');
h.hand              = fread(fid,1,'char');
h.med               = fread(fid,20,'char');
h.category          = fread(fid,20,'char');
h.state             = fread(fid,20,'char');
h.label             = fread(fid,20,'char');
h.date              = fread(fid,10,'char');
h.time              = fread(fid,12,'char');
h.mean_age          = fread(fid,1,'float');
h.stdev             = fread(fid,1,'float');
h.n                 = fread(fid,1,'short');
h.compfile          = fread(fid,38,'char');
h.spectwincomp      = fread(fid,1,'float');
h.meanaccuracy      = fread(fid,1,'float');
h.meanlatency       = fread(fid,1,'float');
h.sortfile          = fread(fid,46,'char');
h.numevents         = fread(fid,1,'int');
h.compoper          = fread(fid,1,'char');
h.avgmode           = fread(fid,1,'char');
h.review            = fread(fid,1,'char');
h.nsweeps           = fread(fid,1,'ushort');
h.compsweeps        = fread(fid,1,'ushort');
h.acceptcnt         = fread(fid,1,'ushort');
h.rejectcnt         = fread(fid,1,'ushort');
h.pnts              = fread(fid,1,'ushort');
h.nchannels         = fread(fid,1,'ushort');
h.avgupdate         = fread(fid,1,'ushort');
h.domain            = fread(fid,1,'char');
h.variance          = fread(fid,1,'char');
h.rate              = fread(fid,1,'ushort');
h.scale             = fread(fid,1,'double');
h.veogcorrect       = fread(fid,1,'char');
h.heogcorrect       = fread(fid,1,'char');
h.aux1correct       = fread(fid,1,'char');
h.aux2correct       = fread(fid,1,'char');
h.veogtrig          = fread(fid,1,'float');
h.heogtrig          = fread(fid,1,'float');
h.aux1trig          = fread(fid,1,'float');
h.aux2trig          = fread(fid,1,'float');
h.heogchnl          = fread(fid,1,'short');
h.veogchnl          = fread(fid,1,'short');
h.aux1chnl          = fread(fid,1,'short');
h.aux2chnl          = fread(fid,1,'short');
h.veogdir           = fread(fid,1,'char');
h.heogdir           = fread(fid,1,'char');
h.aux1dir           = fread(fid,1,'char');
h.aux2dir           = fread(fid,1,'char');
h.veog_n            = fread(fid,1,'short');
h.heog_n            = fread(fid,1,'short');
h.aux1_n            = fread(fid,1,'short');
h.aux2_n            = fread(fid,1,'short');
h.veogmaxcnt        = fread(fid,1,'short');
h.heogmaxcnt        = fread(fid,1,'short');
h.aux1maxcnt        = fread(fid,1,'short');
h.aux2maxcnt        = fread(fid,1,'short');
h.veogmethod        = fread(fid,1,'char');
h.heogmethod        = fread(fid,1,'char');
h.aux1method        = fread(fid,1,'char');
h.aux2method        = fread(fid,1,'char');
h.ampsensitivity    = fread(fid,1,'float');
h.lowpass           = fread(fid,1,'char');
h.highpass          = fread(fid,1,'char');
h.notch             = fread(fid,1,'char');
h.autoclipadd       = fread(fid,1,'char');
h.baseline          = fread(fid,1,'char');
h.offstart          = fread(fid,1,'float');
h.offstop           = fread(fid,1,'float');
h.reject            = fread(fid,1,'char');
h.rejstart          = fread(fid,1,'float');
h.rejstop           = fread(fid,1,'float');
h.rejmin            = fread(fid,1,'float');
h.rejmax            = fread(fid,1,'float');
h.trigtype          = fread(fid,1,'char');
h.trigval           = fread(fid,1,'float');
h.trigchnl          = fread(fid,1,'char');
h.trigmask          = fread(fid,1,'short');
h.trigisi           = fread(fid,1,'float');
h.trigmin           = fread(fid,1,'float');
h.trigmax           = fread(fid,1,'float');
h.trigdir           = fread(fid,1,'char');
h.autoscale         = fread(fid,1,'char');
h.n2                = fread(fid,1,'short');
h.dir               = fread(fid,1,'char');
h.dispmin           = fread(fid,1,'float');
h.dispmax           = fread(fid,1,'float');
h.xmin              = fread(fid,1,'float');
h.xmax              = fread(fid,1,'float');
h.automin           = fread(fid,1,'float');
h.automax           = fread(fid,1,'float');
h.zmin              = fread(fid,1,'float');
h.zmax              = fread(fid,1,'float');
h.lowcut            = fread(fid,1,'float');
h.highcut           = fread(fid,1,'float');
h.common            = fread(fid,1,'char');
h.savemode          = fread(fid,1,'char');
h.manmode           = fread(fid,1,'char');
h.ref               = fread(fid,10,'char');
h.rectify           = fread(fid,1,'char');
h.displayxmin       = fread(fid,1,'float');
h.displayxmax       = fread(fid,1,'float');
h.phase             = fread(fid,1,'char');
h.screen            = fread(fid,16,'char');
h.calmode           = fread(fid,1,'short');
h.calmethod         = fread(fid,1,'short');
h.calupdate         = fread(fid,1,'short');
h.calbaseline       = fread(fid,1,'short');
h.calsweeps         = fread(fid,1,'short');
h.calattenuator     = fread(fid,1,'float');
h.calpulsevolt      = fread(fid,1,'float');
h.calpulsestart     = fread(fid,1,'float');
h.calpulsestop      = fread(fid,1,'float');
h.calfreq           = fread(fid,1,'float');
h.taskfile          = fread(fid,34,'char');
h.seqfile           = fread(fid,34,'char');
h.spectmethod       = fread(fid,1,'char');
h.spectscaling      = fread(fid,1,'char');
h.spectwindow       = fread(fid,1,'char');
h.spectwinlength    = fread(fid,1,'float');
h.spectorder        = fread(fid,1,'char');
h.notchfilter       = fread(fid,1,'char');
h.headgain          = fread(fid,1,'short');
h.additionalfiles   = fread(fid,1,'int');
h.unused            = fread(fid,5,'char');
h.fspstopmethod     = fread(fid,1,'short');
h.fspstopmode       = fread(fid,1,'short');
h.fspfvalue         = fread(fid,1,'float');
h.fsppoint          = fread(fid,1,'short');
h.fspblocksize      = fread(fid,1,'short');
h.fspp1             = fread(fid,1,'ushort');
h.fspp2             = fread(fid,1,'ushort');
h.fspalpha          = fread(fid,1,'float');
h.fspnoise          = fread(fid,1,'float');
h.fspv1             = fread(fid,1,'short');
h.montage           = fread(fid,40,'char');
h.eventfile         = fread(fid,40,'char');
h.fratio            = fread(fid,1,'float');
h.minor_rev         = fread(fid,1,'char');
h.eegupdate         = fread(fid,1,'short');
h.compressed        = fread(fid,1,'char');
h.xscale            = fread(fid,1,'float');
h.yscale            = fread(fid,1,'float');
h.xsize             = fread(fid,1,'float');
h.ysize             = fread(fid,1,'float');
h.acmode            = fread(fid,1,'char');
h.commonchnl        = fread(fid,1,'uchar');
h.xtics             = fread(fid,1,'char');
h.xrange            = fread(fid,1,'char');
h.ytics             = fread(fid,1,'char');
h.yrange            = fread(fid,1,'char');
h.xscalevalue       = fread(fid,1,'float');
h.xscaleinterval    = fread(fid,1,'float');
h.yscalevalue       = fread(fid,1,'float');
h.yscaleinterval    = fread(fid,1,'float');
h.scaletoolx1       = fread(fid,1,'float');
h.scaletooly1       = fread(fid,1,'float');
h.scaletoolx2       = fread(fid,1,'float');
h.scaletooly2       = fread(fid,1,'float');
h.port              = fread(fid,1,'short');
h.numsamples        = fread(fid,1,'long');
h.filterflag        = fread(fid,1,'char');
h.lowcutoff         = fread(fid,1,'float');
h.lowpoles          = fread(fid,1,'short');
h.highcutoff        = fread(fid,1,'float');
h.highpoles         = fread(fid,1,'short');
h.filtertype        = fread(fid,1,'char');
h.filterdomain      = fread(fid,1,'char');
h.snrflag           = fread(fid,1,'char');
h.coherenceflag     = fread(fid,1,'char');
h.continuoustype    = fread(fid,1,'char');
h.eventtablepos     = fread(fid,1,'long');
h.continuousseconds = fread(fid,1,'float');
h.channeloffset     = fread(fid,1,'long');
h.autocorrectflag   = fread(fid,1,'char');
h.dcthreshold       = fread(fid,1,'uchar');

for n = 1:h.nchannels
	e(n).lab            = fread(fid,10,'char');
	e(n).reference      = fread(fid,1,'char');
	e(n).skip           = fread(fid,1,'char');
	e(n).reject         = fread(fid,1,'char');
	e(n).display        = fread(fid,1,'char');
	e(n).bad            = fread(fid,1,'char');
	e(n).n              = fread(fid,1,'ushort');
	e(n).avg_reference  = fread(fid,1,'char');
	e(n).clipadd        = fread(fid,1,'char');
	e(n).x_coord        = fread(fid,1,'float');
	e(n).y_coord        = fread(fid,1,'float');
	e(n).veog_wt        = fread(fid,1,'float');
	e(n).veog_std       = fread(fid,1,'float');
	e(n).snr            = fread(fid,1,'float');
	e(n).heog_wt        = fread(fid,1,'float');
	e(n).heog_std       = fread(fid,1,'float');
	e(n).baseline       = fread(fid,1,'short');
	e(n).filtered       = fread(fid,1,'char');
	e(n).fsp            = fread(fid,1,'char');
	e(n).aux1_wt        = fread(fid,1,'float');
	e(n).aux1_std       = fread(fid,1,'float');
	e(n).sensitivity    = fread(fid,1,'float');
	e(n).gain           = fread(fid,1,'char');
	e(n).hipass         = fread(fid,1,'char');
	e(n).lopass         = fread(fid,1,'char');
	e(n).page           = fread(fid,1,'uchar');
	e(n).size           = fread(fid,1,'uchar');
	e(n).impedance      = fread(fid,1,'uchar');
	e(n).physicalchnl   = fread(fid,1,'uchar');
	e(n).rectify        = fread(fid,1,'char');
	e(n).calib          = fread(fid,1,'float');
end

if strcmp(f.filetype,'avg')
	for i = 1:h.nchannels
		d(i).header      = fread(fid,5,'char');
		d(i).samples     = fread(fid,h.pnts,'float');
	end
	for j = 1:h.nchannels
		v(j).samples     = fread(fid,h.pnts,'float');
	end
else
    h.datastart=ftell(fid);
	SeekStatus=fseek(fid,h.eventtablepos,'bof');
	t.type=fread(fid,1,'char');
	t.size=fread(fid,1,'long');
	t.offset=fread(fid,1,'long');
	% 								Relative file position 
	%                            	0 means the data starts immediately
	%                             	>0 means the data starts at a relative offset
	%                             	from current position at the end of the tag
	if t.type==1
		ntags = t.size./8;
	elseif t.type==2
		ntags = t.size./19;
	else
		error('Invalid tag type!')
	end
	for i=1:ntags
		s(i).stimtype=fread(fid,1,'ushort');
		evtags(i)=s(i).stimtype;
		s(i).keyboard=fread(fid,1,'uchar');
		s(i).keypad=fread(fid,1,'ubit4');
		s(i).accept=fread(fid,1,'ubit4');
		s(i).offset=fread(fid,1,'long');
		offset(i)=s(i).offset;
		if t.type==2
			s(i).responsetype=fread(fid,1,'short');
			s(i).responsecode=fread(fid,1,'short');
			s(i).responselatency=fread(fid,1,'float');
			s(i).responseepochevent=fread(fid,1,'char');
			s(i).responseaccept=fread(fid,1,'char');
			s(i).responseaccuracy=fread(fid,1,'char');
		end
	end
	h.numsamples=(h.eventtablepos-h.datastart)./(h.nchannels.*2); %Neuroscan bug for h.numsamples
end
frewind(fid);
fclose(fid);

f.header = h;
f.electloc = e;
if strcmp(f.filetype,'avg')
	f.data = d;
	f.variance = v;
else
	f.tag = t;
	f.events = s;
end
return;

% ************************************************************************
%  DEFINITIONS OF EVENT TYPES 
% 
%  This structure describes an event type 0 in a continous file					  Bytes
%  typedef struct{
%         unsigned short StimType; //range  0-65535									2
%         unsigned char KeyBoard; //range  0-11  corresponding to function keys +1	1
%         unsigned char KeyPad:4; //range  0-15  bit coded response pad   			1/2	
%         unsigned char Accept:4; //values 0xd=Accept 0xc=Reject 					1/2
%         long Offset;    //file offset of event  									4
% } EVENT1;																		-------
%  Event1Size=																		8
%  This structure describes an event type 1 in a continous file
%  It  contains addition information regarding subject performance in 
%  behavioral task
% 
%  typedef struct{
%         EVENT1  Event1; 															8
%         short    Type;															2
%         short    Code;   															2    
%         float   Latency;															4
%         char    EpochEvent;														1
%         char    Accept;															1
%         char    Accuracy;															1
% } EVENT2;																		---------
%  Event2Size=																		19
% ************************************************************************
