#!/usr/bin/perl -w
#
# tsc-data.pl
# version 0.9 -- 22 January 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:h:d:f:';

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

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

-d	 : description, surrounded by commas
-t	 : tau (seconds, default 1)
-h	 : this (help) message
-f	 : logfile using full pathname; for output to console, use "-f -"

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

#----------
# 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('femto.febo.com');

$t_cmd = new Net::Telnet (Timeout => 20,Port=>$cmd_port);
$t_cmd->open('femto.febo.com');


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

# 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 = ($stop_mjd - $start_mjd) * 86400;
	printf LOG "# Run stopped at %s (MJD %11.6F).\n",
		$stop_iso,$stop_mjd;
	printf LOG "# Duration: %d seconds, %d readings (%4.2F per second).\n",
		$duration,$total,$total/$duration;
	close LOG;
	$t_data->close;
	$t_cmd->close;
	exit(0);
}

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