#!/usr/bin/perl -w

use strict;
use Opt;
use Tty;
use POSIX;
use Vec;
use Ascii;

use Data::Dumper;

$Opt::synopsis = "Make points/holes in the x/y plane according to the pattern given by the function and arguments given.
\tThe argument output=<xx> decides the output, where xx can be gcode, xy (list of points) or ps (postscript).";

$Opt::OPT{dev} = "/dev/ttyUSB0";
$Opt::OPT{baud} = 115200;

my %save = ( state => 0, fh => undef );

########################################

sub sigQuit() {
    print "Hej quitting\n";
    my $cx = Ascii::CTRL("X");
    print "^X\n";
    my $fh = $save{fh};
    print $fh $cx;
}
sub DevAbortCurrentJob($) {
    # device dependant actions to abort running job
    my $fh = shift;
    my $cx = Ascii::CTRL("X");

    # write ^X and wait for Grbl again, the release the alarm state and go home
#    print "^X\n";
#    print $fh $cx;

#    @str = ('$X', "f1000"); # just in case we didn't had time to send it yet
#    push @str, split(/ /, $Opt::OPT{gcend});
#    $ix = 0;
#    $gcode_global = 0;


    waitGrbl($fh);

    while (<$fh>) {
	next unless (defined($_));
	print $_;
	if (m/^\[MSG:/) {
	    last;
	}
    }
}
sub waitGrbl($) {
    my $fh = shift;

    print "waitGrbl\n";
    while (<$fh>) {
	next unless (defined($_));
	print $_;
	if (m/^Grbl/) {
	    last;
	}
    }
}
sub doDev() {
    waitGrbl($save{fh});

    #DevExit($save_termios) if ($gcode_global);
    while (my $inp = <>) {
	if ($save{state} & Tty::st_blocked) {
	    DevAbortCurrentJob($save{fh});
	};
	#print $inp;
	my $fh = $save{fh};
	print $fh $inp;

	my $rsp = <$save{fh}>;
	next unless (defined($rsp));
	print $rsp;
    }

    DevExit(\%save);
}

sub ProcLines() {
    sleep 1;
    print `stty -F $Opt::OPT{dev} -a`;
}

########################################

sub Init() {
    $SIG{'INT'} = \&sigQuit;
    my $baudbits = TtyTermios::Num2Bits($Opt::OPT{baud});
    print "$Opt::OPT{baud} -: $baudbits\n";
    %save = Tty::tty_open($Opt::OPT{dev}, $baudbits, \&TtyTermios::Rawline);
    if (!defined($save{fh})) {
	die "open fail\n";
	return;
    };
}
sub Exit() {
    if (defined($save{fh})) {
	Tty::tty_close(\%save);
    }
    exit(0);
}

########################################

sub main() {
    @ARGV = Opt::opt();
    Opt::opt(\&Opt::UsageDisp);
    print STDERR Opt::Show(\%Opt::OPT);

    Init();
    ProcLines();
    Exit();
}

main();

__END__

1. comment (includes message).
2. set feed rate mode (G93, G94 â inverse time or per minute).
3. set feed rate (F).
4. set spindle speed (S).
5. select tool (T).
6. change tool (M6).
7. spindle on or off (M3, M4, M5).
8. coolant on or off (M7, M8, M9).
9. enable or disable overrides (M48, M49).
10. dwell (G4).
11. set active plane (G17, G18, G19).
12. set length units (G20, G21).
13. cutter radius compensation on or off (G40, G41, G42)
14. cutter length compensation on or off (G43, G49)
15. coordinate system selection (G54, G55, G56, G57, G58, G59, G59.1, G59.2, G59.3).
16. set path control mode (G61, G61.1, G64)
17. set distance mode (G90, G91).
18. set retract mode (G98, G99).
19. home (G28, G30) or

          change coordinate system data (G10) or
          set axis offsets (G92, G92.1, G92.2, G94).
20. perform motion (G0 to G3, G80 to G89), as modifed (possibly) by G53.
21. stop (M0, M1, M2, M30, M60).
