File Coverage

blib/lib/CNC/Cog/Gcode.pm
Criterion Covered Total %
statement 12 143 8.3
branch 0 46 0.0
condition 0 14 0.0
subroutine 4 23 17.3
pod 0 19 0.0
total 16 245 6.5


line stmt bran cond sub pod time code
1             # Written by Mark Winder, mark.winder4@btinternet.com
2 1     1   5067 use vars qw($VERSION);
  1         3  
  1         90  
3             $VERSION=0.061;
4            
5             package Gcode;
6 1     1   6 use vars qw(@ISA);
  1         2  
  1         72  
7             @ISA=qw(CNC::Cog::Gcode);
8             # I define another package Gcode, this enables you to say new Gcode(...
9             # instead of new CNC::Cog::Gcode(...;
10            
11            
12             package CNC::Cog::Gcode;
13 1     1   10 use vars qw(@ISA);
  1         3  
  1         59  
14             @ISA=qw(Exporter);
15 1     1   6 use Carp;
  1         2  
  1         2394  
16            
17             my $f="%9f ";
18             my $ff="%2.1f";
19            
20             my $lineno=0;
21             # effectively providesone level of buffereing for commands. Needed to make sure recursive calls do what you think they should.
22             sub proc
23             {
24 0     0 0   my ($g,$c)=@_; # params are gcode object, code
25            
26 0           my ($file)=$g->{file};
27            
28 0 0         printf($file "%s\n",$g->{pending}) if ($g->{pending});
29 0           $g->{pending}=$c;
30 0           return $c;
31             }
32             # object creator
33             sub new
34             {
35 0     0 0   my ($class,$file,$feed,$toolnumber)=@_;
36 0   0       $class=ref($class) || $class;
37 0           my ($x)={};
38 0           $x->{file}=$file;
39 0 0         open($file,">".$file) or croak("Unable to open file $file for write");
40 0           $x->{pending}="%\nG40 G17";
41 0           $x->{feed}=$feed;
42 0           $x->{cuttersize}=0;
43 0           $x->{toolnumber}=1;
44 0 0         $x->{toolnumber}=$toolnumber if (defined $toolnumber);
45 0           return bless $x,$class;
46             }
47             # initialisation code at the start of gcode
48             sub ginit
49 0     0 0   {
50            
51             }
52             sub setcuttersize
53             {
54 0     0 0   my ($g,$s)=@_; # set cutter diameter default to inches.
55             # can add pt for point, mm for millimetres, cm for centimetres
56             # can add i for inches (default)
57             # can add t for thous of an inch
58 0           $s=~s/i//;
59 0 0         $s=~s/pt// and $s/=72;
60 0 0         $s=~s/mm// and $s/=25.4;
61 0 0         $s=~s/cm// and $s/=2.54;
62 0 0         $s=~s/t// and $s/=1000.0;
63            
64 0 0         $s=~/[a-zA-Z]/ and die "Invalid unit specification $s";
65            
66 0           $g->{cuttersize}=$s;
67            
68             }
69             sub getcuttersize
70             {
71 0     0 0   my ($g)=@_;
72            
73 0           return $g->{cuttersize};
74             }
75            
76            
77             # produces a comment protected by gcodes comment convention
78             sub gcomment
79             {
80 0     0 0   my $gc=shift;
81 0           my ($c)=@_;
82            
83 0           $c=~s/\n$//;
84 0           my @c=split("\n",$c);
85 0           @c=grep { $_ ne ''} @c;
  0            
86 0 0         return "" if (@c==0);
87 0           while (@c>1)
88             {
89 0           $c=shift @c;
90 0           proc($gc,"( $c )");
91             }
92 0           $c=shift @c;
93 0           return proc($gc,"( $c )");
94             }
95             # rapid move command.
96             sub grapid
97             {
98 0     0 0   my $g="G0";
99 0           my $c;
100 0           my $gc=shift;
101 0           while (@_)
102             {
103 0 0         $c.=sprintf("%s $f",uc($_[0]),$_[1]) if ($_[0] =~/^[xyz]$/i);
104             # $c.=sprintf("F $ff",$_[1]) if ($_[0] =~/^f$/i);
105 0           shift; shift;
  0            
106             }
107 0 0         return proc($gc, "$g $c") if ($c);
108 0           return "";
109             }
110             # move command. perhaps this would be a good point to explain the calling convention here.
111             # its a bit odd. In order to preserve the useful feature of gcode that you can provide what
112             # ever parameters you want to provide (and in whatever order) the convention is that
113             # that you pass an x followed by the x value and so on.
114             # can be intollerent of faulty calls
115             sub gmove
116             {
117 0     0 0   my $g="G1";
118 0           my $c;
119 0           my $gc=shift;
120 0           my $hasfeed=0;
121 0           while (@_)
122             {
123 0 0         $c.=sprintf("%s $f",uc($_[0]),$_[1]) if ($_[0] =~/^[xyz]$/i);
124 0 0         $c.=sprintf("F $ff",$hasfeed=$_[1]) if ($_[0] =~/^f$/i);
125 0           shift; shift;
  0            
126             }
127 0   0       $gc->{feedsent}||=0;
128 0 0 0       $c.=sprintf("F $ff",$gc->{feed}) if (!$hasfeed and !$gc->{feedsent});
129 0           $gc->{feedsent}=1;
130 0 0         return proc($gc, "$g $c") if ($c);
131 0           return "";
132             }
133             sub gdwell
134             {
135 0     0 0   my $g="G4 ";
136 0           my $c='';
137 0           my $gc=shift;
138 0           while (@_)
139             {
140 0 0         if ($_[0] =~/^[p]$/i) # we adopting a slightly different aroach here to other functions
141             { # if provided, ignore it, otherwise assume arg is dwell in seconds
142 0           shift; # so can do gdwell('p',2) or gdwell(2)
143             }
144             else
145             {
146 0           $c.=sprintf(" P$f",$_[0]);
147 0           shift;
148             }
149             }
150 0 0         return proc($gc, "$g $c") if ($c);
151 0           return "";
152             }
153            
154             # arc clockwise, x,y and r radius only implemented.
155             sub garccw
156             {
157             # clockwise arc
158 0     0 0   my $g="G2 ";
159 0           my $c;
160 0           my $gc=shift;
161 0           while (@_)
162             {
163 0 0         $c.=sprintf("%s $f",uc($_[0]),$_[1]) if ($_[0] =~/^[xyzrij]$/i);
164 0 0         $c.=sprintf("F $ff",$_[1]) if ($_[0] =~/f/i);
165 0           shift; shift;
  0            
166             }
167 0 0         return proc($gc,"$g $c\n") if ($c);
168 0           return "";
169             }
170             # arc clockwise
171             sub garcccw
172             {
173             # counter clockwise arc
174 0     0 0   my $g="G3 ";
175 0           my $c;
176            
177 0           my $gc=shift;
178 0           while (@_)
179             {
180 0 0         $c.=sprintf("%s $f",uc($_[0]),$_[1]) if ($_[0] =~/^[xyzrij]$/i);
181 0 0         $c.=sprintf("F $ff",$_[1]) if ($_[0] =~/f/i);
182 0           shift; shift;
  0            
183             }
184 0 0         return proc($gc,"$g $c\n") if ($c);
185 0           return "";
186             }
187             # cutter compensation on driving on the righ
188             # you can supply an additional function if you want the compensation to linearly
189             # come into effect as a move is performed.
190             sub gcompr
191             {
192             # cutter compensation on, cutting to the right
193            
194            
195 0     0 0   my ($c)="G42 ";
196 0           my ($gc)=shift;
197            
198 0           while ($_[0] =~/^[d]$/i)
199             {
200 0           $c.=sprintf("%s %d",uc($_[0]),$_[1]) ;
201 0           shift; shift;
  0            
202             }
203            
204 0   0       while (@_>0 and $_[0]=~/^G/i)
205             {
206 0           $c.=" ".$_[0];
207 0           shift;
208 0           $gc->{pending}=''; # we clear this if additional values are passed
209             }
210 0           return proc($gc,$c);
211             }
212             # cutter (radius) compensation, drive on the left.
213             sub gcompl
214             {
215             # cutter compensation on, cutting to the left
216            
217 0     0 0   my ($c)="G41 ";
218 0           my ($gc)=shift;
219 0           while ($_[0] =~/^[d]$/i)
220             {
221 0           $c.=sprintf("%s %d",uc($_[0]),$_[1]) ;
222 0           shift; shift;
  0            
223             }
224 0           while ($_[0]=~/G/i)
225             {
226 0           $c.=" ".$_[0];
227 0           shift;
228 0           $gc->{pending}=''; # we clear this if additional values are passed
229             }
230 0           return proc($gc,$c);
231             }
232             # switch off compensation.
233             sub gcomp0
234             {
235             # cutter compensation off
236            
237 0     0 0   my ($c)="G40 ";
238 0           my ($gc)=shift;
239 0   0       while (@_>0 and $_[0]=~/G/i)
240             {
241 0           $c.=" ".$_[0];
242 0           shift;
243 0           $gc->{pending}=''; # we clear this if additional values are passed
244             }
245 0           return proc($gc,$c);
246             }
247             # end of program.
248             sub gend
249             {
250 0     0 0   my ($gc)=@_;
251 0           $gc->proc('');
252 0           my $file= $gc->{file};
253 0           print $file "%\n";
254 0           close $file;
255             }
256            
257             # The following routines are used for debug purposes. In this package they should always do nothing.
258 0     0 0   sub gmark {} # make a cross mark at a given point
259 0     0 0   sub gline {} # draw a line between 2 points.
260 0     0 0   sub gruler{} # draw a ruler for sizing purposes.
261             sub rednext # make the next line red, not used in g code output produces comment **** red ****
262             {
263 0     0 0   my ($g)=@_;
264 0           $g->gcomment("**** red ****");
265             }
266             1;
267