#!/usr/bin/perl -w
#
# 5334plotter.pl
# version 0.9 -- 31 Aug 2012
#
# Record time interval readings from HP 5334a counter
# Set switches, take one reading, then exit
# 
# Copyright 2012 by John R. Ackermann  N8UR (jra@febo.com)
#
# This program may be copied, modified, distributed and used for 
# any legal purpose provided that (a) the copyright notice above as well
# as these terms are retained on all copies; (b) any modifications that 
# correct bugs or errors, or increase the program's functionality, are 
# sent via email to the author at the address above; and (c) such 
# modifications are made subject to these license terms.

use strict;
use POSIX qw(setsid);
use Getopt::Std;
use Time::HiRes qw(usleep);
use LinuxGpib;
use DateTime;
use n8ur qw(lower_case trim squash collapse round);
use n8ur_gpib qw(checkSRQ serviceSRQ logline);

# device name from /etc/gpib.conf
my $board = "gpib0";
my $device1 = "hp5334a";
my $device2 = "switch_1";
my $device3 = "switch_2";

my $sw1;
my $sw2;
my $logfile;
my $result;
my $command;
my $count;

# 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';

#----------
# display usage
my $opt_string = 'vhwa:b:c:t:z:f:';

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

usage: $0 [-v] [-z a|b|ab] [-h] [-t iso|mjd] [-w] [-c comment ]
       -a ch -b ch -f logfile

-a	 : start channel (1 - 7)
-b	 : stop channel (1 - 7)
-c	 : comment for logfile header
-f 	 : logfile using full pathname; for output to console, use "-f -"
-h	 : this (help) message
-t	 : timestamp format: iso or mjd (default is mjd)
-v	 : aVerage for 100 readings
-w	 : wrap if reading > 500ms (take reciprocal)
-z	 : 50 ohm termination for channel a, b, or ab

EOF
}

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

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

# set variables to command line params

$logfile = $opt{f};

# Input A, start signal
my $a = 1;
if ($opt{a}) { $a = $opt{a}; }

# Input B, stop signal
my $b = 1;
if ($opt{b}) { $b = $opt{b}; }

my $v = 0;
my $avg = "off";
if ($opt{v}) {
	$v = 1;
	$avg = "on";
	}

my $w = 0;
if ($opt{w}) {
	$w = 1;
	}

my $tag = "mjd";
if ($opt{t}) { $tag = trim(lower_case($opt{t})); }

my $term = "";
if ($opt{z}) { $term = trim(lower_case($opt{z})); }

my $comment = "";
if ($opt{c}) { $comment = $opt{c}; }

#----------
# set up logfile ; use non-buffered since log rate is slow
if (-e $logfile) {
	open (LOG, ">>$logfile") || die "Can't open logfile $logfile!\n";
} else {
	open (LOG, ">$logfile") || die "Can't create logfile $logfile!\n";
	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;
	print LOG "# Data from $device1.";
	print LOG " 100 gate averaging $avg, phase values in seconds.\n";
	print LOG "# Start channel ",$a,".  Stop channel ",$b,".\n";
	if ($comment) { print LOG "# ",$comment,"\n"; }
	}
select(LOG), $| = 1;

#----------
# initialize counter
my $brd = LinuxGpib::ibfind($board);
my $dev1 = LinuxGpib::ibfind($device1);
my $dev2 = LinuxGpib::ibfind($device2);
my $dev3 = LinuxGpib::ibfind($device3);

# clear
LinuxGpib::ibclr($dev1);
usleep(10000);
LinuxGpib::ibclr($dev2);
usleep(10000);
LinuxGpib::ibclr($dev3);
usleep(10000);

# time interval, auto trigger off, wait to be addressed, SRQ mask 1
$command = "INFN5AU0WA1SM1";
LinuxGpib::ibwrt($dev1,$command,length($command));
usleep(10000);

# GV1 to do 100 gate averaging
$command = "GV0";
if ($v) {
	$command = "GV1";
}
LinuxGpib::ibwrt($dev1,$command,length($command));
usleep(10000);

# set 50 ohm input
$command = "";
if ($term eq "a") {
	$command = "AZ1";
	}
if ($term eq "b") {
	$command = "BZ1";
	}
if ($term eq "ab") {
	$command = "AZ1BZ1";
	}
if ($command) {
	LinuxGpib::ibwrt($dev1,$command,length($command));
	usleep(10000);
	}

#----------
# Switch position (for both A and B) is:

sub set_switch {

	SWITCH1: {
		$a == 1 && do { $sw1 = "A1B1" ; last SWITCH1; };
		$a == 2 && do { $sw1 = "A2B1" ; last SWITCH1; };
		$a == 3 && do { $sw1 = "A3B1" ; last SWITCH1; };
		$a == 4 && do { $sw1 = "A4B1" ; last SWITCH1; };
		$a == 5 && do { $sw1 = "A4B2" ; last SWITCH1; };
		$a == 6 && do { $sw1 = "A4B3" ; last SWITCH1; };
		$a == 7 && do { $sw1 = "A4B4" ; last SWITCH1; };
}

	SWITCH2: {
		$b == 1 && do { $sw2 = "A1B1" ; last SWITCH2; };
		$b == 2 && do { $sw2 = "A2B1" ; last SWITCH2; };
		$b == 3 && do { $sw2 = "A3B1" ; last SWITCH2; };
		$b == 4 && do { $sw2 = "A4B1" ; last SWITCH2; };
		$b == 5 && do { $sw2 = "A4B2" ; last SWITCH2; };
		$b == 6 && do { $sw2 = "A4B3" ; last SWITCH2; };
		$b == 7 && do { $sw2 = "A4B4" ; last SWITCH2; };
}

	$command = $sw1;
	LinuxGpib::ibwrt($dev2,$command,length($command));
	usleep(10000);

	$command = $sw2;
	LinuxGpib::ibwrt($dev3,$command,length($command));
	usleep(10000);
}

#----------

# main loop

#set start and stop channel
set_switch;
usleep(100000);

# reset current measurement
$command = "RE";
LinuxGpib::ibwrt($dev1,$command,length($command));

$result = 0;
$count = 0;
while ((!$result) && ($count < 5)) {
	# at most 3 passes so sleep a bit
	if ($v) { sleep 35; } else { usleep 700000; }
	if (checkSRQ($brd) && (!$result)) {
		$result = substr(squash(trim(serviceSRQ($dev1))),1);
		}
	$count++
	}

# 5334 can't deal with negative time interval.  Assume if reading is
# > 500 milliseconds, that it's really early and take reciprocal.
if ( ($w) && ($result > 0.5) ) {
	$result = 1.0 - $result 
	};

print LOG logline($tag,9,$result);

# return to local
LinuxGpib::ibloc($dev1);
usleep(10000);
LinuxGpib::ibloc($dev2);
usleep(10000);
LinuxGpib::ibloc($dev3);
usleep(10000);

close LOG;
exit(0);
#---------
# handle signals and errors -- mainly to clear lockfile on termination
sub sig_handler {
	usleep(10000);
	close LOG;
	exit(0);
}

#----------
exit(0);
