Case-insensitive g-code option (#16932)
This commit is contained in:
parent
18b875dc9f
commit
832951ec44
3 changed files with 34 additions and 13 deletions
|
@ -2790,6 +2790,8 @@
|
||||||
//#define GCODE_QUOTED_STRINGS // Support for quoted string parameters
|
//#define GCODE_QUOTED_STRINGS // Support for quoted string parameters
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
//#define GCODE_CASE_INSENSITIVE // Accept G-code sent to the firmware in lowercase
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* CNC G-code options
|
* CNC G-code options
|
||||||
* Support CNC-style G-code dialects used by laser cutters, drawing machine cams, etc.
|
* Support CNC-style G-code dialects used by laser cutters, drawing machine cams, etc.
|
||||||
|
|
|
@ -118,11 +118,18 @@ void GCodeParser::parse(char *p) {
|
||||||
|
|
||||||
reset(); // No codes to report
|
reset(); // No codes to report
|
||||||
|
|
||||||
|
auto uppercase = [](char c) {
|
||||||
|
#if ENABLED(GCODE_CASE_INSENSITIVE)
|
||||||
|
if (WITHIN(c, 'a', 'z')) c += 'A' - 'a';
|
||||||
|
#endif
|
||||||
|
return c;
|
||||||
|
};
|
||||||
|
|
||||||
// Skip spaces
|
// Skip spaces
|
||||||
while (*p == ' ') ++p;
|
while (*p == ' ') ++p;
|
||||||
|
|
||||||
// Skip N[-0-9] if included in the command line
|
// Skip N[-0-9] if included in the command line
|
||||||
if (*p == 'N' && NUMERIC_SIGNED(p[1])) {
|
if (uppercase(*p) == 'N' && NUMERIC_SIGNED(p[1])) {
|
||||||
#if ENABLED(FASTER_GCODE_PARSER)
|
#if ENABLED(FASTER_GCODE_PARSER)
|
||||||
//set('N', p + 1); // (optional) Set the 'N' parameter value
|
//set('N', p + 1); // (optional) Set the 'N' parameter value
|
||||||
#endif
|
#endif
|
||||||
|
@ -135,7 +142,7 @@ void GCodeParser::parse(char *p) {
|
||||||
command_ptr = p;
|
command_ptr = p;
|
||||||
|
|
||||||
// Get the command letter, which must be G, M, or T
|
// Get the command letter, which must be G, M, or T
|
||||||
const char letter = *p++;
|
const char letter = uppercase(*p++);
|
||||||
|
|
||||||
// Nullify asterisk and trailing whitespace
|
// Nullify asterisk and trailing whitespace
|
||||||
char *starpos = strchr(p, '*');
|
char *starpos = strchr(p, '*');
|
||||||
|
@ -271,7 +278,7 @@ void GCodeParser::parse(char *p) {
|
||||||
bool quoted_string_arg = false;
|
bool quoted_string_arg = false;
|
||||||
#endif
|
#endif
|
||||||
string_arg = nullptr;
|
string_arg = nullptr;
|
||||||
while (const char param = *p++) { // Get the next parameter. A NUL ends the loop
|
while (const char param = uppercase(*p++)) { // Get the next parameter. A NUL ends the loop
|
||||||
|
|
||||||
// Special handling for M32 [P] !/path/to/file.g#
|
// Special handling for M32 [P] !/path/to/file.g#
|
||||||
// The path must be the last parameter
|
// The path must be the last parameter
|
||||||
|
@ -289,14 +296,14 @@ void GCodeParser::parse(char *p) {
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Arguments MUST be uppercase for fast GCode parsing
|
|
||||||
#if ENABLED(FASTER_GCODE_PARSER)
|
#if ENABLED(FASTER_GCODE_PARSER)
|
||||||
#define PARAM_TEST WITHIN(param, 'A', 'Z')
|
// Arguments MUST be uppercase for fast GCode parsing
|
||||||
|
#define PARAM_OK(P) WITHIN((P), 'A', 'Z')
|
||||||
#else
|
#else
|
||||||
#define PARAM_TEST true
|
#define PARAM_OK(P) true
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (PARAM_TEST) {
|
if (PARAM_OK(param)) {
|
||||||
|
|
||||||
while (*p == ' ') p++; // Skip spaces between parameters & values
|
while (*p == ' ') p++; // Skip spaces between parameters & values
|
||||||
|
|
||||||
|
|
|
@ -166,7 +166,6 @@ public:
|
||||||
#ifdef CPU_32_BIT
|
#ifdef CPU_32_BIT
|
||||||
FORCE_INLINE static bool seen(const char * const str) { return !!(codebits & letter_bits(str)); }
|
FORCE_INLINE static bool seen(const char * const str) { return !!(codebits & letter_bits(str)); }
|
||||||
#else
|
#else
|
||||||
// At least one of a list of code letters was seen
|
|
||||||
FORCE_INLINE static bool seen(const char * const str) {
|
FORCE_INLINE static bool seen(const char * const str) {
|
||||||
const uint32_t letrbits = letter_bits(str);
|
const uint32_t letrbits = letter_bits(str);
|
||||||
const uint8_t * const cb = (uint8_t*)&codebits;
|
const uint8_t * const cb = (uint8_t*)&codebits;
|
||||||
|
@ -177,14 +176,27 @@ public:
|
||||||
|
|
||||||
static inline bool seen_any() { return !!codebits; }
|
static inline bool seen_any() { return !!codebits; }
|
||||||
|
|
||||||
#define SEEN_TEST(L) TEST32(codebits, LETTER_BIT(L))
|
FORCE_INLINE static bool seen_test(const char c) { return TEST32(codebits, LETTER_BIT(c)); }
|
||||||
|
|
||||||
#else // !FASTER_GCODE_PARSER
|
#else // !FASTER_GCODE_PARSER
|
||||||
|
|
||||||
|
#if ENABLED(GCODE_CASE_INSENSITIVE)
|
||||||
|
FORCE_INLINE static char* strgchr(char *p, char g) {
|
||||||
|
auto uppercase = [](char c) {
|
||||||
|
return c + (WITHIN(c, 'a', 'z') ? 'A' - 'a' : 0);
|
||||||
|
};
|
||||||
|
const char d = uppercase(g);
|
||||||
|
for (char cc; (cc = uppercase(*p)); p++) if (cc == d) return p;
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
#define strgchr strchr
|
||||||
|
#endif
|
||||||
|
|
||||||
// Code is found in the string. If not found, value_ptr is unchanged.
|
// Code is found in the string. If not found, value_ptr is unchanged.
|
||||||
// This allows "if (seen('A')||seen('B'))" to use the last-found value.
|
// This allows "if (seen('A')||seen('B'))" to use the last-found value.
|
||||||
static inline bool seen(const char c) {
|
static inline bool seen(const char c) {
|
||||||
char *p = strchr(command_args, c);
|
char *p = strgchr(command_args, c);
|
||||||
const bool b = !!p;
|
const bool b = !!p;
|
||||||
if (b) value_ptr = valid_float(&p[1]) ? &p[1] : nullptr;
|
if (b) value_ptr = valid_float(&p[1]) ? &p[1] : nullptr;
|
||||||
return b;
|
return b;
|
||||||
|
@ -192,12 +204,12 @@ public:
|
||||||
|
|
||||||
static inline bool seen_any() { return *command_args == '\0'; }
|
static inline bool seen_any() { return *command_args == '\0'; }
|
||||||
|
|
||||||
#define SEEN_TEST(L) !!strchr(command_args, L)
|
FORCE_INLINE static bool seen_test(const char c) { return (bool)strgchr(command_args, c); }
|
||||||
|
|
||||||
// At least one of a list of code letters was seen
|
// At least one of a list of code letters was seen
|
||||||
static inline bool seen(const char * const str) {
|
static inline bool seen(const char * const str) {
|
||||||
for (uint8_t i = 0; const char c = str[i]; i++)
|
for (uint8_t i = 0; const char c = str[i]; i++)
|
||||||
if (SEEN_TEST(c)) return true;
|
if (seen_test(c)) return true;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -205,7 +217,7 @@ public:
|
||||||
|
|
||||||
// Seen any axis parameter
|
// Seen any axis parameter
|
||||||
static inline bool seen_axis() {
|
static inline bool seen_axis() {
|
||||||
return SEEN_TEST('X') || SEEN_TEST('Y') || SEEN_TEST('Z') || SEEN_TEST('E');
|
return seen_test('X') || seen_test('Y') || seen_test('Z') || seen_test('E');
|
||||||
}
|
}
|
||||||
|
|
||||||
#if ENABLED(GCODE_QUOTED_STRINGS)
|
#if ENABLED(GCODE_QUOTED_STRINGS)
|
||||||
|
|
Reference in a new issue