Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions Marlin/Configuration_adv.h
Original file line number Diff line number Diff line change
Expand Up @@ -4118,6 +4118,15 @@
//#define GCODE_QUOTED_STRINGS // Support for quoted string parameters
#endif

/**
* Variables
*
* Define a variable from 100-115 with G-code like '#101=19.6'.
* A variable can then be used in a G-code expression like 'G0 X[#101+3]'.
* See https://gcodetutor.com/cnc-macro-programming/cnc-variables.html
*/
//#define GCODE_VARIABLES

/**
* Support for MeatPack G-code compression (https://github.com/scottmudge/OctoPrint-MeatPack)
*/
Expand Down
4 changes: 4 additions & 0 deletions Marlin/src/gcode/gcode.h
Original file line number Diff line number Diff line change
Expand Up @@ -351,6 +351,10 @@
*** "T" Codes ***
*
* T0-T3 - Select an extruder (tool) by index: 'T<n> F<units/min>'
*
*** 'L' Codes ***
*
* L100-L115 - Definable variables
*/

#include "../inc/MarlinConfig.h"
Expand Down
108 changes: 104 additions & 4 deletions Marlin/src/gcode/parser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,8 @@ bool GCodeParser::volumetric_enabled;

char *GCodeParser::command_ptr,
*GCodeParser::string_arg,
*GCodeParser::value_ptr;
*GCodeParser::value_ptr,
*GCodeParser::var_arg;
char GCodeParser::command_letter;
uint16_t GCodeParser::codenum;

