mirror of
https://github.com/grblHAL/core.git
synced 2026-09-22 11:29:17 +08:00
Changed safety door/parking handling to be compliant with legacy Grbl.
Added $384 setting for controlling G92 offset persistence. Improved $help command output and handling. Moved the optional tool table in non-volatile storage. Added gcode parameter support and optional expression support.
This commit is contained in:
@@ -23,6 +23,9 @@ target_sources(grbl INTERFACE
|
||||
${CMAKE_CURRENT_LIST_DIR}/tool_change.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/alarms.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/errors.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/ngc_params.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/ngc_expr.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/regex.c
|
||||
)
|
||||
|
||||
target_include_directories(grbl INTERFACE ${CMAKE_CURRENT_LIST_DIR})
|
||||
|
||||
@@ -11,7 +11,7 @@ It has been written to complement grblHAL and has features such as proper keyboa
|
||||
|
||||
---
|
||||
|
||||
Latest build date is 20210907, see the [changelog](changelog.md) for details.
|
||||
Latest build date is 20210928, see the [changelog](changelog.md) for details.
|
||||
__NOTE:__ Drivers built with more than three axes configured \(`N_AXIS` > `3`\) will force a settings reset when upgraded. Backup and restore of settings is recommended for these.
|
||||
|
||||
---
|
||||
@@ -68,7 +68,7 @@ List of Supported G-Codes:
|
||||
- Coolant Control: M7, M8, M9
|
||||
- Spindle Control: M3, M4, M5
|
||||
- Tool Change: M6* (Two modes possible: manual** - supports jogging, ATC), M61
|
||||
- Switches: M49, M50, M51, M53
|
||||
- Switches: M48, M49, M50, M51, M53
|
||||
- Output control***: M62, M63, M64, M65, M66, M67, M68
|
||||
- Valid Non-Command Words: A*, B*, C*, F, H*, I, J, K, L, N, P, Q*, R, S, T, X, Y, Z
|
||||
|
||||
@@ -80,4 +80,4 @@ List of Supported G-Codes:
|
||||
Some [plugins](https://github.com/grblHAL/plugins) implements additional M-codes.
|
||||
|
||||
---
|
||||
2021-09-08
|
||||
2021-09-28
|
||||
|
||||
@@ -1,5 +1,26 @@
|
||||
## grblHAL changelog
|
||||
|
||||
Build 20210928:
|
||||
|
||||
Core:
|
||||
* Changed safety door/parking handling to be compliant with legacy Grbl - now a cycle start command has to be issued to resume after the door is closed.
|
||||
* Added `$384` setting for controlling G92 offset persistence, set to `1` to disable persistence across a reboot, `0` to enable. Only available if [compatibility level](https://github.com/grblHAL/core/wiki/Compatibility-level) is < 2, default value is `0`.
|
||||
* Improved `$help` command output and handling, added description to `$$=<n>` output.
|
||||
* Moved the optional tool table in non-volatile storage \(typically EEPROM\) to above the core area. This allows a larger number of tools \(max. 16\) to be defined.
|
||||
__NOTE:__ If you have tool table support enabled before upgrading the current table will be lost and possibly also all other settings. Backup and restore!
|
||||
* Added gcode parameter support. All [NIST RS274NGC version 3](https://www.nist.gov/publications/nist-rs274ngc-interpreter-version-3) parameters (see section 3.2.1) and most [LinuxCNC](http://www.linuxcnc.org/docs/html/gcode/overview.html#_parameters) parameters are supported.
|
||||
The `$#=<n>` or `$#=<name>` commands can be used to output a parameter value. Replace `<n>` with a parameter number, `<name>` with a parameter name.
|
||||
__NOTE 1:__ Named parameters and parameters in the range 1 to 5160 are volatile and will not persist across a reboot.
|
||||
__NOTE 2:__ Space for the volatile parameters is allocated at run-time, available memory \(heap\) sets a limit to how many can be set.
|
||||
__NOTE 3:__ Maximum name length is 20 characters, maximum number of parameters that can be set in a block \(line\) is 10.
|
||||
* Added gcode [expression](http://www.linuxcnc.org/docs/html/gcode/overview.html#gcode:expressions) support. This has to be enabled in [grbl/config.h](./config.h) by uncommenting `//#define NGC_EXPRESSIONS_ENABLE 1`. _Experimental_.
|
||||
__NOTE:__ Processors with limited memory may not compile with this enabled.
|
||||
|
||||
Drivers & plugins:
|
||||
|
||||
* Added [WebUI plugin](https://github.com/grblHAL/Plugin_WebUI) support for some networking capable boards.
|
||||
* Updated some drivers for internal API changes. Some minor bug fixes.
|
||||
|
||||
Build 20210907:
|
||||
|
||||
Core:
|
||||
|
||||
@@ -83,7 +83,7 @@ __NOTE:__ if switching to a level > 1 please reset non-volatile storage with \a
|
||||
// immediately forces a feed hold and then safely de-energizes the machine. Resuming is blocked until
|
||||
// the safety door is re-engaged. When it is, Grbl will re-energize the machine and then resume on the
|
||||
// previous tool path, as if nothing happened.
|
||||
// #define ENABLE_SAFETY_DOOR_INPUT_PIN // Default disabled. Uncomment to enable.
|
||||
//#define ENABLE_SAFETY_DOOR_INPUT_PIN // Default disabled. Uncomment to enable.
|
||||
|
||||
// After the safety door switch has been toggled and restored, this setting sets the power-up delay
|
||||
// between restoring the spindle and coolant and resuming the cycle.
|
||||
@@ -472,9 +472,24 @@ __NOTE:__ these definitions are only referenced in this file. Do __NOT__ change!
|
||||
//#define DEFAULT_REPORT_PARSER_STATE
|
||||
//#define DEFAULT_REPORT_ALARM_SUBSTATE
|
||||
|
||||
// G92 offsets is by default stored to non-volatile storage (NVS) on changes and restored on startup
|
||||
// if COMPATIBILITY_LEVEL is <= 1. If COMPATIBILITY_LEVEL is <= 1 then setting $384 can be used to change this at run-time.
|
||||
// To allow store/restore of the G92 offset when COMPATIBILITY_LEVEL > 1 uncomment the line below and reset settings with $RST=*.
|
||||
//#define DISABLE_G92_PERSISTENCE 0
|
||||
|
||||
#if COMPATIBILITY_LEVEL == 0
|
||||
// Number of tools in ATC tool table, comment out to disable
|
||||
// #define N_TOOLS 8
|
||||
// Number of tools in tool table, uncomment and edit if neccesary to enable (max. 16 allowed)
|
||||
//#define N_TOOLS 8
|
||||
#endif
|
||||
|
||||
// Sanity checks - N_TOOLS may have been defined on the compiler command line.
|
||||
#if defined(N_TOOLS) && N_TOOLS == 0
|
||||
#undef N_TOOLS
|
||||
#endif
|
||||
|
||||
#if defined(N_TOOLS) && N_TOOLS > 16
|
||||
#undef N_TOOLS
|
||||
#define N_TOOLS 16
|
||||
#endif
|
||||
|
||||
// Max number of entries in log for PID data reporting, to be used for tuning
|
||||
@@ -624,4 +639,7 @@ __NOTE:__ these definitions are only referenced in this file. Do __NOT__ change!
|
||||
|
||||
#endif // DEFAULT_HOMING_ENABLE
|
||||
|
||||
// Uncomment to enable experimental support for parameters and expressions
|
||||
//#define NGC_EXPRESSIONS_ENABLE 1
|
||||
|
||||
#endif
|
||||
|
||||
+14
@@ -37,6 +37,14 @@
|
||||
// Note: DEFAULT_ACCELERATION is only referenced in this file
|
||||
#define DEFAULT_ACCELERATION (10.0f * 60.0f * 60.0f) // 10*60*60 mm/min^2 = 10 mm/sec^2
|
||||
|
||||
#ifndef DISABLE_G92_PERSISTENCE
|
||||
#if COMPATIBILITY_LEVEL <= 1
|
||||
#define DISABLE_G92_PERSISTENCE 0
|
||||
#else
|
||||
#define DISABLE_G92_PERSISTENCE 1
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef DEFAULT_REPORT_MACHINE_POSITION
|
||||
#undef DEFAULT_REPORT_MACHINE_POSITION
|
||||
#define DEFAULT_REPORT_MACHINE_POSITION 1
|
||||
@@ -609,6 +617,12 @@
|
||||
#define INVERT_COOLANT_MIST_PIN 0
|
||||
#endif
|
||||
|
||||
#ifndef NGC_EXPRESSIONS_ENABLE
|
||||
#define NGC_EXPRESSIONS_ENABLE 0
|
||||
#else
|
||||
#define NGC_N_ASSIGN_PARAMETERS_PER_BLOCK 10
|
||||
#endif
|
||||
|
||||
// ---------------------------------------------------------------------------------------
|
||||
// COMPILE-TIME ERROR CHECKING OF DEFINE VALUES:
|
||||
|
||||
|
||||
+1
-1
@@ -240,7 +240,7 @@
|
||||
#if NETWORK_IPMODE < 0 || NETWORK_IPMODE > 2
|
||||
#error "Invalid IP mode selected!"
|
||||
#endif
|
||||
#if NETWORK_WEBSOCKET_PORT == NETWORK_HTTP_PORT
|
||||
#if HTTP_ENABLE && NETWORK_WEBSOCKET_PORT == NETWORK_HTTP_PORT
|
||||
#warning "HTTP and WebSocket protocols cannot share the same port!"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@@ -81,7 +81,15 @@ PROGMEM static const status_detail_t status_detail[] = {
|
||||
{ Status_MotorFault, "Motor fault", "Motor fault." },
|
||||
{ Status_SettingValueOutOfRange, "Value out of range.", "Setting value is out of range." },
|
||||
{ Status_SettingDisabled, "Setting disabled", "Setting is not available, possibly due to limited driver support." },
|
||||
{ Status_GcodeInvalidRetractPosition, "Invalid gcode ID:54", "Retract position is less than drill depth." }
|
||||
{ Status_GcodeInvalidRetractPosition, "Invalid gcode ID:54", "Retract position is less than drill depth." },
|
||||
#if NGC_EXPRESSIONS_ENABLE
|
||||
{ Status_ExpressionUknownOp, "Unknown operation found in expression", "Unknown operation found in expression." },
|
||||
{ Status_ExpressionDivideByZero, "Divide by zero in expression", "Divide by zero in expression attempted." },
|
||||
{ Status_ExpressionArgumentOutOfRange, "Expression argument out of range", "Too large or too small argrument provided." },
|
||||
{ Status_ExpressionInvalidArgument, "Invalid expression argument", "Argument is not valid for the operation" },
|
||||
{ Status_ExpressionSyntaxError, "Syntax error in expression", "Expression is not valid." },
|
||||
{ Status_ExpressionInvalidResult, "Invalid result returned from expression", "Either NAN (not a number) or infinity was returned from expression." }
|
||||
#endif
|
||||
};
|
||||
|
||||
static error_details_t details = {
|
||||
|
||||
@@ -93,6 +93,15 @@ typedef enum {
|
||||
Status_SDFileEmpty = 64,
|
||||
|
||||
Status_BTInitError = 70,
|
||||
|
||||
//
|
||||
Status_ExpressionUknownOp = 71,
|
||||
Status_ExpressionDivideByZero = 72,
|
||||
Status_ExpressionArgumentOutOfRange = 73,
|
||||
Status_ExpressionInvalidArgument = 74,
|
||||
Status_ExpressionSyntaxError = 75,
|
||||
Status_ExpressionInvalidResult = 76,
|
||||
|
||||
Status_Unhandled, // For internal use only
|
||||
Status_StatusMax = Status_Unhandled
|
||||
} status_code_t;
|
||||
|
||||
@@ -30,6 +30,11 @@
|
||||
#include "protocol.h"
|
||||
#include "state_machine.h"
|
||||
|
||||
#if NGC_EXPRESSIONS_ENABLE
|
||||
#include "ngc_expr.h"
|
||||
#include "ngc_params.h"
|
||||
#endif
|
||||
|
||||
// NOTE: Max line number is defined by the g-code standard to be 99999. It seems to be an
|
||||
// arbitrary value, and some GUIs may require more. So we increased it based on a max safe
|
||||
// value when converting a float (7.2 digit precision)s to an integer.
|
||||
@@ -307,10 +312,8 @@ void gc_init (void)
|
||||
if (!settings_read_coord_data(gc_state.modal.coord_system.id, &gc_state.modal.coord_system.xyz))
|
||||
grbl.report.status_message(Status_SettingReadFail);
|
||||
|
||||
#if COMPATIBILITY_LEVEL <= 1
|
||||
if (sys.cold_start && !settings_read_coord_data(CoordinateSystem_G92, &gc_state.g92_coord_offset))
|
||||
if (sys.cold_start && !settings.flags.g92_is_volatile && !settings_read_coord_data(CoordinateSystem_G92, &gc_state.g92_coord_offset))
|
||||
grbl.report.status_message(Status_SettingReadFail);
|
||||
#endif
|
||||
|
||||
// if(settings.flags.lathe_mode)
|
||||
// gc_state.modal.plane_select = PlaneSelect_ZX;
|
||||
@@ -373,12 +376,126 @@ static status_code_t init_sync_motion (plan_line_data_t *pl_data, float pitch)
|
||||
return Status_OK;
|
||||
}
|
||||
|
||||
// Executes one block (line) of 0-terminated G-Code. The block is assumed to contain only uppercase
|
||||
// characters and signed floating point values (no whitespace). Comments and block delete
|
||||
// characters have been removed. In this function, all units and positions are converted and
|
||||
// exported to grbl's internal functions in terms of (mm, mm/min) and absolute machine
|
||||
// coordinates, respectively.
|
||||
status_code_t gc_execute_block(char *block, char *message)
|
||||
// Remove whitespace, control characters, comments and if block delete is active block delete lines
|
||||
// else the block delete character. Remaining characters are converted to upper case.
|
||||
// If the driver handles message comments then the first is extracted and returned in a dynamically
|
||||
// allocated memory block, the caller must free this after the message has been processed.
|
||||
|
||||
char *gc_normalize_block (char *block, char **message)
|
||||
{
|
||||
char c, *s1, *s2, *comment = NULL;
|
||||
|
||||
// Remove leading whitespace & control characters
|
||||
while(*block && *block <= ' ')
|
||||
block++;
|
||||
|
||||
if(*block == ';' || (*block == '/' && sys.flags.block_delete_enabled)) {
|
||||
*block = '\0';
|
||||
return block;
|
||||
}
|
||||
|
||||
if(*block == '/')
|
||||
block++;
|
||||
|
||||
s1 = s2 = block;
|
||||
|
||||
while((c = *s1) != '\0') {
|
||||
|
||||
if(c > ' ') switch(c) {
|
||||
|
||||
case ';':
|
||||
if(!comment) {
|
||||
*s1 = '\0';
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
|
||||
case '(':
|
||||
// TODO: generate error if a left paranthesis is found inside a comment...
|
||||
comment = s1;
|
||||
break;
|
||||
|
||||
case ')':
|
||||
if(comment && !hal.driver_cap.no_gcode_message_handling) {
|
||||
size_t len = s1 - comment - 4;
|
||||
if(message && *message == NULL && !strncmp(comment, "(MSG,", 5) && (*message = malloc(len))) {
|
||||
*s1 = '\0';
|
||||
memcpy(*message, comment + 5, len);
|
||||
}
|
||||
}
|
||||
comment = NULL;
|
||||
break;
|
||||
|
||||
default:
|
||||
if(comment == NULL)
|
||||
*s2++ = CAPS(c);
|
||||
break;
|
||||
}
|
||||
|
||||
if(comment && s1 - comment < 5)
|
||||
*s1 = CAPS(c);
|
||||
|
||||
s1++;
|
||||
}
|
||||
|
||||
*s2 = '\0';
|
||||
|
||||
return block;
|
||||
}
|
||||
|
||||
#if NGC_EXPRESSIONS_ENABLE
|
||||
|
||||
#define NGC_N_ASSIGN_PARAMETERS_PER_BLOCK 10
|
||||
|
||||
static ngc_param_t ngc_params[NGC_N_ASSIGN_PARAMETERS_PER_BLOCK];
|
||||
|
||||
static status_code_t read_parameter (char *line, uint_fast8_t *char_counter, float *value)
|
||||
{
|
||||
char c = *(line + *char_counter);
|
||||
status_code_t status = Status_OK;
|
||||
|
||||
if(c == '#') {
|
||||
|
||||
(*char_counter)++;
|
||||
|
||||
if(*(line + *char_counter) == '<') {
|
||||
|
||||
(*char_counter)++;
|
||||
char *pos = line + *char_counter;
|
||||
|
||||
while(*line && *line != '>')
|
||||
line++;
|
||||
|
||||
*char_counter += line - pos + 1;
|
||||
|
||||
if(*line == '>') {
|
||||
*line = '\0';
|
||||
if(!ngc_named_param_get(pos, value))
|
||||
status = Status_BadNumberFormat;
|
||||
} else
|
||||
status = Status_BadNumberFormat;
|
||||
|
||||
} else if (read_float(line, char_counter, value)) {
|
||||
if(!ngc_param_get((ngc_param_id_t)*value, value))
|
||||
status = Status_BadNumberFormat;
|
||||
} else
|
||||
status = Status_BadNumberFormat;
|
||||
|
||||
} else if(c == '[')
|
||||
status = ngc_eval_expression(line, char_counter, value);
|
||||
else if(!read_float(line, char_counter, value))
|
||||
*value = NAN;
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
// Parses and executes one block (line) of 0-terminated G-Code.
|
||||
// In this function, all units and positions are converted and exported to internal functions
|
||||
// in terms of (mm, mm/min) and absolute machine coordinates, respectively.
|
||||
|
||||
status_code_t gc_execute_block(char *block)
|
||||
{
|
||||
static const parameter_words_t axis_words_mask = {
|
||||
.x = On,
|
||||
@@ -428,6 +545,22 @@ status_code_t gc_execute_block(char *block, char *message)
|
||||
|
||||
static parser_block_t gc_block;
|
||||
|
||||
#if NGC_EXPRESSIONS_ENABLE
|
||||
uint_fast8_t ngc_param_count = 0;
|
||||
#endif
|
||||
|
||||
char *message = NULL;
|
||||
|
||||
block = gc_normalize_block(block, &message);
|
||||
|
||||
if(block[0] == '\0') {
|
||||
if(message) {
|
||||
report_message(message, Message_Plain);
|
||||
free(message);
|
||||
}
|
||||
return Status_OK;
|
||||
}
|
||||
|
||||
// Determine if the line is a program start/end marker.
|
||||
// Old comment from protocol.c:
|
||||
// NOTE: This maybe installed to tell Grbl when a program is running vs manual input,
|
||||
@@ -436,6 +569,10 @@ status_code_t gc_execute_block(char *block, char *message)
|
||||
// functions that empty the planner buffer to execute its task on-time.
|
||||
if (block[0] == CMD_PROGRAM_DEMARCATION && block[1] == '\0') {
|
||||
gc_state.file_run = !gc_state.file_run;
|
||||
if(message) {
|
||||
report_message(message, Message_Plain);
|
||||
free(message);
|
||||
}
|
||||
return Status_OK;
|
||||
}
|
||||
|
||||
@@ -490,6 +627,64 @@ status_code_t gc_execute_block(char *block, char *message)
|
||||
while ((letter = block[char_counter++]) != '\0') { // Loop until no more g-code words in block.
|
||||
|
||||
// Import the next g-code word, expecting a letter followed by a value. Otherwise, error out.
|
||||
|
||||
#if NGC_EXPRESSIONS_ENABLE
|
||||
|
||||
status_code_t status;
|
||||
|
||||
if(letter == '#') {
|
||||
|
||||
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 = read_parameter(block, &char_counter, &value)) != Status_OK)
|
||||
FAIL(status); // [Expected parameter value]
|
||||
if(!ngc_named_param_set(name, value))
|
||||
FAIL(Status_BadNumberFormat); // [Expected equal sign]
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
float param;
|
||||
if (!read_float(block, &char_counter, ¶m))
|
||||
FAIL(Status_BadNumberFormat); // [Expected parameter number]
|
||||
|
||||
if (block[char_counter++] != '=')
|
||||
FAIL(Status_BadNumberFormat); // [Expected equal sign]
|
||||
|
||||
if((status = read_parameter(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]
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if((letter < 'A') || (letter > 'Z'))
|
||||
FAIL(Status_ExpectedCommandLetter); // [Expected word letter]
|
||||
|
||||
if((status = read_parameter(block, &char_counter, &value)) != Status_OK)
|
||||
return status;
|
||||
|
||||
if(!is_user_mcode && isnanf(value))
|
||||
FAIL(Status_BadNumberFormat); // [Expected word value]
|
||||
|
||||
#else
|
||||
|
||||
if((letter < 'A') || (letter > 'Z'))
|
||||
FAIL(Status_ExpectedCommandLetter); // [Expected word letter]
|
||||
|
||||
@@ -500,6 +695,8 @@ status_code_t gc_execute_block(char *block, char *message)
|
||||
FAIL(Status_BadNumberFormat); // [Expected word value]
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
// Convert values to smaller uint8 significand and mantissa values for parsing this word.
|
||||
// NOTE: Mantissa is multiplied by 100 to catch non-integer command values. This is more
|
||||
// accurate than the NIST gcode requirement of x10 when used for commands, but not quite
|
||||
@@ -805,7 +1002,7 @@ status_code_t gc_execute_block(char *block, char *message)
|
||||
if(!settings.parking.flags.enable_override_control) // TODO: check if enabled?
|
||||
FAIL(Status_GcodeUnsupportedCommand); // [Unsupported M command]
|
||||
// no break;
|
||||
case 49: case 50: case 51: case 53:
|
||||
case 48: case 49: case 50: case 51: case 53:
|
||||
word_bit.modal_group.M9 = On;
|
||||
gc_block.override_command = (override_mode_t)int_value;
|
||||
break;
|
||||
@@ -1309,9 +1506,14 @@ status_code_t gc_execute_block(char *block, char *message)
|
||||
}
|
||||
switch(gc_block.override_command) {
|
||||
|
||||
case Override_FeedSpeed:
|
||||
gc_block.modal.override_ctrl.feed_rate_disable = gc_block.values.p == 0.0f;
|
||||
gc_block.modal.override_ctrl.spindle_rpm_disable = gc_block.values.p == 0.0f;
|
||||
case Override_FeedSpeedEnable:
|
||||
gc_block.modal.override_ctrl.feed_rate_disable = Off;
|
||||
gc_block.modal.override_ctrl.spindle_rpm_disable = Off;
|
||||
break;
|
||||
|
||||
case Override_FeedSpeedDisable:
|
||||
gc_block.modal.override_ctrl.feed_rate_disable = On;
|
||||
gc_block.modal.override_ctrl.spindle_rpm_disable = On;
|
||||
break;
|
||||
|
||||
case Override_FeedRate:
|
||||
@@ -2571,25 +2773,29 @@ status_code_t gc_execute_block(char *block, char *message)
|
||||
break;
|
||||
|
||||
case NonModal_SetCoordinateOffset: // G92
|
||||
gc_state.g92_coord_offset_applied = true; // TODO: check for all zero?
|
||||
memcpy(gc_state.g92_coord_offset, gc_block.values.xyz, sizeof(gc_state.g92_coord_offset));
|
||||
#if COMPATIBILITY_LEVEL <= 1
|
||||
settings_write_coord_data(CoordinateSystem_G92, &gc_state.g92_coord_offset); // Save G92 offsets to non-volatile storage
|
||||
#endif
|
||||
if(!settings.flags.g92_is_volatile)
|
||||
settings_write_coord_data(CoordinateSystem_G92, &gc_state.g92_coord_offset); // Save G92 offsets to non-volatile storage
|
||||
system_flag_wco_change();
|
||||
break;
|
||||
|
||||
case NonModal_ResetCoordinateOffset: // G92.1
|
||||
gc_state.g92_coord_offset_applied = false;
|
||||
clear_vector(gc_state.g92_coord_offset); // Disable G92 offsets by zeroing offset vector.
|
||||
settings_write_coord_data(CoordinateSystem_G92, &gc_state.g92_coord_offset); // Save G92 offsets to non-volatile storage
|
||||
if(!settings.flags.g92_is_volatile)
|
||||
settings_write_coord_data(CoordinateSystem_G92, &gc_state.g92_coord_offset); // Save G92 offsets to non-volatile storage
|
||||
system_flag_wco_change();
|
||||
break;
|
||||
|
||||
case NonModal_ClearCoordinateOffset: // G92.2
|
||||
gc_state.g92_coord_offset_applied = false;
|
||||
clear_vector(gc_state.g92_coord_offset); // Disable G92 offsets by zeroing offset vector.
|
||||
system_flag_wco_change();
|
||||
break;
|
||||
|
||||
case NonModal_RestoreCoordinateOffset: // G92.3
|
||||
gc_state.g92_coord_offset_applied = true; // TODO: check for all zero?
|
||||
settings_read_coord_data(CoordinateSystem_G92, &gc_state.g92_coord_offset); // Restore G92 offsets from non-volatile storage
|
||||
system_flag_wco_change();
|
||||
break;
|
||||
@@ -2804,6 +3010,13 @@ status_code_t gc_execute_block(char *block, char *message)
|
||||
gc_state.modal.program_flow = ProgramFlow_Running; // Reset program flow.
|
||||
}
|
||||
|
||||
#if NGC_EXPRESSIONS_ENABLE
|
||||
if(ngc_param_count) do {
|
||||
ngc_param_count--;
|
||||
ngc_param_set(ngc_params[ngc_param_count].id, ngc_params[ngc_param_count].value);
|
||||
} while(ngc_param_count);
|
||||
#endif
|
||||
|
||||
// TODO: % to denote start of program.
|
||||
|
||||
return Status_OK;
|
||||
|
||||
@@ -167,8 +167,8 @@ typedef enum {
|
||||
Do not alter values!
|
||||
*/
|
||||
typedef enum {
|
||||
SpindleSpeedMode_RPM = 0, //!< 0 - G96 - Default, must be zero
|
||||
SpindleSpeedMode_CSS = 1 //!< 1 - G97
|
||||
SpindleSpeedMode_RPM = 0, //!< 0 - G97 - Default, must be zero
|
||||
SpindleSpeedMode_CSS = 1 //!< 1 - G96
|
||||
} spindle_rpm_mode_t;
|
||||
|
||||
/*! Modal Group M4: Program flow
|
||||
@@ -186,7 +186,8 @@ typedef enum {
|
||||
|
||||
// Modal Group M9: Override control
|
||||
typedef enum {
|
||||
Override_FeedSpeed = 49, //!< 49 - M49
|
||||
Override_FeedSpeedEnable = 48, //!< 48 - M48
|
||||
Override_FeedSpeedDisable = 49, //!< 49 - M49
|
||||
Override_FeedRate = 50, //!< 50 - M50
|
||||
Override_SpindleSpeed = 51, //!< 51 - M51
|
||||
Override_FeedHold = 53, //!< 53 - M53
|
||||
@@ -397,7 +398,7 @@ typedef union {
|
||||
// NOTE: When this struct is zeroed, the above defines set the defaults for the system.
|
||||
typedef struct {
|
||||
motion_mode_t motion; //!< {G0,G1,G2,G3,G38.2,G80}
|
||||
feed_mode_t feed_mode; //!< {G93,G94}
|
||||
feed_mode_t feed_mode; //!< {G93,G94,G95}
|
||||
bool units_imperial; //!< {G20,G21}
|
||||
bool distance_incremental; //!< {G90,G91}
|
||||
bool diameter_mode; //!< {G7,G8} Lathe diameter mode.
|
||||
@@ -496,6 +497,7 @@ typedef struct {
|
||||
bool tool_change;
|
||||
status_code_t last_error; //!< last return value from parser
|
||||
//!< The following variables are not cleared upon warm restart when COMPATIBILITY_LEVEL <= 1
|
||||
bool g92_coord_offset_applied; //!< true when G92 offset applied
|
||||
float g92_coord_offset[N_AXIS]; //!< Retains the G92 coordinate offset (work coordinates) relative to
|
||||
//!< machine zero in mm. Persistent and loaded from non-volatile storage
|
||||
//!< on boot when COMPATIBILITY_LEVEL <= 1
|
||||
@@ -534,8 +536,10 @@ typedef struct {
|
||||
// Initialize the parser
|
||||
void gc_init (void);
|
||||
|
||||
char *gc_normalize_block (char *block, char **message);
|
||||
|
||||
// Execute one block of rs275/ngc/g-code
|
||||
status_code_t gc_execute_block (char *block, char *message);
|
||||
status_code_t gc_execute_block (char *block);
|
||||
|
||||
// Sets g-code parser position in mm. Input in steps. Called by the system abort and hard
|
||||
// limit pull-off routines.
|
||||
|
||||
@@ -34,7 +34,7 @@
|
||||
#else
|
||||
#define GRBL_VERSION "1.1f"
|
||||
#endif
|
||||
#define GRBL_VERSION_BUILD "20210907"
|
||||
#define GRBL_VERSION_BUILD "20210928"
|
||||
|
||||
// The following symbols are set here if not already set by the compiler or in config.h
|
||||
// Do NOT change here!
|
||||
|
||||
@@ -54,7 +54,6 @@ struct system sys = {0}; //!< System global variable structure.
|
||||
grbl_t grbl;
|
||||
grbl_hal_t hal;
|
||||
|
||||
|
||||
#ifdef KINEMATICS_API
|
||||
|
||||
kinematics_t kinematics;
|
||||
@@ -90,11 +89,6 @@ void dummy_bool_handler (bool arg)
|
||||
|
||||
int grbl_enter (void)
|
||||
{
|
||||
#ifdef N_TOOLS
|
||||
assert(NVS_ADDR_GLOBAL + sizeof(settings_t) + NVS_CRC_BYTES < NVS_ADDR_TOOL_TABLE);
|
||||
#else
|
||||
assert(NVS_ADDR_GLOBAL + sizeof(settings_t) + NVS_CRC_BYTES < NVS_ADDR_PARAMETERS);
|
||||
#endif
|
||||
assert(NVS_ADDR_PARAMETERS + N_CoordinateSystems * (sizeof(coord_data_t) + NVS_CRC_BYTES) < NVS_ADDR_STARTUP_BLOCK);
|
||||
assert(NVS_ADDR_STARTUP_BLOCK + N_STARTUP_LINE * (sizeof(stored_line_t) + NVS_CRC_BYTES) < NVS_ADDR_BUILD_INFO);
|
||||
|
||||
@@ -106,6 +100,7 @@ int grbl_enter (void)
|
||||
grbl.enqueue_gcode = protocol_enqueue_gcode;
|
||||
grbl.enqueue_realtime_command = stream_enqueue_realtime_command;
|
||||
grbl.on_report_options = dummy_bool_handler;
|
||||
grbl.on_report_command_help = system_command_help;
|
||||
|
||||
// Clear all and set some HAL function pointers
|
||||
memset(&hal, 0, sizeof(grbl_hal_t));
|
||||
|
||||
+796
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,8 @@
|
||||
/* ngc_expr.h */
|
||||
|
||||
#ifndef _NGC_EXPR_H_
|
||||
#define _NGC_EXPR_H_
|
||||
|
||||
status_code_t ngc_eval_expression (char *line, uint_fast8_t *pos, float *value);
|
||||
|
||||
#endif
|
||||
+662
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
ngc_params.c - get/set NGC parameter value by id or name
|
||||
|
||||
Part of grblHAL
|
||||
|
||||
Copyright (c) 2021 Terje Io
|
||||
|
||||
Grbl is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Grbl is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Grbl. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/*
|
||||
All predefined parameters defined in NIST RS274NGC version 3 (ref section 3.2.1) are implemented.
|
||||
Most additional predefined parameters defined by LinuxCNC (ref section 5.2.3.1) are implemented.
|
||||
Currently it is not possible to set any parameters or reference them from gcode.
|
||||
*/
|
||||
|
||||
#ifndef _NGC_PARAMS_H_
|
||||
#define _NGC_PARAMS_H_
|
||||
|
||||
typedef uint16_t ngc_param_id_t;
|
||||
|
||||
typedef struct {
|
||||
ngc_param_id_t id;
|
||||
float value;
|
||||
} ngc_param_t;
|
||||
|
||||
bool ngc_param_get (ngc_param_id_t id, float *value);
|
||||
bool ngc_param_set (ngc_param_id_t id, float value);
|
||||
bool ngc_param_is_rw (ngc_param_id_t id);
|
||||
bool ngc_param_exists (ngc_param_id_t id);
|
||||
bool ngc_named_param_get (char *name, float *value);
|
||||
bool ngc_named_param_set (char *name, float value);
|
||||
bool ngc_named_param_exists (char *name);
|
||||
|
||||
#endif
|
||||
+5
-1
@@ -39,13 +39,17 @@
|
||||
#define M_PI 3.14159265358979323846f
|
||||
#endif
|
||||
|
||||
#define TOLERANCE_EQUAL 0.0001f
|
||||
|
||||
#define TAN_30 0.57735f // Used for threading calculations (60 degree inserts)
|
||||
#define RADDEG 0.0174532925f // Radians per degree
|
||||
#define DEGRAD 57.29577951f // Degrees per radians
|
||||
|
||||
#define ABORTED (sys.abort || sys.cancel)
|
||||
|
||||
// Convert character to uppercase
|
||||
#define CAPS(c) ((c >= 'a' && c <= 'z') ? c & 0x5F : c)
|
||||
#define CAPS(c) ((c >= 'a' && c <= 'z') ? (c & 0x5F) : c)
|
||||
#define LCAPS(c) ((c >= 'A' && c <= 'Z') ? (c | 0x20) : c)
|
||||
|
||||
#ifndef STM32F103xB
|
||||
#ifndef UNUSED
|
||||
|
||||
@@ -33,7 +33,7 @@ Minimum 1024 bytes required, more if space for driver and/or plugin data and set
|
||||
/*! \brief Number of bytes at the start of the NVS area reserved for core settings and parameters.
|
||||
Minimum 1024 bytes required.
|
||||
*/
|
||||
#define GRBL_NVS_SIZE 1024
|
||||
#define GRBL_NVS_END 1023
|
||||
|
||||
//! Number of bytes used for storing CRC values. Do not change this!
|
||||
#define NVS_CRC_BYTES 1
|
||||
@@ -50,7 +50,10 @@ __NOTE:__ 1024 bytes of persistent storage is the minimum required.
|
||||
#define NVS_ADDR_BUILD_INFO 942U
|
||||
#define NVS_ADDR_STARTUP_BLOCK (NVS_ADDR_BUILD_INFO - 1 - N_STARTUP_LINE * (sizeof(stored_line_t) + NVS_CRC_BYTES))
|
||||
#ifdef N_TOOLS
|
||||
#define NVS_ADDR_TOOL_TABLE (NVS_ADDR_PARAMETERS - 1 - N_TOOLS * (sizeof(tool_data_t) + NVS_CRC_BYTES))
|
||||
#define NVS_ADDR_TOOL_TABLE (GRBL_NVS_END + 1)
|
||||
#define GRBL_NVS_SIZE (GRBL_NVS_END + 1 + N_TOOLS * (sizeof(tool_data_t) + NVS_CRC_BYTES))
|
||||
#else
|
||||
#define GRBL_NVS_SIZE (GRBL_NVS_END + 1)
|
||||
#endif
|
||||
///@}
|
||||
|
||||
|
||||
+36
-23
@@ -32,6 +32,9 @@
|
||||
#include "hal.h"
|
||||
#include "nvs_buffer.h"
|
||||
#include "protocol.h"
|
||||
#include "settings.h"
|
||||
#include "gcode.h"
|
||||
#include "nvs.h"
|
||||
|
||||
static uint8_t *nvsbuffer = NULL;
|
||||
static nvs_io_t physical_nvs;
|
||||
@@ -51,6 +54,7 @@ typedef struct {
|
||||
#define NVS_GROUP_STARTUP 3
|
||||
#define NVS_GROUP_BUILD 4
|
||||
|
||||
|
||||
#define PARAMETER_ADDR(n) (NVS_ADDR_PARAMETERS + n * (sizeof(coord_data_t) + NVS_CRC_BYTES))
|
||||
#define STARTLINE_ADDR(n) (NVS_ADDR_STARTUP_BLOCK + n * (sizeof(stored_line_t) + NVS_CRC_BYTES))
|
||||
#ifdef N_TOOLS
|
||||
@@ -59,19 +63,7 @@ typedef struct {
|
||||
|
||||
static const emap_t target[] = {
|
||||
{NVS_ADDR_GLOBAL, NVS_GROUP_GLOBAL, 0},
|
||||
#ifdef N_TOOLS
|
||||
{TOOL_ADDR(0), NVS_GROUP_TOOLS, 0},
|
||||
{TOOL_ADDR(1), NVS_GROUP_TOOLS, 1},
|
||||
{TOOL_ADDR(2), NVS_GROUP_TOOLS, 2},
|
||||
{TOOL_ADDR(3), NVS_GROUP_TOOLS, 3},
|
||||
{TOOL_ADDR(4), NVS_GROUP_TOOLS, 4},
|
||||
{TOOL_ADDR(5), NVS_GROUP_TOOLS, 5},
|
||||
{TOOL_ADDR(6), NVS_GROUP_TOOLS, 6},
|
||||
{TOOL_ADDR(7), NVS_GROUP_TOOLS, 7},
|
||||
#if N_TOOLS > 8
|
||||
#error Increase number of tool entries!
|
||||
#endif
|
||||
#endif
|
||||
|
||||
{PARAMETER_ADDR(0), NVS_GROUP_PARAMETERS, 0},
|
||||
{PARAMETER_ADDR(1), NVS_GROUP_PARAMETERS, 1},
|
||||
{PARAMETER_ADDR(2), NVS_GROUP_PARAMETERS, 2},
|
||||
@@ -90,6 +82,29 @@ static const emap_t target[] = {
|
||||
#error Increase number of startup line entries!
|
||||
#endif
|
||||
{NVS_ADDR_BUILD_INFO, NVS_GROUP_BUILD, 0},
|
||||
#ifdef N_TOOLS
|
||||
{TOOL_ADDR(0), NVS_GROUP_TOOLS, 0},
|
||||
{TOOL_ADDR(1), NVS_GROUP_TOOLS, 1},
|
||||
{TOOL_ADDR(2), NVS_GROUP_TOOLS, 2},
|
||||
{TOOL_ADDR(3), NVS_GROUP_TOOLS, 3},
|
||||
{TOOL_ADDR(4), NVS_GROUP_TOOLS, 4},
|
||||
{TOOL_ADDR(5), NVS_GROUP_TOOLS, 5},
|
||||
{TOOL_ADDR(6), NVS_GROUP_TOOLS, 6},
|
||||
{TOOL_ADDR(7), NVS_GROUP_TOOLS, 7},
|
||||
#if N_TOOLS > 8
|
||||
{TOOL_ADDR(8), NVS_GROUP_TOOLS, 8},
|
||||
{TOOL_ADDR(9), NVS_GROUP_TOOLS, 9},
|
||||
{TOOL_ADDR(10), NVS_GROUP_TOOLS, 10},
|
||||
{TOOL_ADDR(11), NVS_GROUP_TOOLS, 11},
|
||||
{TOOL_ADDR(12), NVS_GROUP_TOOLS, 12},
|
||||
{TOOL_ADDR(13), NVS_GROUP_TOOLS, 13},
|
||||
{TOOL_ADDR(14), NVS_GROUP_TOOLS, 14},
|
||||
{TOOL_ADDR(15), NVS_GROUP_TOOLS, 15},
|
||||
#endif
|
||||
#if N_TOOLS > 16
|
||||
#error Increase number of tool entries!
|
||||
#endif
|
||||
#endif
|
||||
{0, 0, 0} // list termination - do not remove
|
||||
};
|
||||
|
||||
@@ -106,8 +121,6 @@ inline static void ram_put_byte (uint32_t addr, uint8_t new_value)
|
||||
nvsbuffer[addr] = new_value;
|
||||
}
|
||||
|
||||
// Extensions added as part of Grbl
|
||||
|
||||
static nvs_transfer_result_t memcpy_to_ram (uint32_t destination, uint8_t *source, uint32_t size, bool with_checksum)
|
||||
{
|
||||
if(hal.nvs.driver_area.address && destination > hal.nvs.driver_area.address + hal.nvs.driver_area.size)
|
||||
@@ -373,14 +386,6 @@ void nvs_memmap (void)
|
||||
strcat(buf, uitoa(sizeof(settings_t) + NVS_CRC_BYTES));
|
||||
report_message(buf, Message_Plain);
|
||||
|
||||
#ifdef N_TOOLS
|
||||
strcpy(buf, "Tool table: ");
|
||||
strcat(buf, uitoa(NVS_ADDR_TOOL_TABLE));
|
||||
strcat(buf, " ");
|
||||
strcat(buf, uitoa(N_TOOLS * (sizeof(tool_data_t) + NVS_CRC_BYTES)));
|
||||
report_message(buf, Message_Plain);
|
||||
#endif
|
||||
|
||||
strcpy(buf, "Parameters: ");
|
||||
strcat(buf, uitoa(NVS_ADDR_PARAMETERS));
|
||||
strcat(buf, " ");
|
||||
@@ -399,6 +404,14 @@ void nvs_memmap (void)
|
||||
strcat(buf, uitoa(sizeof(stored_line_t) + NVS_CRC_BYTES));
|
||||
report_message(buf, Message_Plain);
|
||||
|
||||
#ifdef N_TOOLS
|
||||
strcpy(buf, "Tool table: ");
|
||||
strcat(buf, uitoa(NVS_ADDR_TOOL_TABLE));
|
||||
strcat(buf, " ");
|
||||
strcat(buf, uitoa(N_TOOLS * (sizeof(tool_data_t) + NVS_CRC_BYTES)));
|
||||
report_message(buf, Message_Plain);
|
||||
#endif
|
||||
|
||||
strcpy(buf, "Driver: ");
|
||||
strcat(buf, uitoa(hal.nvs.driver_area.address));
|
||||
strcat(buf, " ");
|
||||
|
||||
@@ -34,8 +34,12 @@ typedef struct {
|
||||
uint8_t startup_lines;
|
||||
uint16_t coord_data;
|
||||
#ifdef N_TOOLS
|
||||
#if N_TOOLS > 16
|
||||
uint32_t tool_data;
|
||||
#else
|
||||
uint16_t tool_data;
|
||||
#endif
|
||||
#endif
|
||||
} settings_dirty_t;
|
||||
|
||||
extern settings_dirty_t settings_dirty;
|
||||
|
||||
+27
-74
@@ -45,18 +45,10 @@ typedef union {
|
||||
uint8_t overflow :1,
|
||||
comment_parentheses :1,
|
||||
comment_semicolon :1,
|
||||
block_delete :1,
|
||||
unassigned :4;
|
||||
unassigned :5;
|
||||
};
|
||||
} line_flags_t;
|
||||
|
||||
typedef struct {
|
||||
char *message;
|
||||
uint_fast8_t idx;
|
||||
uint_fast8_t tracker;
|
||||
bool show;
|
||||
} user_message_t;
|
||||
|
||||
typedef struct {
|
||||
volatile uint_fast8_t head;
|
||||
volatile uint_fast8_t tail;
|
||||
@@ -67,8 +59,6 @@ static uint_fast16_t char_counter = 0;
|
||||
static char line[LINE_BUFFER_SIZE]; // Line to be executed. Zero-terminated.
|
||||
static char xcommand[LINE_BUFFER_SIZE];
|
||||
static bool keep_rt_commands = false;
|
||||
static user_message_t user_message = {NULL, 0, 0, false};
|
||||
static const char *msg = "(MSG,";
|
||||
static realtime_queue_t realtime_queue = {0};
|
||||
|
||||
static void protocol_exec_rt_suspend ();
|
||||
@@ -163,10 +153,9 @@ bool protocol_main_loop (void)
|
||||
int16_t c;
|
||||
char eol = '\0';
|
||||
line_flags_t line_flags = {0};
|
||||
bool nocaps = false, line_is_comment = false;
|
||||
|
||||
xcommand[0] = '\0';
|
||||
user_message.show = keep_rt_commands = false;
|
||||
keep_rt_commands = false;
|
||||
|
||||
while(true) {
|
||||
|
||||
@@ -177,7 +166,7 @@ bool protocol_main_loop (void)
|
||||
if(c == ASCII_CAN) {
|
||||
|
||||
eol = xcommand[0] = '\0';
|
||||
keep_rt_commands = nocaps = line_is_comment = user_message.show = false;
|
||||
keep_rt_commands = false;
|
||||
char_counter = line_flags.value = 0;
|
||||
gc_state.last_error = Status_OK;
|
||||
|
||||
@@ -206,7 +195,7 @@ bool protocol_main_loop (void)
|
||||
// Direct and execute one line of formatted input, and report status of execution.
|
||||
if (line_flags.overflow) // Report line overflow error.
|
||||
gc_state.last_error = Status_Overflow;
|
||||
else if ((line[0] == '\0' || char_counter == 0) && !user_message.show && !line_is_comment) // Empty or comment line. For syncing purposes.
|
||||
else if(line[0] == '\0') // Empty line. For syncing purposes.
|
||||
gc_state.last_error = Status_OK;
|
||||
else if (line[0] == '$') {// Grbl '$' system command
|
||||
if((gc_state.last_error = system_execute_line(line)) == Status_LimitsEngaged) {
|
||||
@@ -223,7 +212,7 @@ bool protocol_main_loop (void)
|
||||
else { // Parse and execute g-code block.
|
||||
|
||||
#endif
|
||||
gc_state.last_error = gc_execute_block(line, user_message.show ? user_message.message : NULL);
|
||||
gc_state.last_error = gc_execute_block(line);
|
||||
}
|
||||
|
||||
// Add a short delay for each block processed in Check Mode to
|
||||
@@ -238,74 +227,39 @@ bool protocol_main_loop (void)
|
||||
grbl.report.status_message(gc_state.last_error);
|
||||
|
||||
// Reset tracking data for next line.
|
||||
keep_rt_commands = nocaps = user_message.show = false;
|
||||
keep_rt_commands = false;
|
||||
char_counter = line_flags.value = 0;
|
||||
|
||||
} else if (c <= (nocaps ? ' ' - 1 : ' ') || line_flags.value) {
|
||||
// Throw away all whitepace, control characters, comment characters and overflow characters.
|
||||
if(c >= ' ' && line_flags.comment_parentheses) {
|
||||
if(user_message.tracker == 5)
|
||||
user_message.message[user_message.idx++] = c == ')' ? '\0' : c;
|
||||
else if(user_message.tracker > 0 && CAPS(c) == msg[user_message.tracker])
|
||||
user_message.tracker++;
|
||||
else
|
||||
user_message.tracker = 0;
|
||||
if (c == ')') {
|
||||
// End of '()' comment. Resume line.
|
||||
line_flags.comment_parentheses = Off;
|
||||
keep_rt_commands = false;
|
||||
user_message.show = user_message.show || user_message.tracker == 5;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
} else if (c <= (char_counter > 0 ? ' ' - 1 : ' '))
|
||||
continue; // Strip control characters and leading whitespace.
|
||||
else {
|
||||
switch(c) {
|
||||
|
||||
case '/':
|
||||
if(char_counter == 0)
|
||||
line_flags.block_delete = sys.flags.block_delete_enabled;
|
||||
break;
|
||||
|
||||
case '$':
|
||||
case '[':
|
||||
// Do not uppercase system or user commands - will destroy passwords etc...
|
||||
if(char_counter == 0)
|
||||
nocaps = keep_rt_commands = true;
|
||||
keep_rt_commands = true;
|
||||
break;
|
||||
|
||||
case '(':
|
||||
if(char_counter == 0)
|
||||
line_is_comment = On;
|
||||
if(!keep_rt_commands) {
|
||||
// Enable comments flag and ignore all characters until ')' or EOL unless it is a message.
|
||||
// NOTE: This doesn't follow the NIST definition exactly, but is good enough for now.
|
||||
// In the future, we could simply remove the items within the comments, but retain the
|
||||
// comment control characters, so that the g-code parser can error-check it.
|
||||
if((line_flags.comment_parentheses = !line_flags.comment_semicolon)) {
|
||||
if(!hal.driver_cap.no_gcode_message_handling) {
|
||||
if(user_message.message == NULL)
|
||||
user_message.message = malloc(LINE_BUFFER_SIZE);
|
||||
if(user_message.message) {
|
||||
user_message.idx = 0;
|
||||
user_message.tracker = 1;
|
||||
}
|
||||
}
|
||||
keep_rt_commands = true;
|
||||
}
|
||||
}
|
||||
if(!keep_rt_commands && (line_flags.comment_parentheses = !line_flags.comment_semicolon))
|
||||
keep_rt_commands = !hal.driver_cap.no_gcode_message_handling; // Suspend real-time processing of printable command characters.
|
||||
break;
|
||||
|
||||
case ')':
|
||||
if(!line_flags.comment_semicolon)
|
||||
line_flags.comment_parentheses = keep_rt_commands = false;
|
||||
break;
|
||||
|
||||
case ';':
|
||||
if(char_counter == 0)
|
||||
line_is_comment = On;
|
||||
// NOTE: ';' comment to EOL is a LinuxCNC definition. Not NIST.
|
||||
if(!keep_rt_commands) {
|
||||
if((line_flags.comment_semicolon = !line_flags.comment_parentheses))
|
||||
keep_rt_commands = true;
|
||||
if(!line_flags.comment_parentheses) {
|
||||
keep_rt_commands = false;
|
||||
line_flags.comment_semicolon = On;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (line_flags.value == 0 && !(line_flags.overflow = char_counter >= (LINE_BUFFER_SIZE - 1)))
|
||||
line[char_counter++] = nocaps ? c : CAPS(c);
|
||||
if(!(line_flags.overflow = char_counter >= (LINE_BUFFER_SIZE - 1)))
|
||||
line[char_counter++] = c;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -317,7 +271,7 @@ bool protocol_main_loop (void)
|
||||
else if (state_get() & (STATE_ALARM|STATE_ESTOP|STATE_JOG)) // Everything else is gcode. Block if in alarm, eStop or jog state.
|
||||
grbl.report.status_message(Status_SystemGClock);
|
||||
else // Parse and execute g-code block.
|
||||
gc_execute_block(xcommand, NULL);
|
||||
gc_execute_block(xcommand);
|
||||
|
||||
xcommand[0] = '\0';
|
||||
}
|
||||
@@ -518,7 +472,7 @@ bool protocol_exec_rt_system (void)
|
||||
sync_position();
|
||||
flush_override_buffers();
|
||||
if(!((state_get() == STATE_ALARM) && (sys.alarm == Alarm_LimitsEngaged || sys.alarm == Alarm_HomingRequried)))
|
||||
state_set(STATE_IDLE);
|
||||
state_set(hal.control.get_state().safety_door_ajar ? STATE_SAFETY_DOOR : STATE_IDLE);
|
||||
}
|
||||
|
||||
// Execute and print status to output stream
|
||||
@@ -700,9 +654,9 @@ static void protocol_exec_rt_suspend (void)
|
||||
// Handle spindle overrides during suspend
|
||||
state_suspend_manager();
|
||||
|
||||
// If door closed keep issuing cycle start requests until resumed
|
||||
// If door closed keep issuing door closed requests until resumed
|
||||
if(state_get() == STATE_SAFETY_DOOR && !hal.control.get_state().safety_door_ajar)
|
||||
system_set_exec_state_flag(EXEC_CYCLE_START);
|
||||
system_set_exec_state_flag(EXEC_DOOR_CLOSED);
|
||||
|
||||
// Check for sleep conditions and execute auto-park, if timeout duration elapses.
|
||||
// Sleep is valid for both hold and door states, if the spindle or coolant are on or
|
||||
@@ -783,7 +737,7 @@ ISR_CODE bool protocol_enqueue_realtime_command (char c)
|
||||
break;
|
||||
|
||||
case CMD_SAFETY_DOOR:
|
||||
if(!hal.signals_cap.safety_door_ajar) {
|
||||
if(state_get() != STATE_SAFETY_DOOR) {
|
||||
system_set_exec_state_flag(EXEC_SAFETY_DOOR);
|
||||
drop = true;
|
||||
}
|
||||
@@ -933,4 +887,3 @@ void protocol_execute_noop (sys_state_t state)
|
||||
{
|
||||
(void)state;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
// regex.c - A Regular Expression Matcher
|
||||
//
|
||||
// Code by Rob Pike, exegesis by Brian Kernighan
|
||||
//
|
||||
// http://genius.cat-v.org/brian-kernighan/articles/beautiful
|
||||
//
|
||||
// c matches any literal character c
|
||||
// . matches any single character
|
||||
// ^ matches the beginning of the input string
|
||||
// $ matches the end of the input string
|
||||
// * matches zero or more occurrences of the previous character
|
||||
|
||||
#include "regex.h"
|
||||
|
||||
/* match: search for regexp anywhere in text */
|
||||
int match(char *regexp, char *text)
|
||||
{
|
||||
if (regexp[0] == '^')
|
||||
return matchhere(regexp+1, text);
|
||||
do { /* must look even if string is empty */
|
||||
if (matchhere(regexp, text))
|
||||
return 1;
|
||||
} while (*text++ != '\0');
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* matchhere: search for regexp at beginning of text */
|
||||
int matchhere(char *regexp, char *text)
|
||||
{
|
||||
if (regexp[0] == '\0')
|
||||
return 1;
|
||||
if (regexp[1] == '*')
|
||||
return matchstar(regexp[0], regexp+2, text);
|
||||
if (regexp[0] == '$' && regexp[1] == '\0')
|
||||
return *text == '\0';
|
||||
if (*text!='\0' && (regexp[0]=='.' || regexp[0]==*text))
|
||||
return matchhere(regexp+1, text+1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* matchstar: search for c*regexp at beginning of text */
|
||||
int matchstar(int c, char *regexp, char *text)
|
||||
{
|
||||
do { /* a * matches zero or more instances */
|
||||
if (matchhere(regexp, text))
|
||||
return 1;
|
||||
} while (*text != '\0' && (*text++ == c || c == '.'));
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
// regex.h - A Regular Expression Matcher
|
||||
//
|
||||
// Code by Rob Pike, exegesis by Brian Kernighan
|
||||
//
|
||||
// http://genius.cat-v.org/brian-kernighan/articles/beautiful
|
||||
//
|
||||
// c matches any literal character c
|
||||
// . matches any single character
|
||||
// ^ matches the beginning of the input string
|
||||
// $ matches the end of the input string
|
||||
// * matches zero or more occurrences of the previous character
|
||||
|
||||
#pragma once
|
||||
|
||||
/* match: search for regexp anywhere in text */
|
||||
int match(char *regexp, char *text);
|
||||
|
||||
/* matchhere: search for regexp at beginning of text */
|
||||
int matchhere(char *regexp, char *text);
|
||||
|
||||
/* matchstar: search for c*regexp at beginning of text */
|
||||
int matchstar(int c, char *regexp, char *text);
|
||||
@@ -38,6 +38,7 @@
|
||||
#include "nvs_buffer.h"
|
||||
#include "limits.h"
|
||||
#include "state_machine.h"
|
||||
#include "regex.h"
|
||||
|
||||
#ifdef ENABLE_SPINDLE_LINEARIZATION
|
||||
#include <stdio.h>
|
||||
@@ -353,88 +354,82 @@ void report_grbl_help (void)
|
||||
hal.stream.write("[HLP:$$ $# $G $I $N $x=val $Nx=line $J=line $SLP $C $X $H $B ~ ! ? ctrl-x]" ASCII_EOL);
|
||||
}
|
||||
|
||||
#define CAPS(c) ((c >= 'a' && c <= 'z') ? c & 0x5F : c)
|
||||
|
||||
static void report_group_settings (const setting_group_detail_t *groups, const uint_fast8_t n_groups, char *lcargs)
|
||||
static bool report_group_settings (const setting_group_detail_t *groups, const uint_fast8_t n_groups, char *args)
|
||||
{
|
||||
bool found = false;
|
||||
uint_fast8_t idx;
|
||||
uint_fast8_t len = strlen(lcargs);
|
||||
char c, *s, group[25];
|
||||
|
||||
for(idx = 0; idx < n_groups; idx++) {
|
||||
if(strlen(groups[idx].name) == len) {
|
||||
char *s1 = lcargs, *s2 = (char *)groups[idx].name;
|
||||
while(*s1 && CAPS(*s1) == CAPS(*s2)) {
|
||||
s1++;
|
||||
s2++;
|
||||
}
|
||||
if(*s1 == '\0') {
|
||||
report_settings_details(SettingsFormat_HumanReadable, Setting_SettingsAll, groups[idx].id);
|
||||
break;
|
||||
}
|
||||
|
||||
s = group;
|
||||
strncpy(group, groups[idx].name, sizeof(group));
|
||||
|
||||
// Uppercase group name
|
||||
while((c = *s))
|
||||
*s++ = CAPS(c);
|
||||
|
||||
if((found = matchhere(args, group))) {
|
||||
hal.stream.write(ASCII_EOL "---- ");
|
||||
hal.stream.write(groups[idx].name);
|
||||
hal.stream.write(":" ASCII_EOL);
|
||||
report_settings_details(SettingsFormat_HumanReadable, Setting_SettingsAll, groups[idx].id);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return found;
|
||||
}
|
||||
|
||||
status_code_t report_help (char *args, char *lcargs)
|
||||
status_code_t report_help (char *args)
|
||||
{
|
||||
setting_details_t *settings_info = settings_get_details();
|
||||
|
||||
// Strip leading spaces
|
||||
while(*args == ' ')
|
||||
args++;
|
||||
|
||||
if(*args == '\0') {
|
||||
|
||||
hal.stream.write("Help arguments:" ASCII_EOL);
|
||||
hal.stream.write("Help topics:" ASCII_EOL);
|
||||
hal.stream.write(" Commands" ASCII_EOL);
|
||||
hal.stream.write(" Settings" ASCII_EOL);
|
||||
report_setting_group_details(false, " ");
|
||||
|
||||
} else {
|
||||
if(!strncmp(args, "COMMANDS", 8)) {
|
||||
hal.stream.write("$I - list system information" ASCII_EOL);
|
||||
hal.stream.write("$$ - list settings" ASCII_EOL);
|
||||
hal.stream.write("$# - list offsets, tool table, probing and home position" ASCII_EOL);
|
||||
hal.stream.write("$G - list parser state" ASCII_EOL);
|
||||
hal.stream.write("$N - list startup lines" ASCII_EOL);
|
||||
if(settings.homing.flags.enabled)
|
||||
hal.stream.write("$H - home configured axes" ASCII_EOL);
|
||||
if(settings.homing.flags.single_axis_commands)
|
||||
hal.stream.write("$H<axisletter> - home single axis" ASCII_EOL);
|
||||
hal.stream.write("$X - unlock machine" ASCII_EOL);
|
||||
hal.stream.write("$SLP - enter sleep mode" ASCII_EOL);
|
||||
hal.stream.write("$HELP <arg> - help" ASCII_EOL);
|
||||
hal.stream.write("$RST=* - restore/reset all" ASCII_EOL);
|
||||
hal.stream.write("$RST=$ - restore default settings" ASCII_EOL);
|
||||
if(settings_info->on_get_settings)
|
||||
hal.stream.write("$RST=& - restore driver and plugin default settings" ASCII_EOL);
|
||||
#ifdef N_TOOLS
|
||||
hal.stream.write("$RST=# - reset offsets and tool data" ASCII_EOL);
|
||||
#else
|
||||
hal.stream.write("$RST=# - reset offsets" ASCII_EOL);
|
||||
#endif
|
||||
|
||||
char c, *s = args;
|
||||
|
||||
// Upper case argument
|
||||
while((c = *s))
|
||||
*s++ = CAPS(c);
|
||||
|
||||
if(matchhere(args, "COMMANDS")) {
|
||||
if(grbl.on_report_command_help)
|
||||
grbl.on_report_command_help();
|
||||
} else if(!strncmp(args, "SETTINGS", 8))
|
||||
|
||||
} else if(matchhere(args, "SETTINGS"))
|
||||
report_settings_details(SettingsFormat_HumanReadable, Setting_SettingsAll, Group_All);
|
||||
|
||||
else {
|
||||
|
||||
// Strip leading spaces from lowercase version
|
||||
while(*lcargs == ' ')
|
||||
lcargs++;
|
||||
bool found = false;
|
||||
setting_details_t *settings_info = settings_get_details();
|
||||
|
||||
report_group_settings(settings_info->groups, settings_info->n_groups, lcargs);
|
||||
found = report_group_settings(settings_info->groups, settings_info->n_groups, args);
|
||||
|
||||
if(grbl.on_get_settings) {
|
||||
if(!found && grbl.on_get_settings) {
|
||||
|
||||
on_get_settings_ptr on_get_settings = grbl.on_get_settings;
|
||||
|
||||
while(on_get_settings) {
|
||||
settings_info = on_get_settings();
|
||||
if(settings_info->groups)
|
||||
report_group_settings(settings_info->groups, settings_info->n_groups, lcargs);
|
||||
if(settings_info->groups && (found = report_group_settings(settings_info->groups, settings_info->n_groups, args)))
|
||||
break;
|
||||
on_get_settings = settings_info->on_get_settings;
|
||||
}
|
||||
}
|
||||
|
||||
if(!found)
|
||||
hal.stream.write( ASCII_EOL "N/A" ASCII_EOL);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -579,6 +574,41 @@ void report_tool_offsets (void)
|
||||
hal.stream.write("]" ASCII_EOL);
|
||||
}
|
||||
|
||||
// Prints NIST/LinuxCNC NGC parameter value
|
||||
status_code_t report_ngc_parameter (ngc_param_id_t id)
|
||||
{
|
||||
float value;
|
||||
|
||||
hal.stream.write("[PARAM:");
|
||||
hal.stream.write(uitoa(id));
|
||||
if(ngc_param_get(id, &value)) {
|
||||
hal.stream.write("=");
|
||||
hal.stream.write(ftoa(value, 3));
|
||||
} else
|
||||
hal.stream.write("=N/A");
|
||||
hal.stream.write("]" ASCII_EOL);
|
||||
|
||||
return Status_OK;
|
||||
}
|
||||
|
||||
// Prints named LinuxCNC NGC parameter value
|
||||
status_code_t report_named_ngc_parameter (char *arg)
|
||||
{
|
||||
float value;
|
||||
|
||||
hal.stream.write("[PARAM:");
|
||||
hal.stream.write(arg);
|
||||
if(ngc_named_param_get(arg, &value)) {
|
||||
hal.stream.write("=");
|
||||
hal.stream.write(ftoa(value, 3));
|
||||
} else
|
||||
hal.stream.write("=N/A");
|
||||
hal.stream.write("]" ASCII_EOL);
|
||||
|
||||
return Status_OK;
|
||||
}
|
||||
|
||||
|
||||
// Prints Grbl NGC parameters (coordinate offsets, probing, tool table)
|
||||
void report_ngc_parameters (void)
|
||||
{
|
||||
@@ -942,6 +972,10 @@ void report_build_info (char *line, bool extended)
|
||||
if(settings.mode == Mode_Lathe)
|
||||
strcat(buf, "LATHE,");
|
||||
|
||||
#if NGC_EXPRESSIONS_ENABLE
|
||||
strcat(buf, "EXPR,");
|
||||
#endif
|
||||
|
||||
#ifdef N_TOOLS
|
||||
if(hal.driver_cap.atc && hal.tool.change)
|
||||
strcat(buf, "ATC,");
|
||||
@@ -1395,7 +1429,7 @@ static void report_settings_detail (settings_format_t format, const setting_deta
|
||||
switch(format)
|
||||
{
|
||||
case SettingsFormat_HumanReadable:
|
||||
hal.stream.write("$");
|
||||
hal.stream.write(ASCII_EOL "$");
|
||||
hal.stream.write(uitoa(setting->id + offset));
|
||||
hal.stream.write(": ");
|
||||
if(setting->group == Group_Axis0)
|
||||
@@ -1454,6 +1488,26 @@ static void report_settings_detail (settings_format_t format, const setting_deta
|
||||
hal.stream.write(setting->max_value);
|
||||
}
|
||||
}
|
||||
#ifndef NO_SETTINGS_DESCRIPTIONS
|
||||
// Add description if driver is capable of outputting it...
|
||||
if(hal.stream.write_n) {
|
||||
const char *description = setting_get_description(setting->id);
|
||||
if(description && *description != '\0') {
|
||||
char *lf;
|
||||
hal.stream.write(ASCII_EOL);
|
||||
if((lf = strstr(description, "\\n"))) while(lf) {
|
||||
hal.stream.write(ASCII_EOL);
|
||||
hal.stream.write_n(description, lf - description);
|
||||
description = lf + 2;
|
||||
lf = strstr(description, "\\n");
|
||||
}
|
||||
if(*description != '\0') {
|
||||
hal.stream.write(ASCII_EOL);
|
||||
hal.stream.write(description);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
|
||||
case SettingsFormat_MachineReadable:
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
#define _REPORT_H_
|
||||
|
||||
#include "system.h"
|
||||
#include "ngc_params.h"
|
||||
|
||||
// Message types for uncoded messages
|
||||
typedef enum {
|
||||
@@ -59,7 +60,7 @@ message_code_t report_feedback_message (message_code_t message_code);
|
||||
void report_init_message (void);
|
||||
|
||||
// Prints Grbl help.
|
||||
status_code_t report_help (char *args, char *lcargs);
|
||||
status_code_t report_help (char *args);
|
||||
void report_grbl_help();
|
||||
|
||||
// Prints Grbl settings
|
||||
@@ -80,6 +81,12 @@ void report_probe_parameters (void);
|
||||
// Prints current tool offsets.
|
||||
void report_tool_offsets (void);
|
||||
|
||||
// Prints NIST/LinuxCNC NGC parameter value
|
||||
status_code_t report_ngc_parameter (ngc_param_id_t id);
|
||||
|
||||
// Prints named LinuxCNC NGC parameter value
|
||||
status_code_t report_named_ngc_parameter (char *arg);
|
||||
|
||||
// Prints Grbl NGC parameters (coordinate offsets, probe).
|
||||
void report_ngc_parameters (void);
|
||||
|
||||
|
||||
+33
-1
@@ -77,6 +77,11 @@ PROGMEM const settings_t defaults = {
|
||||
.flags.legacy_rt_commands = DEFAULT_LEGACY_RTCOMMANDS,
|
||||
.flags.report_inches = DEFAULT_REPORT_INCHES,
|
||||
.flags.sleep_enable = DEFAULT_SLEEP_ENABLE,
|
||||
#if DISABLE_G92_PERSISTENCE
|
||||
.flags.g92_is_volatile = 1,
|
||||
#else
|
||||
.flags.g92_is_volatile = 0,
|
||||
#endif
|
||||
#if DEFAULT_LASER_MODE
|
||||
.mode = Mode_Laser,
|
||||
.flags.disable_laser_during_hold = DEFAULT_ENABLE_LASER_DURING_HOLD,
|
||||
@@ -355,10 +360,14 @@ static status_code_t set_rotational_axes (setting_id_t id, uint_fast16_t int_val
|
||||
static status_code_t set_limits_invert_mask (setting_id_t id, uint_fast16_t int_value);
|
||||
#endif
|
||||
static status_code_t set_axis_setting (setting_id_t setting, float value);
|
||||
#if COMPATIBILITY_LEVEL <= 1
|
||||
static status_code_t set_g92_disable_persistence (setting_id_t id, uint_fast16_t int_value);
|
||||
#endif
|
||||
static float get_float (setting_id_t setting);
|
||||
static uint32_t get_int (setting_id_t id);
|
||||
static bool is_setting_available (const setting_detail_t *setting);
|
||||
|
||||
|
||||
static char control_signals[] = "Reset,Feed hold,Cycle start,Safety door,Block delete,Optional stop,EStop,Probe connected,Motor fault";
|
||||
static char spindle_signals[] = "Spindle enable,Spindle direction,PWM";
|
||||
static char coolant_signals[] = "Flood,Mist";
|
||||
@@ -481,6 +490,9 @@ PROGMEM static const setting_detail_t setting_detail[] = {
|
||||
{ Setting_DualAxisLengthFailPercent, Group_Limits_DualAxis, "Dual axis length fail", "percent", Format_Decimal, "##0.0", "0", "100", Setting_IsExtended, &settings.homing.dual_axis.fail_length_percent, NULL, NULL },
|
||||
{ Setting_DualAxisLengthFailMin, Group_Limits_DualAxis, "Dual axis length fail min", "mm", Format_Decimal, "#####0.000", NULL, NULL, Setting_IsExtended, &settings.homing.dual_axis.fail_distance_min, NULL, NULL },
|
||||
{ Setting_DualAxisLengthFailMax, Group_Limits_DualAxis, "Dual axis length fail max", "mm", Format_Decimal, "#####0.000", NULL, NULL, Setting_IsExtended, &settings.homing.dual_axis.fail_distance_max, NULL, NULL },
|
||||
#if COMPATIBILITY_LEVEL <= 1
|
||||
{ Setting_DisableG92Persistence, Group_General, "Disable G92 persistence", NULL, Format_Bool, NULL, NULL, NULL, Setting_IsExtendedFn, set_g92_disable_persistence, get_int, NULL },
|
||||
#endif
|
||||
#if N_AXIS == 4
|
||||
{ Settings_Axis_Rotational, Group_Stepper, "Rotational axes", NULL, Format_Bitfield, "A-Axis", NULL, NULL, Setting_IsExtendedFn, set_rotational_axes, get_int, NULL }
|
||||
#elif N_AXIS == 5
|
||||
@@ -612,7 +624,10 @@ PROGMEM static const setting_descr_t setting_descr[] = {
|
||||
{ Setting_ToolChangePulloffRate, "Pull-off rate for the retract move before the slower locating phase." },
|
||||
{ Setting_DualAxisLengthFailPercent, "Dual axis length fail in percent of axis max travel." },
|
||||
{ Setting_DualAxisLengthFailMin, "Dual axis length fail minimum distance." },
|
||||
{ Setting_DualAxisLengthFailMax, "Dual axis length fail minimum distance." }
|
||||
{ Setting_DualAxisLengthFailMax, "Dual axis length fail minimum distance." },
|
||||
#if COMPATIBILITY_LEVEL <= 1
|
||||
{ Setting_DisableG92Persistence, "Disables save/restore of G92 offset to non-volatile storage (NVS)." },
|
||||
#endif
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -900,6 +915,15 @@ static status_code_t set_hold_actions (setting_id_t id, uint_fast16_t int_value)
|
||||
return Status_OK;
|
||||
}
|
||||
|
||||
#if COMPATIBILITY_LEVEL <= 1
|
||||
static status_code_t set_g92_disable_persistence (setting_id_t id, uint_fast16_t int_value)
|
||||
{
|
||||
settings.flags.g92_is_volatile = int_value != 0;
|
||||
|
||||
return Status_OK;
|
||||
}
|
||||
#endif
|
||||
|
||||
static status_code_t set_force_initialization_alarm (setting_id_t id, uint_fast16_t int_value)
|
||||
{
|
||||
settings.flags.force_initialization_alarm = int_value != 0;
|
||||
@@ -1231,6 +1255,10 @@ static uint32_t get_int (setting_id_t id)
|
||||
value = settings.tool_change.mode;
|
||||
break;
|
||||
|
||||
case Setting_DisableG92Persistence:
|
||||
value = settings.flags.g92_is_volatile;
|
||||
break;
|
||||
|
||||
#if N_AXIS > 3
|
||||
case Settings_Axis_Rotational:
|
||||
value = (settings.steppers.is_rotational.mask & AXES_BITMASK) >> 3;
|
||||
@@ -1475,6 +1503,10 @@ bool read_global_settings ()
|
||||
if(settings.mode == Mode_Laser && !hal.driver_cap.variable_spindle)
|
||||
settings.mode = Mode_Standard;
|
||||
|
||||
#if COMPATIBILITY_LEVEL > 1 && DISABLE_G92_PERSISTENCE
|
||||
settings.flags.g92_is_volatile = On;
|
||||
#endif
|
||||
|
||||
return ok && settings.version == SETTINGS_VERSION;
|
||||
}
|
||||
|
||||
|
||||
+20
-2
@@ -31,7 +31,7 @@
|
||||
// Version of the persistent storage data. Will be used to migrate existing data from older versions of Grbl
|
||||
// when firmware is upgraded. Always stored in byte 0 of non-volatile storage
|
||||
|
||||
// TODO: add ftp port to network settings
|
||||
// TODO: add ftp port to network settings, enable safety_door settings
|
||||
|
||||
#if N_AXIS > 3 // TODO: remove on next version update
|
||||
#define SETTINGS_VERSION 20 // NOTE: Check settings_reset() when moving to next version.
|
||||
@@ -241,6 +241,7 @@ typedef enum {
|
||||
Setting_CoolantMaxTemp = 381,
|
||||
Setting_CoolantOffset = 382,
|
||||
Setting_CoolantGain = 383,
|
||||
Setting_DisableG92Persistence = 384,
|
||||
|
||||
Setting_EncoderSettingsBase = 400, // NOTE: Reserving settings values >= 400 for encoder settings. Up to 449.
|
||||
Setting_EncoderSettingsMax = 449,
|
||||
@@ -318,7 +319,8 @@ typedef union {
|
||||
legacy_rt_commands :1,
|
||||
restore_after_feed_hold :1,
|
||||
keep_coolant_state_on_door_open :1,
|
||||
unassigned :7;
|
||||
g92_is_volatile :1,
|
||||
unassigned :6;
|
||||
};
|
||||
} settingflags_t;
|
||||
|
||||
@@ -354,6 +356,21 @@ typedef union {
|
||||
};
|
||||
} reportmask_t;
|
||||
|
||||
typedef union {
|
||||
uint8_t value;
|
||||
struct {
|
||||
uint8_t ignore_when_idle :1,
|
||||
keep_coolant_on :1,
|
||||
unassigned :6;
|
||||
};
|
||||
} safety_door_setting_flags_t;
|
||||
|
||||
typedef union {
|
||||
safety_door_setting_flags_t flags;
|
||||
float spindle_on_delay;
|
||||
float coolant_on_delay;
|
||||
} safety_door_settings_t;
|
||||
|
||||
typedef union {
|
||||
uint8_t value;
|
||||
struct {
|
||||
@@ -558,6 +575,7 @@ typedef struct {
|
||||
homing_settings_t homing;
|
||||
limit_settings_t limits;
|
||||
parking_settings_t parking;
|
||||
// safety_door_settings_t safety_door;
|
||||
position_pid_t position; // Used for synchronized motion
|
||||
ioport_signals_t ioport;
|
||||
} settings_t;
|
||||
|
||||
+231
-180
File diff suppressed because it is too large
Load Diff
@@ -145,7 +145,7 @@ void system_execute_startup (void)
|
||||
if (!settings_read_startup_line(n, line))
|
||||
report_execute_startup_message(line, Status_SettingReadFail);
|
||||
else if (*line != '\0')
|
||||
report_execute_startup_message(line, gc_execute_block(line, NULL));
|
||||
report_execute_startup_message(line, gc_execute_block(line));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -177,7 +177,7 @@ status_code_t read_int (char *s, int32_t *value)
|
||||
PROGMEM static const sys_command_t sys_commands[] = {
|
||||
{ "G", true, output_parser_state },
|
||||
{ "J", false, jog },
|
||||
{ "#", true, output_ngc_parameters },
|
||||
{ "#", false, output_ngc_parameters },
|
||||
{ "$", false, output_settings },
|
||||
{ "+", false, output_all_settings },
|
||||
#ifndef NO_SETTINGS_DESCRIPTIONS
|
||||
@@ -231,6 +231,57 @@ PROGMEM static const sys_command_t sys_commands[] = {
|
||||
#endif
|
||||
};
|
||||
|
||||
void system_command_help (void)
|
||||
{
|
||||
hal.stream.write("$I - output system information" ASCII_EOL);
|
||||
hal.stream.write("$<n> - output setting <n> value" ASCII_EOL);
|
||||
hal.stream.write("$<n>=<value> - assign <value> to settings <n>" ASCII_EOL);
|
||||
hal.stream.write("$I - output system information" ASCII_EOL);
|
||||
hal.stream.write("$I+ - output extended system information" ASCII_EOL);
|
||||
hal.stream.write("$$ - output all setting values" ASCII_EOL);
|
||||
hal.stream.write("$+ - output all setting values" ASCII_EOL);
|
||||
hal.stream.write("$$=<n> - output setting details for setting <n>" ASCII_EOL);
|
||||
hal.stream.write("$# - output offsets, tool table, probing and home position" ASCII_EOL);
|
||||
hal.stream.write("$#=<n> - output value for parameter <n>" ASCII_EOL);
|
||||
hal.stream.write("$G - output parser state" ASCII_EOL);
|
||||
hal.stream.write("$N - output startup lines" ASCII_EOL);
|
||||
if(settings.homing.flags.enabled)
|
||||
hal.stream.write("$H - home configured axes" ASCII_EOL);
|
||||
if(settings.homing.flags.single_axis_commands)
|
||||
hal.stream.write("$H<axisletter> - home single axis" ASCII_EOL);
|
||||
hal.stream.write("$X - unlock machine" ASCII_EOL);
|
||||
hal.stream.write("$SLP - enter sleep mode" ASCII_EOL);
|
||||
hal.stream.write("$HELP - output help topics" ASCII_EOL);
|
||||
hal.stream.write("$HELP <topic> - output help for <topic>" ASCII_EOL);
|
||||
hal.stream.write("$RST=* - restore/reset all" ASCII_EOL);
|
||||
hal.stream.write("$RST=$ - restore default settings" ASCII_EOL);
|
||||
if(settings_get_details()->on_get_settings)
|
||||
hal.stream.write("$RST=& - restore driver and plugin default settings" ASCII_EOL);
|
||||
#ifdef N_TOOLS
|
||||
hal.stream.write("$RST=# - reset offsets and tool data" ASCII_EOL);
|
||||
#else
|
||||
hal.stream.write("$RST=# - reset offsets" ASCII_EOL);
|
||||
#endif
|
||||
hal.stream.write("$TLR - set tool offset reference" ASCII_EOL);
|
||||
hal.stream.write("$TPW - probe tool plate" ASCII_EOL);
|
||||
hal.stream.write("$EA - enumerate alarms" ASCII_EOL);
|
||||
hal.stream.write("$EAG - enumerate alarms, Grbl formatted" ASCII_EOL);
|
||||
hal.stream.write("$EE - enumerate status codes" ASCII_EOL);
|
||||
hal.stream.write("$EEG - enumerate status codes, Grbl formatted" ASCII_EOL);
|
||||
hal.stream.write("$ES - enumerate settings" ASCII_EOL);
|
||||
hal.stream.write("$ESG - enumerate settings, Grbl formatted" ASCII_EOL);
|
||||
hal.stream.write("$ESH- enumerate settings, grblHAL formatted" ASCII_EOL);
|
||||
hal.stream.write("$ESG - enumerate alarms" ASCII_EOL);
|
||||
hal.stream.write("$E* - enumerate alarms, status codes and settings" ASCII_EOL);
|
||||
if(hal.enumerate_pins)
|
||||
hal.stream.write("$PINS - enumerate pin bindings" ASCII_EOL);
|
||||
hal.stream.write("$LEV - output last control signal events" ASCII_EOL);
|
||||
hal.stream.write("$LIM - output current limit pins state" ASCII_EOL);
|
||||
#ifndef NO_SETTINGS_DESCRIPTIONS
|
||||
hal.stream.write("$SED=<n> - output settings description for setting <n>" ASCII_EOL);
|
||||
#endif
|
||||
}
|
||||
|
||||
// Directs and executes one line of formatted input from protocol_process. While mostly
|
||||
// incoming streaming g-code blocks, this also executes Grbl internal commands, such as
|
||||
// settings, initiating the homing cycle, and toggling switch states. This differs from
|
||||
@@ -248,9 +299,6 @@ status_code_t system_execute_line (char *line)
|
||||
return Status_OK;
|
||||
}
|
||||
|
||||
if(strlen(line) >= ((LINE_BUFFER_SIZE / 2) - 1))
|
||||
return Status_Overflow;
|
||||
|
||||
sys_commands_t base = {
|
||||
.n_commands = sizeof(sys_commands) / sizeof(sys_command_t),
|
||||
.commands = sys_commands,
|
||||
@@ -258,37 +306,38 @@ status_code_t system_execute_line (char *line)
|
||||
};
|
||||
|
||||
status_code_t retval = Status_Unhandled;
|
||||
char c, *org = line, *ucline = line, *lcline = line + (LINE_BUFFER_SIZE / 2);
|
||||
|
||||
// Uppercase original and copy original out in the buffer
|
||||
// TODO: create a common function for stripping down uppercase version?
|
||||
do {
|
||||
c = *org++;
|
||||
if(c != ' ') // Remove spaces from uppercase version
|
||||
*ucline++ = CAPS(c);
|
||||
*lcline++ = c;
|
||||
} while(c);
|
||||
char c, *s1, *s2;
|
||||
|
||||
lcline = line + (LINE_BUFFER_SIZE / 2);
|
||||
s1 = s2 = ++line;
|
||||
|
||||
if(!strncmp(&line[1], "HELP", 4))
|
||||
return report_help(&line[5], &lcline[5]);
|
||||
|
||||
char *args = strchr(line, '='), *lcargs = strchr(lcline, '=');
|
||||
|
||||
if(args) {
|
||||
*args++ = '\0';
|
||||
*lcargs++ = '\0';
|
||||
c = *s1;
|
||||
while(c && c != '=') {
|
||||
if(c != ' ')
|
||||
*s2++ = CAPS(c);
|
||||
c = *++s1;
|
||||
}
|
||||
|
||||
while((c = *s1++))
|
||||
*s2++ = c;
|
||||
|
||||
*s2 = '\0';
|
||||
|
||||
if(!strncmp(line, "HELP", 4))
|
||||
return report_help(&line[4]);
|
||||
|
||||
char *args = strchr(line, '=');
|
||||
|
||||
if(args)
|
||||
*args++ = '\0';
|
||||
|
||||
uint_fast8_t idx;
|
||||
sys_commands_t *cmd = &base;
|
||||
|
||||
do {
|
||||
for(idx = 0; idx < cmd->n_commands; idx++) {
|
||||
if(!strcmp(&line[1], cmd->commands[idx].command)) {
|
||||
if(!cmd->commands[idx].noargs || lcargs == NULL) {
|
||||
if((retval = cmd->commands[idx].execute(state_get(), lcargs)) != Status_Unhandled)
|
||||
if(!strcmp(line, cmd->commands[idx].command)) {
|
||||
if(!cmd->commands[idx].noargs || args == NULL) {
|
||||
if((retval = cmd->commands[idx].execute(state_get(), args)) != Status_Unhandled)
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -298,26 +347,26 @@ status_code_t system_execute_line (char *line)
|
||||
|
||||
// Let user code have a peek at system commands before check for global setting
|
||||
if(retval == Status_Unhandled && grbl.on_unknown_sys_command) {
|
||||
if(lcargs)
|
||||
*(--lcargs) = '=';
|
||||
if(args)
|
||||
*(--args) = '=';
|
||||
|
||||
retval = grbl.on_unknown_sys_command(state_get(), lcline);
|
||||
retval = grbl.on_unknown_sys_command(state_get(), line);
|
||||
|
||||
if(lcargs)
|
||||
*lcargs++ = '\0';
|
||||
if(args)
|
||||
*args++ = '\0';
|
||||
}
|
||||
|
||||
if (retval == Status_Unhandled) {
|
||||
// Check for global setting, store if so
|
||||
if(state_get() == STATE_IDLE || (state_get() & (STATE_ALARM|STATE_ESTOP|STATE_CHECK_MODE))) {
|
||||
uint_fast8_t counter = 1;
|
||||
uint_fast8_t counter = 0;
|
||||
float parameter;
|
||||
if(!read_float(line, &counter, ¶meter))
|
||||
retval = Status_BadNumberFormat;
|
||||
else if(!isintf(parameter))
|
||||
retval = Status_InvalidStatement;
|
||||
else if(args)
|
||||
retval = settings_store_setting((setting_id_t)parameter, lcargs);
|
||||
retval = settings_store_setting((setting_id_t)parameter, args);
|
||||
else
|
||||
retval = report_grbl_setting((setting_id_t)parameter, NULL);
|
||||
} else
|
||||
@@ -339,7 +388,7 @@ static status_code_t jog (sys_state_t state, char *args)
|
||||
args -= 2;
|
||||
}
|
||||
|
||||
return args == NULL ? Status_InvalidStatement : gc_execute_block(strcaps(args), NULL); // NOTE: $J= is ignored inside g-code parser and used to detect jog motions.
|
||||
return args == NULL ? Status_InvalidStatement : gc_execute_block(args); // NOTE: $J= is ignored inside g-code parser and used to detect jog motions.
|
||||
}
|
||||
|
||||
static status_code_t enumerate_alarms (sys_state_t state, char *args)
|
||||
@@ -536,7 +585,7 @@ static status_code_t disable_lock (sys_state_t state, char *args)
|
||||
|
||||
static status_code_t output_help (sys_state_t state, char *args)
|
||||
{
|
||||
return report_help(args, args);
|
||||
return report_help(args);
|
||||
}
|
||||
|
||||
static status_code_t go_home (sys_state_t state, axes_signals_t axes)
|
||||
@@ -667,9 +716,19 @@ static status_code_t tool_probe_workpiece (sys_state_t state, char *args)
|
||||
|
||||
static status_code_t output_ngc_parameters (sys_state_t state, char *args)
|
||||
{
|
||||
report_ngc_parameters();
|
||||
status_code_t retval = Status_OK;
|
||||
|
||||
return Status_OK;
|
||||
if(args) {
|
||||
int32_t id;
|
||||
retval = read_int(args, &id);
|
||||
if(retval == Status_OK && id >= 0)
|
||||
retval = report_ngc_parameter((ngc_param_id_t)id);
|
||||
else
|
||||
retval = report_named_ngc_parameter(args);
|
||||
} else
|
||||
report_ngc_parameters();
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
static status_code_t build_info (sys_state_t state, char *args)
|
||||
@@ -781,11 +840,11 @@ static status_code_t set_startup_line (sys_state_t state, char *args, uint_fast8
|
||||
|
||||
status_code_t retval = Status_OK;
|
||||
|
||||
strcaps(args);
|
||||
args = gc_normalize_block(args, NULL);
|
||||
|
||||
if(strlen(args) >= (sizeof(stored_line_t) - 1))
|
||||
retval = Status_Overflow;
|
||||
else if ((retval = gc_execute_block(args, NULL)) == Status_OK) // Execute gcode block to ensure block is valid.
|
||||
else if ((retval = gc_execute_block(args)) == Status_OK) // Execute gcode block to ensure block is valid.
|
||||
settings_write_startup_line(lnr, args);
|
||||
|
||||
return retval;
|
||||
|
||||
@@ -53,6 +53,7 @@ know when there is a realtime command to execute.
|
||||
#define EXEC_GCODE_REPORT bit(11)
|
||||
#define EXEC_TLO_REPORT bit(12)
|
||||
#define EXEC_RT_COMMAND bit(13)
|
||||
#define EXEC_DOOR_CLOSED bit(14)
|
||||
///@}
|
||||
|
||||
//! \def sys_state
|
||||
@@ -295,6 +296,9 @@ void system_apply_jog_limits (float *target);
|
||||
//! Raise and report alarm state
|
||||
void system_raise_alarm (alarm_code_t alarm);
|
||||
|
||||
//! Provide system command help
|
||||
void system_command_help (void);
|
||||
|
||||
// Special handlers for setting and clearing Grbl's real-time execution flags.
|
||||
#define system_set_exec_state_flag(mask) hal.set_bits_atomic(&sys.rt_exec_state, (mask))
|
||||
#define system_clear_exec_state_flag(mask) hal.clear_bits_atomic(&sys.rt_exec_state, (mask))
|
||||
|
||||
Reference in New Issue
Block a user