#!/usr/bin/perl

use Device::SerialPort;

$debug =2;
$|=1;

$ob = Device::SerialPort->new("/dev/ttyS1");
$ob->baudrate(9600);
$ob->parity("none");
$ob->databits(8);
$ob->stopbits(1);
$ob->handshake("none");
$ob->rts_active(No);
$ob->dtr_active(No);
$ob->read_const_time(500);
$ob->read_char_time(10);
$ob->debug($debug) if($debug);
$ob->write_settings;

$func{"0"} = "Addr";
$func{"1"} = "Cmd";
$func{"2"} = "Ain0";
$func{"3"} = "Ain1";
$func{"4"} = "Ain2";
$func{"5"} = "Ain3";
$func{"6"} = "VFHi";
$func{"7"} = "VFLo";

#print ping(83);
#print "\n";

#print ping(83,6);
#print "\n";

#$foo = read_raw(1);
#print_data($foo,1);


$i = ping(1,0x10);

$i = setup_charger(1,0,100,255);

print "setup_charger returned $i\n";


sub setup_charger() {
	$unit = shift;
	$volts = shift;
	$amps = shift;
	$time = shift;

	$time_hi = ($time & 0xFF00) / 256;
	$time_lo = $time & 0x00FF;
	
	print "setup_charger()\n" if ($debug);

	$data = chr($unit) . chr(0x0C) . chr($volts) . chr($amps) . chr($time_lo) . chr($time_hi) . chr(0) . chr(0);
	
	do_write($data);
	

	($len, $data) = $ob->read(8);
	
	if($len < 8) {
		print "Error: short read on setup_charger: $len\n" if ($debug);
		return -1;
	}

	$data = chr($unit) . chr(0x0D) . chr($volts) . chr($amps) . chr($time_lo) . chr($time_hi) . chr(0) . chr(0);
	
	do_write($data);
	($len, $data) = $ob->read(8);
	
	if($len < 8) {
		print "Error: short read on setup_charger: $len\n" if ($debug);
		return -2;
	}

	@string = split(//,$data);

	if(($ord = ord($string[1])) != 0x0F) {
		print "Unexpected result $ord from cmd - expected 16" if($debug);
		return -3;
	}
		
	return 1;
}

sub read_raw {

	$unit = shift;

	$string = chr($unit) . chr(0x0B) . chr(0) . chr(0) . chr(0) . chr(0) . chr(0) . chr(0);
	do_write($string);

	($len,$data) = $ob->read(8);

       	if($len < 8) {
		print "Error: short read($len)\n" if($debug);
		print_data($data) if $debug;
		return undef;
	}
		
		

	@array = split(//,$data);
	if(($foo = ord($array[1])) != 0x0A) {
		print "Error: read_raw returned unexpected result $foo\n" if($debug);
		return undef;
	}
	return $data;
}
	
sub ping {

	$unit = shift;
	$cmd = shift || 1;


	$string = chr($unit) . chr($cmd) . chr(0) . chr(0) . chr(0) . chr(0) . chr(0) . chr(0);
	do_write($string);

	($len,$data) = $ob->read(8);

       	if($len < 8) {
		print "Error: short read($len)\n" if($debug);
		print_data($data) if $debug;
		return -1;
	}
		
		

	@array = split(//,$data);
	if(($foo = ord($array[1])) != 2) {
		print "Error: ping returned unexpected result $foo\n" if($debug);
		print_data($data) if($debug);
		return -2;
	}
	return ord($array[0]);
}

sub read_eeprom {
	$unit = shift;
	$addr = shift;

	$addr_hi = ($addr & 0xFF00) / 256;
	$addr_lo = $addr & 0x00FF;

	print "addr: $addr_hi $addr_lo\n" if($debug);

	$string = chr($unit) . chr(0x09) . chr(($addr_hi + 0x80)) . chr($addr_lo) . chr(0) . chr(0) . chr(0) . chr(0);

	print_data($string) if $debug;

	do_write($string);

	($len, $data) = $ob->read(8);
	return -1 if($len < 8);

	@array = split(//,$data);
	print_data($data) if $debug;
	
	return(ord($array[2]));
}


sub write_eeprom {
	$unit = shift;
	$addr = shift;
	$data = shift;

	$addr_hi = ($addr & 0xFF00) / 256;
	$addr_lo = $addr & 0x00FF;

	# prepare a prep cmd

	$string = chr($unit) . chr(0x03) . chr($addr_hi + 0x80) . chr($addr_lo) . chr ($data) . chr(0) . chr(0) . chr(0);

	do_write($string);

	($len, $ldata) = $ob->read(8);
	return -1 if($len < 8);
	
	print "\nPrep cmd done:\n" if $debug;
	print_data($ldata) if $debug;

	@array = split(//,$ldata);

	$string = chr($unit) . chr(0x06) . chr($addr_hi + 0x80) . chr($addr_lo) . chr($data) . chr(255) . chr(255) . chr(255);

	print "\nMain cmd done:\n" if $debug;
	print_data($string) if $debug;


	do_write($string);
	

	($len, $ldata) = $ob->read(8);
	
	if ($len < 8) {
		print "Short read: $len\n" if $debug;
		print_data($ldata) if $debug;
		return -2;
	}

	@array = split(//,$ldata);

	if(($foo = ord($array[1])) != 0x07) {
		print "ERROR: Expected 0x07 got back $foo\n" if($debug);
		return -3;
	}

	return(0);
}

sub wait_a_tick() {
	select(undef,undef,undef,1);
}


sub print_data {
	$string = shift;
	$func_on = shift;

	@letters = split(//,$string);

	$l = 0;
	

	foreach $letter (@letters) {
		$o = ord($letter);
		if($func_on) {
			$f = $func{$l};
			print "$l: $o ($f)\n";	
		} else {
			print "$l: $o\n";
		}
		$l++;
	}
}


sub do_write {
	$string = shift;
	@letters = split(//,$string);

	$count = 0;

	foreach $letter (@letters) {
		$ord = ord($letter);
		print "$count: sending $ord\n" if($debug > 1);
		$count++;
		$ob->write($letter);
		select(undef,undef,undef,0.05);
	}
}


