Fork of Smoothie to port to mbed non-LPC targets.

Dependencies:   mbed

Fork of Smoothie by Stéphane Cachat

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers Gcode.cpp Source File

Gcode.cpp

00001 /*
00002       This file is part of Smoothie (http://smoothieware.org/). The motion control part is heavily based on Grbl (https://github.com/simen/grbl).
00003       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.
00004       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.
00005       You should have received a copy of the GNU General Public License along with Smoothie. If not, see <http://www.gnu.org/licenses/>.
00006 */
00007 
00008 
00009 #include <string>
00010 using std::string;
00011 #include "Gcode.h"
00012 #include "libs/StreamOutput.h"
00013 #include "utils.h"
00014 
00015 #include <stdlib.h>
00016 
00017 // This is a gcode object. It reprensents a GCode string/command, an caches some important values about that command for the sake of performance.
00018 // It gets passed around in events, and attached to the queue ( that'll change )
00019 Gcode::Gcode(const string& command, StreamOutput* stream) : command(command), m(0), g(0), add_nl(false), stream(stream) {
00020     prepare_cached_values();
00021     this->millimeters_of_travel = 0.0F;
00022     this->accepted_by_module=false;
00023 }
00024 
00025 Gcode::Gcode(const Gcode& to_copy){
00026     this->command.assign( to_copy.command );
00027     this->millimeters_of_travel = to_copy.millimeters_of_travel;
00028     this->has_m                 = to_copy.has_m;
00029     this->has_g                 = to_copy.has_g;
00030     this->m                     = to_copy.m;
00031     this->g                     = to_copy.g;
00032     this->add_nl                = to_copy.add_nl;
00033     this->stream                = to_copy.stream;
00034     this->accepted_by_module=false;
00035     this->txt_after_ok.assign( to_copy.txt_after_ok );
00036 }
00037 
00038 Gcode& Gcode::operator= (const Gcode& to_copy){
00039     if( this != &to_copy ){
00040         this->command.assign( to_copy.command );
00041         this->millimeters_of_travel = to_copy.millimeters_of_travel;
00042         this->has_m                 = to_copy.has_m;
00043         this->has_g                 = to_copy.has_g;
00044         this->m                     = to_copy.m;
00045         this->g                     = to_copy.g;
00046         this->add_nl                = to_copy.add_nl;
00047         this->stream                = to_copy.stream;
00048         this->txt_after_ok.assign( to_copy.txt_after_ok );
00049     }
00050     this->accepted_by_module=false;
00051     return *this;
00052 }
00053 
00054 
00055 // Whether or not a Gcode has a letter
00056 bool Gcode::has_letter( char letter ){
00057     //return ( this->command->find( letter ) != string::npos );
00058     for (std::string::const_iterator c = this->command.cbegin(); c != this->command.cend(); c++) {
00059         if( *c == letter ){
00060             return true;
00061         }
00062     }
00063     return false;
00064 }
00065 
00066 // Retrieve the value for a given letter
00067 // 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
00068 float Gcode::get_value( char letter ){
00069     //__disable_irq();
00070     const char* cs = command.c_str();
00071     char* cn = NULL;
00072     for (; *cs; cs++){
00073          if( letter == *cs ){
00074              cs++;
00075              float r = strtof(cs, &cn);
00076              if (cn > cs)
00077                  return r;
00078          }
00079     }
00080     //__enable_irq();
00081     return 0;
00082 }
00083 
00084 int Gcode::get_int( char letter )
00085 {
00086     const char* cs = command.c_str();
00087     char* cn = NULL;
00088     for (; *cs; cs++){
00089         if( letter == *cs ){
00090             cs++;
00091             int r = strtol(cs, &cn, 10);
00092             if (cn > cs)
00093                 return r;
00094         }
00095     }
00096     return 0;
00097 }
00098 
00099 int Gcode::get_num_args(){
00100     int count = 0;
00101     for(size_t i=1; i<this->command.length(); i++){
00102         if( this->command.at(i) >= 'A' && this->command.at(i) <= 'Z' ){
00103             count++;
00104         }
00105     }
00106     return count;
00107 }
00108 
00109 // Cache some of this command's properties, so we don't have to parse the string every time we want to look at them
00110 void Gcode::prepare_cached_values(){
00111     if( this->has_letter('G') ){
00112         this->has_g = true;
00113         this->g = this->get_int('G');
00114     }else{
00115         this->has_g = false;
00116     }
00117     if( this->has_letter('M') ){
00118         this->has_m = true;
00119         this->m = this->get_int('M');
00120     }else{
00121         this->has_m = false;
00122     }
00123 }
00124 
00125 void Gcode::mark_as_taken(){
00126     this->accepted_by_module = true;
00127 }