#!/usr/bin/perl
use warnings;
use strict;
use Device::SerialPort;
use Data::Dump qw(dump);

my $port = '/dev/ttyUSB1';
$port = '/dev/serial/by-id/usb-Prolific_Technology_Inc._USB-Serial_Controller-if00-port0';

my $debug = $ENV{DEBUG} || 0;

my $ob = new Device::SerialPort ($port)
                 || die "Can't open $port: $!\n";

$ob->baudrate(38400)	|| die "fail setting baudrate";
$ob->parity("none")	|| die "fail setting parity";
$ob->databits(8)	|| die "fail setting databits";
$ob->stopbits(1)	|| die "fail setting stopbits";
$ob->handshake("none")	|| die "fail setting handshake";
$ob->debug($debug);

my $InBytes = 255;

my @commands = qw(
system
status
config
);

$ob->write( shift(@commands) . "\n" );

my $got = '';
my $s;

my $show_response = $debug;

while ( 1 ) {
	my ($count_in, $string_in) = $ob->read($InBytes);
	print "<< $count_in << ",dump($string_in),"\n" if $debug && $count_in > 0;
	$got .= $string_in;
	if ( $got =~ m/(OK|E!)\r\n/ ) {
		warn "# got = ",dump( $got ) if $show_response;
		$show_response = $debug;
		my $new;
		foreach ( split(/[\r\n]+/,$got) ) {
			my ($k,$v) = split(/:\s+/,$_,2);
			if ( ! defined $v ) {
				warn "SKIP: [$_]\n" if $debug;
			} else {
				$new->{$k} = $v if ! defined $s->{$k} || $s->{$k} ne $v;
				$s->{$k} = $v;
			}
		}
		warn "# new = ",dump( $new ) if $debug;

		print join("", map {
			my $n = $_;
			if ( my $v = $s->{$n} ) {
				$v =~ s/(\d+) (\d+)$/$1/; # strip adc
				"$n $v" . ( exists $new->{$n} ? '*' : ' ' );
			} else { '?' };
		} qw(
VIN
VSET
VOUT
CSET
COUT
OUTPUT
CONSTANT
    		) ), "\n";


		$got = '';
		if ( @commands ) {
			$ob->write( shift(@commands) . "\n" );
		} else {
			alarm(1);
			my $c;
			eval {
				local $SIG{ALRM} = sub { die };
				$c = <STDIN>;
				chomp $c;
				alarm(0);
				if ( length($c) == 0 ) {
					print ">> ";
					$c = <STDIN>;
					chomp $c;
				}
				$show_response = 1;
				push @commands, 'config';
			};


			if ( $c eq '?' ) {
				print dump($s);
				$c = '';
			} 

			# always emit something to keep update working
			$c ||= "status";
			warn ">> ",dump($c) if $debug;
			$ob->write( "$c\n" );
		}
	}
}

