2 This file is part of Smoothie (http://smoothieware.org/). The motion control part is heavily based on Grbl (https://github.com/simen/grbl).
3 Smoothie is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
4 Smoothie is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
5 You should have received a copy of the GNU General Public License along with Smoothie. If not, see <http://www.gnu.org/licenses/>.
10 #include "libs/StreamOutput.h"
15 // This is a gcode object. It reprensents a GCode string/command, an caches some important values about that command for the sake of performance.
16 // It gets passed around in events, and attached to the queue ( that'll change )
17 Gcode::Gcode(const string
&command
, StreamOutput
*stream
, bool strip
)
19 this->command
= strdup(command
.c_str());
24 this->millimeters_of_travel
= 0.0F
;
25 this->accepted_by_module
= false;
26 prepare_cached_values(strip
);
31 if(command
!= nullptr) {
32 // TODO we can reference count this so we share copies, may save more ram than the extra count we need to store
37 Gcode::Gcode(const Gcode
&to_copy
)
39 this->command
= strdup(to_copy
.command
); // TODO we can reference count this so we share copies, may save more ram than the extra count we need to store
40 this->millimeters_of_travel
= to_copy
.millimeters_of_travel
;
41 this->has_m
= to_copy
.has_m
;
42 this->has_g
= to_copy
.has_g
;
45 this->add_nl
= to_copy
.add_nl
;
46 this->stream
= to_copy
.stream
;
47 this->accepted_by_module
= false;
48 this->txt_after_ok
.assign( to_copy
.txt_after_ok
);
51 Gcode
&Gcode::operator= (const Gcode
&to_copy
)
53 if( this != &to_copy
) {
54 this->command
= strdup(to_copy
.command
); // TODO we can reference count this so we share copies, may save more ram than the extra count we need to store
55 this->millimeters_of_travel
= to_copy
.millimeters_of_travel
;
56 this->has_m
= to_copy
.has_m
;
57 this->has_g
= to_copy
.has_g
;
60 this->add_nl
= to_copy
.add_nl
;
61 this->stream
= to_copy
.stream
;
62 this->txt_after_ok
.assign( to_copy
.txt_after_ok
);
64 this->accepted_by_module
= false;
69 // Whether or not a Gcode has a letter
70 bool Gcode::has_letter( char letter
) const
72 for (size_t i
= 0; i
< strlen(this->command
); ++i
) {
73 if( command
[i
] == letter
) {
80 // Retrieve the value for a given letter
81 float Gcode::get_value( char letter
, char **ptr
) const
83 const char *cs
= command
;
88 float r
= strtof(cs
, &cn
);
89 if(ptr
!= nullptr) *ptr
= cn
;
94 if(ptr
!= nullptr) *ptr
= nullptr;
98 int Gcode::get_int( char letter
, char **ptr
) const
100 const char *cs
= command
;
103 if( letter
== *cs
) {
105 int r
= strtol(cs
, &cn
, 10);
106 if(ptr
!= nullptr) *ptr
= cn
;
111 if(ptr
!= nullptr) *ptr
= nullptr;
115 int Gcode::get_num_args() const
118 for(size_t i
= 1; i
< strlen(command
); i
++) {
119 if( this->command
[i
] >= 'A' && this->command
[i
] <= 'Z' ) {
126 // Cache some of this command's properties, so we don't have to parse the string every time we want to look at them
127 void Gcode::prepare_cached_values(bool strip
)
130 if( this->has_letter('G') ) {
132 this->g
= this->get_int('G', &p
);
136 if( this->has_letter('M') ) {
138 this->m
= this->get_int('M', &p
);
145 // remove the Gxxx or Mxxx from string
147 char *n
= strdup(p
); // create new string starting at end of the numeric value
153 void Gcode::mark_as_taken()
155 this->accepted_by_module
= true;
158 // strip off X Y Z I J parameters if G0/1/2/3
159 void Gcode::strip_parameters()
162 // strip the command of the XYZIJK parameters
165 // find the start of each parameter
166 char *pch
= strpbrk(cn
, "XYZIJK");
167 while (pch
!= nullptr) {
169 // copy non parameters to new string
170 newcmd
.append(cn
, pch
-cn
);
172 // find the end of the parameter and its value
175 cn
= eos
; // point to end of last parameter
176 pch
= strpbrk(cn
, "XYZIJ"); // find next parameter
178 // append anything left on the line
180 // strip whitespace to save even more
181 newcmd
.erase(std::remove_if(newcmd
.begin(), newcmd
.end(), ::isspace
), newcmd
.end());
183 // release the old one
185 // copy the new shortened one
186 command
= strdup(newcmd
.c_str());