PiloinControl:
To do that, you're going to want to find a way to not sit and wait for an input command. In other words, you want non-blocking input.
It looks like you're headed in the right direction, since your code looks like you're trying to read a character. But by default, perl will wait until you have an
entire line of data before it will return from my $char = <STDIN>;. If you use Term::ReadKey, it can let you read a character or get an undef if there isn't
a character ready.
I don't have a serial thingie set up on my computer, so here's a silly little example of how you might be able to do it:
$ cat funky_i_o.pl
use strict;
use warnings;
use Term::ReadKey;
use Time::HiRes qw( alarm );
# Buffer used to build our command line
my $command_line = "";
# Buffer for our (fake) serial data
my @serial_data = ();
# Put console into raw mode
ReadMode 4;
setup_serial_interface();
my $are_we_done_yet = 0;
while (!$are_we_done_yet) {
my $con_key = ReadKey(-1);
if (defined $con_key) {
if ($con_key eq "\r" or $con_key eq "\n") {
# user finished entering the command
handle_command($command_line);
$command_line = "";
}
else {
# Not end of line, so add to command line.
# NOTE: you'll want to handle backspace and/or
# other line editing commands. But that's too
# much work for a quick demo...
$command_line .= $con_key;
}
}
elsif (is_serial_data_ready()) {
# Serial device gave us something to do
handle_serial_data();
}
else {
# Don't eat *ALL* the cpu, since nothing came in from
# the console or serial line, pause a brief time to let
# something arrive
# Here, you'd normally use a sleep or usleep. But alarm
# and sleep aren't necessarily on friendly terms with each
# other, and we're using alarm to fake a serial device. So
# we're not actually going to delay here, but you would want
# to in a real application.
}
}
# Restore normal console mode
ReadMode(0);
sub handle_command {
my $cmd = shift;
if ($cmd =~ /^q/i) {
print "Quitting!\n";
$are_we_done_yet = 1;
}
elsif ($cmd =~ /^d.*(\d+)/i) {
print "Starting a task that takes $1 seconds!\n";
my $t = time;
while ($t + $1 > time) {
; # fake process ... just wait until time expires
}
print "...and now we're done!\n";
}
else {
print "Unknown command: $cmd\n";
}
}
###
# Our fake serial interface
###
sub setup_serial_interface {
my $seconds_per_transmission = 0.567;
$SIG{ALRM} = sub {
push @serial_data, rand;
alarm $seconds_per_transmission;
};
# First packet of data should occur in a couple seconds
alarm 2.5;
}
sub is_serial_data_ready {
return scalar @serial_data;
}
sub handle_serial_data {
print "We haz teh dataz! (", join(", ", @serial_data), ")\n";
@serial_data = ();
}
When I ran it, I got the following (with a bunch of lines snipped out, as indicated):
$ perl funky_i_o.pl
We haz teh dataz! (0.947528113451884)
<<< snip! don't want output to be too long! >>>
We haz teh dataz! (0.345542351805733)
We haz teh dataz! (0.91829197130572)
Unknown command: now is
We haz teh dataz! (0.226257566965014)
We haz teh dataz! (0.517020773183582)
<<< snip again! >>>
We haz teh dataz! (0.917061227597888)
Starting a task that takes 5 seconds!
...and now we're done!
We haz teh dataz! (0.214499409451559, 0.574298714543268, 0.86510970635
+5287, 0.412658576047463, 0.56280680260377, 0.488052299033619, 0.60365
+2722987906)
We haz teh dataz! (0.375474185862402)
We haz teh dataz! (0.382325609198627)
Unknown command: now is
We haz teh dataz! (0.951879935396668)
<<< snip! >>>
We haz teh dataz! (0.760059503593943)
Quitting!
...roboticus
When your only tool is a hammer, all problems look like your thumb.