diff --git a/CMakeLists.txt b/CMakeLists.txt
index 230010f..4f2e121 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -21,6 +21,8 @@ target_sources(grbl INTERFACE
${CMAKE_CURRENT_LIST_DIR}/stepper.c
${CMAKE_CURRENT_LIST_DIR}/system.c
${CMAKE_CURRENT_LIST_DIR}/tool_change.c
+ ${CMAKE_CURRENT_LIST_DIR}/alarms.c
+ ${CMAKE_CURRENT_LIST_DIR}/errors.c
)
target_include_directories(grbl INTERFACE ${CMAKE_CURRENT_LIST_DIR})
diff --git a/README.md b/README.md
index 64c6bf9..016b008 100644
--- a/README.md
+++ b/README.md
@@ -11,7 +11,7 @@ It has been written to complement grblHAL and has features such as proper keyboa
---
-Latest build date is 20210819, see the [changelog](changelog.md) for details.
+Latest build date is 20210907, 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.
---
@@ -77,5 +77,7 @@ List of Supported G-Codes:
*** number of outputs supported dependent on driver implementation.
```
+Some [plugins](https://github.com/grblHAL/plugins) implements additional M-codes.
+
---
-2021-07-26
+2021-09-08
diff --git a/alarms.c b/alarms.c
new file mode 100644
index 0000000..35ce01e
--- /dev/null
+++ b/alarms.c
@@ -0,0 +1,59 @@
+/*
+ alarms.c -
+
+ Part of grblHAL
+
+ Copyright (c) 2017-2021 Terje Io
+ Copyright (c) 2011-2016 Sungeun K. Jeon for Gnea Research LLC
+ Copyright (c) 2009-2011 Simen Svale Skogsrud
+
+ 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 .
+*/
+
+#include
+
+#include "grbl.h"
+#include "core_handlers.h"
+
+PROGMEM static const alarm_detail_t alarm_detail[] = {
+ { Alarm_HardLimit, "Hard limit", "Hard limit has been triggered. Machine position is likely lost due to sudden halt. Re-homing is highly recommended." },
+ { Alarm_SoftLimit, "Soft limit", "Soft limit alarm. G-code motion target exceeds machine travel. Machine position retained. Alarm may be safely unlocked." },
+ { Alarm_AbortCycle, "Abort during cycle", "Reset while in motion. Machine position is likely lost due to sudden halt. Re-homing is highly recommended." },
+ { Alarm_ProbeFailInitial, "Probe fail", "Probe fail. Probe is not in the expected initial state before starting probe cycle when G38.2 and G38.3 is not triggered and G38.4 and G38.5 is triggered." },
+ { Alarm_ProbeFailContact, "Probe fail", "Probe fail. Probe did not contact the workpiece within the programmed travel for G38.2 and G38.4." },
+ { Alarm_HomingFailReset, "Homing fail", "Homing fail. The active homing cycle was reset." },
+ { Alarm_HomingFailDoor, "Homing fail", "Homing fail. Safety door was opened during homing cycle." },
+ { Alarm_FailPulloff, "Homing fail", "Homing fail. Pull off travel failed to clear limit switch. Try increasing pull-off setting or check wiring." },
+ { Alarm_HomingFailApproach, "Homing fail", "Homing fail. Could not find limit switch within search distances. Try increasing max travel, decreasing pull-off distance, or check wiring." },
+ { Alarm_EStop, "EStop", "EStop asserted. Clear and reset" },
+ { Alarm_HomingRequried, "Homing required", "Homing required. Execute homing command ($H) to continue." },
+ { Alarm_LimitsEngaged, "Limit switch engaged", "Limit switch engaged. Clear before continuing." },
+ { Alarm_ProbeProtect, "Probe protection triggered", "Probe protection triggered. Clear before continuing." },
+ { Alarm_Spindle, "Spindle at speed timeout", "Spindle at speed timeout. Clear before continuing." },
+ { Alarm_HomingFailAutoSquaringApproach, "Homing fail", "Homing fail. Could not find second limit switch for auto squared axis within search distances. Try increasing max travel, decreasing pull-off distance, or check wiring." },
+ { Alarm_SelftestFailed, "Selftest failed", "Power on selftest (POS) failed." },
+ { Alarm_MotorFault, "Motor fault", "Motor fault." }
+};
+
+static alarm_details_t details = {
+ .alarms = alarm_detail,
+ .n_alarms = sizeof(alarm_detail) / sizeof(alarm_detail_t)
+};
+
+alarm_details_t *alarms_get_details (void)
+{
+ details.on_get_alarms = grbl.on_get_alarms;
+
+ return &details;
+}
diff --git a/alarms.h b/alarms.h
index 5d10396..8ac1230 100644
--- a/alarms.h
+++ b/alarms.h
@@ -43,7 +43,8 @@ typedef enum {
Alarm_Spindle = 14,
Alarm_HomingFailAutoSquaringApproach = 15,
Alarm_SelftestFailed = 16,
- Alarm_MotorFault = 17
+ Alarm_MotorFault = 17,
+ Alarm_AlarmMax = Alarm_MotorFault
} alarm_code_t;
typedef struct {
@@ -52,25 +53,16 @@ typedef struct {
const char *description;
} alarm_detail_t;
-PROGMEM static const alarm_detail_t alarm_detail[] = {
- { Alarm_HardLimit, "Hard limit", "Hard limit has been triggered. Machine position is likely lost due to sudden halt. Re-homing is highly recommended." },
- { Alarm_SoftLimit, "Soft limit", "Soft limit alarm. G-code motion target exceeds machine travel. Machine position retained. Alarm may be safely unlocked." },
- { Alarm_AbortCycle, "Abort during cycle", "Reset while in motion. Machine position is likely lost due to sudden halt. Re-homing is highly recommended." },
- { Alarm_ProbeFailInitial, "Probe fail", "Probe fail. Probe is not in the expected initial state before starting probe cycle when G38.2 and G38.3 is not triggered and G38.4 and G38.5 is triggered." },
- { Alarm_ProbeFailContact, "Probe fail", "Probe fail. Probe did not contact the workpiece within the programmed travel for G38.2 and G38.4." },
- { Alarm_HomingFailReset, "Homing fail", "Homing fail. The active homing cycle was reset." },
- { Alarm_HomingFailDoor, "Homing fail", "Homing fail. Safety door was opened during homing cycle." },
- { Alarm_FailPulloff, "Homing fail", "Homing fail. Pull off travel failed to clear limit switch. Try increasing pull-off setting or check wiring." },
- { Alarm_HomingFailApproach, "Homing fail", "Homing fail. Could not find limit switch within search distances. Try increasing max travel, decreasing pull-off distance, or check wiring." },
- { Alarm_EStop, "EStop", "EStop asserted. Clear and reset" },
- { Alarm_HomingRequried, "Homing required", "Homing required. Execute homing command ($H) to continue." },
- { Alarm_LimitsEngaged, "Limit switch engaged", "Limit switch engaged. Clear before continuing." },
- { Alarm_ProbeProtect, "Probe protection triggered", "Probe protection triggered. Clear before continuing." },
- { Alarm_Spindle, "Spindle at speed timeout", "Spindle at speed timeout. Clear before continuing." },
- { Alarm_HomingFailAutoSquaringApproach, "Homing fail", "Homing fail. Could not find second limit switch for auto squared axis within search distances. Try increasing max travel, decreasing pull-off distance, or check wiring." },
- { Alarm_SelftestFailed, "Selftest failed", "Power on selftest (POS) failed." },
- { Alarm_MotorFault, "Motor fault", "Motor fault." }
-};
+typedef struct alarm_details {
+ const uint16_t n_alarms;
+ const alarm_detail_t *alarms;
+ struct alarm_details *(*on_get_alarms)(void);
+} alarm_details_t;
+
+// NOTE: this must match the signature of on_get_alarms in the alarm_details_t struct above!
+typedef alarm_details_t *(*on_get_alarms_ptr)(void);
+
+alarm_details_t *alarms_get_details (void);
#endif
diff --git a/changelog.md b/changelog.md
index 18f69ed..1f8ece3 100644
--- a/changelog.md
+++ b/changelog.md
@@ -1,5 +1,17 @@
## grblHAL changelog
+Build 20210907:
+
+Core:
+* Improved HAL/core stream handling for plugin issued [realtime commands](http://svn.io-engineering.com/grblHAL/html/structgrbl__t.html#a2ff011529d0a7809a44c8609490e0306).
+* Some minor bug fixes and added rudimentary settings validations relevant when switching board map files.
+
+Drivers & plugins:
+* Fixed regression in encoder plugin.
+* Updated all drivers and relevant plugins for HAL/core API changes.
+* Added PWM inversion option to [iMXRT1062 driver](https://github.com/grblHAL/iMXRT1062).
+* Significantly improved [STM32F7xx driver](https://github.com/grblHAL/STM32F7xx), still work in progress.
+
Build 20210819:
Core:
diff --git a/config.h b/config.h
index b7f1525..c1691c1 100644
--- a/config.h
+++ b/config.h
@@ -416,19 +416,14 @@ __NOTE:__ these definitions are only referenced in this file. Do __NOT__ change!
// #define INVERT_LIMIT_BIT_MASK (X_AXIS_BIT|Y_AXIS_BIT) // Default disabled. Uncomment to enable.
// For inverting the probe pin use DEFAULT_INVERT_PROBE_BIT in defaults.h
-// Inverts the spindle enable pin from low-disabled/high-enabled to low-enabled/high-disabled. Useful
-// for some pre-built electronic boards.
-// NOTE: If VARIABLE_SPINDLE is enabled(default), this option has no effect as the PWM output and
-// spindle enable are combined to one pin. If you need both this option and spindle speed PWM,
-// uncomment the config option USE_SPINDLE_DIR_AS_ENABLE_PIN below.
+// Inverts the selected spindle output signals from active high to active low. Useful for some pre-built electronic boards.
// #define INVERT_SPINDLE_ENABLE_PIN 1 // Default disabled. Uncomment to enable.
// #define INVERT_SPINDLE_CCW_PIN 1 // Default disabled. Uncomment to enable. NOTE: not supported by all drivers.
// #define INVERT_SPINDLE_PWM_PIN 1 // Default disabled. Uncomment to enable. NOTE: not supported by all drivers.
-// Inverts the selected coolant pin from low-disabled/high-enabled to low-enabled/high-disabled. Useful
-// for some pre-built electronic boards.
+// Inverts the selected coolant signals from active high to active low. Useful for some pre-built electronic boards.
// #define INVERT_COOLANT_FLOOD_PIN 1 // Default disabled. Uncomment to enable.
-// #define INVERT_COOLANT_MIST_PIN 1 // Default disabled. Note: Enable M7 mist coolant in config.h
+// #define INVERT_COOLANT_MIST_PIN 1 // Default disabled. Note: not supported by all drivers.
// Used by variable spindle output only. This forces the PWM output to a minimum duty cycle when enabled.
diff --git a/core_handlers.h b/core_handlers.h
index e0e5889..1e22ccc 100644
--- a/core_handlers.h
+++ b/core_handlers.h
@@ -27,6 +27,8 @@
#include "system.h"
#include "stream.h"
+#include "alarms.h"
+#include "errors.h"
#include "settings.h"
#include "report.h"
@@ -61,6 +63,9 @@ typedef struct {
// Core event handler and other entry points.
// Most of the event handlers defaults to NULL, a few is set up to call a dummy handler for simpler code.
+typedef bool (*enqueue_gcode_ptr)(char *data);
+typedef bool (*protocol_enqueue_realtime_command_ptr)(char c);
+
typedef void (*on_state_change_ptr)(sys_state_t state);
typedef void (*on_probe_completed_ptr)(void);
typedef void (*on_program_completed_ptr)(program_flow_t program_flow, bool check_mode);
@@ -70,10 +75,9 @@ typedef bool (*on_unknown_realtime_cmd_ptr)(char c);
typedef void (*on_report_options_ptr)(bool newopt);
typedef void (*on_report_command_help_ptr)(void);
typedef void (*on_global_settings_restore_ptr)(void);
-typedef setting_details_t *(*on_get_settings_ptr)(void); // NOTE: this must match the signature of the same definition in
- // the setting_details_t structure in settings.h!
typedef void (*on_realtime_report_ptr)(stream_write_ptr stream_write, report_tracking_flags_t report);
typedef void (*on_unknown_feedback_message_ptr)(stream_write_ptr stream_write);
+typedef void (*on_stream_changed_ptr)(stream_type_t type);
typedef bool (*on_laser_ppi_enable_ptr)(uint_fast16_t ppi, uint_fast16_t pulse_length);
typedef status_code_t (*on_unknown_sys_command_ptr)(sys_state_t state, char *line); // return Status_Unhandled.
typedef status_code_t (*on_user_command_ptr)(char *line);
@@ -91,6 +95,8 @@ typedef struct {
on_report_options_ptr on_report_options;
on_report_command_help_ptr on_report_command_help;
on_global_settings_restore_ptr on_global_settings_restore;
+ on_get_alarms_ptr on_get_alarms;
+ on_get_errors_ptr on_get_errors;
on_get_settings_ptr on_get_settings;
on_realtime_report_ptr on_realtime_report;
on_unknown_feedback_message_ptr on_unknown_feedback_message;
@@ -98,9 +104,11 @@ typedef struct {
on_unknown_sys_command_ptr on_unknown_sys_command; // return Status_Unhandled if not handled.
on_get_commands_ptr on_get_commands;
on_user_command_ptr on_user_command;
+ on_stream_changed_ptr on_stream_changed;
on_laser_ppi_enable_ptr on_laser_ppi_enable;
// core entry points - set up by core before driver_init() is called.
- bool (*protocol_enqueue_gcode)(char *data);
+ enqueue_gcode_ptr enqueue_gcode;
+ enqueue_realtime_command_ptr enqueue_realtime_command;
} grbl_t;
extern grbl_t grbl;
diff --git a/errors.c b/errors.c
new file mode 100644
index 0000000..32b2b33
--- /dev/null
+++ b/errors.c
@@ -0,0 +1,97 @@
+/*
+ errors.c -
+
+ Part of grblHAL
+
+ Copyright (c) 2017-2021 Terje Io
+ Copyright (c) 2011-2016 Sungeun K. Jeon for Gnea Research LLC
+ Copyright (c) 2009-2011 Simen Svale Skogsrud
+
+ 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 .
+*/
+
+#include
+
+#include "grbl.h"
+#include "core_handlers.h"
+
+PROGMEM static const status_detail_t status_detail[] = {
+ { Status_OK, "ok", NULL },
+ { Status_ExpectedCommandLetter, "Expected command letter", "G-code words consist of a letter and a value. Letter was not found." },
+ { Status_BadNumberFormat, "Bad number format", "Missing the expected G-code word value or numeric value format is not valid." },
+ { Status_InvalidStatement, "Invalid statement", "'$' system command was not recognized or supported." },
+ { Status_NegativeValue, "Value < 0", "Negative value received for an expected positive value." },
+ { Status_HomingDisabled, "Homing disabled", "Homing cycle failure. Homing is not configured via settings." },
+ { Status_SettingStepPulseMin, "Value < 2 microseconds", "Step pulse time must be greater or equal to 2 microseconds." },
+ { Status_SettingReadFail, "Settings read failed. Using defaults", "A settings read failed. Auto-restoring affected settings to default values." },
+ { Status_IdleError, "Not idle", "'$' command cannot be used unless controller state is IDLE. Ensures smooth operation during a job." },
+ { Status_SystemGClock, "G-code lock", "G-code commands are locked out during alarm or jog state." },
+ { Status_SoftLimitError, "Homing not enabled", "Soft limits cannot be enabled without homing also enabled." },
+ { Status_Overflow, "Line overflow", "Max characters per line exceeded. Received command line was not executed." },
+ { Status_MaxStepRateExceeded, "Max step rate too high", "'$' setting value cause the step rate to exceed the maximum supported." },
+ { Status_CheckDoor, "Check Door", "Safety door detected as opened and door state initiated." },
+ { Status_LineLengthExceeded, "Line length exceeded", "Build info or startup line exceeded line length limit. Line not stored." },
+ { Status_TravelExceeded, "Travel exceeded", "Jog target exceeds machine travel. Jog command has been ignored." },
+ { Status_InvalidJogCommand, "Invalid jog command", "Jog command has no '=' or contains prohibited g-code." },
+ { Status_SettingDisabledLaser, "Setting disabled", "Laser mode requires PWM output." },
+ { Status_Reset, "Reset asserted", "" },
+ { Status_NonPositiveValue, "Non positive value", "" },
+ { Status_GcodeUnsupportedCommand, "Unsupported command", "Unsupported or invalid g-code command found in block." },
+ { Status_GcodeModalGroupViolation, "Modal group violation", "More than one g-code command from same modal group found in block." },
+ { Status_GcodeUndefinedFeedRate, "Undefined feed rate", "Feed rate has not yet been set or is undefined." },
+ { Status_GcodeCommandValueNotInteger, "Invalid gcode ID:23", "G-code command in block requires an integer value." },
+ { Status_GcodeAxisCommandConflict, "Invalid gcode ID:24", "More than one g-code command that requires axis words found in block." },
+ { Status_GcodeWordRepeated, "Invalid gcode ID:25", "Repeated g-code word found in block." },
+ { Status_GcodeNoAxisWords, "Invalid gcode ID:26", "No axis words found in block for g-code command or current modal state which requires them." },
+ { Status_GcodeInvalidLineNumber, "Invalid gcode ID:27", "Line number value is invalid." },
+ { Status_GcodeValueWordMissing, "Invalid gcode ID:28", "G-code command is missing a required value word." },
+ { Status_GcodeUnsupportedCoordSys, "Invalid gcode ID:29", "G59.x work coordinate systems are not supported." },
+ { Status_GcodeG53InvalidMotionMode, "Invalid gcode ID:30", "G53 only allowed with G0 and G1 motion modes." },
+ { Status_GcodeAxisWordsExist, "Invalid gcode ID:31", "Axis words found in block when no command or current modal state uses them." },
+ { Status_GcodeNoAxisWordsInPlane, "Invalid gcode ID:32", "G2 and G3 arcs require at least one in-plane axis word." },
+ { Status_GcodeInvalidTarget, "Invalid gcode ID:33", "Motion command target is invalid." },
+ { Status_GcodeArcRadiusError, "Invalid gcode ID:34", "Arc radius value is invalid." },
+ { Status_GcodeNoOffsetsInPlane, "Invalid gcode ID:35", "G2 and G3 arcs require at least one in-plane offset word." },
+ { Status_GcodeUnusedWords, "Invalid gcode ID:36", "Unused value words found in block." },
+ { Status_GcodeG43DynamicAxisError, "Invalid gcode ID:37", "G43.1 dynamic tool length offset is not assigned to configured tool length axis." },
+ { Status_GcodeIllegalToolTableEntry, "Invalid gcode ID:38", "Tool number greater than max supported value or undefined tool selected." },
+ { Status_GcodeValueOutOfRange, "Invalid gcode ID:39", "Value out of range." },
+ { Status_GcodeToolChangePending, "Invalid gcode ID:40", "G-code command not allowed when tool change is pending." },
+ { Status_GcodeSpindleNotRunning, "Invalid gcode ID:41", "Spindle not running when motion commanded in CSS or spindle sync mode." },
+ { Status_GcodeIllegalPlane, "Invalid gcode ID:42", "Plane must be ZX for threading." },
+ { Status_GcodeMaxFeedRateExceeded, "Invalid gcode ID:43", "Max. feed rate exceeded." },
+ { Status_GcodeRPMOutOfRange, "Invalid gcode ID:44", "RPM out of range." },
+ { Status_LimitsEngaged, "Limit switch engaged", "Only homing is allowed when a limit switch is engaged." },
+ { Status_HomingRequired, "Homing required", "Home machine to continue." },
+ { Status_GCodeToolError, "Invalid gcode ID:47", "ATC: current tool is not set. Set current tool with M61." },
+ { Status_ValueWordConflict, "Invalid gcode ID:48", "Value word conflict." },
+ { Status_SelfTestFailed, "Self test failed", "Power on self test failed. A hard reset is required." },
+ { Status_EStop, "E-stop", "Emergency stop active." },
+ { 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." }
+ };
+
+static error_details_t details = {
+ .errors = status_detail,
+ .n_errors = sizeof(status_detail) / sizeof(status_detail_t)
+};
+
+error_details_t *errors_get_details (void)
+{
+ details.on_get_errors = grbl.on_get_errors;
+
+ return &details;
+}
diff --git a/errors.h b/errors.h
index ea7bcb4..79b6543 100644
--- a/errors.h
+++ b/errors.h
@@ -93,7 +93,8 @@ typedef enum {
Status_SDFileEmpty = 64,
Status_BTInitError = 70,
- Status_Unhandled // For internal use only
+ Status_Unhandled, // For internal use only
+ Status_StatusMax = Status_Unhandled
} status_code_t;
typedef struct {
@@ -102,68 +103,15 @@ typedef struct {
const char *description;
} status_detail_t;
-PROGMEM static const status_detail_t status_detail[] = {
- { Status_OK, "ok", NULL },
- { Status_ExpectedCommandLetter, "Expected command letter", "G-code words consist of a letter and a value. Letter was not found." },
- { Status_BadNumberFormat, "Bad number format", "Missing the expected G-code word value or numeric value format is not valid." },
- { Status_InvalidStatement, "Invalid statement", "Grbl '$' system command was not recognized or supported." },
- { Status_NegativeValue, "Value < 0", "Negative value received for an expected positive value." },
- { Status_HomingDisabled, "Homing disabled", "Homing cycle failure. Homing is not configured via settings." },
- { Status_SettingStepPulseMin, "Value < 2 microseconds", "Step pulse time must be greater or equal to 2 microseconds." },
- { Status_SettingReadFail, "EEPROM read fail. Using defaults", "An EEPROM read failed. Auto-restoring affected EEPROM to default values." },
- { Status_IdleError, "Not idle", "Grbl '$' command cannot be used unless Grbl is IDLE. Ensures smooth operation during a job." },
- { Status_SystemGClock, "G-code lock", "G-code commands are locked out during alarm or jog state." },
- { Status_SoftLimitError, "Homing not enabled", "Soft limits cannot be enabled without homing also enabled." },
- { Status_Overflow, "Line overflow", "Max characters per line exceeded. Received command line was not executed." },
- { Status_MaxStepRateExceeded, "Step rate > 30kHz", "Grbl '$' setting value cause the step rate to exceed the maximum supported." },
- { Status_CheckDoor, "Check Door", "Safety door detected as opened and door state initiated." },
- { Status_LineLengthExceeded, "Line length exceeded", "Build info or startup line exceeded EEPROM line length limit. Line not stored." },
- { Status_TravelExceeded, "Travel exceeded", "Jog target exceeds machine travel. Jog command has been ignored." },
- { Status_InvalidJogCommand, "Invalid jog command", "Jog command has no '=' or contains prohibited g-code." },
- { Status_SettingDisabledLaser, "Setting disabled", "Laser mode requires PWM output." },
- { Status_Reset, "Reset asserted", "" },
- { Status_NonPositiveValue, "Non positive value", "" },
- { Status_GcodeUnsupportedCommand, "Unsupported command", "Unsupported or invalid g-code command found in block." },
- { Status_GcodeModalGroupViolation, "Modal group violation", "More than one g-code command from same modal group found in block." },
- { Status_GcodeUndefinedFeedRate, "Undefined feed rate", "Feed rate has not yet been set or is undefined." },
- { Status_GcodeCommandValueNotInteger, "Invalid gcode ID:23", "G-code command in block requires an integer value." },
- { Status_GcodeAxisCommandConflict, "Invalid gcode ID:24", "More than one g-code command that requires axis words found in block." },
- { Status_GcodeWordRepeated, "Invalid gcode ID:25", "Repeated g-code word found in block." },
- { Status_GcodeNoAxisWords, "Invalid gcode ID:26", "No axis words found in block for g-code command or current modal state which requires them." },
- { Status_GcodeInvalidLineNumber, "Invalid gcode ID:27", "Line number value is invalid." },
- { Status_GcodeValueWordMissing, "Invalid gcode ID:28", "G-code command is missing a required value word." },
- { Status_GcodeUnsupportedCoordSys, "Invalid gcode ID:29", "G59.x work coordinate systems are not supported." },
- { Status_GcodeG53InvalidMotionMode, "Invalid gcode ID:30", "G53 only allowed with G0 and G1 motion modes." },
- { Status_GcodeAxisWordsExist, "Invalid gcode ID:31", "Axis words found in block when no command or current modal state uses them." },
- { Status_GcodeNoAxisWordsInPlane, "Invalid gcode ID:32", "G2 and G3 arcs require at least one in-plane axis word." },
- { Status_GcodeInvalidTarget, "Invalid gcode ID:33", "Motion command target is invalid." },
- { Status_GcodeArcRadiusError, "Invalid gcode ID:34", "Arc radius value is invalid." },
- { Status_GcodeNoOffsetsInPlane, "Invalid gcode ID:35", "G2 and G3 arcs require at least one in-plane offset word." },
- { Status_GcodeUnusedWords, "Invalid gcode ID:36", "Unused value words found in block." },
- { Status_GcodeG43DynamicAxisError, "Invalid gcode ID:37", "G43.1 dynamic tool length offset is not assigned to configured tool length axis." },
- { Status_GcodeIllegalToolTableEntry, "Invalid gcode ID:38", "Tool number greater than max supported value or undefined tool selected." },
- { Status_GcodeValueOutOfRange, "Invalid gcode ID:39", "Value out of range." },
- { Status_GcodeToolChangePending, "Invalid gcode ID:40", "G-code command not allowed when tool change is pending." },
- { Status_GcodeSpindleNotRunning, "Invalid gcode ID:41", "Spindle not running when motion commanded in CSS or spindle sync mode." },
- { Status_GcodeIllegalPlane, "Invalid gcode ID:42", "Plane must be ZX for threading." },
- { Status_GcodeMaxFeedRateExceeded, "Invalid gcode ID:43", "Max. feed rate exceeded." },
- { Status_GcodeRPMOutOfRange, "Invalid gcode ID:44", "RPM out of range." },
- { Status_LimitsEngaged, "Limit switch engaged", "Only homing is allowed when a limit switch is engaged." },
- { Status_HomingRequired, "Homing required", "Home machine to continue." },
- { Status_GCodeToolError, "Invalid gcode ID:47", "ATC: current tool is not set. Set current tool with M61." },
- { Status_ValueWordConflict, "Invalid gcode ID:48", "Value word conflict." },
- { Status_SelfTestFailed, "Self test failed", "Power on self test failed. A hard reset is required." },
- { Status_EStop, "E-stop", "Emergency stop active." },
- { 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_SDMountError, "SD Card", "SD Card mount failed." },
- { Status_SDReadError, "SD Card", "SD Card file open/read failed." },
- { Status_SDFailedOpenDir, "SD Card", "SD Card directory listing failed." },
- { Status_SDDirNotFound, "SD Card", "SD Card directory not found." },
- { Status_SDFileEmpty, "SD Card", "SD Card file empty." },
- { Status_BTInitError, "Bluetooth", "Bluetooth initalisation failed." }
-};
+typedef struct error_details {
+ const uint16_t n_errors;
+ const status_detail_t *errors;
+ struct error_details *(*on_get_errors)(void);
+} error_details_t;
+
+// NOTE: this must match the signature of on_get_alarms in the on_get_statuses struct above!
+typedef error_details_t *(*on_get_errors_ptr)(void);
+
+error_details_t *errors_get_details (void);
#endif
diff --git a/grbl.h b/grbl.h
index 1d4ab83..be581b7 100644
--- a/grbl.h
+++ b/grbl.h
@@ -34,7 +34,7 @@
#else
#define GRBL_VERSION "1.1f"
#endif
-#define GRBL_VERSION_BUILD "20210819"
+#define GRBL_VERSION_BUILD "20210907"
// The following symbols are set here if not already set by the compiler or in config.h
// Do NOT change here!
diff --git a/grbllib.c b/grbllib.c
index 9765f06..565acb6 100644
--- a/grbllib.c
+++ b/grbllib.c
@@ -103,7 +103,8 @@ int grbl_enter (void)
// Clear all and set some core function pointers
memset(&grbl, 0, sizeof(grbl_t));
grbl.on_execute_realtime = protocol_execute_noop;
- grbl.protocol_enqueue_gcode = protocol_enqueue_gcode;
+ grbl.enqueue_gcode = protocol_enqueue_gcode;
+ grbl.enqueue_realtime_command = stream_enqueue_realtime_command;
grbl.on_report_options = dummy_bool_handler;
// Clear all and set some HAL function pointers
@@ -181,7 +182,7 @@ int grbl_enter (void)
#endif
#ifdef SPINDLE_PWM_DIRECT
- driver_ok = driver_ok && hal.spindle.get_pwm != NULL && hal.spindle.update_pwm != NULL;
+ driver_ok = driver_ok && (!hal.driver_cap.variable_spindle || (hal.spindle.get_pwm != NULL && hal.spindle.update_pwm != NULL));
#endif
if(!driver_ok) {
diff --git a/nvs_buffer.c b/nvs_buffer.c
index 74faa6d..87f0fc6 100644
--- a/nvs_buffer.c
+++ b/nvs_buffer.c
@@ -68,7 +68,7 @@ static const emap_t target[] = {
{TOOL_ADDR(5), NVS_GROUP_TOOLS, 5},
{TOOL_ADDR(6), NVS_GROUP_TOOLS, 6},
{TOOL_ADDR(7), NVS_GROUP_TOOLS, 7},
-#if N_TOOL > 8
+#if N_TOOLS > 8
#error Increase number of tool entries!
#endif
#endif
@@ -373,6 +373,14 @@ 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, " ");
diff --git a/planner.c b/planner.c
index b3bd33d..9ba9ecd 100644
--- a/planner.c
+++ b/planner.c
@@ -315,7 +315,7 @@ inline static float plan_compute_profile_parameters (plan_block_t *block, float
}
// Re-calculates buffered motions profile parameters upon a motion-based override change.
-void plan_update_velocity_profile_parameters ()
+static void plan_update_velocity_profile_parameters ()
{
plan_block_t *block = block_buffer_tail;
float prev_nominal_speed = SOME_LARGE_VALUE; // Set high for first block nominal speed calculation.
diff --git a/planner.h b/planner.h
index c7a1776..2eaceb2 100644
--- a/planner.h
+++ b/planner.h
@@ -132,9 +132,6 @@ float plan_get_exec_block_exit_speed_sqr();
// Called by main program during planner calculations and step segment buffer during initialization.
float plan_compute_profile_nominal_speed(plan_block_t *block);
-// Re-calculates buffered motions profile parameters upon a motion-based override change.
-void plan_update_velocity_profile_parameters();
-
// Reset the planner position vector (in steps)
void plan_sync_position();
@@ -147,7 +144,6 @@ uint_fast16_t plan_get_block_buffer_available();
// Returns the status of the block ring buffer. True, if buffer is full.
bool plan_check_full_buffer();
-void plan_get_planner_mpos(float *target);
void plan_feed_override (uint_fast8_t feed_override, uint_fast8_t rapid_override);
#endif
diff --git a/plugins_init.h b/plugins_init.h
index 3be81c5..bca7c28 100644
--- a/plugins_init.h
+++ b/plugins_init.h
@@ -48,6 +48,11 @@
openpnp_init();
#endif
+#if WEBUI_ENABLE
+ extern void webui_init (void);
+ webui_init();
+#endif
+
my_plugin_init();
#if ODOMETER_ENABLE
diff --git a/report.c b/report.c
index f02dac2..7f6024d 100644
--- a/report.c
+++ b/report.c
@@ -1381,6 +1381,15 @@ static void report_bitfield (const char *format, bool bitmap)
}
}
+static void write_quoted (const char *s, const char *sep)
+{
+ hal.stream.write("\"");
+ hal.stream.write(s); // TODO: escape double quoutes
+ hal.stream.write("\"");
+ if(sep)
+ hal.stream.write(sep);
+}
+
static void report_settings_detail (settings_format_t format, const setting_detail_t *setting, uint_fast8_t offset)
{
switch(format)
@@ -1474,126 +1483,130 @@ static void report_settings_detail (settings_format_t format, const setting_deta
break;
case SettingsFormat_Grbl:
- hal.stream.write("\"");
- hal.stream.write(uitoa(setting->id + offset));
- hal.stream.write("\",\"");
- if(setting->group == Group_Axis0)
- hal.stream.write(axis_letter[offset]);
- hal.stream.write(setting->name[0] == '?' ? &setting->name[1] : setting->name); // temporary hack for ? prefix...
- if(setting->unit) {
- hal.stream.write("\",\"");
- hal.stream.write(setting->unit);
- } else // TODO: output sensible unit from datatype
- hal.stream.write("\",\"");
-#ifndef NO_SETTINGS_DESCRIPTIONS
- hal.stream.write("\",\"");
- report_setting_description(format, (setting_id_t)(setting->id + offset));
- hal.stream.write("\"");
-#else
- hal.stream.write("\",\"\"");
-#endif
+ {
+ write_quoted(uitoa(setting->id + offset), ",");
+ hal.stream.write("\"");
+ if(setting->group == Group_Axis0)
+ hal.stream.write(axis_letter[offset]);
+ hal.stream.write(setting->name[0] == '?' ? &setting->name[1] : setting->name); // temporary hack for ? prefix...
+ hal.stream.write("\",");
+ if(setting->unit) {
+ write_quoted(setting->unit, ",");
+ } else // TODO: output sensible unit from datatype
+ write_quoted("", ",");
+
+ #ifndef NO_SETTINGS_DESCRIPTIONS
+ const char *description = setting_get_description((setting_id_t)(setting->id + offset));
+ write_quoted(description ? description : "", ",");
+ #else
+ write_quoted("", NULL);
+ #endif
+ }
break;
case SettingsFormat_grblHAL:
- hal.stream.write(uitoa(setting->id + offset));
+ {
+ hal.stream.write(uitoa(setting->id + offset));
- hal.stream.write("\t");
+ hal.stream.write("\t");
- if(setting->group == Group_Axis0)
- hal.stream.write(axis_letter[offset]);
- hal.stream.write(setting->name[0] == '?' ? &setting->name[1] : setting->name); // temporary hack for ? prefix...
+ if(setting->group == Group_Axis0)
+ hal.stream.write(axis_letter[offset]);
+ hal.stream.write(setting->name[0] == '?' ? &setting->name[1] : setting->name); // temporary hack for ? prefix...
- hal.stream.write("\t");
+ hal.stream.write("\t");
- if(setting->unit)
- hal.stream.write(setting->unit);
- else if(setting->datatype == Format_AxisMask || setting->datatype == Format_Bitfield || setting->datatype == Format_XBitfield)
- hal.stream.write("mask");
- else if(setting->datatype == Format_Bool)
- hal.stream.write("boolean");
- else if(setting->datatype == Format_RadioButtons)
- hal.stream.write("integer");
-
- hal.stream.write("\t");
-/*
- Format_Bool = 0,
- Format_Bitfield,
- Format_XBitfield,
- Format_RadioButtons,
- Format_AxisMask,
- Format_Integer, // 32 bit
- ,
- Format_String,
- Format_Password,
- Format_IPv4,
- // For internal use only
- Format_Int8,
- Format_Int16,
-*/
- switch(setting_datatype_to_external(setting->datatype)) {
-
- case Format_Integer:
+ if(setting->unit)
+ hal.stream.write(setting->unit);
+ else if(setting->datatype == Format_AxisMask || setting->datatype == Format_Bitfield || setting->datatype == Format_XBitfield)
+ hal.stream.write("mask");
+ else if(setting->datatype == Format_Bool)
+ hal.stream.write("boolean");
+ else if(setting->datatype == Format_RadioButtons)
hal.stream.write("integer");
- break;
- case Format_Decimal:
- hal.stream.write("float");
- break;
+ hal.stream.write("\t");
+ /*
+ Format_Bool = 0,
+ Format_Bitfield,
+ Format_XBitfield,
+ Format_RadioButtons,
+ Format_AxisMask,
+ Format_Integer, // 32 bit
+ ,
+ Format_String,
+ Format_Password,
+ Format_IPv4,
+ // For internal use only
+ Format_Int8,
+ Format_Int16,
+ */
+ switch(setting_datatype_to_external(setting->datatype)) {
- case Format_Bool:
- hal.stream.write("bool");
- break;
+ case Format_Integer:
+ hal.stream.write("integer");
+ break;
- case Format_AxisMask:
- case Format_Bitfield:
- hal.stream.write("bitfield");
- break;
+ case Format_Decimal:
+ hal.stream.write("float");
+ break;
- case Format_XBitfield:
- hal.stream.write("xbitfield");
- break;
+ case Format_Bool:
+ hal.stream.write("bool");
+ break;
- case Format_RadioButtons:
- hal.stream.write("radiobuttons");
- break;
+ case Format_AxisMask:
+ case Format_Bitfield:
+ hal.stream.write("bitfield");
+ break;
- case Format_IPv4:
- hal.stream.write("ipv4");
- break;
+ case Format_XBitfield:
+ hal.stream.write("xbitfield");
+ break;
- case Format_String:
- hal.stream.write("string");
- break;
+ case Format_RadioButtons:
+ hal.stream.write("radiobuttons");
+ break;
- case Format_Password:
- hal.stream.write("password");
- break;
+ case Format_IPv4:
+ hal.stream.write("ipv4");
+ break;
- default:
- break;
+ case Format_String:
+ hal.stream.write("string");
+ break;
+
+ case Format_Password:
+ hal.stream.write("password");
+ break;
+
+ default:
+ break;
+ }
+
+ hal.stream.write("\t");
+
+ if(setting->format)
+ hal.stream.write(setting->format);
+ else if (setting->datatype == Format_AxisMask)
+ hal.stream.write("axes");
+
+ hal.stream.write("\t");
+
+ #ifndef NO_SETTINGS_DESCRIPTIONS
+ const char *description = setting_get_description((setting_id_t)(setting->id + offset));
+ hal.stream.write(description ? description : "");
+ #endif
+ hal.stream.write("\t");
+
+ if(setting->min_value)
+ hal.stream.write(setting->min_value);
+
+ hal.stream.write("\t");
+
+ if(setting->max_value)
+ hal.stream.write(setting->max_value);
}
-
- hal.stream.write("\t");
-
- if(setting->format)
- hal.stream.write(setting->format);
- else if (setting->datatype == Format_AxisMask)
- hal.stream.write("axes");
-
- hal.stream.write("\t");
-
-#ifndef NO_SETTINGS_DESCRIPTIONS
- report_setting_description(format, (setting_id_t)(setting->id + offset));
-#endif
- hal.stream.write("\t");
-
- if(setting->min_value)
- hal.stream.write(setting->min_value);
-
- hal.stream.write("\t");
-
- if(setting->max_value)
- hal.stream.write(setting->max_value);
break;
}
@@ -1746,21 +1759,7 @@ status_code_t report_settings_details (settings_format_t format, setting_id_t id
status_code_t report_setting_description (settings_format_t format, setting_id_t id)
{
- uint_fast16_t idx;
- const char *description = NULL;
- setting_details_t *settings = settings_get_details();
- const setting_detail_t *setting = setting_get_details(id, NULL);
-
- if(setting) do {
- if(settings->descriptions) {
- idx = settings->n_descriptions;
- do {
- if(settings->descriptions[--idx].id == setting->id)
- description = settings->descriptions[idx].description;
- } while(idx && description == NULL);
- }
- settings = settings->on_get_settings ? settings->on_get_settings() : NULL;
- } while(settings && description == NULL);
+ const char *description = setting_get_description(id);
if(format == SettingsFormat_MachineReadable) {
hal.stream.write("[SETTINGDESCR:");
@@ -1778,42 +1777,74 @@ status_code_t report_setting_description (settings_format_t format, setting_id_t
#endif
-status_code_t report_alarm_details (void)
+status_code_t report_alarm_details (bool grbl_format)
{
- uint_fast16_t idx, n_alarms = sizeof(alarm_detail) / sizeof(alarm_detail_t);
+ uint_fast16_t idx;
+ alarm_details_t *list = alarms_get_details();
- for(idx = 0; idx < n_alarms; idx++) {
+ if(grbl_format)
+ hal.stream.write("\"Alarm Code in v1.1+\",\" Alarm Message in v1.0-\",\" Alarm Description\"" ASCII_EOL);
- hal.stream.write("[ALARMCODE:");
+ do { // TODO: add sorting?
- hal.stream.write(uitoa(alarm_detail[idx].id));
- hal.stream.write(vbar);
- hal.stream.write(alarm_detail[idx].name);
- hal.stream.write(vbar);
- if(alarm_detail[idx].description)
- hal.stream.write(alarm_detail[idx].description);
- hal.stream.write("]" ASCII_EOL);
- }
+ for(idx = 0; idx < list->n_alarms; idx++) {
+
+ if(grbl_format) {
+ write_quoted(uitoa(list->alarms[idx].id), ",");
+ write_quoted(list->alarms[idx].name, ",");
+ write_quoted(list->alarms[idx].description ? list->alarms[idx].description : "", NULL);
+ hal.stream.write(ASCII_EOL);
+ } else {
+ hal.stream.write("[ALARMCODE:");
+ hal.stream.write(uitoa(list->alarms[idx].id));
+ hal.stream.write(vbar);
+ hal.stream.write(list->alarms[idx].name);
+ hal.stream.write(vbar);
+ if(list->alarms[idx].description)
+ hal.stream.write(list->alarms[idx].description);
+ hal.stream.write("]" ASCII_EOL);
+ }
+ }
+
+ list = list->on_get_alarms ? list->on_get_alarms() : NULL;
+
+ } while(list);
return Status_OK;
}
-status_code_t report_error_details (void)
+status_code_t report_error_details (bool grbl_format)
{
- uint_fast16_t idx, n_alarms = sizeof(status_detail) / sizeof(status_detail_t);
+ uint_fast16_t idx;
+ error_details_t *list = errors_get_details();
- for(idx = 0; idx < n_alarms; idx++) {
+ if(grbl_format)
+ hal.stream.write("\"Error Code in v1.1+\",\"Error Message in v1.0-\",\"Error Description\"" ASCII_EOL);
- hal.stream.write("[ERRORCODE:");
+ do { // TODO: add sorting?
- hal.stream.write(uitoa(status_detail[idx].id));
- hal.stream.write(vbar);
- hal.stream.write(status_detail[idx].name);
- hal.stream.write(vbar);
- if(status_detail[idx].description)
- hal.stream.write(status_detail[idx].description);
- hal.stream.write("]" ASCII_EOL);
- }
+ for(idx = 0; idx < list->n_errors; idx++) {
+
+ if(grbl_format) {
+ write_quoted(uitoa(list->errors[idx].id), ",");
+ write_quoted(list->errors[idx].name, ",");
+ write_quoted(list->errors[idx].description ? list->errors[idx].description : "", NULL);
+ hal.stream.write(ASCII_EOL);
+ } else {
+ hal.stream.write("[ERRORCODE:");
+ hal.stream.write(uitoa(list->errors[idx].id));
+ hal.stream.write(vbar);
+ hal.stream.write(list->errors[idx].name);
+ hal.stream.write(vbar);
+ if(list->errors[idx].description)
+ hal.stream.write(list->errors[idx].description);
+ hal.stream.write("]" ASCII_EOL);
+ }
+ }
+
+ list = list->on_get_errors ? list->on_get_errors() : NULL;
+
+ } while(list);
return Status_OK;
}
@@ -1943,7 +1974,6 @@ status_code_t report_current_limit_state (sys_state_t state, char *args)
return Status_OK;
}
-
// Prints spindle data (encoder pulse and index count, angular position).
status_code_t report_spindle_data (sys_state_t state, char *args)
{
diff --git a/report.h b/report.h
index 4025718..7a6fc39 100644
--- a/report.h
+++ b/report.h
@@ -93,8 +93,8 @@ void report_execute_startup_message (char *line, status_code_t status_code);
// Prints build info and user info.
void report_build_info (char *line, bool extended);
-status_code_t report_alarm_details (void);
-status_code_t report_error_details (void);
+status_code_t report_alarm_details (bool grbl_format);
+status_code_t report_error_details (bool grbl_format);
status_code_t report_setting_group_details (bool by_id, char *prefix);
status_code_t report_settings_details (settings_format_t format, setting_id_t setting, setting_group_t group);
#ifndef NO_SETTINGS_DESCRIPTIONS
diff --git a/settings.c b/settings.c
index c328a5f..29d7671 100644
--- a/settings.c
+++ b/settings.c
@@ -1465,17 +1465,21 @@ bool settings_read_tool_data (uint32_t tool, tool_data_t *tool_data)
#endif
}
-// Read Grbl global settings from persistent storage.
+// Read global settings from persistent storage.
// Checks version-byte of non-volatile storage and global settings copy.
bool read_global_settings ()
{
bool ok = hal.nvs.type != NVS_None && SETTINGS_VERSION == hal.nvs.get_byte(0) && hal.nvs.memcpy_from_nvs((uint8_t *)&settings, NVS_ADDR_GLOBAL, sizeof(settings_t), true) == NVS_TransferResult_OK;
+ // Sanity check of settings, board map could have been changed...
+ if(settings.mode == Mode_Laser && !hal.driver_cap.variable_spindle)
+ settings.mode = Mode_Standard;
+
return ok && settings.version == SETTINGS_VERSION;
}
-// Write Grbl global settings to persistent storage
+// Write global settings to persistent storage
void settings_write_global (void)
{
if(override_backup.valid)
@@ -1486,7 +1490,7 @@ void settings_write_global (void)
}
-// Restore Grbl global settings to defaults and write to persistent storage
+// Restore global settings to defaults and write to persistent storage
void settings_restore (settings_restore_t restore)
{
uint_fast8_t idx;
@@ -1728,6 +1732,32 @@ const setting_detail_t *setting_get_details (setting_id_t id, setting_details_t
return NULL;
}
+const char *setting_get_description (setting_id_t id)
+{
+ const char *description = NULL;
+
+#ifndef NO_SETTINGS_DESCRIPTIONS
+
+ uint_fast16_t idx;
+ setting_details_t *settings = settings_get_details();
+ const setting_detail_t *setting = setting_get_details(id, NULL);
+
+ if(setting) do {
+ if(settings->descriptions) {
+ idx = settings->n_descriptions;
+ do {
+ if(settings->descriptions[--idx].id == setting->id)
+ description = settings->descriptions[idx].description;
+ } while(idx && description == NULL);
+ }
+ settings = settings->on_get_settings ? settings->on_get_settings() : NULL;
+ } while(settings && description == NULL);
+
+#endif
+
+ return description;
+}
+
static status_code_t validate_value (const setting_detail_t *setting, float value)
{
float val;
diff --git a/settings.h b/settings.h
index 98fd5f3..7d866eb 100644
--- a/settings.h
+++ b/settings.h
@@ -704,6 +704,9 @@ typedef struct setting_details {
driver_settings_restore_ptr restore;
} setting_details_t;
+// NOTE: this must match the signature of on_get_settings in the setting_details_t structure above!
+typedef setting_details_t *(*on_get_settings_ptr)(void);
+
extern settings_t settings;
// Initialize the configuration subsystem (load settings from persistent storage)
@@ -749,6 +752,7 @@ setting_details_t *settings_get_details (void);
bool settings_is_group_available (setting_group_t group);
bool settings_iterator (const setting_detail_t *setting, setting_output_ptr callback, void *data);
const setting_detail_t *setting_get_details (setting_id_t id, setting_details_t **set);
+const char *setting_get_description (setting_id_t id);
setting_datatype_t setting_datatype_to_external (setting_datatype_t datatype);
setting_group_t settings_normalize_group (setting_group_t group);
char *setting_get_value (const setting_detail_t *setting, uint_fast16_t offset);
diff --git a/stepper.c b/stepper.c
index 67b02e0..bd3cee4 100644
--- a/stepper.c
+++ b/stepper.c
@@ -550,15 +550,16 @@ void st_reset ()
// NOTE: buffer indices starts from 1 for simpler driver coding!
// Set up stepper block ringbuffer as circular linked list and add id
- uint_fast8_t idx;
- for(idx = 0 ; idx <= SEGMENT_BUFFER_SIZE - 2 ; idx++) {
- st_block_buffer[idx].next = &st_block_buffer[idx == SEGMENT_BUFFER_SIZE - 2 ? 0 : idx + 1];
+ uint_fast8_t idx, idx_max = (sizeof(st_block_buffer) / sizeof(st_block_t)) - 1;
+ for(idx = 0 ; idx <= idx_max ; idx++) {
+ st_block_buffer[idx].next = &st_block_buffer[idx == idx_max ? 0 : idx + 1];
st_block_buffer[idx].id = idx + 1;
}
// Set up segments ringbuffer as circular linked list, add id and clear AMASS level
- for(idx = 0 ; idx <= SEGMENT_BUFFER_SIZE - 1 ; idx++) {
- segment_buffer[idx].next = &segment_buffer[idx == SEGMENT_BUFFER_SIZE - 1 ? 0 : idx + 1];
+ idx_max = (sizeof(segment_buffer) / sizeof(segment_t)) - 1;
+ for(idx = 0 ; idx <= idx_max ; idx++) {
+ segment_buffer[idx].next = &segment_buffer[idx == idx_max ? 0 : idx + 1];
segment_buffer[idx].id = idx + 1;
segment_buffer[idx].amass_level = 0;
}
diff --git a/stream.c b/stream.c
index 5996518..12405c7 100644
--- a/stream.c
+++ b/stream.c
@@ -91,6 +91,11 @@ ISR_CODE bool stream_buffer_all (char c)
return false;
}
+ISR_CODE bool stream_enqueue_realtime_command (char c)
+{
+ return hal.stream.enqueue_rt_command ? hal.stream.enqueue_rt_command(c) : protocol_enqueue_realtime_command(c);
+}
+
ISR_CODE bool stream_enable_mpg (const io_stream_t *mpg_stream, bool mpg_mode)
{
static io_stream_t org_stream = {
@@ -138,12 +143,14 @@ ISR_CODE bool stream_enable_mpg (const io_stream_t *mpg_stream, bool mpg_mode)
#ifdef DEBUGOUT
-static stream_write_ptr dbg_write;
+static stream_write_ptr dbg_write = NULL;
-static void debug_write (const char *s)
+void debug_write (const char *s)
{
- dbg_write(s);
- while(hal.debug.get_tx_buffer_count()); // Wait until message is delivered
+ if(dbg_write) {
+ dbg_write(s);
+ while(hal.debug.get_tx_buffer_count()); // Wait until message is delivered
+ }
}
void debug_stream_init (io_stream_t *stream)
diff --git a/stream.h b/stream.h
index 6332e0a..367abf3 100644
--- a/stream.h
+++ b/stream.h
@@ -56,7 +56,7 @@ Helper functions for saving away and restoring a stream input buffer. _Not refer
#endif
#ifndef BLOCK_TX_BUFFER_SIZE
-#define BLOCK_TX_BUFFER_SIZE 256
+#define BLOCK_TX_BUFFER_SIZE 1024
#endif
// Serial baud rate
@@ -124,11 +124,23 @@ This should be called by driver code prior to inserting a character into the inp
*/
typedef bool (*enqueue_realtime_command_ptr)(char c);
+
+/*! \brief Optional, but recommended, pointer to function for enqueueing realtime command characters.
+\param c character to enqueue.
+\returns \a true if sucessfully enqueued, \a false otherwise.
+
+__NOTE:__ Stream implementations should pass the character over the current handler registered by the set_enqueue_rt_handler().
+
+User or plugin code should __not__ enqueue realtime command characters via this handler, it should call \a grbl.enqueue_realtime_command() instead.
+*/
+typedef bool (*enqueue_realtime_command2_ptr)(char c);
+
+
/*! \brief Pointer to function for setting the enqueue realtime commands handler.
\param enqueue_realtime_command_ptr pointer to the new handler function.
\returns \a enqueue_realtime_command_ptr pointer to the replaced function.
-__NOTE:__ Stream implementation should hold a pointer to the handler in a local variable and typically
+__NOTE:__ Stream implementations should hold a pointer to the handler in a local variable and typically
set it to protocol_enqueue_realtime_command() on initialization.
*/
typedef enqueue_realtime_command_ptr (*set_enqueue_rt_handler_ptr)(enqueue_realtime_command_ptr);
@@ -179,7 +191,6 @@ for handing feed-holds, overrides, soft resets etc.
\param disable \a true to disable stream, \a false to enable,
*/
-
typedef bool (*disable_stream_ptr)(bool disable);
//! Properties and handlers for stream I/O
@@ -190,10 +201,11 @@ typedef struct {
stream_write_ptr write; //!< Handler for writing string to current output stream only.
stream_write_ptr write_all; //!< Handler for writing string to all active output streams.
stream_write_char_ptr write_char; //!< Handler for writing a single character to current stream only.
+ enqueue_realtime_command2_ptr enqueue_rt_command; //!< (Optional) handler for enqueueing a realtime command character.
stream_read_ptr read; //!< Handler for reading a single character from the input stream.
flush_stream_buffer_ptr reset_read_buffer; //!< Handler for flushing the input buffer.
cancel_read_buffer_ptr cancel_read_buffer; //!< Handler for flushing the input buffer and inserting an #ASCII_CAN character.
- set_enqueue_rt_handler_ptr set_enqueue_rt_handler; //!< Handler for setting the enqueue realtime commands handler.
+ set_enqueue_rt_handler_ptr set_enqueue_rt_handler; //!< Handler for setting the enqueue realtime command character handler.
suspend_read_ptr suspend_read; //!< Optional handler for saving away and restoring the current input buffer.
stream_write_n_ptr write_n; //!< Optional handler for writing n characters to current output stream only. Required for Modbus support.
disable_stream_ptr disable; //!< Optional handler for disabling/enabling a stream. Recommended?
@@ -257,7 +269,10 @@ bool stream_buffer_all (char c);
bool stream_tx_blocking (void);
+bool stream_enqueue_realtime_command (char c);
+
#ifdef DEBUGOUT
+void debug_write (const char *s);
void debug_stream_init (io_stream_t *stream);
#endif
diff --git a/system.c b/system.c
index e37e68f..c11db1c 100644
--- a/system.c
+++ b/system.c
@@ -35,7 +35,9 @@
static status_code_t jog (sys_state_t state, char *args);
static status_code_t enumerate_alarms (sys_state_t state, char *args);
+static status_code_t enumerate_alarms_grblformatted (sys_state_t state, char *args);
static status_code_t enumerate_errors (sys_state_t state, char *args);
+static status_code_t enumerate_errors_grblformatted (sys_state_t state, char *args);
static status_code_t enumerate_groups (sys_state_t state, char *args);
static status_code_t enumerate_settings (sys_state_t state, char *args);
static status_code_t enumerate_all (sys_state_t state, char *args);
@@ -210,7 +212,9 @@ PROGMEM static const sys_command_t sys_commands[] = {
{ "N0", false, set_startup_line0 },
{ "N1", false, set_startup_line1 },
{ "EA", true, enumerate_alarms },
+ { "EAG", true, enumerate_alarms_grblformatted },
{ "EE", true, enumerate_errors },
+ { "EEG", true, enumerate_errors_grblformatted },
{ "EG", true, enumerate_groups },
{ "ES", true, enumerate_settings },
{ "ESG", true, enumerate_settings_grblformatted },
@@ -340,12 +344,22 @@ static status_code_t jog (sys_state_t state, char *args)
static status_code_t enumerate_alarms (sys_state_t state, char *args)
{
- return report_alarm_details();
+ return report_alarm_details(false);
+}
+
+static status_code_t enumerate_alarms_grblformatted (sys_state_t state, char *args)
+{
+ return report_alarm_details(true);
}
static status_code_t enumerate_errors (sys_state_t state, char *args)
{
- return report_error_details();
+ return report_error_details(false);
+}
+
+static status_code_t enumerate_errors_grblformatted (sys_state_t state, char *args)
+{
+ return report_error_details(true);
}
static status_code_t enumerate_groups (sys_state_t state, char *args)
@@ -370,8 +384,8 @@ static status_code_t enumerate_settings_halformatted (sys_state_t state, char *a
static status_code_t enumerate_all (sys_state_t state, char *args)
{
- report_alarm_details();
- report_error_details();
+ report_alarm_details(false);
+ report_error_details(false);
report_setting_group_details(true, NULL);
return report_settings_details(SettingsFormat_MachineReadable, Setting_SettingsAll, Group_All);
}