#!/usr/bin/gawk -f
###############################################################################
# $Id: gds-csv-common.awk,v 1.1 2010/09/26 21:53:58 tw Exp $
#
# Common fuctions for converting GDS CSV data to function generator data.
#
# Copyright (C) 2009, 2010 Thomas Weidenfeller
# 
# This file is part of gds2000tools/gds-funcgen.
# 
# gds2000tools/gds-funcgen 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-funcgen 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-funcgen.
# If not, see <http://www.gnu.org/licenses/>.
###############################################################################

#
# Reading data lines
#
WDFlag {
	d = $1
	Data[NData++] = d
	Datmin = min(d, Datmin)
	Datmax = max(d, Datmax)
	next
}

#
# Reading meta data
#

$1 == "Memory Length" {
	MemLen = $2
	next
}

$1 == "Vertical Units" {
	VertUnits = $2
	next
}

$1 == "Vertical Scale" {
	VertScale = $2
	next
}

$1 == "Vertical Position" {
	VertPos = $2
	next
}

$1 == "Horizontal Scale" {
	HoriScale = $2
	next
}

$1 == "Sampling Period" {
	SampPeriod = $2
	next
}

$1 == "Waveform Data" {
	WDFlag++	# data is about to be found
	next
}

#
# Ignore anything else
#
{ next }

###############################################################################
# Convenience functions for messages and formating
# 

#
# Print a message. Message includes the current input file name
# and record (line) number if available.
#
# @param p	Message type string
# @param s	The message
#
function msg(p, s, 	o) {
	if(FILENAME != "" && FNR > 0) {
		o = ORS
		ORS = OLD_ORS
		print MY_NAME ": " p ": "  FILENAME ": " FNR ": " 	\
		      					s > "/dev/stderr"
		ORS = o
	} else {
		msg0(p, s)
	}
}


#
# Print a message. Message never includes the current input file name
# or record (line) number.
#
# @param p	Message type string
# @param s	The message
#
function msg0(p, s, 	o) {
	o = ORS
	ORS = OLD_ORS
	print MY_NAME ": " p ": " s > "/dev/stderr"
	ORS = o
}

#
# Print a "for information" message.
# @param s	The message text.
#
function info(s) {
	if(VERBOSE) {
		msg("Info", s)
	}
}

#
# Print a "for information" message. Never include the file number or
# line number in the message.
#
# @param s	The message text.
#
function info0(s) {
	if(VERBOSE) {
		msg0("Info", s)
	}
}

#
# Print an error message.
# @param s	The message text.
#
function error(s) {
	msg("ERROR", s)
}

#
# Print a fatal error message.
# @param s	The message text.
#
function fatal(s) {
	msg("FATAL", s)
}

#
# Print a fatal error message and terminate the application.
# @param s	The message text.
#
function die(s) {
	fatal(s)
	ExitCode = 1
	exit ExitCode
}

#
# Format a floating point number using SI unit prefixes (base units need
# to be attached separately
#
# @param v	The number to format
# @return	The formated number as a string
#
function engNum(v,	a) {
	a = abs(v)
	if(a >= 1e9) {
		return sprintf("%g G", v / 1e9)
	} else if(a >= 1e6) {
		return sprintf("%f M", v / 1e6)
	} else if(a >= 1000) {
		return sprintf("%f k", v / 1000)
	} else if(a >= 1) {
		return sprintf("%f ", v )
	} else if(a >= 0.001) {
		return sprintf("%f m", v / 0.001)
	} else if(a >= 1e-6) {
		return sprintf("%f u", v / 1e-6)
	} else if(a == 0) {
		return sprintf("0 ", v )
	} else {
		return sprintf("%g n", v / 1e-9)
	}
}

###############################################################################
# Misc. Math Functions
# 

function min(a, b) {
	return a < b ? a : b
}

function max(a, b) {
	return a > b ? a : b
}

function abs(a) {
	return a > 0 ? a : -a
}

function sig(a) {
	return a >= 0
}

# Sinus Cardinalis
# @todo This version is numerically unstable near 0
#
# @param x	Argument
# @return	sinc(x)
#
function sinc(x,	t) {
	t = PI * x
	return t == 0 ? 1 : sin(t) / t
}

#
# Simple re-sampling function, using sinc() interpolation.
# TODO: This is a rather bad idea
#
# @param data	Data to be re-sampled and interpolated
# @param N	Number of original values in data
# @param dataprime
#	 	The re-sampled data [out]. dataprime must be an
#		array type.
#		
# @param nprime	Number of values to be generated in dataprime. This is the
#		number of samples the interpolation shall produce.
#
function sinter(data, n, dataprime, nprime, 	i, j, dp, u, ui) {
	u = (n - 1) / (nprime - 1)
	for(i = 0; i < nprime; i++) {
		dp = 0.0
		ui = u * i
		for(j = 0; j < n; j++) {
			dp += data[j] * sinc(ui - j)
		}
		dataprime[i] = dp

		if(VERBOSE && ((i % 127) == 0)) printf("%c\b", ANIM[i % N_ANIM]) > "/dev/stderr"
	}
}
