Skip to content

Commit 236a40c

Browse files
committed
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.
1 parent a7b82c8 commit 236a40c

9 files changed

+162
-67
lines changed

README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ It has been written to complement grblHAL and has features such as proper keyboa
1313

1414
---
1515

16-
Latest build date is 20241014, see the [changelog](changelog.md) for details.
16+
Latest build date is 20241016, see the [changelog](changelog.md) for details.
1717

1818
__NOTE:__ Build 20240222 has moved the probe input to the ioPorts pool of inputs and will be allocated from it when configured.
1919
The change is major and _potentially dangerous_, it may damage your probe, so please _verify correct operation_ after installing this, or later, builds.

changelog.md

+14
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,19 @@
11
## grblHAL changelog
22

3+
<a name="20241016">Build 20241016
4+
5+
Core:
6+
7+
* Improved parameter handling some more, now allows indirected O-calls and line numbers with O-word.
8+
9+
* Fix for [issue #609](https://github.com/grblHAL/core/issues/609), homing may cause a controller crash.
10+
11+
Plugins:
12+
13+
* Spindle: Fixed compiler warning. Ref. [issue #33](https://github.com/grblHAL/Plugins_spindle/issues/33)
14+
15+
---
16+
317
<a name="20241014">Build 20241014
418

519
Core:

gcode.c

+45-30
Original file line numberDiff line numberDiff line change
@@ -992,45 +992,60 @@ status_code_t gc_execute_block (char *block)
992992

993993
if(block[char_counter] == '<') {
994994

995-
char *s = &block[++char_counter];
996-
997-
while(*s && *s != '>')
998-
s++;
999-
1000-
if(*s && *(s + 1) == '=') {
1001-
char *name = &block[char_counter];
1002-
*s++ = '\0';
1003-
s++;
1004-
char_counter += s - name;
1005-
if((status = ngc_read_real_value(block, &char_counter, &value)) != Status_OK)
1006-
FAIL(status); // [Expected parameter value]
1007-
if(!ngc_named_param_set(name, value))
1008-
FAIL(Status_BadNumberFormat); // [Expected equal sign]
1009-
}
1010-
995+
char name[NGC_MAX_PARAM_LENGTH + 1];
996+
997+
if((status = ngc_read_name(block, &char_counter, name)) == Status_OK) {
998+
if(block[char_counter++] != '=')
999+
status = Status_BadNumberFormat; // [Expected equal sign]
1000+
else if((status = ngc_read_real_value(block, &char_counter, &value)) == Status_OK) {
1001+
if(!ngc_named_param_set(name, value))
1002+
status = Status_BadNumberFormat; // [Out of memory or attempt to write RO parameter]
1003+
} // else: [Expected value]
1004+
} // else: [Expected parameter name]
10111005
} else {
10121006

10131007
float param;
10141008

1015-
if((status = ngc_read_real_value(block, &char_counter, &param)) != Status_OK) {
1016-
FAIL(status); // [Expected parameter number]
1017-
} else if(!ngc_param_is_rw((ngc_param_id_t)param))
1018-
FAIL(Status_GcodeValueOutOfRange); // [Parameter does not exist or is read only]
1009+
if((status = ngc_read_real_value(block, &char_counter, &param)) == Status_OK) {
1010+
if(!ngc_param_is_rw((ngc_param_id_t)param))
1011+
status = Status_GcodeValueOutOfRange; // [Parameter does not exist or is read only]
1012+
else if(block[char_counter++] != '=')
1013+
status = Status_BadNumberFormat; // [Expected equal sign]
1014+
else if((status = ngc_read_real_value(block, &char_counter, &value)) == Status_OK) {
1015+
if(ngc_param_count < NGC_N_ASSIGN_PARAMETERS_PER_BLOCK) {
1016+
ngc_params[ngc_param_count].id = (ngc_param_id_t)param;
1017+
ngc_params[ngc_param_count++].value = value;
1018+
} else
1019+
FAIL(Status_BadNumberFormat); // [Too many parameters in block]
1020+
} // else: [Expected parameter value]
1021+
} // else: [Expected parameter number]
1022+
}
1023+
1024+
if(status != Status_OK)
1025+
FAIL(status);
10191026

1020-
if(block[char_counter++] != '=')
1021-
FAIL(Status_BadNumberFormat); // [Expected equal sign]
1027+
continue;
1028+
} else if(letter == 'O') {
10221029

1023-
if((status = ngc_read_real_value(block, &char_counter, &value)) != Status_OK)
1024-
FAIL(status); // [Expected parameter value]
1030+
gc_block.words.n = Off; // Hack to allow line number with O word
10251031

1026-
if(ngc_param_count < NGC_N_ASSIGN_PARAMETERS_PER_BLOCK && ngc_param_is_rw((ngc_param_id_t)param)) {
1027-
ngc_params[ngc_param_count].id = (ngc_param_id_t)param;
1028-
ngc_params[ngc_param_count++].value = value;
1032+
if(block[char_counter] == '[') {
1033+
int32_t value;
1034+
if((status = ngc_read_integer_value(block, &char_counter, &value)) == Status_OK) {
1035+
gc_block.words.o = On;
1036+
gc_block.values.o = (uint32_t)value;
1037+
char_counter++;
10291038
} else
1030-
FAIL(Status_BadNumberFormat); // [Expected parameter value]
1039+
FAIL(status);
1040+
} else if(block[char_counter] == '<') {
1041+
/* char o_label[NGC_MAX_PARAM_LENGTH + 1];
1042+
if((status = ngc_read_name(block, &char_counter, o_label)) != Status_OK)
1043+
FAIL(status);
1044+
gc_block.words.o = On;
1045+
gc_block.values.o = 0xFFFFFFFE;
1046+
continue;*/
1047+
FAIL(Status_GcodeUnsupportedCommand); // [For now...]
10311048
}
1032-
1033-
continue;
10341049
}
10351050

10361051
if((gc_block.words.mask & o_label.mask) && (gc_block.words.mask & ~o_label.mask) == 0) {

grbl.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@
4242
#else
4343
#define GRBL_VERSION "1.1f"
4444
#endif
45-
#define GRBL_BUILD 20241014
45+
#define GRBL_BUILD 20241016
4646

4747
#define GRBL_URL "https://github.com/grblHAL"
4848

machine_limits.c

+2-4
Original file line numberDiff line numberDiff line change
@@ -193,7 +193,6 @@ static bool limits_pull_off (axes_signals_t axis, float distance)
193193

194194
plan_data.feed_rate = settings.homing.seek_rate * sqrtf(n_axis); // Adjust so individual axes all move at pull-off rate.
195195
plan_data.condition.coolant = gc_state.modal.coolant;
196-
memcpy(&plan_data.spindle, &gc_state.spindle, sizeof(spindle_t));
197196

198197
#ifdef KINEMATICS_API
199198
coord_data_t k_target;
@@ -275,13 +274,12 @@ static bool homing_cycle (axes_signals_t cycle, axes_signals_t auto_square)
275274
plan_line_data_t plan_data;
276275
rt_exec_t rt_exec, rt_exec_states = EXEC_SAFETY_DOOR|EXEC_RESET|EXEC_CYCLE_COMPLETE;
277276

277+
// Initialize plan data struct for homing motion.
278+
278279
plan_data_init(&plan_data);
279280
plan_data.condition.system_motion = On;
280281
plan_data.condition.no_feed_override = On;
281282
plan_data.line_number = DEFAULT_HOMING_CYCLE_LINE_NUMBER;
282-
283-
// Initialize plan data struct for homing motion.
284-
memcpy(&plan_data.spindle, &gc_state.spindle, sizeof(spindle_t));
285283
plan_data.condition.coolant = gc_state.modal.coolant;
286284

287285
uint_fast8_t idx = N_AXIS;

ngc_expr.c

+88-24
Original file line numberDiff line numberDiff line change
@@ -571,6 +571,39 @@ static status_code_t read_operation_unary (char *line, uint_fast8_t *pos, ngc_un
571571
return status;
572572
}
573573

574+
/*! \brief Reads the name of a parameter out of the line
575+
starting at the index given by the pos offset.
576+
577+
\param line pointer to RS274/NGC code (block).
578+
\param pos offset into line where expression starts.
579+
\param buffer pointer to a character buffer for the name.
580+
\returns #Status_OK enum value if processed without error, appropriate \ref status_code_t enum value if not.
581+
*/
582+
status_code_t ngc_read_name (char *line, uint_fast8_t *pos, char *buffer)
583+
{
584+
char *s;
585+
uint_fast8_t len = 0;
586+
status_code_t status = Status_BadNumberFormat;
587+
588+
if(*(s = line + (*pos)++) == '<') {
589+
590+
s++;
591+
592+
while(*s && *s != '>' && len <= NGC_MAX_PARAM_LENGTH) {
593+
*buffer++ = *s++;
594+
(*pos)++;
595+
len++;
596+
}
597+
598+
if((status = *s == '>' ? Status_OK : Status_FlowControlSyntaxError) == Status_OK) {
599+
*buffer = '\0';
600+
(*pos)++;
601+
}
602+
}
603+
604+
return status;
605+
}
606+
574607
/*! \brief Reads the value out of a parameter of the line, starting at the
575608
index given by the pos offset.
576609
@@ -593,6 +626,7 @@ sequentially, the value of #2 would be 10 after the line was executed.
593626
*/
594627
status_code_t ngc_read_parameter (char *line, uint_fast8_t *pos, float *value, bool check)
595628
{
629+
int32_t param;
596630
status_code_t status = Status_BadNumberFormat;
597631

598632
if(*(line + *pos) == '#') {
@@ -601,34 +635,18 @@ status_code_t ngc_read_parameter (char *line, uint_fast8_t *pos, float *value, b
601635

602636
if(*(line + *pos) == '<') {
603637

604-
(*pos)++;
605-
char *param = line + *pos, *arg = line + *pos;
606-
607-
while(*arg && *arg != '>')
608-
arg++;
638+
char name[NGC_MAX_PARAM_LENGTH + 1];
609639

610-
*pos += arg - param + 1;
611-
612-
if(*arg == '>') {
613-
*arg = '\0';
614-
if(ngc_named_param_get(param, value))
615-
status = Status_OK;
616-
*arg = '>';
640+
if((status = ngc_read_name(line, pos, name)) == Status_OK) {
641+
if(!ngc_named_param_get(name, value))
642+
status = Status_BadNumberFormat;
617643
}
644+
} else if((status = ngc_read_integer_value(line, pos, &param)) == Status_OK) {
618645

619-
} else if((status = ngc_read_real_value(line, pos, value)) == Status_OK) {
620-
621-
uint32_t param = (uint32_t)floorf(*value);
622-
623-
if((*value - (float)param) > 0.9999f) {
624-
param = (uint32_t)ceilf(*value);
625-
} else if((*value - (float)param) > 0.0001f)
626-
status = Status_BadNumberFormat; // not integer
627-
628-
if(check && !ngc_param_exists((ngc_param_id_t)param))
646+
if(param < 0 || (check && !ngc_param_exists((ngc_param_id_t)param)))
647+
status = Status_GcodeValueOutOfRange;
648+
else if(!ngc_param_get((ngc_param_id_t)param, value))
629649
status = Status_GcodeValueOutOfRange;
630-
else if(ngc_param_get((ngc_param_id_t)param, value))
631-
status = Status_OK;
632650
}
633651
}
634652

@@ -761,6 +779,52 @@ status_code_t ngc_read_real_value (char *line, uint_fast8_t *pos, float *value)
761779
return status;
762780
}
763781

782+
/*! \brief Reads explicit unsigned (positive) integer out of the line,
783+
starting at the index given by the pos offset. It expects to find one
784+
or more digits. Any character other than a digit terminates reading
785+
the integer. Note that if the first character is a sign (+ or -),
786+
an error will be reported (since a sign is not a digit).
787+
788+
\param line pointer to RS274/NGC code (block).
789+
\param pos offset into line where expression starts.
790+
\param value pointer to integer where result is to be stored.
791+
\returns #Status_OK enum value if processed without error, appropriate \ref status_code_t enum value if not.
792+
*/
793+
status_code_t ngc_read_integer_unsigned (char *line, uint_fast8_t *pos, uint32_t *value)
794+
{
795+
return line[*pos] == '+' ? Status_GcodeCommandValueNotInteger : read_uint(line, pos, value);
796+
}
797+
798+
/*! \brief Reads an integer (positive, negative or zero) out of the line,
799+
starting at the index given by the pos offset. The value being
800+
read may be written with a decimal point or it may be an expression
801+
involving non-integers, as long as the result comes out within 0.0001
802+
of an integer.
803+
804+
This proceeds by calling read_real_value and checking that it is
805+
close to an integer, then returning the integer it is close to.
806+
807+
\param line pointer to RS274/NGC code (block).
808+
\param pos offset into line where expression starts.
809+
\param value pointer to integer where result is to be stored.
810+
\returns #Status_OK enum value if processed without error, appropriate \ref status_code_t enum value if not.
811+
*/
812+
status_code_t ngc_read_integer_value (char *line, uint_fast8_t *pos, int32_t *value)
813+
{
814+
float fvalue;
815+
status_code_t status;
816+
817+
if((status = ngc_read_real_value(line, pos, &fvalue)) == Status_OK) {
818+
*value = (int32_t)floorf(fvalue);
819+
if((fvalue - (float)*value) > 0.9999f) {
820+
*value = (uint32_t)ceilf(fvalue);
821+
} else if((fvalue - (float)*value) > 0.0001f)
822+
status = Status_GcodeCommandValueNotInteger; // not integer
823+
}
824+
825+
return status;
826+
}
827+
764828
/*! \brief Evaluate expression and set result if successful.
765829
766830
\param line pointer to RS274/NGC code (block).

ngc_expr.h

+4-1
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,11 @@
33
#ifndef _NGC_EXPR_H_
44
#define _NGC_EXPR_H_
55

6-
status_code_t ngc_eval_expression (char *line, uint_fast8_t *pos, float *value);
6+
status_code_t ngc_read_name (char *line, uint_fast8_t *pos, char *buffer);
77
status_code_t ngc_read_real_value (char *line, uint_fast8_t *pos, float *value);
8+
status_code_t ngc_read_integer_value(char *line, uint_fast8_t *pos, int32_t *value);
9+
status_code_t ngc_read_integer_unsigned (char *line, uint_fast8_t *pos, uint32_t *value);
810
status_code_t ngc_read_parameter (char *line, uint_fast8_t *pos, float *value, bool check);
11+
status_code_t ngc_eval_expression (char *line, uint_fast8_t *pos, float *value);
912

1013
#endif

ngc_params.c

+3-6
Original file line numberDiff line numberDiff line change
@@ -41,9 +41,6 @@
4141
#ifndef NGC_MAX_CALL_LEVEL
4242
#define NGC_MAX_CALL_LEVEL 10
4343
#endif
44-
#ifndef NGC_MAX_PARAM_LENGTH
45-
#define NGC_MAX_PARAM_LENGTH 20
46-
#endif
4744

4845
typedef float (*ngc_param_get_ptr)(ngc_param_id_t id);
4946
typedef float (*ngc_named_param_get_ptr)(void);
@@ -622,7 +619,7 @@ static char *ngc_name_tolower (char *s)
622619
uint_fast8_t len = 0;
623620
char c, *s1 = s, *s2 = name;
624621

625-
while((c = *s1++) && len < NGC_MAX_PARAM_LENGTH) {
622+
while((c = *s1++) && len <= NGC_MAX_PARAM_LENGTH) {
626623
if(c > ' ') {
627624
*s2++ = LCAPS(c);
628625
len++;
@@ -679,7 +676,7 @@ bool ngc_named_param_exists (char *name)
679676
} while(idx && !ok);
680677

681678
// If not predefined attempt to find it.
682-
if(!ok && rw_global_params && strlen(name) < NGC_MAX_PARAM_LENGTH) {
679+
if(!ok && rw_global_params && strlen(name) <= NGC_MAX_PARAM_LENGTH) {
683680

684681
void *context = *name == '_' ? NULL : call_context;
685682
ngc_named_rw_param_t *rw_param = rw_global_params;
@@ -712,7 +709,7 @@ bool ngc_named_param_set (char *name, float value)
712709
} while(idx && !ok);
713710

714711
// If not predefined attempt to set it.
715-
if(!ok && (ok = strlen(name) < NGC_MAX_PARAM_LENGTH)) {
712+
if(!ok && (ok = strlen(name) <= NGC_MAX_PARAM_LENGTH)) {
716713

717714
void *context = *name == '_' ? NULL : call_context;
718715
ngc_named_rw_param_t *rw_param = rw_global_params, *rw_param_last = rw_global_params;

ngc_params.h

+4
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,10 @@
3030

3131
#include "gcode.h"
3232

33+
#ifndef NGC_MAX_PARAM_LENGTH
34+
#define NGC_MAX_PARAM_LENGTH 20
35+
#endif
36+
3337
typedef uint16_t ngc_param_id_t;
3438

3539
typedef struct {

0 commit comments

Comments
 (0)