#!/usr/bin/perl package gcode; $VERSION=0.01; @ISA=qw(Exporter); @EXPORT=qw( x y z d f r ); my $f="%9f "; my $ff="%2.1f"; # convience functions to help with calling these functions. # basically so you can write x instead of 'x' # they don work, dont know why. sub x {'x'} sub y {'y'} sub z {'z'} sub f {'f'} sub r {'r'} sub d {'d'} # effectively providesone level of buffereing for commands. Needed to make sure recursive calls do what you think they should. sub proc { my ($g,$c)=@_; # params are gcode object, code my ($file)=$g->{file}; print $file $g->{pending}."\n" if ($g->{pending}); $g->{pending}=$c; return $c; } # object creator sub new { my ($x,$file,$feed)=@_; $x={}; $x->{file}=$file; open($file,">".$file) or die; $x->{pending}="%\nG40 G17"; $x->{feed}=$feed; return bless $x; } # initialisation code at the start of gcode sub ginit { } # produces a comment protected by gcodes comment convention sub gcomment { my $gc=shift; my ($c)=@_; return proc($gc,"( $c )"); } # move command. perhaps this would be a good point to explain the calling convention here. # its a bit odd. In order to preserve the useful feature of gcode that you can provide what # ever parameters you want to provide (and in whatever order) the convention is that # that you pass an x followed by the x value and so on. # can be intollerent of faulty calls sub gmove { my $g="G1 "; my $c; my $gc=shift; while (@_) { $c.=sprintf("%s $f",uc($_[0]),$_[1]) if ($_[0] =~/^[xyz]$/i); $c.=sprintf("F $ff",$_[1]) if ($_[0] =~/^f$/i); shift; shift; } return proc($gc, "$g $c") if ($c); return ""; } # arc clockwise, x,y and r radius only implemented. sub garccw { # clockwise arc my $g="G2 "; my $c; my $gc=shift; while (@_) { $c.=sprintf("%s $f",uc($_[0]),$_[1]) if ($_[0] =~/^[xyzrij]$/i); $c.=sprintf("F $ff",$_[1]) if ($_[0] =~/f/i); shift; shift; } return proc($gc,"$g $c\n") if ($c); return ""; } # arc clockwise sub garcccw { # counter clockwise arc my $g="G3 "; my $c; my $gc=shift; while (@_) { $c.=sprintf("%s $f",uc($_[0]),$_[1]) if ($_[0] =~/^[xyzrij]$/i); $c.=sprintf("F $ff",$_[1]) if ($_[0] =~/f/i); shift; shift; } return proc($gc,"$g $c\n") if ($c); return ""; } # cutter compensation on driving on the righ # you can supply an additional function if you want the compensation to linearly # come into effect as a move is performed. sub gcompr { # cutter compensation on, cutting to the right $c="G42 "; $gc=shift; while ($_[0] =~/^[d]$/i) { $c.=sprintf("%s %d",uc($_[0]),$_[1]) ; shift; shift; } while ($_[0]=~/^G/i) { $c.=" ".$_[0]; shift; $gc->{pending}=''; # we clear this if additional values are passed } return proc($gc,$c); } # cutter (radius) compensation, drive on the left. sub gcompl { # cutter compensation on, cutting to the left $c="G41 "; $gc=shift; while ($_[0] =~/^[d]$/i) { $c.=sprintf("%s %d",uc($_[0]),$_[1]) ; shift; shift; } while ($_[0]=~/G/i) { $c.=" ".$_[0]; shift; $gc->{pending}=''; # we clear this if additional values are passed } return proc($gc,$c); } # switch off compensation. sub gcomp0 { # cutter compensation off $c="G40 "; $gc=shift; while ($_[0]=~/G/i) { $c.=" ".$_[0]; shift; $gc->{pending}=''; # we clear this if additional values are passed } return proc($gc,$c); } # end of program. sub gend { my ($gc)=@_; $gc->proc(''); my $file= $gc->{file}; print $file "%\n"; close $file; } 1;