Expand Down Expand Up @@ -106,6 +107,68 @@ void GCodeParser::reset() {

#endif

// Create Variable Declaration
//#if ENABLED(GCODE_VARIABLES)
// Pass the data being stored
// char* GCodeParser::input_var(char* &src); //{
// if (*src == 'L') src; // Skip the leading Letter
// int * const out = src; // Start of the string
// char *dst = src; // Prepare to unescape and terminate
// for (;;) {
// char c = *src++; // Get the next char
// switch (c) {
// case '\\': c = *src++; break; // Get the escaped char
// case '"' : c = '\0'; break; // Convert bare quote to nul
// }
// if (!(*dst++ = c)) break; // Copy and break on nul
// }
// return out;
// }
//
//#endif

//Enable Math Functions and assigning values to variables in GCode
//#if ENABLED(GCODE_MATH_STRINGS)
//
// // Pass the address after the first quote (if any)
// char* GCodeParser::math_string(char* &src) {
// if (*src == '{') ++src; // Skip the leading quote
// char * const out = src; // Start of the string
// char *dst = src; // Prepare to unescape and terminate
// for (;;) {
// char c = *src++; // Get the next char
// switch (c) {
// case '\\': c = *src++; break; // Get the escaped char
// case '"' : c = '\0'; break; // Convert bare quote to nul
// }
// if (!(*dst++ = c)) break; // Copy and break on nul
// }
// return out;
// }
//
//#endif

//Enable Logic Branching and Looping in GCode
//#if ENABLED(GCODE_LOGIC_STRINGS)
//
// // Pass the address after the first quote (if any)
// char* GCodeParser::logic_string(char* &src) {
// if (*src == '"') ++src; // Skip the leading quote
// char * const out = src; // Start of the string
// char *dst = src; // Prepare to unescape and terminate
// for (;;) {
// char c = *src++; // Get the next char
// switch (c) {
// case '\\': c = *src++; break; // Get the escaped char
// case '"' : c = '\0'; break; // Convert bare quote to nul
// }
// if (!(*dst++ = c)) break; // Copy and break on nul
// }
// return out;
// }
//
//#endif

/**
* Populate the command line state (command_letter, codenum, subcode, and string_arg)
* by parsing a single line of G-Code. 58 bytes of SRAM are used to speed up seen/value.
Expand Down Expand Up @@ -171,7 +234,9 @@ void GCodeParser::parse(char *p) {
* With Motion Modes enabled any axis letter can come first.
*/
switch (letter) {
case 'G': case 'M': case 'T': TERN_(MARLIN_DEV_MODE, case 'D':) {
TERN_(MARLIN_DEV_MODE, case 'D':)
TERN_(GCODE_VARIABLES, case 'L':)
case 'G': case 'M': case 'T': {
// Skip spaces to get the numeric part
while (*p == ' ') p++;

Expand Down Expand Up @@ -283,6 +348,14 @@ void GCodeParser::parse(char *p) {
default: break;
}

#if ENABLED(GCODE_VARIABLES)
// Only use string_arg for these L variables
if (letter == 'L') switch (codenum) {
case 100 ... 115: var_arg = input_var(p); return;
default: break;
}
#endif

#if ENABLED(DEBUG_GCODE_PARSER)
const bool debug = codenum == 800;
#endif
Expand All @@ -298,7 +371,13 @@ void GCodeParser::parse(char *p) {
#if ENABLED(GCODE_QUOTED_STRINGS)
bool quoted_string_arg = false;
#endif

#if ENABLED(GCODE_VARIABLES)
bool used_var_arg = false;
#endif

string_arg = nullptr;
var_arg = nullptr;
while (const char param = uppercase(*p++)) { // Get the next parameter. A NUL ends the loop

// Special handling for M32 [P] !/path/to/file.g#
Expand All @@ -317,6 +396,13 @@ void GCodeParser::parse(char *p) {
}
#endif

#if ENABLED(GCODE_VARIABLES)
if (!used_var_arg && param == 'L') {
used_var_arg = true;
var_arg = input_var(p);
}
#endif

#if ENABLED(FASTER_GCODE_PARSER)
// Arguments MUST be uppercase for fast G-Code parsing
#define PARAM_OK(P) WITHIN((P), 'A', 'Z')
Expand All @@ -328,16 +414,30 @@ void GCodeParser::parse(char *p) {

while (*p == ' ') p++; // Skip spaces between parameters & values

bool has_val = false;

#if ENABLED(GCODE_QUOTED_STRINGS)
const bool is_str = (*p == '"'), has_val = is_str || valid_float(p);
const bool is_str = (*p == '"');
has_val = is_str || valid_float(p);
char * const valptr = has_val ? is_str ? unescape_string(p) : p : nullptr;
#else
const bool has_val = valid_float(p);
has_val = valid_float(p);
#if ENABLED(FASTER_GCODE_PARSER)
char * const valptr = has_val ? p : nullptr;
#endif
#endif

#if ENABLED(GCODE_VARIABLES)
const bool is_var = (*p == 'L');
has_val = is_int || valid_float(p + 1);
char * const varptr = has_val ? is_var ? input_var(p) : p + 1 : nullptr;
#else
has_val = valid_float(p);
#if ENABLED(FASTER_GCODE_PARSER)
char * const varptr = has_val ? p : nullptr;
#endif
#endif

#if ENABLED(DEBUG_GCODE_PARSER)
if (debug) {
SERIAL_ECHOPGM("Got param ", C(param), " at index ", p - command_ptr - 1);
Expand Down
20 changes: 19 additions & 1 deletion Marlin/src/gcode/parser.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,10 @@

#include "../inc/MarlinConfig.h"

#if ENABLED(GCODE_VARIABLES)
#include "variables/variables.h"
#endif

//#define DEBUG_GCODE_PARSER
#if ENABLED(DEBUG_GCODE_PARSER)
#include "../libs/hex_print.h"
Expand Down Expand Up @@ -83,7 +87,9 @@ class GCodeParser {
// Command line state
static char *command_ptr, // The command, so it can be echoed
*string_arg, // string of command line
command_letter; // G, M, or T
*var_arg, // string of variable arg
command_letter; // G, M, L, or T

static uint16_t codenum; // 123
#if USE_GCODE_SUBCODES
static uint8_t subcode; // .1
Expand Down Expand Up @@ -232,6 +238,18 @@ class GCodeParser {
FORCE_INLINE static char* unescape_string(char* &src) { return src; }
#endif

//#if ENABLED(GCODE_MATHS_STRINGS)
// static char* math_string(char* &src);
//#else
// FORCE_INLINE static char* math_string(char* &src) { return src; }
//#endif

//#if ENABLED(GCODE_LOGIC_STRINGS)
// static char* logic_string(char* &src);
//#else
// FORCE_INLINE static char* logic_string(char* &src) { return src; }
//#endif

// Populate all fields by parsing a single line of G-Code
// This uses 54 bytes of SRAM to speed up seen/value
static void parse(char * p);
Expand Down
136 changes: 136 additions & 0 deletions Marlin/src/gcode/variables/variables.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
/**
* Marlin 3D Printer Firmware
* Copyright (c) 2022 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
*
* This program 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.
*
* This program 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 this program. If not, see <https://www.gnu.org/licenses/>.
*
*/

/**
* variables.cpp
* Copyright (c) 2022 Carlon LaMont
*/

#include "../../inc/MarlinConfig.h"

#if ENABLED(GCODE_VARIABLES)

#include "variables.h"

#include "../gcode.h"
#include "../queue.h"
#include "../parser.h"

/**
* Get the variable target data from the L parameter
*/

void CNCVariables::append() {
const uint8_t index = parser.codenum - 100;
if (parser.seenval('L')) {
bool used_var_arg = false;
const int8_t q = parser.value_byte();
char * const p = parser.string_arg;
const bool is_var = (parser.string_arg[0] == 'L'),
has_int = valid_int(p + 1),
has_val = is_var || has_int;
char * const varptr = has_val ? (is_var ? input_var(parser.string_arg) : parser.string_arg + 1) : nullptr;
if (!has_val)
export_val();
elif (has_int)
import_val();
//else {
// #if ENABLED(FASTER_GCODE_PARSER)
// const bool has_val = valid_int(p);
// char * const varptr = has_val ? p : nullptr;
// #endif
//}
}
}

//int8_t GcodeSuite::input_var() {
// #if (parser.seenval('L')) {
// const bool is_var = (*p == 'L'), has_val = is_var || valid_float(p + 1);
// char * const input_var = has_val ? is_var ? input_var(p) : p+1 : nullptr;
// #else
// int bool has_val = valid_float(p);
// #if ENABLED(FASTER_GCODE_PARSER)
// char * const varptr = has_val ? p : nullptr;
// #endif
//#endif

//bool used_var_arg = false;

// if (parser.seenval('L')) {
// const int8_t q = parser.value_byte();
// if (q > 0) return e;
// SERIAL_ECHO_START();
// SERIAL_CHAR('L'); SERIAL_ECHO(parser.codenum);
// SERIAL_ECHOLNPGM(" " STR_INVALID_VARIABLE " ", e);
// return -1;
// }
// return stored_var;
//}


//void GcodeSuite::M98() {
// if (card.isMounted() && parser.seen('P')) {
// char *path = parser.value_string();
// char *lb = strchr(p, ' ');
// if (!lb) lb = strchr(p, ';');
// if (lb) *lb = '\0';
// card.runMacro(path);
// }
//}

//const bool is_var = (*p == 'L'), has_val = is_var || valid_float(p + 1);
//char * const varptr = has_val ? is_var ? input_var(p) : p+1 : nullptr;
// #else
// int bool has_val = valid_float(p);
// #if ENABLED(FASTER_GCODE_PARSER)
// char * const varptr = has_val ? p : nullptr;
// #endif
//#endif

//bool used_var_arg = false;


//#if ENABLED(GCODE_VARIABLES)
// uint16_t GCodeParser::input_var;
//#endif

//char gcode_variables[VARIABLE_SLOTS][VARIABLE_SLOT_SIZE +1] = {{ 0 }};

/**
* L100 - L115: Input Variable #100 - #115
*/
//uint16_t GCodeParser::input_var();
//void GcodeSuite::L100() { parser.input_var; };
//void GcodeSuite::L101() { parser.input_var; };
//void GcodeSuite::L102() { parser.input_var; };
//void GcodeSuite::L103() { parser.input_var; };
//void GcodeSuite::L104() { parser.input_var; };
//void GcodeSuite::L105() { parser.input_var; };
//void GcodeSuite::L106() { parser.input_var; };
//void GcodeSuite::L107() { parser.input_var; };
//void GcodeSuite::L108() { parser.input_var; };
//void GcodeSuite::L109() { parser.input_var; };
//void GcodeSuite::L110() { parser.input_var; };
//void GcodeSuite::L111() { parser.input_var; };
//void GcodeSuite::L112() { parser.input_var; };
//void GcodeSuite::L113() { parser.input_var; };
//void GcodeSuite::L114() { parser.input_var; };
//void GcodeSuite::L115() { parser.input_var; };

#endif // GCODE_VARIABLES
Loading
Loading