/
Gcode.cpp
127 lines (114 loc) · 4.28 KB
/
Gcode.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
/*
This file is part of Smoothie (http://smoothieware.org/). The motion control part is heavily based on Grbl (https://github.com/simen/grbl).
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.
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.
You should have received a copy of the GNU General Public License along with Smoothie. If not, see <http://www.gnu.org/licenses/>.
*/
#include <string>
using std::string;
#include "Gcode.h"
#include "libs/StreamOutput.h"
#include "utils.h"
#include <stdlib.h>
// This is a gcode object. It reprensents a GCode string/command, an caches some important values about that command for the sake of performance.
// It gets passed around in events, and attached to the queue ( that'll change )
Gcode::Gcode(const string& command, StreamOutput* stream) : command(command), m(0), g(0), add_nl(false), stream(stream) {
prepare_cached_values();
this->millimeters_of_travel = 0L;
this->accepted_by_module=false;
}
Gcode::Gcode(const Gcode& to_copy){
this->command.assign( to_copy.command );
this->millimeters_of_travel = to_copy.millimeters_of_travel;
this->has_m = to_copy.has_m;
this->has_g = to_copy.has_g;
this->m = to_copy.m;
this->g = to_copy.g;
this->add_nl = to_copy.add_nl;
this->stream = to_copy.stream;
this->accepted_by_module=false;
this->txt_after_ok.assign( to_copy.txt_after_ok );
}
Gcode& Gcode::operator= (const Gcode& to_copy){
if( this != &to_copy ){
this->command.assign( to_copy.command );
this->millimeters_of_travel = to_copy.millimeters_of_travel;
this->has_m = to_copy.has_m;
this->has_g = to_copy.has_g;
this->m = to_copy.m;
this->g = to_copy.g;
this->add_nl = to_copy.add_nl;
this->stream = to_copy.stream;
this->txt_after_ok.assign( to_copy.txt_after_ok );
}
this->accepted_by_module=false;
return *this;
}
// Whether or not a Gcode has a letter
bool Gcode::has_letter( char letter ){
//return ( this->command->find( letter ) != string::npos );
for (std::string::const_iterator c = this->command.cbegin(); c != this->command.cend(); c++) {
if( *c == letter ){
return true;
}
}
return false;
}
// Retrieve the value for a given letter
// We don't use the high-level methods of std::string because they call malloc and it's very bad to do that inside of interrupts
double Gcode::get_value( char letter ){
//__disable_irq();
const char* cs = command.c_str();
char* cn = NULL;
for (; *cs; cs++){
if( letter == *cs ){
cs++;
double r = strtod(cs, &cn);
if (cn > cs)
return r;
}
}
//__enable_irq();
return 0;
}
int Gcode::get_int( char letter )
{
const char* cs = command.c_str();
char* cn = NULL;
for (; *cs; cs++){
if( letter == *cs ){
cs++;
int r = strtol(cs, &cn, 10);
if (cn > cs)
return r;
}
}
return 0;
}
int Gcode::get_num_args(){
int count = 0;
for(size_t i=1; i<this->command.length(); i++){
if( this->command.at(i) >= 'A' && this->command.at(i) <= 'Z' ){
count++;
}
}
return count;
}
// Cache some of this command's properties, so we don't have to parse the string every time we want to look at them
void Gcode::prepare_cached_values(){
if( this->has_letter('G') ){
this->has_g = true;
this->g = this->get_int('G');
}else{
this->has_g = false;
}
if( this->has_letter('M') ){
this->has_m = true;
this->m = this->get_int('M');
}else{
this->has_m = false;
}
}
void Gcode::mark_as_taken(){
this->accepted_by_module = true;
}