Improved parameter handling some more, now allows indirected O-calls and line numbers with O-word.

Fix for issue #609, homing may cause a controller crash.
This commit is contained in:
Terje Io
2024-10-16 14:13:04 +07:00
parent a7b82c8041
commit 236a40c100
9 changed files with 163 additions and 68 deletions

View File

@@ -13,7 +13,7 @@ It has been written to complement grblHAL and has features such as proper keyboa
---
Latest build date is 20241014, see the [changelog](changelog.md) for details.
Latest build date is 20241016, see the [changelog](changelog.md) for details.
__NOTE:__ Build 20240222 has moved the probe input to the ioPorts pool of inputs and will be allocated from it when configured.
The change is major and _potentially dangerous_, it may damage your probe, so please _verify correct operation_ after installing this, or later, builds.

View File

@@ -1,5 +1,19 @@
## grblHAL changelog
<a name="20241016">Build 20241016
Core:
* Improved parameter handling some more, now allows indirected O-calls and line numbers with O-word.
* Fix for [issue #609](https://github.com/grblHAL/core/issues/609), homing may cause a controller crash.
Plugins:
* Spindle: Fixed compiler warning. Ref. [issue #33](https://github.com/grblHAL/Plugins_spindle/issues/33)
---
<a name="20241014">Build 20241014
Core:

77
gcode.c
View File

@@ -992,45 +992,60 @@ status_code_t gc_execute_block (char *block)
if(block[char_counter] == '<') {
char *s = &block[++char_counter];
while(*s && *s != '>')
s++;
if(*s && *(s + 1) == '=') {
char *name = &block[char_counter];
*s++ = '\0';
s++;
char_counter += s - name;
if((status = ngc_read_real_value(block, &char_counter, &value)) != Status_OK)
FAIL(status); // [Expected parameter value]
if(!ngc_named_param_set(name, value))
FAIL(Status_BadNumberFormat); // [Expected equal sign]
}
char name[NGC_MAX_PARAM_LENGTH + 1];
if((status = ngc_read_name(block, &char_counter, name)) == Status_OK) {
if(block[char_counter++] != '=')
status = Status_BadNumberFormat; // [Expected equal sign]
else if((status = ngc_read_real_value(block, &char_counter, &value)) == Status_OK) {
if(!ngc_named_param_set(name, value))
status = Status_BadNumberFormat; // [Out of memory or attempt to write RO parameter]
} // else: [Expected value]
} // else: [Expected parameter name]
} else {
float param;
if((status = ngc_read_real_value(block, &char_counter, &param)) != Status_OK) {
FAIL(status); // [Expected parameter number]
} else if(!ngc_param_is_rw((ngc_param_id_t)param))
FAIL(Status_GcodeValueOutOfRange); // [Parameter does not exist or is read only]
if(block[char_counter++] != '=')
FAIL(Status_BadNumberFormat); // [Expected equal sign]
if((status = ngc_read_real_value(block, &char_counter, &value)) != Status_OK)
FAIL(status); // [Expected parameter value]
if(ngc_param_count < NGC_N_ASSIGN_PARAMETERS_PER_BLOCK && ngc_param_is_rw((ngc_param_id_t)param)) {
ngc_params[ngc_param_count].id = (ngc_param_id_t)param;
ngc_params[ngc_param_count++].value = value;
} else
FAIL(Status_BadNumberFormat); // [Expected parameter value]
if((status = ngc_read_real_value(block, &char_counter, &param)) == Status_OK) {
if(!ngc_param_is_rw((ngc_param_id_t)param))
status = Status_GcodeValueOutOfRange; // [Parameter does not exist or is read only]
else if(block[char_counter++] != '=')
status = Status_BadNumberFormat; // [Expected equal sign]
else if((status = ngc_read_real_value(block, &char_counter, &value)) == Status_OK) {
if(ngc_param_count < NGC_N_ASSIGN_PARAMETERS_PER_BLOCK) {
ngc_params[ngc_param_count].id = (ngc_param_id_t)param;
ngc_params[ngc_param_count++].value = value;
} else
FAIL(Status_BadNumberFormat); // [Too many parameters in block]
} // else: [Expected parameter value]
} // else: [Expected parameter number]
}
if(status != Status_OK)
FAIL(status);
continue;
} else if(letter == 'O') {
gc_block.words.n = Off; // Hack to allow line number with O word
if(block[char_counter] == '[') {
int32_t value;
if((status = ngc_read_integer_value(block, &char_counter, &value)) == Status_OK) {
gc_block.words.o = On;
gc_block.values.o = (uint32_t)value;
char_counter++;
} else
FAIL(status);
} else if(block[char_counter] == '<') {
/* char o_label[NGC_MAX_PARAM_LENGTH + 1];
if((status = ngc_read_name(block, &char_counter, o_label)) != Status_OK)
FAIL(status);
gc_block.words.o = On;
gc_block.values.o = 0xFFFFFFFE;
continue;*/
FAIL(Status_GcodeUnsupportedCommand); // [For now...]
}
}
if((gc_block.words.mask & o_label.mask) && (gc_block.words.mask & ~o_label.mask) == 0) {

2
grbl.h
View File

@@ -42,7 +42,7 @@
#else
#define GRBL_VERSION "1.1f"
#endif
#define GRBL_BUILD 20241014
#define GRBL_BUILD 20241016
#define GRBL_URL "https://github.com/grblHAL"

View File

@@ -193,7 +193,6 @@ static bool limits_pull_off (axes_signals_t axis, float distance)
plan_data.feed_rate = settings.homing.seek_rate * sqrtf(n_axis); // Adjust so individual axes all move at pull-off rate.
plan_data.condition.coolant = gc_state.modal.coolant;
memcpy(&plan_data.spindle, &gc_state.spindle, sizeof(spindle_t));
#ifdef KINEMATICS_API
coord_data_t k_target;
@@ -275,13 +274,12 @@ static bool homing_cycle (axes_signals_t cycle, axes_signals_t auto_square)
plan_line_data_t plan_data;
rt_exec_t rt_exec, rt_exec_states = EXEC_SAFETY_DOOR|EXEC_RESET|EXEC_CYCLE_COMPLETE;
// Initialize plan data struct for homing motion.
plan_data_init(&plan_data);
plan_data.condition.system_motion = On;
plan_data.condition.no_feed_override = On;
plan_data.line_number = DEFAULT_HOMING_CYCLE_LINE_NUMBER;
// Initialize plan data struct for homing motion.
memcpy(&plan_data.spindle, &gc_state.spindle, sizeof(spindle_t));
plan_data.condition.coolant = gc_state.modal.coolant;
uint_fast8_t idx = N_AXIS;

View File

@@ -571,6 +571,39 @@ static status_code_t read_operation_unary (char *line, uint_fast8_t *pos, ngc_un
return status;
}
/*! \brief Reads the name of a parameter out of the line
starting at the index given by the pos offset.
\param line pointer to RS274/NGC code (block).
\param pos offset into line where expression starts.
\param buffer pointer to a character buffer for the name.
\returns #Status_OK enum value if processed without error, appropriate \ref status_code_t enum value if not.
*/
status_code_t ngc_read_name (char *line, uint_fast8_t *pos, char *buffer)
{
char *s;
uint_fast8_t len = 0;
status_code_t status = Status_BadNumberFormat;
if(*(s = line + (*pos)++) == '<') {
s++;
while(*s && *s != '>' && len <= NGC_MAX_PARAM_LENGTH) {
*buffer++ = *s++;
(*pos)++;
len++;
}
if((status = *s == '>' ? Status_OK : Status_FlowControlSyntaxError) == Status_OK) {
*buffer = '\0';
(*pos)++;
}
}
return status;
}
/*! \brief Reads the value out of a parameter of the line, starting at the
index given by the pos offset.
@@ -593,6 +626,7 @@ sequentially, the value of #2 would be 10 after the line was executed.
*/
status_code_t ngc_read_parameter (char *line, uint_fast8_t *pos, float *value, bool check)
{
int32_t param;
status_code_t status = Status_BadNumberFormat;
if(*(line + *pos) == '#') {
@@ -601,34 +635,18 @@ status_code_t ngc_read_parameter (char *line, uint_fast8_t *pos, float *value, b
if(*(line + *pos) == '<') {
(*pos)++;
char *param = line + *pos, *arg = line + *pos;
char name[NGC_MAX_PARAM_LENGTH + 1];
while(*arg && *arg != '>')
arg++;
*pos += arg - param + 1;
if(*arg == '>') {
*arg = '\0';
if(ngc_named_param_get(param, value))
status = Status_OK;
*arg = '>';
if((status = ngc_read_name(line, pos, name)) == Status_OK) {
if(!ngc_named_param_get(name, value))
status = Status_BadNumberFormat;
}
} else if((status = ngc_read_integer_value(line, pos, &param)) == Status_OK) {
} else if((status = ngc_read_real_value(line, pos, value)) == Status_OK) {
uint32_t param = (uint32_t)floorf(*value);
if((*value - (float)param) > 0.9999f) {
param = (uint32_t)ceilf(*value);
} else if((*value - (float)param) > 0.0001f)
status = Status_BadNumberFormat; // not integer
if(check && !ngc_param_exists((ngc_param_id_t)param))
if(param < 0 || (check && !ngc_param_exists((ngc_param_id_t)param)))
status = Status_GcodeValueOutOfRange;
else if(!ngc_param_get((ngc_param_id_t)param, value))
status = Status_GcodeValueOutOfRange;
else if(ngc_param_get((ngc_param_id_t)param, value))
status = Status_OK;
}
}
@@ -761,6 +779,52 @@ status_code_t ngc_read_real_value (char *line, uint_fast8_t *pos, float *value)
return status;
}
/*! \brief Reads explicit unsigned (positive) integer out of the line,
starting at the index given by the pos offset. It expects to find one
or more digits. Any character other than a digit terminates reading
the integer. Note that if the first character is a sign (+ or -),
an error will be reported (since a sign is not a digit).
\param line pointer to RS274/NGC code (block).
\param pos offset into line where expression starts.
\param value pointer to integer where result is to be stored.
\returns #Status_OK enum value if processed without error, appropriate \ref status_code_t enum value if not.
*/
status_code_t ngc_read_integer_unsigned (char *line, uint_fast8_t *pos, uint32_t *value)
{
return line[*pos] == '+' ? Status_GcodeCommandValueNotInteger : read_uint(line, pos, value);
}
/*! \brief Reads an integer (positive, negative or zero) out of the line,
starting at the index given by the pos offset. The value being
read may be written with a decimal point or it may be an expression
involving non-integers, as long as the result comes out within 0.0001
of an integer.
This proceeds by calling read_real_value and checking that it is
close to an integer, then returning the integer it is close to.
\param line pointer to RS274/NGC code (block).
\param pos offset into line where expression starts.
\param value pointer to integer where result is to be stored.
\returns #Status_OK enum value if processed without error, appropriate \ref status_code_t enum value if not.
*/
status_code_t ngc_read_integer_value (char *line, uint_fast8_t *pos, int32_t *value)
{
float fvalue;
status_code_t status;
if((status = ngc_read_real_value(line, pos, &fvalue)) == Status_OK) {
*value = (int32_t)floorf(fvalue);
if((fvalue - (float)*value) > 0.9999f) {
*value = (uint32_t)ceilf(fvalue);
} else if((fvalue - (float)*value) > 0.0001f)
status = Status_GcodeCommandValueNotInteger; // not integer
}
return status;
}
/*! \brief Evaluate expression and set result if successful.
\param line pointer to RS274/NGC code (block).

View File

@@ -3,8 +3,11 @@
#ifndef _NGC_EXPR_H_
#define _NGC_EXPR_H_
status_code_t ngc_eval_expression (char *line, uint_fast8_t *pos, float *value);
status_code_t ngc_read_name (char *line, uint_fast8_t *pos, char *buffer);
status_code_t ngc_read_real_value (char *line, uint_fast8_t *pos, float *value);
status_code_t ngc_read_integer_value(char *line, uint_fast8_t *pos, int32_t *value);
status_code_t ngc_read_integer_unsigned (char *line, uint_fast8_t *pos, uint32_t *value);
status_code_t ngc_read_parameter (char *line, uint_fast8_t *pos, float *value, bool check);
status_code_t ngc_eval_expression (char *line, uint_fast8_t *pos, float *value);
#endif

View File

@@ -41,9 +41,6 @@
#ifndef NGC_MAX_CALL_LEVEL
#define NGC_MAX_CALL_LEVEL 10
#endif
#ifndef NGC_MAX_PARAM_LENGTH
#define NGC_MAX_PARAM_LENGTH 20
#endif
typedef float (*ngc_param_get_ptr)(ngc_param_id_t id);
typedef float (*ngc_named_param_get_ptr)(void);
@@ -622,7 +619,7 @@ static char *ngc_name_tolower (char *s)
uint_fast8_t len = 0;
char c, *s1 = s, *s2 = name;
while((c = *s1++) && len < NGC_MAX_PARAM_LENGTH) {
while((c = *s1++) && len <= NGC_MAX_PARAM_LENGTH) {
if(c > ' ') {
*s2++ = LCAPS(c);
len++;
@@ -679,7 +676,7 @@ bool ngc_named_param_exists (char *name)
} while(idx && !ok);
// If not predefined attempt to find it.
if(!ok && rw_global_params && strlen(name) < NGC_MAX_PARAM_LENGTH) {
if(!ok && rw_global_params && strlen(name) <= NGC_MAX_PARAM_LENGTH) {
void *context = *name == '_' ? NULL : call_context;
ngc_named_rw_param_t *rw_param = rw_global_params;
@@ -712,7 +709,7 @@ bool ngc_named_param_set (char *name, float value)
} while(idx && !ok);
// If not predefined attempt to set it.
if(!ok && (ok = strlen(name) < NGC_MAX_PARAM_LENGTH)) {
if(!ok && (ok = strlen(name) <= NGC_MAX_PARAM_LENGTH)) {
void *context = *name == '_' ? NULL : call_context;
ngc_named_rw_param_t *rw_param = rw_global_params, *rw_param_last = rw_global_params;

View File

@@ -30,6 +30,10 @@
#include "gcode.h"
#ifndef NGC_MAX_PARAM_LENGTH
#define NGC_MAX_PARAM_LENGTH 20
#endif
typedef uint16_t ngc_param_id_t;
typedef struct {