diff --git a/Marlin/Configuration_adv.h b/Marlin/Configuration_adv.h index 9a6661e97e5b..db75e905408d 100644 --- a/Marlin/Configuration_adv.h +++ b/Marlin/Configuration_adv.h @@ -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) */ diff --git a/Marlin/src/gcode/gcode.h b/Marlin/src/gcode/gcode.h index d80305fb7556..693302934c5f 100644 --- a/Marlin/src/gcode/gcode.h +++ b/Marlin/src/gcode/gcode.h @@ -351,6 +351,10 @@ *** "T" Codes *** * * T0-T3 - Select an extruder (tool) by index: 'T F' + * + *** 'L' Codes *** + * + * L100-L115 - Definable variables */ #include "../inc/MarlinConfig.h" diff --git a/Marlin/src/gcode/parser.cpp b/Marlin/src/gcode/parser.cpp index b692c818aae6..a6ab2b53b7b4 100644 --- a/Marlin/src/gcode/parser.cpp +++ b/Marlin/src/gcode/parser.cpp @@ -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; @@ -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. @@ -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++; @@ -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 @@ -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# @@ -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') @@ -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); diff --git a/Marlin/src/gcode/parser.h b/Marlin/src/gcode/parser.h index 71cad6857dce..d609e181be87 100644 --- a/Marlin/src/gcode/parser.h +++ b/Marlin/src/gcode/parser.h @@ -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" @@ -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 @@ -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); diff --git a/Marlin/src/gcode/variables/variables.cpp b/Marlin/src/gcode/variables/variables.cpp new file mode 100644 index 000000000000..b1211ffaaf46 --- /dev/null +++ b/Marlin/src/gcode/variables/variables.cpp @@ -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 . + * + */ + +/** + * 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 diff --git a/Marlin/src/gcode/variables/variables.h b/Marlin/src/gcode/variables/variables.h new file mode 100644 index 000000000000..6b793a1d033f --- /dev/null +++ b/Marlin/src/gcode/variables/variables.h @@ -0,0 +1,61 @@ +/** + * Marlin 3D Printer Firmware + * Copyright (c) 2022 MarlinFirmware [https://github.com/MarlinFirmware/Marlin] + * + * Copyright (c) 2022 Carlon LaMont + * + * 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 . + * + */ +#pragma once + +/** + * variables.h + * Copyright (c) 2022 Carlon LaMont + */ + +#include "../../inc/MarlinConfigPre.h" + +class CNCVariables { +public: + //char[] letter = { '#' } + //string L = new_string(letter) + + static void var_from_command(const int8_t dval=0); + static void append(); + static uint8_t StoredVar(); + static void input_var(); + static void export_var(); + static void has_val(); + static bool is_var(); + static bool used_var_arg(); + static void var_arg(); + + static void L100(); + static void L101(); + static void L102(); + static void L103(); + static void L104(); + static void L105(); + static void L106(); + static void L107(); + static void L108(); + static void L109(); + static void L110(); + static void L111(); + static void L112(); + static void L113(); + static void L114(); + static void L115(); +}; diff --git a/buildroot/tests/rambo b/buildroot/tests/rambo index 7f8151ba8b50..b4a1f66dd485 100755 --- a/buildroot/tests/rambo +++ b/buildroot/tests/rambo @@ -100,6 +100,7 @@ exec_test $1 $2 "Rambo with PRUSA_MMU3 " "$3" restore_configs opt_set MOTHERBOARD BOARD_EINSY_RAMBO \ X_DRIVER_TYPE TMC2130 Y_DRIVER_TYPE TMC2130 Z_DRIVER_TYPE TMC2130 E0_DRIVER_TYPE TMC2130 +opt_enable GCODE_VARIABLES exec_test $1 $2 "Einsy RAMBo with TMC2130" "$3" # diff --git a/ini/features.ini b/ini/features.ini index 03a9bdbba8d1..249c0eb4f203 100644 --- a/ini/features.ini +++ b/ini/features.ini @@ -369,6 +369,7 @@ HAS_PID_HEATING = build_src_filter=+ INCH_MODE_SUPPORT = build_src_filter=+ TEMPERATURE_UNITS_SUPPORT = build_src_filter=+ +GCODE_VARIABLES = build_src_filter=+ NEED_HEX_PRINT = build_src_filter=+ NEED_LSF = build_src_filter=+ NOZZLE_PARK_FEATURE = build_src_filter=+ + diff --git a/platformio.ini b/platformio.ini index 9f562c0be9e7..ca4cc50c3e57 100644 --- a/platformio.ini +++ b/platformio.ini @@ -84,6 +84,7 @@ default_src_filter = + - - - - - + - ; Library Code - - -