#!/bin/sh
#
# tore2run -- convert Tore's U of Goteborg .dat files to run files
#
# Usage:  tore2run [-f freq] [-t] tore-file [runfile]
#
# where:  -f freq	specifies the sampling frequency in Hz, overriding the
#			sampling period in the data file header (if given)
#	  -t		specifies that traces, rather than waveforms, should
#			be output in the resulting runfile
#	  tore-file	specifies a data file in Tore's format from the
#			U. of Goteborg's Visual BASIC capture software
#	  runfile	specifies the output run file name
#			(default is to use the same basename as tore-file)
#
# Input file format is as follows:
# 7 lead-in bytes, unknown format, except last 2 bytes give size of rest of
#  data (i.e. 4160 bytes) encoded as little-endian integer
# 82 byte header, all values little-endian
# 999 samples for channel 1 follow header, all little-endian 16-bit signed
# 82 byte header for 2nd channel, values unset (ignored)
# 999 samples for channel 2 follow header, all little-endian 16-bit signed
#
# Copyright (c) 2006, Gilles Detillieux, Spinal Cord Research Centre,
# University of Manitoba.  All Rights Reserved.
#
# Contents of 82 byte header, all values little-endian:
#  bytes  0- 5:	???
#  bytes  6- 7:	Sum reduction, size of cummulative sums
#  bytes  8- 9:	inhibition no., size of PSTH
#  bytes 10-11:	multiple, Ehrilng's?
#  bytes 12-13:	s3, when stim. 3 is on
#  bytes 14-15:	s2, when stim. 2 is on
#  bytes 16-17:	s1, when stim. 1 is on
#  bytes 18-19:	heart rate (not used)
#  bytes 20-21:	blood pressure max
#  bytes 22-23:	DC cath. follower 3
#  bytes 24-25:	DC cath. follower 2
#  bytes 26-27:	DC cath. follower 1
#  bytes 28-39:	sweep levels (ch2 & ch1 old, ch2 & ch1 avg, ch2 & ch1 single)
#  bytes 40-41:	sampling period in microseconds (omitted in averaged files)
#  bytes 42-43:	trigger period in milliseconds (also omitted in avg)
#  bytes 44-45:	ch2 input (1=cf1, 2=cf2, 3=A1, 4=A2, 5=cf3)
#  bytes 46-47:	ch2 preamp (10x, 1x)
#  bytes 48-49:	ch2 polarity (+/-1)
#  bytes 50-51:	ch2 high filter (30, 10, 5, 3, 1 KHz), i.e. low-pass
#  bytes 52-53:	ch2 low filter (800, 40, 15, 1 Hz, DC), i.e. high-pass
#  bytes 54-55:	ch2 amplitude (1-181)
#  bytes 56-67:	same as above for ch1
#  bytes 68-69:	trigger
#  bytes 70-71:	discriminator level
#  bytes 72-73:	number of averages (# sweeps)
#  bytes 74-75:	average mode (1=normal, 2=histogram)
#  bytes 76-77:	no. of superimposed traces on screen (not stored)
#  bytes 78-79:	factor by which other parameters are changed
#  bytes 80-81:	???
#

fopt=
topt=u
delayopt=
while :
do
	case "$1" in
	-\?|-help|--help)	sed -n '3,/^# Univ/s/^#/ /p' "$0"; exit ;;
	-f[0-9]*)	fopt=`expr "x$1" : 'x-f\(.*\)'`; shift ;;
	-f)	shift; fopt="$1"; shift ;;
	-t)	topt=t; delayopt=-d-2; shift ;;
	-*)	set --; break ;;
	*)	break ;;
	esac
done

if [ "$#" -lt 1 -o "$#" -gt 2 ]
then
	echo "Usage:  $0 [-f freq] [-t] tore-file [runfile]
	or  $0 --help  for detailed usage information" >&2
	exit 1
fi

ifile="$1"
ofile="${2:-$1}"
case `basename "$ofile"` in
*.[Dd][Aa][Tt])		ofile=`expr "$ofile" : '\(.*\)\.[Dd][Aa][Tt]$'` ;;
esac

if [ ! -r "$ifile" ]
then
	echo "$0: Can't read data file: $ifile" >&2
	exit 1
