#!c:\Perl\bin\Perl
#
# This is an example file showing how to send data to the serial port.
#
# It does not include error checking.
#
use strict;

#use Device::SerialPort; # on UNIX
use Win32::SerialPort; # on Windows
##use Term::Getch;
##use Term::ReadKey;
##ReadMode('cbreak');

#my $DEVICE = "/dev/ttyS1"; # on UNIX
my $DEVICE = "COM5";  # on Windows

my $msg = "Hello World!";
my $dbgon1 = 0; # off for normal running
my $dbgon2 = 0; # off for normal running
my $maxperfile = 10; # for testing 60; # assume one-per-second
my $cnt = 0;
my $InBytes = 256;
my $maxmsg = 512;
###my $cfgfile = "com1.cfg";
my $cfgfile = "c:/Gtools/perl/comm5.txt";
my $gpsbgn = '\$GPRMC';
my $OF;
my $logfile = "templ001.txt";
my $logdir = 'pos/';
my $outfile = $logdir . $logfile;
open ($OF, ">$outfile") or die "Can NOT open log file ... [$outfile]!!! ...";

sub openPort($);
sub closePort($);

print "Openning $DEVICE ...\n";
my $serial = openPort($DEVICE);

print "Reading $InBytes from $DEVICE ...\n";
my ($count_in, $string_in); ### = $serial->read($InBytes);
### warn "read unsuccessful\n" unless ($count_in == $InBytes);
$msg = $string_in;
my $msglast = '';
my $msgend = "";
my $gotstg = 0;
my $pos1 = 0;
my $pos2 = 0;
my $gpsmsg = '';
my $outcnt = 0;
my $totcnt = 0;
###my $maxperfile = 60; # assume one-per-second

my ($count_in, $string_in); ### = $serial->read($InBytes);
$msg = "";
print "Awaiting first GPS message ... Ctrl+C to exit!\n" if $gotstg;
while (1) {
	# stay here until FIRST GPS message received, or at least the $GPRMC beginning
	($count_in, $string_in) = $serial->read($InBytes);
	$msglast = $msg; # keep last
	$msg .= $string_in; # accumulate the input
	print "Read $count_in of $InBytes ... $string_in.\n";
	if ( $msg =~ /\$GPRMC/om ) {
		$pos1 = index ($msg, '$GPRMC');
		if ($pos1 > 0) {
			$msg = substr( $msg, $pos1 );
		}
		print "$msg ... Ctrl+C to exit";
		$gotstg = 1;
		last;
	}
}

print "\nBeginning GPS message accumulation ... Ctrl+C to exit\n" if $gotstg;
$| = 1; # set file flush on
while ($gotstg) {
	($count_in, $string_in) = $serial->read($InBytes);
	$msglast = $msg;
	$msg .= $string_in;
	if ($gotstg) {
		# we already have a start of cycle on $GPRMC sentence
		$msgend = substr($msg,6);
		if ($msgend =~ /\$GPRMC/om) { # got NEXT
			$outcnt++; # bump the GPS message set count
			$totcnt++; # bump the GPS message total count
			if ($dbgon1) {
				print "\nGot GPS Count $totcnt\n";
			} else {
				print "\rGot GPS Count $totcnt/$outcnt ... Ctrl+C to exit!";
			}
			$pos2 = index ($msgend, '$GPRMC');
			$gpsmsg = '$GPRMC' . substr($msgend, 0, $pos2);
			print $gpsmsg if $dbgon2;
			print $OF $gpsmsg;
			$msg = substr ($msgend, $pos2);
			print "NEW START: $msg" if $dbgon2;
			if ($outcnt >= $maxperfile) {
				close ($OF);
				$logfile = nextfilename($logfile);
				$outfile = $logdir . $logfile;
				print "\nNew log file = $outfile ...\n";
				open ($OF, ">$outfile") or die "Can NOT open log file ... $outfile ...";
				$outcnt = 0;
			}
		}
	}

##	if (defined ($char = ReadKey(-1)) ) {
##	if (defined ($char = getch()) ) {
##		# input was waiting and it was $char
##		last;
##	}
}

print "\nExit while ... len=" . length($msg) . "\n";
print "$msg\n";
close ($OF);

###print "Writing $DEVICE ...\n";
###$serial->write("Hello World");
###$cnt = $serial->write($msg);
###print "Written $cnt (", length($msg), ") ... Closing $DEVICE ...\n";
closePort($serial);
###ReadMode('normal');     # restore normal tty settings

#**************************************************************************
#*  Serial functions
#**************************************************************************

#* Open raw serial port using:
#*    8 data bits
#*    1 stop bit
#*    19200 bps
#*    no parity
sub openPort($)
{
	my ($device) = @_;
	print "openPort $device ...\n";
	#my $serial = Device::SerialPort->new ($device, 1); # on UNIX
	my $serial = Win32::SerialPort->new ($device, 1); # on Windows
	die "Can't open serial port $serial: $^E\n" unless ($serial);

  my ($BlockingFlags, $InBytes, $OutBytes, $LatchErrorFlags) = $serial->status
        || warn "could not get port status\n";
  if ($BlockingFlags) { warn "Port is blocked"; }
#  if ($BlockingFlags & BM_fCtsHold) { warn "Waiting for CTS"; }
  if ($BlockingFlags & $serial->BM_fCtsHold) { warn "Waiting for CTS"; }
#  if ($LatchErrorFlags & CE_FRAME) { warn "Framing Error"; }
  if ($LatchErrorFlags & $serial->CE_FRAME) { warn "Framing Error"; }
        # The API resets errors when reading status, $LatchErrorFlags
        # is all $ErrorFlags seen since the last reset_error

	$serial->user_msg(1);
	$serial->databits(8);
	###$serial->baudrate(19200);
	$serial->parity("none");
	$serial->stopbits(1);
	###$serial->handshake("rts");

	$serial->buffers( 4096, 4096 );

#  my ($BlockingFlags, $InBytes, $OutBytes, $LatchErrorFlags) = $serial->status
#        || warn "could not get port status\n";
#  if ($BlockingFlags) { warn "Port is blocked"; }
#  if ($BlockingFlags & BM_fCtsHold) { warn "Waiting for CTS"; }
#  if ($LatchErrorFlags & CE_FRAME) { warn "Framing Error"; }
# $PortObj->transmit_char(0x03);        # bypass buffer (and suspend)
# $ModemStatus = $PortObj->modemlines;
# if ($ModemStatus & $PortObj->MS_RLSD_ON) { print "carrier detected"; }

	$serial->write_settings || die "Setting port FAILED";
	$serial->save($cfgfile); # = 'comm?.txt';

    return $serial;
}

sub closePort($)
{
	my ($serial) = @_;
	print "closePort ...\n";
	$serial->close();
}

# using 'templ' + '001-999' numbers
sub nextfilename {
	my ($tx) = @_;
	my $tx1 = substr ($tx, 0, 5);
	my $tx2 = substr ($tx, 5);
	my $tx3 = substr ($tx2, 0, 3);
	my $tx4 = substr ($tx2, 3);
	$tx3++;
	if ($tx3 > 999) {
		$tx3 = '001';
	}
	return ($tx1 . $tx3 . $tx4);
}
# eof

