Skip to content

Commit ee8eb2c

Browse files
committed
Fixed some odd bugs in NGC flow control, prepared for file based named O-call subroutines.
Fixed incorrect comment string passed to passed to grbl.on_gcode_comment event. Added generic redirector for temporarily changing input stream to read from a file. Supports nesting.
1 parent c07d631 commit ee8eb2c

11 files changed

+399
-52
lines changed

CMakeLists.txt

+1
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ target_sources(grbl INTERFACE
2121
${CMAKE_CURRENT_LIST_DIR}/spindle_control.c
2222
${CMAKE_CURRENT_LIST_DIR}/state_machine.c
2323
${CMAKE_CURRENT_LIST_DIR}/stream.c
24+
${CMAKE_CURRENT_LIST_DIR}/stream_file.c
2425
${CMAKE_CURRENT_LIST_DIR}/stepper.c
2526
${CMAKE_CURRENT_LIST_DIR}/stepper2.c
2627
${CMAKE_CURRENT_LIST_DIR}/system.c

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 20241016, see the [changelog](changelog.md) for details.
16+
Latest build date is 20241023, 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

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

3+
<a name="20241023">Build 20241023
4+
5+
Core:
6+
7+
* Fixed some odd bugs in NGC flow control, prepared for file based named O-call subroutines.
8+
9+
* Fixed incorrect comment string passed to passed to `grbl.on_gcode_comment` event.
10+
11+
* Added generic redirector for temporarily changing input stream to read from a file. Supports nesting.
12+
13+
Drivers:
14+
15+
*ESP32: fix for overriding UART0 pins, reverted and fixed tests for ESP32-S3 conditional code.
16+
17+
Plugins:
18+
19+
* File system macros: updated to use new input stream redirector, allows nesting of `G65` calls
20+
\(max 5 levels depending on available memory\). __NOTE:__ Not extensively tested, feedback required.
21+
22+
* SD card: updated to work alongside new file redirector.
23+
24+
---
25+
326
<a name="20241019">Build 20241019
427

528
Core:

core_handlers.h

+2
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,7 @@ typedef void (*on_gcode_message_ptr)(char *msg);
122122
typedef void (*on_rt_reports_added_ptr)(report_tracking_flags_t report);
123123
typedef const char *(*on_set_axis_setting_unit_ptr)(setting_id_t setting_id, uint_fast8_t axis_idx);
124124
typedef status_code_t (*on_file_open_ptr)(const char *fname, vfs_file_t *handle, bool stream);
125+
typedef status_code_t (*on_file_end_ptr)(vfs_file_t *handle, status_code_t status);
125126
typedef status_code_t (*on_unknown_sys_command_ptr)(sys_state_t state, char *line); // return Status_Unhandled.
126127
typedef status_code_t (*on_user_command_ptr)(char *line);
127128
typedef sys_commands_t *(*on_get_commands_ptr)(void);
@@ -252,6 +253,7 @@ typedef struct {
252253
on_spindle_selected_ptr on_spindle_selected; //!< Called when spindle is selected, do not change HAL pointers here!
253254
on_reset_ptr on_reset; //!< Called from interrupt context.
254255
on_file_open_ptr on_file_open; //!< Called when a file is opened for streaming.
256+
on_file_end_ptr on_file_end; //!< Called when a file opened for streaming reaches the end.
255257
user_mcode_ptrs_t user_mcode; //!< Optional handlers for user defined M-codes.
256258
// core entry points - set up by core before driver_init() is called.
257259
home_machine_ptr home_machine;

gcode.c

+12-19
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
#if NGC_EXPRESSIONS_ENABLE
3838
#include "ngc_expr.h"
3939
#include "ngc_flowctrl.h"
40+
//#include "string_registers.h"
4041
#ifndef NGC_N_ASSIGN_PARAMETERS_PER_BLOCK
4142
#define NGC_N_ASSIGN_PARAMETERS_PER_BLOCK 10
4243
#endif
@@ -587,7 +588,7 @@ char *gc_normalize_block (char *block, char **message)
587588

588589
case '(':
589590
// TODO: generate error if a left parenthesis is found inside a comment...
590-
comment = s1;
591+
comment = s1 + 1;
591592
break;
592593

593594
case ')':
@@ -597,27 +598,27 @@ char *gc_normalize_block (char *block, char **message)
597598

598599
if(message && *message == NULL) {
599600
#if NGC_EXPRESSIONS_ENABLE
600-
if(!strncmp(comment, "(DEBUG,", 7)) { // Debug message string substitution
601+
if(!strncasecmp(comment, "DEBUG,", 6)) { // Debug message string substitution
601602
if(settings.flags.ngc_debug_out) {
602-
comment += 7;
603+
comment += 6;
603604
ngc_substitute_parameters(comment, message);
604605
}
605606
*comment = '\0'; // Do not generate grbl.on_gcode_comment event!
606-
} else if(!strncmp(comment, "(PRINT,", 7)) { // Print message string substitution
607-
comment += 7;
607+
} else if(!strncasecmp(comment, "PRINT,", 6)) { // Print message string substitution
608+
comment += 6;
608609
ngc_substitute_parameters(comment, message);
609610
*comment = '\0'; // Do not generate grbl.on_gcode_comment event!
610-
} else if(!strncmp(comment, "(MSG,", 5)) {
611-
comment += 5;
611+
} else if(!strncasecmp(comment, "MSG,", 4)) {
612+
comment += 4;
612613
ngc_substitute_parameters(comment, message);
613614
}
614615
}
615616
#else
616-
size_t len = s1 - comment - 4;
617+
size_t len = s1 - comment - 3;
617618

618-
if(!strncmp(comment, "(MSG,", 5) && (*message = malloc(len))) {
619+
if(!strncasecmp(comment, "MSG,", 4) && (*message = malloc(len))) {
619620

620-
comment += 5;
621+
comment += 4;
621622
while(*comment == ' ') {
622623
comment++;
623624
len--;
@@ -639,14 +640,6 @@ char *gc_normalize_block (char *block, char **message)
639640
*s2++ = CAPS(c);
640641
break;
641642
}
642-
643-
#if NGC_EXPRESSIONS_ENABLE
644-
if(comment && s1 - comment < (strncmp(comment, "(DEBU", 5) && strncmp(comment, "(PRIN", 5) ? 5 : 7))
645-
*s1 = CAPS(c);
646-
#else
647-
if(comment && s1 - comment < 5)
648-
*s1 = CAPS(c);
649-
#endif
650643
s1++;
651644
}
652645

@@ -923,7 +916,7 @@ status_code_t gc_execute_block (char *block)
923916
if((status = ngc_read_name(block, &char_counter, o_slabel)) != Status_OK)
924917
FAIL(status);
925918
gc_block.words.o = On;
926-
if(gc_block.values.o = string_register_set_name(o_slabel) == 0)
919+
if((gc_block.values.o = string_register_set_name(o_slabel)) == 0)
927920
FAIL(Status_FlowControlOutOfMemory);
928921
continue;
929922
#else

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 20241019
45+
#define GRBL_BUILD 20241023
4646

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

ngc_flowctrl.c

+133-30
Original file line numberDiff line numberDiff line change
@@ -25,11 +25,15 @@
2525

2626
#if NGC_EXPRESSIONS_ENABLE
2727

28+
#include <math.h>
29+
#include <stdio.h>
2830
#include <string.h>
2931

3032
#include "errors.h"
3133
#include "ngc_expr.h"
3234
#include "ngc_params.h"
35+
#include "stream_file.h"
36+
//#include "string_registers.h"
3337

3438
#ifndef NGC_STACK_DEPTH
3539
#define NGC_STACK_DEPTH 20
@@ -193,6 +197,28 @@ static status_code_t read_command (char *line, uint_fast8_t *pos, ngc_cmd_t *ope
193197
return status;
194198
}
195199

200+
static ngc_sub_t *add_sub (uint32_t o_label, vfs_file_t *file)
201+
{
202+
ngc_sub_t *sub;
203+
204+
if((sub = malloc(sizeof(ngc_sub_t))) != NULL) {
205+
sub->o_label = o_label;
206+
sub->file = file;
207+
sub->file_pos = vfs_tell(file);
208+
sub->next = NULL;
209+
if(subs == NULL)
210+
subs = sub;
211+
else {
212+
ngc_sub_t *last = subs;
213+
while(last->next)
214+
last = last->next;
215+
last->next = sub;
216+
}
217+
}
218+
219+
return sub;
220+
}
221+
196222
static void clear_subs (vfs_file_t *file)
197223
{
198224
ngc_sub_t *current = subs, *prev = NULL, *next;
@@ -249,7 +275,10 @@ static void stack_unwind_sub (uint32_t o_label)
249275
stack_pull();
250276

251277
if(stack_idx >= 0) {
252-
vfs_seek(stack[stack_idx].file, stack[stack_idx].file_pos);
278+
if(o_label > NGC_MAX_PARAM_ID)
279+
stream_redirect_close(stack[stack_idx].file);
280+
else
281+
vfs_seek(stack[stack_idx].file, stack[stack_idx].file_pos);
253282
stack_pull();
254283
}
255284

@@ -272,6 +301,56 @@ void ngc_flowctrl_init (void)
272301
stack_pull();
273302
}
274303

304+
/*
305+
306+
static status_code_t onError (status_code_t status)
307+
{
308+
static bool closing = false;
309+
310+
if(stack_idx >= 0) {
311+
312+
uint32_t o_label = 0;
313+
ngc_sub_t *sub;
314+
315+
if((sub = subs)) do {
316+
if(sub->o_label > NGC_MAX_PARAM_ID)
317+
o_label = sub->o_label;
318+
} while((sub = sub->next));
319+
320+
if((sub = subs)) do {
321+
if(sub->o_label == o_label)
322+
break;
323+
} while((sub = sub->next));
324+
325+
if(sub) {
326+
if(!closing) {
327+
char msg[100];
328+
closing = true;
329+
char *name = string_register_get_by_id((string_register_id_t)sub->o_label);
330+
sprintf(msg, "error %d in named sub %s.macro", (uint8_t)status, name);
331+
report_message(msg, Message_Warning);
332+
}
333+
334+
sub->o_label = 1;
335+
336+
stream_redirect_close(sub->file);
337+
status = grbl.report.status_message(status);
338+
}
339+
closing = false;
340+
ngc_flowctrl_init();
341+
}
342+
343+
return status;
344+
}
345+
346+
static status_code_t onFileEnd (vfs_file_t *file, status_code_t status)
347+
{
348+
if(stack_idx >= 0 && stack[stack_idx].file == file)
349+
ngc_flowctrl_unwind_stack(file);
350+
351+
return status;
352+
}
353+
*/
275354
status_code_t ngc_flowctrl (uint32_t o_label, char *line, uint_fast8_t *pos, bool *skip)
276355
{
277356
float value;
@@ -346,13 +425,11 @@ status_code_t ngc_flowctrl (uint32_t o_label, char *line, uint_fast8_t *pos, boo
346425
if(last_op == NGCFlowCtrl_Do && o_label == stack[stack_idx].o_label)
347426
stack_pull();
348427
} else if(!skipping && (status = ngc_eval_expression(line, pos, &value)) == Status_OK) {
349-
if(last_op == NGCFlowCtrl_Do) {
350-
if(o_label == stack[stack_idx].o_label) {
351-
if(value != 0.0f)
352-
vfs_seek(stack[stack_idx].file, stack[stack_idx].file_pos);
353-
else
354-
stack_pull();
355-
}
428+
if(last_op == NGCFlowCtrl_Do && o_label == stack[stack_idx].o_label) {
429+
if(value != 0.0f)
430+
vfs_seek(stack[stack_idx].file, stack[stack_idx].file_pos);
431+
else
432+
stack_pull();
356433
} else if((status = stack_push(o_label, operation)) == Status_OK) {
357434
if(!(stack[stack_idx].skip = value == 0.0f)) {
358435
if((stack[stack_idx].expr = malloc(strlen(expr) + 1))) {
@@ -371,11 +448,13 @@ status_code_t ngc_flowctrl (uint32_t o_label, char *line, uint_fast8_t *pos, boo
371448
case NGCFlowCtrl_EndWhile:
372449
if(hal.stream.file) {
373450
if(last_op == NGCFlowCtrl_While) {
374-
if(!skipping && o_label == stack[stack_idx].o_label) {
375-
uint_fast8_t pos = 0;
376-
if(!stack[stack_idx].skip && (status = ngc_eval_expression(stack[stack_idx].expr, &pos, &value)) == Status_OK) {
377-
if(!(stack[stack_idx].skip = value == 0))
378-
vfs_seek(stack[stack_idx].file, stack[stack_idx].file_pos);
451+
if(o_label == stack[stack_idx].o_label) {
452+
if(!skipping) {
453+
uint_fast8_t pos = 0;
454+
if(!stack[stack_idx].skip && (status = ngc_eval_expression(stack[stack_idx].expr, &pos, &value)) == Status_OK) {
455+
if(!(stack[stack_idx].skip = value == 0.0f))
456+
vfs_seek(stack[stack_idx].file, stack[stack_idx].file_pos);
457+
}
379458
}
380459
if(stack[stack_idx].skip)
381460
stack_pull();
@@ -390,7 +469,8 @@ status_code_t ngc_flowctrl (uint32_t o_label, char *line, uint_fast8_t *pos, boo
390469
if(hal.stream.file) {
391470
if(!skipping && (status = ngc_eval_expression(line, pos, &value)) == Status_OK) {
392471
if((status = stack_push(o_label, operation)) == Status_OK) {
393-
if(!(stack[stack_idx].skip = value == 0.0f)) {
472+
value = nearbyintf(value);
473+
if(!(stack[stack_idx].skip = value <= 0.0f)) {
394474
stack[stack_idx].file = hal.stream.file;
395475
stack[stack_idx].file_pos = vfs_tell(hal.stream.file);
396476
stack[stack_idx].repeats = (uint32_t)value;
@@ -490,20 +570,17 @@ status_code_t ngc_flowctrl (uint32_t o_label, char *line, uint_fast8_t *pos, boo
490570
case NGCFlowCtrl_Sub:
491571
if(hal.stream.file) {
492572
ngc_sub_t *sub;
493-
if((skip_sub = (sub = malloc(sizeof(ngc_sub_t))) != NULL)) {
494-
sub->o_label = o_label;
495-
sub->file = hal.stream.file;
496-
sub->file_pos = vfs_tell(hal.stream.file);
497-
sub->next = NULL;
498-
if(subs == NULL)
499-
subs = sub;
500-
else {
501-
ngc_sub_t *last = subs;
502-
while(last->next)
503-
last = last->next;
504-
last->next = sub;
505-
}
506-
} // else out of memory
573+
if(o_label > NGC_MAX_PARAM_ID) {
574+
575+
if((sub = subs)) do {
576+
// if(sub->o_label == o_label && sub->file == hal.stream.file)
577+
// break;
578+
} while(sub->next && (sub = sub->next));
579+
580+
if(sub == NULL || sub->o_label != o_label)
581+
status = Status_FlowControlSyntaxError;
582+
} else if(!(skip_sub = (sub = add_sub(o_label, hal.stream.file)) != NULL))
583+
status = Status_FlowControlOutOfMemory;
507584
} else
508585
status = Status_FlowControlNotExecutingMacro;
509586
break;
@@ -524,11 +601,37 @@ status_code_t ngc_flowctrl (uint32_t o_label, char *line, uint_fast8_t *pos, boo
524601
break;
525602

526603
case NGCFlowCtrl_Call:
527-
if(hal.stream.file) {
604+
605+
if(hal.stream.file || o_label > NGC_MAX_PARAM_ID) {
606+
528607
if(!skipping) {
529608

530609
ngc_sub_t *sub = subs;
531-
do {
610+
611+
if(o_label > NGC_MAX_PARAM_ID) {
612+
#if 0
613+
char *subname;
614+
if((subname = string_register_get_by_id((string_register_id_t)o_label))) {
615+
char filename[60];
616+
vfs_file_t *file;
617+
618+
strcpy(filename, "/");
619+
strcat(filename, subname);
620+
strcat(filename, ".macro");
621+
622+
#if LITTLEFS_ENABLE
623+
sprintf(filename, "/littlefs/P%d.macro", macro_id);
624+
625+
if((file = vfs_open(filename, "r")) == NULL)
626+
#endif
627+
if((file = stream_redirect_read(filename, onError, onFileEnd))) {
628+
if((sub = add_sub(o_label, file)) == NULL)
629+
status = Status_FlowControlOutOfMemory;
630+
} else
631+
status = Status_FlowControlOutOfMemory; // file not found...
632+
}
633+
#endif
634+
} else do {
532635
if(sub->o_label == o_label && sub->file == hal.stream.file)
533636
break;
534637
} while((sub = sub->next));

ngc_params.h

+2
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,8 @@
3434
#define NGC_MAX_PARAM_LENGTH 20
3535
#endif
3636

37+
#define NGC_MAX_PARAM_ID 65535
38+
3739
typedef uint16_t ngc_param_id_t;
3840

3941
typedef struct {

0 commit comments

Comments
 (0)