#
#
#  expriment to read from serial port.
#  Doug Rice
#
# To get input I found I needed to use: 
#   `stty -F /dev/ttyUSB1 4800 time 50 ` ;
#
# Use Fcntl on Linux to provide a read() with timeout.
#
#
#

use Fcntl;

$usb ="ttyUSB0";

my $cnt = 0;
print "Setting up terminal ....\n";

print `ls /dev/ttyU*` ;
sleep(1);
print `stty -F /dev/$usb 4800 -icanon raw -echo -parity cs8 min 0 time 0 ` ;
sleep(1);
print `stty -F /dev/$usb -a`;

$rin = $win = $ein='';

while(1) {
  print "Opening terminal.......";
  open( COM, "+</dev/$usb") or die "Can't read serial port : $!\n";


  $flags = fcntl( COM,   F_SETFL, $flags | O_NONBLOCK) or die "Can't set flags for the socket: $!\n";
  $flags = fcntl( STDIN, F_SETFL, $flags | O_NONBLOCK) or die "Can't set flags for the socket: $!\n";
  
#  set to SLURP mode - 
  #select( COM );
  #$| = 1 ;
  #select( STDIN );
  #$/ = 1; ;


#
# Use select to wait with time out 
#
# it is not possible to do a poll to see if data available
# You can use select to slow things down
# You can then wait a short period of time for IO.
#  
  $rin = $win = $ein = $nfound = $stdin_bit = $com_bit = "";

  vec( $stdin_bit, fileno( STDIN ), 1 ) = 1;
  vec( $stdout_bit,fileno( STDOUT), 1 ) = 1;
  vec( $com_bit,   fileno( COM   ), 1 ) = 1;

  vec( $rin,       fileno( STDIN ), 1 ) = 1;
  vec( $rin,       fileno( COM   ), 1 ) = 1;

  print "\n==============++++++=======================\n";
  print vec( $stdin_bit, fileno( STDIN ), 1 );
  print "\n==============++++++=======================\n";
  print vec( $stdin_bit, fileno( COM   ), 1 );
  print "\n==============++++++=======================\n";


  # $rin = $stdin_bit | $com_bit;
  $ein = $rin       | $win ;
  
  printf( " bits %x %x %x %x ", $rin, $stdin_bit, $com_bit );
  print   " bits: " . unpack("b8",$rin) . "/" . unpack("b8",$stdin_bit) . "/" . unpack("b8",$com_bit). "/" . unpack("b8",$eout) ;
   
  #print COM "d;\r"; 
  
  # set up the terminal speed after opening serial port
  print `stty -F /dev/$usb 4800 -icanon raw -echo -parity cs8 min 0 time 0 ` ;
  sleep(1);
  #  print COM "\n\rd;\n";
  #  fflush COM ;

  #
  # This blocks awaiing characters
  #
  $cnt=4;
  $timeout = 3;
  $run = ( 1==1 );
  $all = "" ;
  while( $run ){
 
    #
    # Is it possible to set select to work at lines
    # I.E only indicate if line available.
    #
    #
    # select work on charaters, we really only want it to return if COM has a line.
    #

	#
	# we use select slow down the polling.
    ($nfound, $timeleft)  = select( undef, undef , undef , 0.1 );

	#
	# flush out command if any
	#  
	if ( length( $op ) > 0 ) { 
	  print "\n\ncmd: $op \n\n" ; 
      #syswrite COM ,$op , 1, length( $op );
      print COM $op ;
      $op = ""  ;
    }


    $timeoutFlag = 1;
	# we use select to see if any IO is ready.   Only block for a short while
    ($nfound, $timeleft)  = select( $rout=$rin, undef , undef , 0.1 );
    #print "\nfound: t=" .$timeleft." ". $nfound . "/" . unpack("b32",$rout) . "/" . unpack("b32",$stdin_bit) . "/" . unpack("b32",$com_bit) . "/" . unpack("b8",$eout);
    #print "\n==============++++++=======================\n";
    #print vec( $rout, fileno( STDIN ), 1 );
    #print vec( $rout, fileno( COM   ), 1 );

    
    if ( vec( $rout, fileno( COM ), 1 ) == 1 ) {
	  $timeoutFlag = 0;	
	  #	
	  # <COM> blocks until a line is received.
	  # we need a non blocking read 
	  #	http://perldoc.perl.org/functions/readline.html
	  #
	  #readline EXPR
	  #readline
	  #

      #while ( ! eof($fh) ) {
    	  #defined( $_ = <$fh> ) or die "readline failed: $!";
    	  #...
    	  #}
	  #
	  #$temp =select(COM);
      #$/ = undef;	  
      #select( $temp);    
      # print "tell COM:".tell( COM );
      
      $ip  = "";
	  $len = sysread COM, $ip, 4000, 0  	;    
	  $all = $all.$ip;
	  
	  #read COM ,$ip,100 ;
	  #$ip = <COM>;
	  print $all;
      
    } 

    
    if (  vec( $rout, fileno( STDIN ), 1 ) == 1 ) {
	  $timeoutFlag = 0;
	  	
	  #$len = sysread STDIN,$ip,4000 	; 
	  $ip = <STDIN>;	

	  $cmd = $ip;
	  if ( $len > 0) {
   	    print "\nkey:" . $ip .":" ;
	    if ( $cmd eq "go" ) { print "="; print COM "p07;\r" ;	}
	    if ( $cmd =~ /du/ ) { print "="; $op = "d;\n";	}	    
	    if ( $cmd =~ /poll/ ) { print "="; $op = "p07;\n";	}	    
	    if ( $cmd =~ /a/ ) { print "="; $op = "w07ff;\n";	}	    
	    if ( $cmd =~ /b/ ) { print "="; $op = "w0700;\n";	}	    
	    if ( $cmd =~ /S/ ) { print "="; $op = "S;\n";	}	    
	    if ( $cmd =~ /s/ ) { print "="; $op = "s;\n";	}	    

	  }  
	  #$op = "";
    }     
    if ($timeoutFlag == 0 ) {
		$all="";
	}    
  }
  close(COM);
  print "sleep";
  sleep(1);
}
