## Copyright (C) 2009, 2010 Thomas Weidenfeller
## 
## This file is part of gds2000tools/gds-octave.
## 
## gds2000tools/gds-octave is free software: you can redistribute it
## and/or modify it under the terms of the GNU General Public License
## version 3 as published by the Free Software Foundation.
## 
## gds2000tools/gds-octave is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License for more details.
## 
## You should have received a copy of the GNU General Public License
## along with gds2000tools/gds-octave.  If not,
## see <http://www.gnu.org/licenses/>.
##

## usage: GDSSTRUCT = gds_csvread (FILENAME)
##
## Read a GDS-series oscilloscope waveform data file in .csv format.
## This is the format the oscilloscope stores on a USB memory stick
## or SD card (depending on then oscilloscope model), when waveform
## data is saved. It is also the format returned by the gdsh(1) command
## gds-csv.
##
## GDSSTRUCT is a structure containing the values of the header data
## found in the .csv file. Like, for example, "Vertical Scale".
## Structure entries are called like the header keys, except that
## spaces are replaced by an underscore. So, for example, "Vertical Scale"
## becomes GDSSTRUCT.Vertical_Scale
##
## The data as such is returned as the GDSSTRUCT.Waveform_Data vector.
##
## Example return value:
##
## gs = gds_csvread("DS0102.CSV")
## gs =
## {
##  Memory_Length =  25000
##  Trigger_Level =  1.3600
##  Source = CH1
##  Vertical_Units = V
##  Vertical_Scale =  0.50000
##  Vertical_Position = -0.96000
##  Horizontal_Units = s
##  Horizontal_Scale =  2.5000e-04
##  Horizontal_Position = 0
##  Horizontal_Mode = Main
##  Sampling_Period =  1.0000e-05
##  Firmware = V1.04
##  Time = 11-Jun-09 00:12
##  Waveform_Data =
##
##     24
##     5
##  ...
## }
##
## See also: gds_plot, gds_spectrum, gds_struct2val

## Author: Thomas Weidenfeller
## Created: 2009-06-11
## Version: $Id: gds_csvread.m,v 1.12 2010/12/31 13:05:40 tw Exp $
## Keywords: Oscilloscope, GDS-2000, gds2000tools


function [ gs ] = gds_csvread (filename)
	if (nargin != 1)
		print_usage();
	endif
	
	fd = fopen(filename);
	if(fd < 0)
		error("Can't open filename");
	endif

	n = 20;		# nbr of lines to check for header data, shouldn't
			# be more than 20 in any of the encountered formats
			# of the known firmware versions
	i = 0;
	while(i++ < n)
		l = fgetl(fd);
		if(l == -1) 
			fclose(fd);
			error("Header data to short")
		endif
		l = split(l, ",");
		if(rows(l) > 0)
			##
			## found a key
			##
			key = strrep(deblank(l(1,:)), " ", "_");

			if(rows(l) > 1)
				##
				## found a value
				##
				value = deblank(l(2,:));
			else
				value = "?";
			endif
		else
			key = "";
		endif
		switch(key)
		case ""
			fclose(fd);
			error("Empty header data")
		case "Firmwave"
			##
			## Correct typical GW Instek spelling error
			##
			key = "Firmware";
		case "Waveform_Data"
			if(rows(l) < 2)
				fmts = "%d";
			else
				fmts = "%d , "; # format contains superfluous ,
			endif
			break;	# leave header loop, waveform data should follow
		endswitch

		##
		## add header data to result structure
		## consider that value is either a string or a numeric value
		##
		v = str2double(value);
		if(isnan(v))
			##
			## Couldn't be parsed as a numeric value, take it
			## as a string
			##
			var = [ "gs." key "=\"" value "\";" ];
		else
			##
			## Numeric value. eval() below will re-parse value into
			## number
			##
			var = [ "gs." key "="  value ";" ];
		endif
		eval(var);
	endwhile
	if(i >= n)
		fclose(fd);
		error("Header to long")
	endif
	if(gs.Memory_Length < 2)  # TODO: Check against a more realistic value
		error("Header information broken");
	endif

	[m, ndata] = fscanf(fd, fmts, gs.Memory_Length);
	fclose(fd);
	if(ndata != gs.Memory_Length)
		error("Data length or format mismatch. Expected %d value(s), got %d value(s).", gs.Memory_Length, ndata);
	endif

	gs.Waveform_Data = m;

endfunction

%!demo
%! ## Create a temporary file with waveform data
%! fname = tmpnam();
%! gs0 = __gds_demo_gs();
%! gds_csvwrite(fname, gs0);
%! ## Read data back from the temporary file and plot
%! ## both the original and the just read data
%! gs1 = gds_csvread(fname);
%! gs1.Source = [ gs1.Source " - reread"];
%! gds_plot(gs0, gs1);
%! unlink(fname);
