#!/usr/bin/perl -w
#
# prologix.pl

use strict;
use POSIX qw(setsid);
use Getopt::Std;
use Time::HiRes qw(usleep);
use DateTime;
use n8ur qw(lower_case trim squash collapse round);
use n8ur_gpib qw( logline);
use vars qw( $OS_win $ob $port );
use Device::SerialPort;

#----------
# some variables that need to be declared
my $quiet = "1";
my $count = 0;
my $lockfile;
my $reading;
my $temp1;
my $temp2;
my $tmp1 = 0;
my $tmp2 = 0;
my $bat;
my $ob;

#----------
# handle signals and errors -- mainly to clear lockfile on termination
sub sig_handler {
	$ob->close if (defined($ob));
	if (-e $lockfile) {unlink $lockfile;}
	exit 0;
}

# there's got to be a better way!
$SIG{'HUP'} = 'sig_handler';
$SIG{'INT'} = 'sig_handler';
$SIG{'KILL'} = 'sig_handler';
$SIG{'STOP'} = 'sig_handler';
$SIG{'TERM'} = 'sig_handler';
#----------
sub write_gpib {
	my $cmd = shift;
	$ob->write($cmd . "\r\n");
	usleep 1000;
	}

sub read_gpib {
	my $gotit = "";
	$ob->are_match("\n");
	$ob->lookclear;
	until ("" ne $gotit) {
      		$gotit = $ob->lookfor;
     		die "Aborted without match\n" unless (defined $gotit);
      		usleep 10000;
		}
	return $gotit;
	}

sub set_gpib_address {
	my $address = shift;
	write_gpib("++addr " . $address);
	usleep 1000;
	write_gpib("++addr");
	my $result = read_gpib();
	return $result;
	}

#----------
# display usage
my $opt_string = 'dh:f:p:';

sub usage() {
print STDERR << "EOF";

usage: $0 [-adh] -f logfile -i log_interval -p serial_port
-d	: run as daemon
-h	: this (help) message
-f	: logfile using full pathname;
	  for output to console, use "-f -"
-p	: serial port ("ttyS1")

EOF
}

#----------
# daemonize
sub daemonize {
	chdir '/' or die "Can't chdir to /: $!";
	umask 0;
	open STDIN, '/dev/null' or die "Can't read /dev/null: $!";
	open STDOUT, '>/dev/null' or die "Can't write to /dev/null: $!";
	open STDERR, '>/dev/null' or die "Can't write to /dev/null: $!";
	defined(my $pid = fork) or die "Can't fork: $!";
	exit if $pid;
	setsid or die "Can't start a new session: $!";
}
#----------

getopts( "$opt_string", \my %opt ) or usage() and exit;

# print usage
usage() and exit if $opt{h};

# run as daemon?
&daemonize if $opt{d};

# set variables to command line params
my $portbase = $opt{p};
my $logfile = $opt{f};

#----------
# set up serial port
my $port = "/dev/" . $portbase;
$lockfile = "/var/lock/LCK.." . $portbase;
$ob = Device::SerialPort->new ($port,$quiet,$lockfile);
die "Can't open serial port $port!\n" unless ($ob);

$ob->baudrate(115200)	|| die "fail setting baud rate";
$ob->parity("none")	|| die "fail setting parity";
$ob->databits(8)	|| die "fail setting data bits";
$ob->stopbits(1)	|| die "fail setting stop bits";
$ob->write_settings || die "no settings";
usleep 100;

#----------
# set up logfile
open (LOG, ">>$logfile") ||
	die "Can't open logfile $logfile!\n";
# set nonbuffered mode
select(LOG), $| = 1;

# write header line
my $dt = DateTime->now;
my $current_iso = $dt->ymd('-') . 'T' . $dt->hms(':');
my $current_mjd = $dt->mjd;
printf LOG "# Run started at %s (MJD %11.6F).\n",
		$current_iso,$current_mjd;

#----------
my $offset;
my $phase;
my $noise;
my $gain;
my $time_constant;
my $status_bits;

write_gpib("++auto 1");

while (1) {
	set_gpib_address(2);

	write_gpib("M2S4");
	$offset = read_gpib();

	write_gpib("M0S4");
	$phase = read_gpib();

	write_gpib("S22S4");
	$noise = read_gpib();

	write_gpib("S23S4");
	$gain = read_gpib();

	write_gpib("S24S4");
	$time_constant = read_gpib();

	write_gpib("S26S4");
	$status_bits = read_gpib();

	$dt = DateTime->now;

	printf LOG "%11.6F %3.2E %1.2E %i %i %i %s\n",
		$dt->mjd,$phase*1e-6,$offset,$gain,$noise,
		trim($time_constant),trim($status_bits);
	sleep 60;
}

$ob->close if (defined($ob));
exit 0;