fi
(
	dd bs=1 count=5 2>/dev/null >&2		# ignore first 5 lead bytes
	dsize=`dd bs=2 count=1 2>/dev/null | od -t d2 -A n -v -w2 | sed 's/ //g'`
	if [ "$dsize" -ne 4160 ]
	then
		echo "$0: Invalid size field in $ifile: $dsize" >&2
		exit 1
	fi
	dd bs=2 count=6 2>/dev/null >&2		# ignore first 12 header bytes
	s3=`dd bs=2 count=1 2>/dev/null | od -t d2 -A n -v -w2 | sed 's/ //g'`
	s2=`dd bs=2 count=1 2>/dev/null | od -t d2 -A n -v -w2 | sed 's/ //g'`
	s1=`dd bs=2 count=1 2>/dev/null | od -t d2 -A n -v -w2 | sed 's/ //g'`
	hrate=`dd bs=2 count=1 2>/dev/null | od -t d2 -A n -v -w2 | sed 's/ //g'`
	bp=`dd bs=2 count=1 2>/dev/null | od -t d2 -A n -v -w2 | sed 's/ //g'`
	dd bs=2 count=9 2>/dev/null >&2		# ignore next 18 header bytes
	sper=`dd bs=2 count=1 2>/dev/null | od -t d2 -A n -v -w2 | sed 's/ //g'`
	tper=`dd bs=2 count=1 2>/dev/null | od -t d2 -A n -v -w2 | sed 's/ //g'`
	c2in=`dd bs=2 count=1 2>/dev/null | od -t d2 -A n -v -w2 | sed 's/ //g'`
	c2preamp=`dd bs=2 count=1 2>/dev/null | od -t d2 -A n -v -w2 | sed 's/ //g'`
	c2pola=`dd bs=2 count=1 2>/dev/null | od -t d2 -A n -v -w2 | sed 's/ //g'`
	c2hf=`dd bs=2 count=1 2>/dev/null | od -t d2 -A n -v -w2 | sed 's/ //g'`
	c2lf=`dd bs=2 count=1 2>/dev/null | od -t d2 -A n -v -w2 | sed 's/ //g'`
	c2amp=`dd bs=2 count=1 2>/dev/null | od -t d2 -A n -v -w2 | sed 's/ //g'`
	c1in=`dd bs=2 count=1 2>/dev/null | od -t d2 -A n -v -w2 | sed 's/ //g'`
	c1preamp=`dd bs=2 count=1 2>/dev/null | od -t d2 -A n -v -w2 | sed 's/ //g'`
	c1pola=`dd bs=2 count=1 2>/dev/null | od -t d2 -A n -v -w2 | sed 's/ //g'`
	c1hf=`dd bs=2 count=1 2>/dev/null | od -t d2 -A n -v -w2 | sed 's/ //g'`
	c1lf=`dd bs=2 count=1 2>/dev/null | od -t d2 -A n -v -w2 | sed 's/ //g'`
	c1amp=`dd bs=2 count=1 2>/dev/null | od -t d2 -A n -v -w2 | sed 's/ //g'`
	dd bs=2 count=2 2>/dev/null >&2		# ignore next 4 header bytes
	nsweeps=`dd bs=2 count=1 2>/dev/null | od -t d2 -A n -v -w2 | sed 's/ //g'`
	dd bs=2 count=4 2>/dev/null >&2		# ignore next 8 header bytes
	nsamp=999
	if [ ! -z "$fopt" ]
	then
		freq=$fopt
	else
		if [ "$sper" -lt 1 -o "$sper" -gt 32767 ]
		then
			echo "$0: Invalid sampling period in $ifile: $sper" >&2
			case "$ifile" in
			*[Aa]???_???.[Dd][Aa][Tt])
				rfile=`echo "$ifile" | sed 's/[Aa]\(..._.......\)$/D\1/'`
				if [ ! -r "$rfile" ]
				then
					rfile=`echo "$ifile" | sed 's/D\(..._.......\)$/d\1/'`
				fi
				if [ -r "$rfile" ]
				then
					sper=`(dd bs=1 count=47 2>/dev/null >&2; dd bs=2 count=1 2>/dev/null | od -t d2 -A n -v -w2 | sed 's/ //g') < "$rfile"`
				fi
				;;
			esac
			if [ "$sper" -lt 1 -o "$sper" -gt 32767 ]
			then
				echo "$0: Aborting on $ifile" >&2
				exit 1
			elif [ ! -z "$rfile" -a -r "$rfile" ]
			then
				echo "$0: Using sampling period from $rfile: $sper" >&2
			fi
		fi
		freq=`echo "$sper" | awk '{print 1000000.0 / $1}'`
	fi
	case "$c2in" in
	1)	c2in=cf1 ;;
	2)	c2in=cf2 ;;
	3)	c2in=A1 ;;
	4)	c2in=A2 ;;
	5)	c2in=cf3 ;;
	esac
	case "$c1in" in
	1)	c1in=cf1 ;;
	2)	c1in=cf2 ;;
	3)	c1in=A1 ;;
	4)	c1in=A2 ;;
	5)	c1in=cf3 ;;
	esac
	for ch in 0 1
	do
		dd bs=2 count=$nsamp 2>/dev/null |
			od -t d2 -A n -v -w2 | sed 's/  */ /g'
		dd bs=2 count=41 2>/dev/null >&2	# ignore next 82 bytes
	done | awk 'BEGIN {
			i = 0; j = 0; n = '"$nsamp"'; t = "'"$topt"'";
			tp = "'"$tper"'"; f = "'"$freq"'";
		    }
		    {
			d[i, j] = $1
			if (++i >= n) {
				i = 0;
				++j;
			}
		    }
		    END {
			for (i = 0; i < n; i++) {
			    if (t == "t") printf("%c%c", 0, (i>0&&i<53)?2:0);
			    printf("%c%c", (d[i, 0]+65536) % 256, int(d[i, 0] / 256 + 256) % 256);
			    printf("%c%c", (d[i, 1]+65536) % 256, int(d[i, 1] / 256 + 256) % 256);
			}
			# Pad raw data to specified trigger period so that
			# successive raw sweeps can be appended...
			n = int(tp * f / 1000.0 + 0.5);
			while (i < n) {
			    if (t == "t") printf("%c%c", 0, 0);
			    printf("%c%c", 0, 0);
			    printf("%c%c", 0, 0);
			    i++;
			}
		    }' |
		dsepr -f"$freq" -mc $delayopt -w"$nsamp" -n${topt}2 1 1 -o "$ofile"
		#echo "c1=$c1in, c1a=$c1amp, c1lf=$c1lf, c1hf=$c1hf, c1pa=$c1preamp" > "$ofile.txt"
		#echo "c2=$c2in, c2a=$c2amp, c2lf=$c2lf, c2hf=$c2hf, c2pa=$c2preamp" >> "$ofile.txt"
		#echo "s1=$s1, s2=$s2, s3=$s3, n=$nsweeps" >> "$ofile.txt"
		echo "c1lf=$c1lf, c1hf=$c1hf, c1pa=$c1preamp, c2lf=$c2lf, c2hf=$c2hf, c2pa=$c2preamp, s1=$s1, s2=$s2, s3=$s3" > "$ofile.txt"
		case "$topt" in
		u)	topt=w ;;
		esac
		case "$c1amp" in
		1)	c1amp=190 ;;
		2)	c1amp=381 ;;
		3)	c1amp=538 ;;
		5)	c1amp=760 ;;
		6)	c1amp=1071 ;;
		16)	c1amp=3050 ;;
		23)	c1amp=4250 ;;
		32)	c1amp=6000 ;;
		45)	c1amp=8400 ;;
		*)	c1amp=`expr "$c1amp" \* 187` ;;
		esac
		case "$c2amp" in
		1)	c2amp=190 ;;
		2)	c2amp=381 ;;
		3)	c2amp=538 ;;
		5)	c2amp=760 ;;
		6)	c2amp=1071 ;;
		16)	c2amp=3050 ;;
		23)	c2amp=4250 ;;
		32)	c2amp=6000 ;;
		45)	c2amp=8400 ;;
		*)	c2amp=`expr "$c2amp" \* 187` ;;
		esac
		sysvecho "sf${ofile}\nnnqc${topt}0\nh${c1amp}\nl10000\nz0\nn${c1in}\nq${topt}1\nh${c2amp}\nl10000\nz0\nn${c2in}\nqsqqyn" |
			TERM=dumb DISPLAY= analysis 2>/dev/null
) < "$ifile"
