#!/usr/bin/perl -w
#
# tsc-data.pl
# version 1.0 -- 26 December 2009
#
# Capture phase data from TSC-5120A
# 
# Copyright 2007-9 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 DateTime;
use n8ur qw(lower_case trim squash collapse round);
use n8ur_gpib qw(logline logline_tsc);
use Net::Telnet;

my $machine = '192.168.1.248';
my $data_port = '1298';
my $cmd_port = '1299';

my $logfile;
my $data;
my $t_data;
my $t_cmd;
my @tmp;
my @lines;
my @avg;
my @frac;
my $j;
my $counter;
my $total;

# 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 = 't:hd:lf:';

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

usage: $0 [-t tau] [-h] [-l] [-d description] -f logfile

-d	 : description, surrounded by quotes
-t	 : tau (seconds, default 1)
-h	 : this (help) message
-f	 : logfile using full pathname; for output to console, use "-f -"
-l	 : listen only mode (don't interrogate on port 1299)

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};

my $description = "";
if ($opt{d}) {
	$description = $opt{d};
	}

my $tau = 1;
if ($opt{t}) {
	$tau = $opt{t};
	}

my $nth =  1000*$tau;

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

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

#----------
# set up logfile ; use buffered since data rate is pretty high
open (LOG, ">>$logfile") || die "Can't open logfile $logfile!\n";
select(LOG), $| = 1;

#----------
$t_data = new Net::Telnet (Timeout => 20,Port=>$data_port);
$t_data->open($machine);

if (!$listen_only) {
	$t_cmd = new Net::Telnet (Timeout => 20,Port=>$cmd_port);
	$t_cmd->open($machine);
	}


# write header line
my $dt = DateTime->now;
my $start_iso = $dt->ymd('-') . 'T' . $dt->hms(':');
my $start_mjd = $dt->mjd;
printf LOG "# TSC-5120A:  Run started at %s (MJD %11.6F).\n",
	$start_iso,$start_mjd;
if ($description) { print LOG "# $description\n"; }
print LOG "# Tau = ",$nth/1000," seconds, phase relative to input frequency.\n";

if (!$listen_only) {
	print "listen_only = $listen_only\n";
	# Get inputs
	# doubling command is ugly way to make sure output is flushed
	@lines = $t_cmd->cmd("show inputs");
	@lines = $t_cmd->cmd("show inputs");

	@tmp = split(/ /,$lines[1]);
	my $input_freq = $tmp[2];
	my $input_ampl = $tmp[5];
	my $input_start_scale = 1/($input_freq*1e6);

	@tmp = split(/ /,$lines[2]);
	my $ref_freq = $tmp[2];
	my $ref_ampl = $tmp[5];

	print LOG "# Input: " . $input_freq . "MHz " . $input_ampl .
         "dBm Reference: " . $ref_freq . "MHz " . $ref_ampl . "dBm\n";

	# Get start frequency offset

	@lines = $t_cmd->cmd("show fcounter");
	# swallow prompt at end
	for ($j = 3; $j < @lines-1; $j++) {
		@tmp = split(/\s/,$lines[$j]);
		$avg[$j-2] = $tmp[2];
		$frac[$j-2] = sprintf('%e',($tmp[2]-$input_freq)/$input_freq);
	}	
	for ($j = 1; $j < @avg; $j++) {
		if ($avg[$j]) {
			trim($avg[$j]);
			}
		else    {
			$avg[$j] = "";
		}	
	}	
	print LOG "# Start Frequency:\n";
	print LOG "# $avg[1] MHz $frac[1] (1 second)\n";
	if ($avg[2]) { print LOG "# $avg[2] MHz $frac[2] (10 seconds)\n"; }
	if ($avg[3]) { print LOG "# $avg[3] MHz $frac[3] (100 seconds)\n"; }
		if ($avg[4]) { print LOG "# $avg[4] MHz $frac[4] (1000 seconds)\n"; }
	print "#\n";
	print "# Phase data follows (remember to remove linear)\n";
}
#----------
# main loop
$total = 0;
$counter = 1;

while (1) {
	$data = $t_data->getline;
	if ($counter == $nth) {
		print LOG $data;
		$counter = 1;
		$total++;
		$dt = DateTime->now;
		}
	else {
		$counter++
		}
	}


#----------
# handle signals and errors -- mainly to clear lockfile on termination
sub sig_handler {
	# write footer line
	my $stop_iso = $dt->ymd('-') . 'T' . $dt->hms(':');
	my $stop_mjd = $dt->mjd;
	my $duration_hours = ($stop_mjd - $start_mjd) * 24;
	my $duration_seconds = ($stop_mjd - $start_mjd) * 86400;
	printf LOG "# Run stopped at %s (MJD %11.6F).\n",
		$stop_iso,$stop_mjd;
	printf LOG "# Duration: %.2f hours, %d readings (%4.2F per second).\n",
		$duration_hours,$total,$total/$duration_seconds;
	close LOG;
if (!$listen_only) {
		$t_cmd->close;
	}
	$t_data->close;
	exit(0);
}

#----------
sig_handler;
