#!/usr/bin/perl ###################### # # VARIABLES, # PACKAGES, & DEFINES # ###################### use strict; use warnings; use diagnostics; use Term::ReadKey; use Win32::Console::ANSI qw/ Title SetCloseButton Cursor :SW_ /; use Win32::Console::ANSI; use Win32::Console; use Term::ANSIColor; use Term::ANSIScreen qw/:cursor :screen/; ########################## # # SET TERMINAL ATTRIBUTES # ########################## $SIG{INT}= 'IGNORE'; SetCloseButton(0); ShowConsoleWindow(SW_SHOWMAXIMIZED); #################################### # # LOGGING KEY STROKE TIME STAMP SUB # #################################### my $time = localtime(time); # ADD TIME STAMP TO LOGFILE ################## # # SET SERIAL PORT # ################## my $port = setup_serial_port("COM7") or die "Open Port Failed. $!\n"; ################## # # MAIN SCREEN SUB # ################## no warnings 'numeric'; #Title "Simple Signals Driver"; print colored("CONNECTING TO SIGNAL SYSTEM...", 'bold green'), "\n"; sleep(15); print "\n", colored("CONNECTED...",'bold green'), "\n", colored("STARTING RELAY SIGNAL PROGRAM", 'bold green'), "\n\n"; # Buffer used to build our command line my $command_line = ""; # Buffer for our serial data my $serial_input; # Holds incomplete command(s) my @serial_data = (); # Commands ready to process # Put console into raw mode ReadMode 4; setup_serial_interface(); my $are_we_done_yet = 0; while (!$are_we_done_yet) { # Check for console activity 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 { # NOTE: I'd try to wait here so we don't kill a CPU, but without # Time::HiRes, we can only sleep for an entire second, and that # would make console I/O feel sluggish. So until we resolve that, # we'll just kill a CPU #NEED SHORT DELAY HERE TO LET OTHER PROCESSES HAVE CPU } } close_serial_port(); ReadMode(0); # RESTORE CONSOLE MODE ################# # # HANDLE COMMAND # ################# sub handle_command { my $cmd = shift; if ($cmd =~ /^q/i) { print "\n", colored("QUIT PROGRAM!", 'bold yellow'), "\n"; $are_we_done_yet = 1; } elsif ($cmd =~ /^\d+$/i) { print colored("\nSENDING COMMAND $cmd $time...", 'bold yellow'), "\n\n"; $port->write("$cmd\r"); $port->lookclear(); print colored("DONE!", 'bold yellow'), "\n\n"; } else { print colored("UNKNOWN COMMAND: $cmd", 'bold red'), "\n"; } } ############################# # # USB/SERIAL/INTERFACE WITH # THE ARDUINO # ############################# sub setup_serial_interface { use Win32::SerialPort; my $COM = shift; $port = Win32::SerialPort->new($COM) or die "Open Port Failed. $!\n"; $port->is_rs232; # SET UP THE SERIAL PORT # 9600 OR 19200, 81N ON THE USB FTDI DRIVER $port->initialize(); $port->baudrate(9600); $port->databits(8); $port->parity("none"); $port->stopbits(1); $port->write_settings || undef $port; return $port; } sub close_serial_port { $port->purge_all; $port->close or die "CLOSE FAILED: $!\n"; undef $port; # FREES PORT MEMORY } sub is_serial_data_ready { # Non-blocking read: otherwise, we'll hang up here! my $c = $port->input; # Process the incoming characters for my $char (split '', $c) { if ($char eq "\n" or $char eq "\r") { # End of line found, add current line to buffer # (unless it's empty) if ($serial_input ne '') { push @serial_data, $serial_input; # start a new blank line $serial_input = ""; } } else { # Just a normal character, add to the input $serial_input .= $char; } } # Returns true if there are any completed lines to handle return scalar @serial_data; } sub handle_serial_data { while (my $cmd = shift @serial_data) { print colored("Incoming Data:", 'bold green'), colored($cmd, 'bold yellow'), "\n"; } }