mirror of
https://github.com/grblHAL/core.git
synced 2026-09-25 08:44:17 +08:00
Added support for named o-sub/o-call to flow control, for calling gcode subroutines stored on SD card or in littlefs.
Sub name matches filename with extension .macro. Added core event for handling special gcode comments used by expressions and flow control: DEBUG, PRINT and ABORT. Added overrideable default $-setting values for second PWM spindle to grbl/config.c.
This commit is contained in:
@@ -1,5 +1,25 @@
|
||||
## grblHAL changelog
|
||||
|
||||
<a name="20241116">Build 20241116
|
||||
|
||||
Core:
|
||||
|
||||
* Added support for named o-sub/o-call to flow control, for calling gcode subroutines stored on SD card or in littlefs. Sub name matches filename with extension _.macro_.
|
||||
|
||||
* Added core event for handling special gcode comments used by expressions: `DEBUG`, `PRINT` and `ABORT`. These can now be extended by or new added to by plugins.
|
||||
|
||||
* Added overrideable default $-setting values for second PWM spindle to _grbl/config.c_.
|
||||
|
||||
Plugins:
|
||||
|
||||
* Trinamic: changed some default parameter values, fix bug in previously unused TMC2660 code.
|
||||
|
||||
* Motors: fixed bugs in handling and visibility of extended settings.
|
||||
|
||||
* Misc, eventout: added info to `$pins` command for pins mapped to event actions.
|
||||
|
||||
---
|
||||
|
||||
<a name="20241113">Build 20241113
|
||||
|
||||
Core:
|
||||
@@ -18,6 +38,8 @@ Plugins:
|
||||
|
||||
* Misc: added plugin for feed rate overrides via Marlin style M-code and plugin for configuring per axis homing pulloff distance.
|
||||
|
||||
* Keypad, macros: added some overridable defaults.
|
||||
|
||||
---
|
||||
|
||||
<a name="20241110">Build 20241110
|
||||
|
||||
@@ -1212,6 +1212,81 @@ Defines the parameters for the fourth entry in the spindle RPM linearization tab
|
||||
|
||||
#endif // ENABLE_SPINDLE_LINEARIZATION
|
||||
|
||||
// Settings for second PWM spindle
|
||||
|
||||
/*! @name $716 - Setting_SpindleInvertMask1
|
||||
Inverts the selected spindle output signals from active high to active low. Useful for some pre-built electronic boards.
|
||||
*/
|
||||
///@{
|
||||
#if !defined DEFAULT_INVERT_SPINDLE1_ENABLE_PIN || defined __DOXYGEN__
|
||||
#define DEFAULT_INVERT_SPINDLE1_ENABLE_PIN Off
|
||||
#endif
|
||||
#if !defined DEFAULT_INVERT_SPINDLE1_CCW_PIN || defined __DOXYGEN__
|
||||
#define DEFAULT_INVERT_SPINDLE1_CCW_PIN Off // NOTE: not supported by all drivers.
|
||||
#endif
|
||||
#if !defined DEFAULT_INVERT_SPINDLE1_PWM_PIN || defined __DOXYGEN__
|
||||
#define DEFAULT_INVERT_SPINDLE1_PWM_PIN Off // NOTE: not supported by all drivers.
|
||||
#endif
|
||||
///@}
|
||||
|
||||
/*! @name $730 - Setting_RpmMax1
|
||||
*/
|
||||
///@{
|
||||
#if !defined DEFAULT_SPINDLE1_RPM_MAX || defined __DOXYGEN__
|
||||
#define DEFAULT_SPINDLE1_RPM_MAX 1000.0f // rpm
|
||||
#endif
|
||||
///@}
|
||||
|
||||
/*! @name $731 - Setting_RpmMin1
|
||||
*/
|
||||
///@{
|
||||
#if !defined DEFAULT_SPINDLE1_RPM_MIN || defined __DOXYGEN__
|
||||
#define DEFAULT_SPINDLE1_RPM_MIN 0.0f // rpm
|
||||
#endif
|
||||
///@}
|
||||
|
||||
/*! @name $733 - Setting_PWMFreq1
|
||||
*/
|
||||
///@{
|
||||
#if !defined DEFAULT_SPINDLE1_PWM_FREQ || defined __DOXYGEN__
|
||||
#define DEFAULT_SPINDLE1_PWM_FREQ 5000 // Hz
|
||||
#endif
|
||||
///@}
|
||||
|
||||
/*! @name $734 - Setting_PWMOffValue1
|
||||
*/
|
||||
///@{
|
||||
#if !defined DEFAULT_SPINDLE1_PWM_OFF_VALUE || defined __DOXYGEN__
|
||||
#define DEFAULT_SPINDLE1_PWM_OFF_VALUE 0.0f // Percent
|
||||
#endif
|
||||
///@}
|
||||
|
||||
/*! @name $735 - Setting_PWMMinValue1
|
||||
Used by variable spindle output only. This forces the PWM output to a minimum duty cycle when enabled.
|
||||
The PWM pin will still read 0V when the spindle is disabled. Most users will not need this option, but
|
||||
it may be useful in certain scenarios. This minimum PWM settings coincides with the spindle rpm minimum
|
||||
setting, like rpm max to max PWM. This is handy if you need a larger voltage difference between 0V disabled
|
||||
and the voltage set by the minimum PWM for minimum rpm. This difference is 0.02V per PWM value. So, when
|
||||
minimum PWM is at 1, only 0.02 volts separate enabled and disabled. At PWM 5, this would be 0.1V. Keep
|
||||
in mind that you will begin to lose PWM resolution with increased minimum PWM values, since you have less
|
||||
and less range over the total 255 PWM levels to signal different spindle speeds.
|
||||
<br>__!! NOTE:__ Compute duty cycle at the minimum PWM by this equation: (% duty cycle)=(SPINDLE1_PWM_MIN_VALUE/255)*100
|
||||
*/
|
||||
///@{
|
||||
#if !defined DEFAULT_SPINDLE1_PWM_MIN_VALUE || defined __DOXYGEN__
|
||||
#define DEFAULT_SPINDLE1_PWM_MIN_VALUE 0.0f // Must be greater than zero. Integer (+-255).
|
||||
#endif
|
||||
///@}
|
||||
|
||||
/*! @name $736 - Setting_PWMMaxValue
|
||||
*/
|
||||
///@{
|
||||
#if !defined DEFAULT_SPINDLE1_PWM_MAX_VALUE || defined __DOXYGEN__
|
||||
#define DEFAULT_SPINDLE1_PWM_MAX_VALUE 100.0f // Percent
|
||||
#endif
|
||||
///@}
|
||||
|
||||
|
||||
// Tool change settings (Group_Toolchange)
|
||||
|
||||
/*! @name $341 - Setting_ToolChangeMode
|
||||
|
||||
+14
-12
@@ -118,6 +118,7 @@ typedef void (*on_reset_ptr)(void);
|
||||
typedef void (*on_jog_cancel_ptr)(sys_state_t state);
|
||||
typedef bool (*on_spindle_select_ptr)(spindle_ptrs_t *spindle);
|
||||
typedef void (*on_spindle_selected_ptr)(spindle_ptrs_t *spindle);
|
||||
typedef char *(*on_process_gcode_comment_ptr)(char *msg);
|
||||
typedef status_code_t (*on_gcode_message_ptr)(char *msg);
|
||||
typedef void (*on_rt_reports_added_ptr)(report_tracking_flags_t report);
|
||||
typedef const char *(*on_set_axis_setting_unit_ptr)(setting_id_t setting_id, uint_fast8_t axis_idx);
|
||||
@@ -242,19 +243,20 @@ typedef struct {
|
||||
on_probe_start_ptr on_probe_start;
|
||||
on_probe_completed_ptr on_probe_completed;
|
||||
on_set_axis_setting_unit_ptr on_set_axis_setting_unit;
|
||||
on_gcode_message_ptr on_gcode_message; //!< Called on output of message parsed from gcode. NOTE: string pointed to is freed after this call.
|
||||
on_gcode_message_ptr on_gcode_comment; //!< Called when a plain gcode comment has been parsed.
|
||||
on_tool_selected_ptr on_tool_selected; //!< Called prior to executing M6 or after executing M61.
|
||||
on_tool_changed_ptr on_tool_changed; //!< Called after executing M6 or M61.
|
||||
on_toolchange_ack_ptr on_toolchange_ack; //!< Called from interrupt context.
|
||||
on_jog_cancel_ptr on_jog_cancel; //!< Called from interrupt context.
|
||||
on_process_gcode_comment_ptr on_process_gcode_comment;
|
||||
on_gcode_message_ptr on_gcode_message; //!< Called on output of message parsed from gcode. NOTE: string pointed to is freed after this call.
|
||||
on_gcode_message_ptr on_gcode_comment; //!< Called when a plain gcode comment has been parsed.
|
||||
on_tool_selected_ptr on_tool_selected; //!< Called prior to executing M6 or after executing M61.
|
||||
on_tool_changed_ptr on_tool_changed; //!< Called after executing M6 or M61.
|
||||
on_toolchange_ack_ptr on_toolchange_ack; //!< Called from interrupt context.
|
||||
on_jog_cancel_ptr on_jog_cancel; //!< Called from interrupt context.
|
||||
on_laser_ppi_enable_ptr on_laser_ppi_enable;
|
||||
on_spindle_select_ptr on_spindle_select; //!< Called before spindle is selected, hook in HAL overrides here
|
||||
on_spindle_selected_ptr on_spindle_selected; //!< Called when spindle is selected, do not change HAL pointers here!
|
||||
on_reset_ptr on_reset; //!< Called from interrupt context.
|
||||
on_file_open_ptr on_file_open; //!< Called when a file is opened for streaming.
|
||||
on_file_end_ptr on_file_end; //!< Called when a file opened for streaming reaches the end.
|
||||
user_mcode_ptrs_t user_mcode; //!< Optional handlers for user defined M-codes.
|
||||
on_spindle_select_ptr on_spindle_select; //!< Called before spindle is selected, hook in HAL overrides here
|
||||
on_spindle_selected_ptr on_spindle_selected; //!< Called when spindle is selected, do not change HAL pointers here!
|
||||
on_reset_ptr on_reset; //!< Called from interrupt context.
|
||||
on_file_open_ptr on_file_open; //!< Called when a file is opened for streaming.
|
||||
on_file_end_ptr on_file_end; //!< Called when a file opened for streaming reaches the end.
|
||||
user_mcode_ptrs_t user_mcode; //!< Optional handlers for user defined M-codes.
|
||||
// core entry points - set up by core before driver_init() is called.
|
||||
home_machine_ptr home_machine;
|
||||
travel_limits_ptr check_travel_limits;
|
||||
|
||||
+6
-2
@@ -288,18 +288,22 @@
|
||||
// Driver spindle 1
|
||||
|
||||
#if SPINDLE_ENABLE & ((1<<SPINDLE_PWM1)|(1<<SPINDLE_PWM1_NODIR)|(1<<SPINDLE_ONOFF1)|(1<<SPINDLE_ONOFF1_DIR))
|
||||
#if N_SPINDLE > 1
|
||||
#define DRIVER_SPINDLE1_ENABLE 1
|
||||
#else
|
||||
#warning "Configure N_SPINDLE > 1 in grbl/config.h when enabling second driver spindle!"
|
||||
#endif
|
||||
#else
|
||||
#define DRIVER_SPINDLE1_ENABLE 0
|
||||
#endif
|
||||
|
||||
#if SPINDLE_ENABLE & ((1<<SPINDLE_PWM1)|(1<<SPINDLE_ONOFF1_DIR))
|
||||
#if DRIVER_SPINDLE1_ENABLE && (SPINDLE_ENABLE & ((1<<SPINDLE_PWM1)|(1<<SPINDLE_ONOFF1_DIR)))
|
||||
#define DRIVER_SPINDLE1_DIR_ENABLE 1
|
||||
#else
|
||||
#define DRIVER_SPINDLE1_DIR_ENABLE 0
|
||||
#endif
|
||||
|
||||
#if SPINDLE_ENABLE & ((1<<SPINDLE_PWM1)|(1<<SPINDLE_PWM1_NODIR))
|
||||
#if DRIVER_SPINDLE1_ENABLE && (SPINDLE_ENABLE & ((1<<SPINDLE_PWM1)|(1<<SPINDLE_PWM1_NODIR)))
|
||||
#define DRIVER_SPINDLE1_PWM_ENABLE 1
|
||||
#define DRIVER_SPINDLE1_NAME "PWM2"
|
||||
#else
|
||||
|
||||
@@ -593,40 +593,32 @@ char *gc_normalize_block (char *block, status_code_t *status, char **message)
|
||||
|
||||
case ')':
|
||||
if(comment && !gc_state.skip_blocks) {
|
||||
|
||||
*s1 = '\0';
|
||||
if(!hal.driver_cap.no_gcode_message_handling) {
|
||||
|
||||
if(message && *message == NULL) {
|
||||
#if NGC_EXPRESSIONS_ENABLE
|
||||
if(!strncasecmp(comment, "DEBUG,", 6)) { // Debug message string substitution
|
||||
if(settings.flags.ngc_debug_out) {
|
||||
comment += 6;
|
||||
ngc_substitute_parameters(comment, message);
|
||||
}
|
||||
*comment = '\0'; // Do not generate grbl.on_gcode_comment event!
|
||||
} else if(!strncasecmp(comment, "PRINT,", 6)) { // Print message string substitution
|
||||
comment += 6;
|
||||
ngc_substitute_parameters(comment, message);
|
||||
*comment = '\0'; // Do not generate grbl.on_gcode_comment event!
|
||||
} else {
|
||||
#endif
|
||||
size_t len = s1 - comment - 3;
|
||||
|
||||
if(!strncasecmp(comment, "MSG,", 4) && (*message = malloc(len))) {
|
||||
if(grbl.on_process_gcode_comment)
|
||||
*message = grbl.on_process_gcode_comment(comment);
|
||||
|
||||
comment += 4;
|
||||
while(*comment == ' ') {
|
||||
comment++;
|
||||
len--;
|
||||
if(*message == NULL) {
|
||||
|
||||
size_t len = s1 - comment - 3;
|
||||
if(!strncasecmp(comment, "MSG,", 4) && (*message = malloc(len))) {
|
||||
|
||||
comment += 4;
|
||||
while(*comment == ' ') {
|
||||
comment++;
|
||||
len--;
|
||||
}
|
||||
memcpy(*message, comment, len);
|
||||
}
|
||||
memcpy(*message, comment, len);
|
||||
}
|
||||
#if NGC_EXPRESSIONS_ENABLE
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
if(*comment && *message == NULL && grbl.on_gcode_comment)
|
||||
|
||||
if(*comment && (message == NULL || *message == NULL) && grbl.on_gcode_comment)
|
||||
*status = grbl.on_gcode_comment(comment);
|
||||
}
|
||||
comment = NULL;
|
||||
@@ -912,17 +904,14 @@ status_code_t gc_execute_block (char *block)
|
||||
} else
|
||||
FAIL(status);
|
||||
} else if(block[char_counter] == '<') {
|
||||
#if 0
|
||||
|
||||
char o_slabel[NGC_MAX_PARAM_LENGTH + 1];
|
||||
if((status = ngc_read_name(block, &char_counter, o_slabel)) != Status_OK)
|
||||
FAIL(status);
|
||||
gc_block.words.o = On;
|
||||
if((gc_block.values.o = string_register_set_name(o_slabel)) == 0)
|
||||
if((gc_block.values.o = ngc_string_param_set_name(o_slabel)) == 0)
|
||||
FAIL(Status_FlowControlOutOfMemory);
|
||||
continue;
|
||||
#else
|
||||
FAIL(Status_GcodeUnsupportedCommand); // [For now...]
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -42,7 +42,7 @@
|
||||
#else
|
||||
#define GRBL_VERSION "1.1f"
|
||||
#endif
|
||||
#define GRBL_BUILD 20241113
|
||||
#define GRBL_BUILD 20241116
|
||||
|
||||
#define GRBL_URL "https://github.com/grblHAL"
|
||||
|
||||
|
||||
@@ -35,6 +35,9 @@
|
||||
#include "state_machine.h"
|
||||
#include "nvs_buffer.h"
|
||||
#include "stream.h"
|
||||
#if NGC_EXPRESSIONS_ENABLE
|
||||
#include "ngc_expr.h"
|
||||
#endif
|
||||
#if ENABLE_BACKLASH_COMPENSATION
|
||||
#include "motion_control.h"
|
||||
#endif
|
||||
@@ -182,6 +185,9 @@ int grbl_enter (void)
|
||||
grbl.on_get_alarms = alarms_get_details;
|
||||
grbl.on_get_errors = errors_get_details;
|
||||
grbl.on_get_settings = settings_get_details;
|
||||
#if NGC_EXPRESSIONS_ENABLE
|
||||
grbl.on_process_gcode_comment = ngc_process_comment;
|
||||
#endif
|
||||
|
||||
// Clear all and set some HAL function pointers
|
||||
memset(&hal, 0, sizeof(grbl_hal_t));
|
||||
|
||||
+46
-13
@@ -984,28 +984,31 @@ static int8_t get_format (char c, int8_t pos, uint8_t *decimals)
|
||||
return pos;
|
||||
}
|
||||
|
||||
/*! \brief Substitute references to parameters and expressions in a string with their values.
|
||||
/*! \brief Substitute references to parameters in a string with their values.
|
||||
|
||||
_NOTE:_ The returned string must be freed by the caller.
|
||||
|
||||
\param comment pointer to the original comment string.
|
||||
\param message pointer to a char pointer to receive the resulting string.
|
||||
\param line pointer to the original string.
|
||||
\returns pointer to the resulting string on success, NULL on failure.
|
||||
*/
|
||||
char *ngc_substitute_parameters (char *comment, char **message)
|
||||
char *ngc_substitute_parameters (char *line)
|
||||
{
|
||||
if(line == NULL)
|
||||
return NULL;
|
||||
|
||||
size_t len = 0;
|
||||
float value;
|
||||
char *s, c;
|
||||
char *message = NULL, *s, c;
|
||||
uint_fast8_t char_counter = 0;
|
||||
int8_t parse_format = 0;
|
||||
uint8_t decimals = ngc_float_decimals(); // LinuxCNC is 1 (or l?)
|
||||
|
||||
// Trim leading spaces
|
||||
while(*comment == ' ')
|
||||
comment++;
|
||||
while(*line == ' ')
|
||||
line++;
|
||||
|
||||
// Calculate length of substituted string
|
||||
while((c = comment[char_counter++])) {
|
||||
while((c = line[char_counter++])) {
|
||||
if(parse_format) {
|
||||
if((parse_format = get_format(c, parse_format, &decimals)) < 0) {
|
||||
len -= parse_format;
|
||||
@@ -1015,7 +1018,7 @@ char *ngc_substitute_parameters (char *comment, char **message)
|
||||
parse_format = 1;
|
||||
else if(c == '#') {
|
||||
char_counter--;
|
||||
if(ngc_read_parameter(comment, &char_counter, &value, true) == Status_OK)
|
||||
if(ngc_read_parameter(line, &char_counter, &value, true) == Status_OK)
|
||||
len += strlen(decimals ? ftoa(value, decimals) : trim_float(ftoa(value, decimals)));
|
||||
else
|
||||
len += 3; // "N/A"
|
||||
@@ -1024,14 +1027,14 @@ char *ngc_substitute_parameters (char *comment, char **message)
|
||||
}
|
||||
|
||||
// Perform substitution
|
||||
if((s = *message = malloc(len + 1))) {
|
||||
if((s = message = malloc(len + 1))) {
|
||||
|
||||
char fmt[5] = {0};
|
||||
|
||||
*s = '\0';
|
||||
char_counter = 0;
|
||||
|
||||
while((c = comment[char_counter++])) {
|
||||
while((c = line[char_counter++])) {
|
||||
if(parse_format) {
|
||||
fmt[parse_format] = c;
|
||||
if((parse_format = get_format(c, parse_format, &decimals)) < 0)
|
||||
@@ -1046,7 +1049,7 @@ char *ngc_substitute_parameters (char *comment, char **message)
|
||||
fmt[0] = c;
|
||||
} else if(c == '#') {
|
||||
char_counter--;
|
||||
if(ngc_read_parameter(comment, &char_counter, &value, true) == Status_OK)
|
||||
if(ngc_read_parameter(line, &char_counter, &value, true) == Status_OK)
|
||||
strcat(s, decimals ? ftoa(value, decimals) : trim_float(ftoa(value, decimals)));
|
||||
else
|
||||
strcat(s, "N/A");
|
||||
@@ -1058,7 +1061,37 @@ char *ngc_substitute_parameters (char *comment, char **message)
|
||||
}
|
||||
}
|
||||
|
||||
return *message;
|
||||
return message;
|
||||
}
|
||||
|
||||
/*! \brief Process gcode comment string.
|
||||
Returns string with substituted parameter references if starts with DEBUG, or PRINT, NULL if not.
|
||||
|
||||
_NOTE:_ The returned string must be freed by the caller.
|
||||
|
||||
\param comment pointer to the comment string.
|
||||
\returns pointer to the resulting string on success, NULL on failure.
|
||||
*/
|
||||
char *ngc_process_comment (char *comment)
|
||||
{
|
||||
if(comment == NULL)
|
||||
return NULL;
|
||||
|
||||
char *message = NULL;
|
||||
|
||||
if(!strncasecmp(comment, "DEBUG,", 6)) { // DEBUG message string substitution
|
||||
if(settings.flags.ngc_debug_out) {
|
||||
comment += 6;
|
||||
message = ngc_substitute_parameters(comment);
|
||||
}
|
||||
*comment = '\0'; // Do not generate grbl.on_gcode_comment event!
|
||||
} else if(!strncasecmp(comment, "PRINT,", 6)) { // PRINT message string substitution
|
||||
comment += 6;
|
||||
message = ngc_substitute_parameters(comment);
|
||||
*comment = '\0'; // Do not generate grbl.on_gcode_comment event!
|
||||
}
|
||||
|
||||
return message;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
+2
-2
@@ -9,7 +9,7 @@ status_code_t ngc_read_integer_value(char *line, uint_fast8_t *pos, int32_t *val
|
||||
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);
|
||||
/**/
|
||||
char *ngc_substitute_parameters (char *comment, char **message);
|
||||
char *ngc_substitute_parameters (char *line);
|
||||
char *ngc_process_comment (char *comment);
|
||||
|
||||
#endif
|
||||
|
||||
+69
-41
@@ -198,6 +198,27 @@ static status_code_t read_command (char *line, uint_fast8_t *pos, ngc_cmd_t *ope
|
||||
return status;
|
||||
}
|
||||
|
||||
// Returns the last called named sub with reference count
|
||||
static ngc_sub_t *get_refcount (uint32_t *refcount)
|
||||
{
|
||||
ngc_sub_t *sub, *last = NULL;
|
||||
uint32_t o_label = 0;
|
||||
|
||||
if((sub = subs)) do {
|
||||
if(sub->o_label > NGC_MAX_PARAM_ID)
|
||||
o_label = sub->o_label;
|
||||
} while((sub = sub->next));
|
||||
|
||||
if((sub = subs)) do {
|
||||
if(sub->o_label == o_label) {
|
||||
last = sub;
|
||||
(*refcount)++;
|
||||
}
|
||||
} while((sub = sub->next));
|
||||
|
||||
return last;
|
||||
}
|
||||
|
||||
static ngc_sub_t *add_sub (uint32_t o_label, vfs_file_t *file)
|
||||
{
|
||||
ngc_sub_t *sub;
|
||||
@@ -276,10 +297,15 @@ static void stack_unwind_sub (uint32_t o_label)
|
||||
stack_pull();
|
||||
|
||||
if(stack_idx >= 0) {
|
||||
if(o_label > NGC_MAX_PARAM_ID)
|
||||
if(o_label > NGC_MAX_PARAM_ID) {
|
||||
uint32_t count = 0;
|
||||
if(stack[stack_idx].sub == get_refcount(&count) && count == 1)
|
||||
ngc_string_param_delete((ngc_string_id_t)o_label);
|
||||
clear_subs(stack[stack_idx].file);
|
||||
stream_redirect_close(stack[stack_idx].file);
|
||||
else
|
||||
} else
|
||||
vfs_seek(stack[stack_idx].file, stack[stack_idx].file_pos);
|
||||
|
||||
stack_pull();
|
||||
}
|
||||
|
||||
@@ -301,10 +327,14 @@ static status_code_t onGcodeComment (char *comment)
|
||||
status_code_t status = Status_OK;
|
||||
|
||||
if(!strncasecmp(comment, "ABORT,", 6)) {
|
||||
char *buf = NULL;
|
||||
if(ngc_substitute_parameters(comment + pos, &buf)) {
|
||||
report_message(buf, Message_Error);
|
||||
free(buf);
|
||||
char *msg = NULL;
|
||||
*comment = '!';
|
||||
msg = grbl.on_process_gcode_comment(comment);
|
||||
if(msg == NULL)
|
||||
msg = ngc_substitute_parameters(comment + pos);
|
||||
if(msg) {
|
||||
report_message(msg, Message_Error);
|
||||
free(msg);
|
||||
}
|
||||
status = Status_UserException;
|
||||
} else if(on_gcode_comment)
|
||||
@@ -328,41 +358,37 @@ void ngc_flowctrl_init (void)
|
||||
stack_pull();
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
static status_code_t onError (status_code_t status)
|
||||
// NOTE: onNamedSubError will be called recursively for each
|
||||
// redirected file by the grbl.report.status_message() call.
|
||||
static status_code_t onNamedSubError (status_code_t status)
|
||||
{
|
||||
static bool closing = false;
|
||||
|
||||
if(stack_idx >= 0) {
|
||||
|
||||
uint32_t o_label = 0;
|
||||
ngc_sub_t *sub;
|
||||
uint32_t o_label = 0;
|
||||
|
||||
if((sub = subs)) do {
|
||||
if(sub->o_label > NGC_MAX_PARAM_ID)
|
||||
if(sub->file == hal.stream.file && sub->o_label > NGC_MAX_PARAM_ID)
|
||||
o_label = sub->o_label;
|
||||
} while((sub = sub->next));
|
||||
|
||||
if((sub = subs)) do {
|
||||
if(sub->o_label == o_label)
|
||||
break;
|
||||
} while((sub = sub->next));
|
||||
} while(o_label == 0 && (sub = sub->next));
|
||||
|
||||
if(sub) {
|
||||
|
||||
if(!closing) {
|
||||
char msg[100];
|
||||
char *name, msg[100];
|
||||
closing = true;
|
||||
char *name = string_register_get_by_id((string_register_id_t)sub->o_label);
|
||||
sprintf(msg, "error %d in named sub %s.macro", (uint8_t)status, name);
|
||||
report_message(msg, Message_Warning);
|
||||
if((name = ngc_string_param_get((ngc_string_id_t)o_label))) {
|
||||
sprintf(msg, "error %d in named sub %s.macro", (uint8_t)status, name);
|
||||
report_message(msg, Message_Warning);
|
||||
}
|
||||
}
|
||||
|
||||
sub->o_label = 1;
|
||||
|
||||
stream_redirect_close(sub->file);
|
||||
stack_unwind_sub(o_label);
|
||||
status = grbl.report.status_message(status);
|
||||
}
|
||||
|
||||
closing = false;
|
||||
ngc_flowctrl_init();
|
||||
}
|
||||
@@ -370,14 +396,16 @@ static status_code_t onError (status_code_t status)
|
||||
return status;
|
||||
}
|
||||
|
||||
static status_code_t onFileEnd (vfs_file_t *file, status_code_t status)
|
||||
static status_code_t onNamedSubEOF (vfs_file_t *file, status_code_t status)
|
||||
{
|
||||
if(stack_idx >= 0 && stack[stack_idx].file == file)
|
||||
ngc_flowctrl_unwind_stack(file);
|
||||
if(stack_idx >= 0 && stack[stack_idx].file == file) {
|
||||
stream_redirect_close(stack[stack_idx].file);
|
||||
ngc_flowctrl_unwind_stack(stack[stack_idx].file);
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
*/
|
||||
|
||||
status_code_t ngc_flowctrl (uint32_t o_label, char *line, uint_fast8_t *pos, bool *skip)
|
||||
{
|
||||
float value;
|
||||
@@ -600,8 +628,8 @@ status_code_t ngc_flowctrl (uint32_t o_label, char *line, uint_fast8_t *pos, boo
|
||||
if(o_label > NGC_MAX_PARAM_ID) {
|
||||
|
||||
if((sub = subs)) do {
|
||||
// if(sub->o_label == o_label && sub->file == hal.stream.file)
|
||||
// break;
|
||||
if(sub->o_label == o_label && sub->file == hal.stream.file)
|
||||
break;
|
||||
} while(sub->next && (sub = sub->next));
|
||||
|
||||
if(sub == NULL || sub->o_label != o_label)
|
||||
@@ -636,28 +664,28 @@ status_code_t ngc_flowctrl (uint32_t o_label, char *line, uint_fast8_t *pos, boo
|
||||
ngc_sub_t *sub;
|
||||
|
||||
if(o_label > NGC_MAX_PARAM_ID) {
|
||||
#if 0
|
||||
|
||||
char *subname;
|
||||
if((subname = string_register_get_by_id((string_register_id_t)o_label))) {
|
||||
if((subname = ngc_string_param_get((ngc_string_id_t)o_label))) {
|
||||
char filename[60];
|
||||
vfs_file_t *file;
|
||||
|
||||
strcpy(filename, "/");
|
||||
strcat(filename, subname);
|
||||
strcat(filename, ".macro");
|
||||
|
||||
#if LITTLEFS_ENABLE
|
||||
sprintf(filename, "/littlefs/P%d.macro", macro_id);
|
||||
sprintf(filename, "/littlefs/%s.macro", subname);
|
||||
|
||||
if((file = vfs_open(filename, "r")) == NULL)
|
||||
if((file = stream_redirect_read(filename, onNamedSubError, onNamedSubEOF)) == NULL) {
|
||||
sprintf(filename, "/%s.macro", subname);
|
||||
file = stream_redirect_read(filename, onNamedSubError, onNamedSubEOF);
|
||||
}
|
||||
#else
|
||||
sprintf(filename, "/%s.macro", subname);
|
||||
file = stream_redirect_read(filename, onNamedSubError, onNamedSubEOF);
|
||||
#endif
|
||||
if((file = stream_redirect_read(filename, onError, onFileEnd))) {
|
||||
if(file) {
|
||||
if((sub = add_sub(o_label, file)) == NULL)
|
||||
status = Status_FlowControlOutOfMemory;
|
||||
} else
|
||||
status = Status_FlowControlOutOfMemory; // file not found...
|
||||
}
|
||||
#endif
|
||||
} else if((sub = subs)) do {
|
||||
if(sub->o_label == o_label && sub->file == hal.stream.file)
|
||||
break;
|
||||
|
||||
+130
@@ -71,6 +71,13 @@ typedef struct ngc_named_rw_param {
|
||||
struct ngc_named_rw_param *next;
|
||||
} ngc_named_rw_param_t;
|
||||
|
||||
typedef struct ngc_string_param {
|
||||
struct ngc_string_param *next;
|
||||
ngc_string_id_t id;
|
||||
uint8_t len;
|
||||
char value[1];
|
||||
} ngc_string_param_t;
|
||||
|
||||
typedef struct {
|
||||
uint32_t level;
|
||||
void *context;
|
||||
@@ -83,6 +90,8 @@ static gc_modal_t *modal_state;
|
||||
static ngc_param_context_t call_levels[NGC_MAX_CALL_LEVEL];
|
||||
static ngc_rw_param_t *rw_params = NULL;
|
||||
static ngc_named_rw_param_t *rw_global_params = NULL;
|
||||
static ngc_string_id_t ref_id = (uint32_t)-1;
|
||||
static ngc_string_param_t *ngc_string_params = NULL;
|
||||
|
||||
static float _absolute_pos (uint_fast8_t axis)
|
||||
{
|
||||
@@ -740,6 +749,127 @@ bool ngc_named_param_set (char *name, float value)
|
||||
return ok;
|
||||
}
|
||||
|
||||
static ngc_string_param_t *sp_get_by_name (char *name)
|
||||
{
|
||||
ngc_string_param_t *sr = ngc_string_params;
|
||||
|
||||
if(sr) do {
|
||||
if(sr->id > NGC_MAX_PARAM_ID && !(strcmp(sr->value, name)))
|
||||
break;
|
||||
} while((sr = sr->next));
|
||||
|
||||
return sr;
|
||||
}
|
||||
|
||||
static ngc_string_param_t *sp_set (ngc_string_id_t id, char *value)
|
||||
{
|
||||
size_t len;
|
||||
ngc_string_param_t *last = NULL, *sp;
|
||||
|
||||
if((sp = ngc_string_params)) do {
|
||||
if(sp->id == id)
|
||||
break;
|
||||
last = sp;
|
||||
} while((sp = sp->next));
|
||||
|
||||
if((len = strlen(value)) <= 255) {
|
||||
|
||||
if(sp == NULL || len > sp->len) {
|
||||
|
||||
ngc_string_param_t *sp_org = sp;
|
||||
|
||||
if((sp = realloc(sp, sizeof(ngc_string_param_t) + len))) {
|
||||
|
||||
if(sp_org == NULL) {
|
||||
sp->id = id;
|
||||
sp->next = NULL;
|
||||
}
|
||||
sp->len = len;
|
||||
|
||||
if(last == NULL) {
|
||||
ngc_string_params = sp;
|
||||
} else {
|
||||
if(sp_org == NULL)
|
||||
last->next = sp;
|
||||
else if(sp_org != sp) {
|
||||
|
||||
ngc_string_param_t *sr = ngc_string_params;
|
||||
|
||||
do {
|
||||
if(sr->next == sp_org) {
|
||||
sr->next = sp;
|
||||
break;
|
||||
}
|
||||
} while((sr = sr->next));
|
||||
}
|
||||
}
|
||||
} else if(sp_org)
|
||||
ngc_string_param_delete(sp_org->id);
|
||||
}
|
||||
|
||||
if(sp)
|
||||
strcpy(sp->value, value);
|
||||
|
||||
} else if(sp) {
|
||||
ngc_string_param_delete(sp->id);
|
||||
sp = NULL;
|
||||
}
|
||||
|
||||
return sp;
|
||||
}
|
||||
|
||||
char *ngc_string_param_get (ngc_string_id_t id)
|
||||
{
|
||||
ngc_string_param_t *sp;
|
||||
|
||||
if((sp = ngc_string_params)) do {
|
||||
if(sp->id == id)
|
||||
break;
|
||||
} while((sp = sp->next));
|
||||
|
||||
return sp->value;
|
||||
}
|
||||
|
||||
bool ngc_string_param_exists (ngc_string_id_t id)
|
||||
{
|
||||
return !!ngc_string_param_get(id);
|
||||
}
|
||||
|
||||
bool ngc_string_param_set (ngc_param_id_t id, char *value)
|
||||
{
|
||||
return id > 0 && !!sp_set((ngc_string_id_t)id, value);
|
||||
}
|
||||
|
||||
ngc_string_id_t ngc_string_param_set_name (char *name)
|
||||
{
|
||||
ngc_string_param_t *sr = *name ? sp_get_by_name(name) : NULL;
|
||||
|
||||
if(*name && sr == NULL)
|
||||
sr = sp_set(--ref_id, name);
|
||||
|
||||
return sr ? sr->id : 0;
|
||||
}
|
||||
|
||||
void ngc_string_param_delete (ngc_string_id_t id)
|
||||
{
|
||||
ngc_string_param_t *sr = ngc_string_params, *rm;
|
||||
|
||||
if(sr) {
|
||||
if(sr->id == id) {
|
||||
rm = sr;
|
||||
ngc_string_params = sr->next;
|
||||
free(rm);
|
||||
} else do {
|
||||
if(sr->next && sr->next->id == id) {
|
||||
rm = sr->next;
|
||||
sr->next = sr->next->next;
|
||||
free(rm);
|
||||
break;
|
||||
}
|
||||
} while((sr = sr->next));
|
||||
}
|
||||
}
|
||||
|
||||
bool ngc_modal_state_save (gc_modal_t *state, bool auto_restore)
|
||||
{
|
||||
gc_modal_t **saved_state = call_level == -1 ? &modal_state : &call_levels[call_level].modal_state;
|
||||
|
||||
@@ -37,6 +37,7 @@
|
||||
#define NGC_MAX_PARAM_ID 65535
|
||||
|
||||
typedef uint16_t ngc_param_id_t;
|
||||
typedef uint32_t ngc_string_id_t;
|
||||
|
||||
typedef struct {
|
||||
ngc_param_id_t id;
|
||||
@@ -111,6 +112,13 @@ bool ngc_named_param_get (char *name, float *value);
|
||||
float ngc_named_param_get_by_id (ncg_name_param_id_t id);
|
||||
bool ngc_named_param_set (char *name, float value);
|
||||
bool ngc_named_param_exists (char *name);
|
||||
|
||||
bool ngc_string_param_set (ngc_param_id_t id, char *value);
|
||||
ngc_string_id_t ngc_string_param_set_name (char *name);
|
||||
char *ngc_string_param_get (ngc_string_id_t id);
|
||||
bool ngc_string_param_exists (ngc_string_id_t id);
|
||||
void ngc_string_param_delete (ngc_string_id_t id);
|
||||
|
||||
bool ngc_call_push (void *context);
|
||||
bool ngc_call_pop (void);
|
||||
uint_fast8_t ngc_call_level (void);
|
||||
|
||||
+4
-4
@@ -441,7 +441,7 @@ static status_code_t set_ngc_debug_out (setting_id_t id, uint_fast16_t int_value
|
||||
|
||||
static bool machine_mode_changed = false;
|
||||
#if COMPATIBILITY_LEVEL <= 1
|
||||
static char homing_options[] = "Enable,Enable single axis commands,Homing on startup required,Set machine origin to 0,Two switches shares one input pin,Allow manual,Override locks,Keep homed status on reset,Use limit switches";
|
||||
static char homing_options[] = "Enable,Enable single axis commands,Homing on startup required,Set machine origin to 0,Two switches shares one input,Allow manual,Override locks,Keep homed status on reset,Use limit switches";
|
||||
#endif
|
||||
static char control_signals[] = "Reset,Feed hold,Cycle start,Safety door,Block delete,Optional stop,EStop,Probe connected,Motor fault,Motor warning,Limits override,Single step blocks";
|
||||
static char spindle_signals[] = "Spindle enable,Spindle direction,PWM";
|
||||
@@ -509,8 +509,8 @@ PROGMEM static const setting_detail_t setting_detail[] = {
|
||||
{ Setting_JunctionDeviation, Group_General, "Junction deviation", "mm", Format_Decimal, "#####0.000", NULL, NULL, Setting_IsLegacy, &settings.junction_deviation, NULL, NULL },
|
||||
{ Setting_ArcTolerance, Group_General, "Arc tolerance", "mm", Format_Decimal, "#####0.000", NULL, NULL, Setting_IsLegacy, &settings.arc_tolerance, NULL, NULL },
|
||||
{ Setting_ReportInches, Group_General, "Report in inches", NULL, Format_Bool, NULL, NULL, NULL, Setting_IsLegacyFn, set_report_inches, get_int, NULL },
|
||||
{ Setting_ControlInvertMask, Group_ControlSignals, "Invert control pins", NULL, Format_Bitfield, control_signals, NULL, NULL, Setting_IsExpandedFn, set_control_invert, get_int, NULL },
|
||||
{ Setting_CoolantInvertMask, Group_Coolant, "Invert coolant pins", NULL, Format_Bitfield, coolant_signals, NULL, NULL, Setting_IsExtended, &settings.coolant_invert.mask, NULL, NULL },
|
||||
{ Setting_ControlInvertMask, Group_ControlSignals, "Invert control inputs", NULL, Format_Bitfield, control_signals, NULL, NULL, Setting_IsExpandedFn, set_control_invert, get_int, NULL },
|
||||
{ Setting_CoolantInvertMask, Group_Coolant, "Invert coolant outputs", NULL, Format_Bitfield, coolant_signals, NULL, NULL, Setting_IsExtended, &settings.coolant_invert.mask, NULL, NULL },
|
||||
{ Setting_SpindleInvertMask, Group_Spindle, "Invert spindle signals", NULL, Format_Bitfield, spindle_signals, NULL, NULL, Setting_IsExtendedFn, set_spindle_invert, get_int, is_setting_available, { .reboot_required = On } },
|
||||
{ Setting_ControlPullUpDisableMask, Group_ControlSignals, "Pullup disable control inputs", NULL, Format_Bitfield, control_signals, NULL, NULL, Setting_IsExtendedFn, set_control_disable_pullup, get_int, NULL },
|
||||
{ Setting_LimitPullUpDisableMask, Group_Limits, "Pullup disable limit inputs", NULL, Format_AxisMask, NULL, NULL, NULL, Setting_IsExtended, &settings.limits.disable_pullup.mask, NULL, NULL },
|
||||
@@ -646,7 +646,7 @@ PROGMEM static const setting_detail_t setting_detail[] = {
|
||||
{ Setting_RotaryWrap, Group_Stepper, "Fast rotary go to G28", NULL, Format_Bitfield, rotary_axes, NULL, NULL, Setting_IsExtendedFn, set_rotary_wrap_axes, get_int, NULL },
|
||||
#endif
|
||||
{ Setting_FSOptions, Group_General, "File systems options", NULL, Format_Bitfield, fs_options, NULL, NULL, Setting_IsExtended, &settings.fs_options.mask, NULL, is_setting_available },
|
||||
{ Setting_HomePinsInvertMask, Group_Limits, "Invert home pins", NULL, Format_AxisMask, NULL, NULL, NULL, Setting_IsExtended, &settings.home_invert.mask, NULL, is_setting_available },
|
||||
{ Setting_HomePinsInvertMask, Group_Limits, "Invert home inputs", NULL, Format_AxisMask, NULL, NULL, NULL, Setting_IsExtended, &settings.home_invert.mask, NULL, is_setting_available },
|
||||
{ Setting_HoldCoolantOnDelay, Group_Coolant, "Coolant on delay", "s", Format_Decimal, "#0.0", "0.5", "20", Setting_IsExtended, &settings.safety_door.coolant_on_delay, NULL, is_setting_available }
|
||||
};
|
||||
|
||||
|
||||
+11
-10
@@ -1032,17 +1032,18 @@ static void spindle1_settings_save (void)
|
||||
static void spindle1_settings_restore (void)
|
||||
{
|
||||
static const spindle_settings_t defaults = {
|
||||
.rpm_max = DEFAULT_SPINDLE_RPM_MAX,
|
||||
.rpm_min = DEFAULT_SPINDLE_RPM_MIN,
|
||||
.rpm_max = DEFAULT_SPINDLE1_RPM_MAX,
|
||||
.rpm_min = DEFAULT_SPINDLE1_RPM_MIN,
|
||||
.flags.pwm_disable = false,
|
||||
.flags.enable_rpm_controlled = DEFAULT_SPINDLE_ENABLE_OFF_WITH_ZERO_SPEED,
|
||||
.invert.on = DEFAULT_INVERT_SPINDLE_ENABLE_PIN,
|
||||
.invert.ccw = DEFAULT_INVERT_SPINDLE_CCW_PIN,
|
||||
.invert.pwm = DEFAULT_INVERT_SPINDLE_PWM_PIN,
|
||||
.pwm_freq = DEFAULT_SPINDLE_PWM_FREQ,
|
||||
.pwm_off_value = DEFAULT_SPINDLE_PWM_OFF_VALUE,
|
||||
.pwm_min_value = DEFAULT_SPINDLE_PWM_MIN_VALUE,
|
||||
.pwm_max_value = DEFAULT_SPINDLE_PWM_MAX_VALUE,
|
||||
.flags.enable_rpm_controlled = 0, //DEFAULT_SPINDLE_ENABLE_OFF_WITH_ZERO_SPEED, TODO: add setting?
|
||||
.flags.laser_mode_disable = 0, // TODO: add setting? Not possible?
|
||||
.invert.on = DEFAULT_INVERT_SPINDLE1_ENABLE_PIN,
|
||||
.invert.ccw = DEFAULT_INVERT_SPINDLE1_CCW_PIN,
|
||||
.invert.pwm = DEFAULT_INVERT_SPINDLE1_PWM_PIN,
|
||||
.pwm_freq = DEFAULT_SPINDLE1_PWM_FREQ,
|
||||
.pwm_off_value = DEFAULT_SPINDLE1_PWM_OFF_VALUE,
|
||||
.pwm_min_value = DEFAULT_SPINDLE1_PWM_MIN_VALUE,
|
||||
.pwm_max_value = DEFAULT_SPINDLE1_PWM_MAX_VALUE,
|
||||
.at_speed_tolerance = DEFAULT_SPINDLE_AT_SPEED_TOLERANCE,
|
||||
.ppr = DEFAULT_SPINDLE_PPR,
|
||||
.pid.p_gain = DEFAULT_SPINDLE_P_GAIN,
|
||||
|
||||
Reference in New Issue
Block a user